Some build systems (e.g. tup) can track file accesses during a build. This enables them to find errors in the build config. For example, if a file is read but not specified as a dependency.
Now I already have a complicated CMake build configuration. Is there a tool or trick to do such file access tracking during a build with Cmake?
Related
I am building the Poco libraries from source code using cmake, following the instructions from the official website, on OSX High Sierra.
From that I get a bunch of files representing the dynamic libraries with extension *.dylib for example libPocoJSON.23.dylib.
However an external application is looking (in the same path locations), apart from the files created with the build, for other files of the library with a similar name such as to the created ones (they are different only for a d appended to the first part of the name). One example of such file is:
libPocoJSONd.23.dylib
I have found that these files are created with the debug build (while the release build creates only the files without the d extension).
How to perform the build of the debug? Should I look for a flag to active in any of the cmake file or it is a complete different source code?
How to perform the build of the debug?
Use cmake -DCMAKE_BUILD_TYPE=Debug
See CMAKE_BUILD_TYPE for details.
CMake has a find_package() backed by a bunch of FindXYZ scripts (which you can also add to).
What mechanism, if any, is available to me to tell cmake: "Find this package, and if you haven't found it, download it and trigger its build" - with the downloading and building part also backed by per-package scripts or settings (so that downloading could be with wget or git clone, building could be with cmake or maven or a package-specific command, etc.) ?
Yeah, I was bitten by that Friday.
So, CMake has an ExternalProject directive, meant for exactly that, get/update if necessary, configure, build and install this and that external project. Awesome!
Sadly, CMake isn't that awesome.
You can't use the target defined by ExternalProject as a library in target_link_libraries. I've really tried to.
The basic problem is that the updating, building and installation of the external project happens at build time, whereas CMake insists on only using libraries that it found during pre-build (i.e. during the CMake run); you can't re-detect stuff while running make/ninja/msvc… .
You can define a custom target, tell it where the .so you'd want to link against later will be, and try to coerce CMake into believing you without checking at pre-build. Sadly, at least in the CMake versions I had, that broke dependency tracking, so that it simply didn't build the external library, because nothing needed it.
From the error messages you get when trying to use an external project in target_link_library, it seems CMake assumes you'd only want to install tools you need at build time that way, not libraries. A bummer.
You can roll your own version of download-on-demand using execute_process() (which runs on the CMake configure step) with ${CMAKE_COMMAND} as the command invoked on a CMakeLists.txt containing ExternalProject_Add().
You could even either configure_file() the CMakeLists.txt to fill out custom variables or dynamically create the CMakeLists.txt file.
I have a CMake project. It is a crossplatform project developed by a team of developers. Visual Studio and other make files are inside version control for library release and external developers.
Each time a file is added we need to recompile all project files for all platforms. How do I force CMake to generate new project files for all systems at once (if possible from inside CMakeLists.txt, not as command line arguments)?
I think it doesn't make sense for this to be possible within the CMakeLists.txt file. CMake is a makefile generator. Everything in the CMakeLists.txt file is configuring the makefile, and it can also be repurposed to make project files.
If the CMakeLists.txt file could also request to generate a different kind of makefile... it would be different from every other command in the CMakeLists.txt file in that it isn't describing the currently selected makefile.
If I were you I would just make a shell script, or a simple makefile, separate from CMake, which rebuilds each of the project files, by invoking CMake from command line with appropriate parameters.
Is the goal of the versioned CMake produced build scripts to not force developers to install CMake?
In any case: it's best to use the right tool for the right job. CMake is for producing build-files and the little scripting necessary to do so. Use a scripting environment (Bash, cmd.exe) to run CMake as necessary for all your platforms.
This keeps the CMake files clean (and readable, CMake scripting is hard to read) and provides clean separation of concerns.
Is there any way to create a FindXXX.cmake automatically where XXX is my Cmake project? I see many projects that they created their FindXXX.cmake manually but I believe it's possible to create it automatically.
And, where I should install my project on Linux?
Thanks!
Take a look at CMake's project config file mechanism (along with the CMakePackageConfigHelper module; you might also want to take a look at this wiki page).
Find scripts are most useful for locating dependencies that are not aware of CMake themselves. If on the other hand the dependency was also built using CMake, you can let CMake auto-generate a project config file for you as part of that project's build process. This config file will allow you to refer to the targets of that project from an enclosing project as if they were being built as part of the enclosing project's CMake run. This is even more powerful than using find scripts, as it allows for example distinct handling of configurations beyond the debug/optimized options available to traditional find scripts.
On Windows, projects generating config files this way will register themselves with CMake, so that depending projects building on the same machine can find them automatically without any additional configuration. If you are building on non-Windows platforms (or you are building the two libraries on different machines) you will have to place the config file in a default directory (the docs for find_package describe which directories are searched) or explicitly point CMake to the location using CMAKE_MODULE_PATH.
Modern CMake-aware libraries should always prefer this approach over traditional find scripts. A prominent example of a library that does this already is Qt5.
CMake supports templating with configure_file() command.
Standard dirs where CMake searches for FindXXX.cmake modules are listed in the documentation of find_package() command.
I am working on a cross-platform project which uses a large number of third party libraries (currently 22 and counting, and I expect this number to increase significantly). My project is CMake-based, and keeps the ThirdParty/ directory organized like so:
ThirdParty/$libname/include/
ThirdParty/$libname/lib/$platform/$buildtype/
My CMakeLists.txt has logic to determine the appropriate values for $platform (mac-i386, mac-ia64, win32-i386, and so on) and $buildtype (debug/release).
The difficulty arises in keeping these libraries up-to-date for each platform. Currently I am doing this manually - when I update one library, I go and rebuild it for each platform. But this is a nightmare, and adding a new platform is a two day affair.
This would be easy to automate if the third party libraries were themselves CMake-based, but they use everything from CMake to autoconf to custom solutions to hand-rolled Makefiles. There is no consistency between them, and all require various hoops to be jumped through with regards to build platform (especially with regards to 32- vs. 64-bit builds).
Are there any tools (or CMake extensions) which would make this easier to manage? Is there even any reasonable common ground that can be reached between CMake and autoconf, for example?
The ideal solution would give me a single command to build everything that needs rebuilding for a given platform (cross-compilation is not necessary, as I have access to all necessary platforms), but anything that incrementally makes my life easier would be appreciated.
You can probably use ExternalProject for this.
Create custom targets to build projects in external trees.
The 'ExternalProject_Add' function creates a custom target to drive download, update/patch, configure, build, install and test steps of an external project.
If you already have the source in your project's file hierarchy, then you can use something like this (for zlib):
include(ExternalProject)
ExternalProject_Add(zlib URL ${CMAKE_CURRENT_SOURCE_DIR}/zlib-1.2.4/
CONFIGURE_COMMAND cd <SOURCE_DIR> && ./configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/zlib-build
BUILD_IN_SOURCE 1
BUILD_COMMAND make)
That will copy the zlib source code from your source tree into the build tree, run the configure step (after cd'ing into the copied directory), then run make on the configured directory. Finally the built version of zlib is installed into the current build directory, in a sub-directory called zlib-build.
You can tweak the setup, configure, and build steps however you like - zlib 1.2.4 for example doesn't like to have "configure" run out-of-source.
For a custom setup, you can skip the CONFIGURE step and just run the build command (for example). This requires a recent version of CMake to work (2.8+).