CMake - Build custom build paths for different configurations - makefile

I have a project whose make process generates different build artifacts for each configuration, e.g. if initiated with make a=a0 b=b0 it would build object files into builds/a0.b0, generate a binary myproject.a0.b0, and finally update an ambiguous executable link to point to the most recently built project ln -s myproject.a0.b0 myproject. For this project, this is a useful feature mainly because:
It separates the object files for different configurations (so when I rebuild in another configuration I don't have to recompile every single source with new defines and configurations set, (unfortunately) a very common procedure).
It retains the binaries for each configuration (so it's not required to rebuild to use a different configuration if it has already been built).
It makes a copy (or link) to the last built binary which is useful in testing.
Right now this is implemented in an ugly decades-old non-portable Makefile. I'd like to reproduce the same behavior in CMake to allow easier building on other platforms but I have not been able to reproduce it in any reasonable manner. It seems like adding targets with add_library/executable, but doing this for each possible permutation of input parameters seems wrong. And I'm not sure I could get the utilization correct, allowing make, make a=a0, make b=b0 a=a0 as opposed to what specifying a cmake target would require: make myproject-a0.b0.
Is this possible to do in cmake? Namely:
Specify the build directory based on input parameters.
Accept the parameters as make arguments which can be left out (defaulted) to select the appropriate target at the level of the makefile (so it's not required to rerun cmake for a new configuration).

Related

Specifying uncached compile-time constants in CMakeLists file

In one of my CMakeList files I specified an option which conditionally defines a compile-time constant in a generated header file.
However, I recognized that the value of the option is being cached by cmake.
This leads to the unintentional behaviour that I need to delete the cmake cache everytime I change the option and issue cmake ..
Currently this is the only option being used. Later on I would like to use more options.
It is really confusing to me that the CMakeLists.txt does not represent the actual build setting due to the caching mechanism.
E.g. an build flag set in the CMakeLists.txt but still unset in the cache.
I don't want to disable caching, I just want that my build is always in sync with the build flag set in the CMakeLists.txt. I understand that cmake's caching mechanism is saving lot of time during large builds. Which is actually good.
Does there exist some means to force an option to be up-to-date on cmake .?
I tried to turn the option into a set instruction. The cmake still uses the cached value instead of the actual one.
What am I doing wrong?
Here is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(Test VERSION 1.0)
option(MY_BUILD_FLAG "bla" OFF)
configure_file(TestConfig.h.in TestConfig.h)
Here is my change which I unsuccessfully tried out:
cmake_minimum_required(VERSION 3.10)
project(Test VERSION 1.0)
# Here you can set several build flags ON or OFF
set(MY_BUILD_FLAG "bla" OFF)
configure_file(TestConfig.h.in TestConfig.h)
I understand that cmake's caching mechanism is saving lot of time during large builds.
This is incorrect. The purpose of cmake cache variables is to persist variables across information for subsequent reconfigurations of the same build directory.
The fact that e.g. .o files remain in the build directory unless explicitly cleared and aren't rebuilt, if the sources for compiling it is an entirely different mechanism.
Note that you may in fact see improvements of the CMake configuration time, since e.g. results of try_compile are cached. This may actually result in a perceived improved build time, if you often rewrite the cmake files and therefore trigger an automatic cmake reconfiguration of your project before the actual build starts. However if you do not change the cmake logic, the use of CMake cache variables doesn't improve build times at all (or conditionally applying other logic resulting in a different amount of work for compiler or linker).
Note: Another notable use for cache variables is to provide project configuration options to the user. I'm not elaborating on this, since this doesn't affect build times without additional CMake logic dependent on the value influencing the amount of code to build.

Using dpkg-buildpackage to build multiple packages from same source

I have a source tree that can build two different projects from the same source. You call make A or make B, and the code is affected by ifdefs and similar using preprocessor variables to make two versions of the output. I'm looking to make dpkgs for these, and can make one fine, but am unsure of a good way to do this.
Currently I run dpkg-buildpackage, and I get A.deb or similar. Is there a way to do dpkg-buildpackage -target B so that it would then build a debian package for that project?
Things such as Creating multiple packages with dpkg-buildpackage seem to refer to having separate source code for the separate projects, which is not the case here.
I am in control of the source code so can make changes there.
Thanks.
You can set up one rules file to build two separate Debian packages at the same time. But if they are unrelated, this is an abuse of the Debian packaging procedure. It's designed for building multiple related Debian binary packages from a single source.

Method to make IncludeDirs available to external tool

I'm currently trying to make splint available as an external tool in Visual Studio 2010.
It has problems with finding all includes for the file, since it seems that the INCLUDE variable is only set at build time and I haven't found any other possibility to extract the include files in any way.
My question: Would there be any way to extract the IncludeDir field from the current file's project's Properties page, ideally with the VC++'s AdditionalIncludeDirectories?
Note also that AdditionalIncludeDirectories is per file, as it can be changed for individual source files as well as on the project level, and if it contains macros it can evaluate differently for each source file too!
I'm not familiar with driving the MSBuild objects via the API, but that's used by the IDE. Whether that way or by simply running MSBuild.exe, you need to get it to figure out all the properties, conditions, etc. and then tell you the result. If everything is well behaved, you could create a target that also uses the ClCompile item array and emits the %(AdditionalIncludeDirectories) metadata somehow such as writing it to a file or passing it to your other tool somehow. That's what's used to generate the /I parameters to CL, and you can get the same values.
If things are not well behaved in that necessary values are changed during the detailed build process, you would need to get the same prelims done just like the ClCompile target normally does, too. Or just override ClCompile with your own (last definition of a target is used) so it certainly is in the same context.
Either way, there are places where build script files can be automatically included into all projects, so you can add your stuff there or use a command argument (I think) to MSBuild to add another Include.
—John

How do I suppress Xcode from generating a folder named after the build configuration in cmake?

I have a cmake configuration that works great for my project on Windows and Linux. We're tinkering with MacOS right now and we're at the point where Xcode spits out the libraries built one directory off from what we define. Instead of it being dropped in ~/bin it is dropped in ~/bin/Debug, for example. As best I can tell Xcode is taking upon itself to add this folder to the path and I don't want that.
How can I disable Xcode from doing this from within my cmake configuration?
You'll need to specify the target properties ARCHIVE_OUTPUT_DIRECTORY_<CONFIG>, LIBRARY_OUTPUT_DIRECTORY_<CONFIG>, and/or RUNTIME_OUTPUT_DIRECTORY_<CONFIG> for each config type and each target you want to affect.
To affect all targets, you can set variables named as these with CMAKE_ prepended. Any relevant target added after these have been set will be affected.
So, for example you could either do:
add_library(MyLib ${Sources})
set_target_properties(MyLib PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}
ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR})
or you could do:
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR})
add_library(MyLib ${Sources})
Having said that, I normally find it's best to let multi-configuration generators like XCode and MSVC just add the config-specific directories. Unless you plan to also change the default names of exes and libs, these multi-config IDEs will overwrite one config's outputs with another's. So, it's hard to tell whether you're looking at a Debug or Release exe for example.
For single-config generators, I think it's common to have separate build trees per configuration to keep the distinction clear.
Basically, I wouldn't fight against the generator. CMake automates so much of the build process that I never find this slight difference between generators to be a problem. You rarely have to consider whether the output path contains a config dir or not.

make target, unmake target?

Since make knows all dependencies to make a target, it knows (almost) all intermediate artefacts. Is there a make version that can 'rollback', or 'unmake' a target?
(I know it removes targets created by implicit rules)
Most Makefiles provide the clean target, which removes all generated files. Additionally, autoconf-automake systems offer distclean, which also removes the files generated by configure.
These are no automatic targets, however; the makefile generation system gives a list of generated files to make. In general, make doesn't keep track which files it generated, so it can't distinguish between genuine source files (which are dependencies) and intermediate files (which are also dependencies). Even the leaf nodes of the dependency graph can't be used for distinguishment, because stamp files often have no dependencies as well.

Resources