Switch between different build settings - caching

Sorry for the vague title, I'm not sure how to phrase this correctly. I would like to write a cmake script that allows to build a target with different settings for bit width (forced 32 bit, forced 64 bit or native bit width) and static linking. I figured out how to set up the build under each condition and so far I'm using cmake options to switch between different setups.
My problem is that changing one of these build options with ccmake or on the command line also requires to look for new library paths. Since these paths are cached, I currently have to delete the cache when changing bit width. This way users also loose all other settings for options that are independent of bit width and static linking.
Is there a common way to handle this?

Use different build directories for different settings:
cmake -H. -B_builds/arch64 -DCMAKE_CXX_FLAGS=-m64
cmake -H. -B_builds/arch32 -DCMAKE_CXX_FLAGS=-m32
cmake -H. -B_builds/shared -DBUILD_SHARED_LIBS=ON
cmake -H. -B_builds/static -DBUILD_SHARED_LIBS=OFF
cmake -H. -B_builds/debug -DCMAKE_BUILD_TYPE=Debug
cmake -H. -B_builds/release -DCMAKE_BUILD_TYPE=Release
Exceptions
Note that in each case there may be exceptions, like:
add_library(foo STATIC ${FOO_SOURCES}) # BUILD_SHARED_LIBS will be ignored
or for Visual Studio and Xcode Debug/Release will be:
cmake -H. -B_builds/xcode -GXcode
cmake --build _builds/xcode --config Debug # build Debug
cmake --build _builds/xcode --config Release # build Release
instead of xcode-debug and xcode-release
Related
CMAKE_BUILD_TYPE not being used in CMakeLists.txt

Related

How to configure CMakeLists to use Windows command line compiler instead of Visual Studio

I would like to convert my project from a Visual Studio solution to build with CMake and compile it with Makefiles.
This is a 2-part question.
Right now the CMakeLists.txt is:
cmake_minimum_required(VERSION 3.13.0)
project(Project2015 CXX)
add_executable(Project Source/main.cpp)
When I run cmake .. out of the build directory, it generates *.vcxproj and *.sln files, but there is no Makefile. How can I change the CMakeLists file to generate a Makefile?
What is the command line equivalent compiler to gcc for windows? And how do I set this compiler as the target for CMake and the generated Makefile?
Reading about the build tools https://learn.microsoft.com/en-us/cpp/build/walkthrough-compile-a-c-program-on-the-command-line?view=vs-2019
Do I need to target the cl.exe compiler? Would this work with CMake and Makefiles?
I'm reading online that these command line flags will set the compiler, how can I add these to the CMakeLists.txt to be used automatically?
DCMAKE_C_COMPILER=cl
DCMAKE_C_COMPILER_FORCED=ON
DCMAKE_CXX_COMPILER=cl
DCMAKE_CXX_COMPILER_FORCED=ON
DCMAKE_BUILD_TYPE=Debug
DCMAKE_INSTALL_PREFIX=%CFITSIO_DIR%
G"NMake Makefiles"
You should use the build tool mode of CMake for builds from the command line.
After configuring your project for a 64bit build using Visual Studio 2019 e.g. with
cmake -S <sourcedir> -B <builddir> -G "Visual Studio 16 2019" -A x64
you would run
cmake --build <builddir> --target ALL_BUILD --config Release
For further options see here for an almost quiet build from the command line see here.
As suggested by #vre, you can run everything from the command line, while still using the Visual Studio generator. Just use CMake's command line build tools:
cmake ..
cmake --build . --config Release
This way, you don't have to open Visual Studio at all to build your libraries/executables.
Another option is to use Microsoft's nmake utility, which will generate NMake Makefiles. You can tell CMake to use this generator instead using this:
cmake -G"NMake Makefiles" ..
The full list of CMake generators you can choose from is listed here.
If you don't want to manually set the CMake generator in the command line, you can set it at the top of your CMakeLists.txt file:
set (CMAKE_GENERATOR "NMake Makefiles" CACHE INTERNAL "" FORCE)
It will be used on the second CMake configuration in this case, as the first run will use the system default generator. If you want CMake to use it on the first configuration, you can utilize the Preload.cmake procedure outlined in this answer.

CMake and slow MSVC compilation

CMake generate project for MSVC 10 (2010) and build time are relativly low, ie. after I click build for given project it start compiling in like seconds, which is expected.
For Qt Creator I choose CodeBlocks - NMake Makefiles as CMake generator, set build configuration to use the same target as above. When I click build I see
cmake --build . --target name
and silence for like 2 minutes. ThenScanning dependencies for ... and 1,5 minutes more of silence.
To make things even worse - later compilation use only 1 thread. So compilation time is ... unacceptably long.
How should I configure project to achieve comparable, short compilation times as from under MSVC? I've tried Qt Creator 4.3 Beta and beside
CMake per default does not multiprocessor builds. So its up to you to force it to...
You can specify the /MP flag when you configure your project with cmake.
cmake -G "<MSVC-Generator>" -DCMAKE_CXX_FLAGS="/MP" <target_dir>
I do this for all my cmake projects in the file CMakeLists.txt itself so the client does not have to:
if(MSVC)
target_compile_options(<target> PRIVATE "/MP")
endif()
CMake calls the compiler with default parameters, that is, with a single thread build, even for MSVC. Your build in MSVS is faster because Visual Studio calls the compiler with the settings configured for multiprocessor build.
How to use multiprocessor build for CodeBlocks - NMake Makefiles or other cmake generators?
Add -jn option for gcc compiler:
cmake --build . --target name -- -j4
or /m for MSVC:
cmake --build . --target name -- /m
For MSVS 2017 or newer instead of /m you can use -m form. Also, you can specify the maximum number of concurrent processes to use when building-m:3.
NMake and NMake JOM are slow.
When I change to Ninja build system - compilation times are similar to those inside MSVC.

make without makefile after cmake

I try to use the c++ language bindings for the ev3dev lego brick: https://github.com/ddemidov/ev3dev-lang-cpp
The instruction is as follows:
mkdir build
cd build
cmake .. -DEV3DEV_PLATFORM=EV3
make
I am running windows and have cmake and mingw available. After running cmake it creates some files in the build directory. However: There is no makefile which could be picked of by make. So I am wondering how iam supposed to compile these bindings
On Windows, CMake generates a MSVC solution by default. Check for a .sln file in your build directory.
The instructions you linked are assuming a Unix-ish platform, where the default is to create Makefiles.
If you actually want Makefiles on Windows, add -G "Unix Makefiles" to the cmake line.
If you want to use MSVC as compiler but work on the command line, another option is -G "NMake Makefiles", and calling nmake after that.
Make sure to delete your build directory before trying to build a new generator target. CMake can be touchy about that.
Check cmake --help for a list of available options. (Especially the generator targets are platform-specific.)

How to change the build type to Release mode in cmake?

I am trying to build a project in Release mode. By default it is built in debug mode. I am setting the variable CMAKE_BUILD_TYPE to "Release" in CMakeLists.txt. But it is still building the project in debug mode.
When I pass "Release" as the build type in the CMake command, it still does not work.
The CMake command that I am using is:
cmake -G"Visual Studio 10" -DCMAKE_BUILD_TYPE=Release
-H"source_path" -B"Build path"
Please provide a solution if any.
To change the build type, on Windows, it must be done at build time:
cmake --build {DIR} --config Release
By default it's Debug. I'm still looking for a way of changing this default. CMAKE_BUILD_TYPE doesn't work of course, and tweaking CMAKE_CONFIGURATION_TYPES doesn't work either, obviously for the same reason, they only apply for Unix makefiles, not for Visual projects.
I checked it with Visual Studio 2015 and cmake 3.3 .
Short answer
Link
cmake --build {BUILD_DIR_PATH} --target ALL_BUILD --config {BUILD_TYPE}
Example
cmake --build . --target ALL_BUILD --config Release
Long answer
cmake -G{GENERATOR_NAME} -B{BUILD_DIR_PATH} -H{SOURCE_DIR_PATH}
cmake --build {BUILD_DIR_PATH} --target ALL_BUILD --config {BUILD_TYPE}
Example
cmake -GVisual Studio 14 -Bbuild/win32/x86 -H.
cmake --build build/win32/x86 --target ALL_BUILD --config Release
Additional info
"-G" - specifies the generator name
"-B" - specifies path to the build folder
"-H" - specifies path to the source folder
You cannot set the default build type for Visual Studio from the command line.
CMake's Visual Studio Generators will generate the four standard profiles (Debug, RelWithDebInfo, MinSizeRel and Release) and you have to choose the one you want to build from within VS. This is because the information about the active configuration is not part of the project files generated by CMake, but part of the .suo file generated by VS.
If you want an automated build of a particular configuration, use MSBuild instead of VS which allows you to specify a configuration on the command line.
Tried the things below which worked for me to build the binaries in release/debug mode in Windows.
Added the following line in the root CMakeLists.txt file, just above the project command:
SET(CMAKE_CONFIGURATION_TYPES ${CMAKE_BUILD_TYPE} CACHE STRING "" FORCE)
Used the following command for setting the release mode configuration:
cmake -DCMAKE_BUILD_TYPE=Release ..
Used this command to build the same in Release mode:
cmake --build . --config Release
You can repeat the same procedure for debug mode as well, it works.
Bit late, but I found this worked for me and was quite clean:
This means that just calling cmake builds in release mode, but if you want debug mode just call cmake -DCMAKE_BUILD_TYPE=Debug
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose Release or Debug" FORCE)
endif()
If your generator is a single-config generator like "Unix Makefiles" or "Ninja", then the build type is specified by the CMAKE_BUILD_TYPE variable, which can be set in the configure command by using -DCMAKE_BUILD_TYPE:STRING=Release.
For multi-config generators like the Visual Studio generators and "Ninja Multi-Config", the config to build is specified in the build command using the --config argument argument like --config Release. A default value can currently be specified at configure time for the Ninja Multi-Config generator by setting the value of the CMAKE_DEFAULT_BUILD_TYPE variable, which will be used if the --config argument isn't passed to the build command. At the current time, a default cannot be set for Visual Studio generators.
Use it as you do it but in the root cmake file add the following before the project keyword
SET(CMAKE_CONFIGURATION_TYPES ${CMAKE_BUILD_TYPE} CACHE STRING "" FORCE)
PROJECT(MY_PROJECT)#It's here just to show where you should add it.

How to create a new configuration with CMake

I'm trying to create a NewConfiguration for my project:
set (CMAKE_CONFIGURATION_TYPES "Release;RelWithDebInfo;Debug;NewConfiguration" CACHE STRING "Configurations" FORCE)
But when I run CMake, I have multiple errors:
CMake Error: Error required internal CMake variable not set, cmake may be not be
built correctly.
Missing variable is:
CMAKE_SHARED_LINKER_FLAGS_NEWCONFIGURATION
CMake Error: Error required internal CMake variable not set, cmake may be not be
built correctly.
Missing variable is:
CMAKE_CXX_FLAGS_NEWCONFIGURATION
I think I'm missing something...
I also followed CMake FAQ:
if(CMAKE_CONFIGURATION_TYPES)
set(CMAKE_CONFIGURATION_TYPES Release RelWithDebInfo Debug NewConfiguration)
set(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" CACHE STRING
"Reset the configurations to what we need"
FORCE)
endif()
But same errors...
EDIT:
If I do:
SET( CMAKE_CXX_FLAGS_PLAYERVIEWER "-Wall -Wabi" CACHE STRING "Flags used by the C++ compiler during maintainer builds." FORCE )
SET( CMAKE_C_FLAGS_PLAYERVIEWER "-Wall -pedantic" CACHE STRING "Flags used by the C compiler during maintainer builds." FORCE )
SET( CMAKE_EXE_LINKER_FLAGS_PLAYERVIEWER "-Wl,--warn-unresolved-symbols,--warn-once" CACHE STRING "Flags used for linking binaries during maintainer builds." FORCE )
SET( CMAKE_SHARED_LINKER_FLAGS_PLAYERVIEWER "-Wl,--warn-unresolved-symbols,--warn-once" CACHE STRING "Flags used by the shared libraries linker during maintainer builds." FORCE )
set (CMAKE_CONFIGURATION_TYPES "Release;RelWithDebInfo;Debug;PlayerViewer" CACHE STRING "Configurations" FORCE)
It creates the new configuration, but I can not compile. I think flags are not correct. I am using Visual Studio 2008.
Thank you :)
I've just created 6 or 7 new configurations for VS2008 with cmake 2.8.4 (now it is days or even hours from 2.8.5 release) for simple hello world project.
The reason why your attemps failed what flags are inccorect e.g. they must be /MDd no -MDd
You notation will work for GCC based compilers, not for VS.
What I recommend you is to get closest flags set and modify it then
set(CMAKE_CXX_FLAGS_FOO ${CMAKE_CXX_FLAGS_DEBUG})
# .. modifiy it - add or remove flags
also i noticed that cmake sometimes does not actually write to .sln or it is not always reloaded (well, I am running win7 on VirualBox maybe it is source of issues).
what i did is the following -
file(GLOB WILL_REMOVE "${CMAKE_CURRENT_BINARY_DIR}/*.vcproj")
execute_process(COMMAND ${CMAKE_COMMAND} -E remove -f ${WILL_REMOVE})
file(GLOB WILL_REMOVE "${CMAKE_CURRENT_BINARY_DIR}/*.sln")
execute_process(COMMAND ${CMAKE_COMMAND} -E remove -f ${WILL_REMOVE})
file(GLOB WILL_REMOVE "${CMAKE_CURRENT_BINARY_DIR}/*.user")
execute_process(COMMAND ${CMAKE_COMMAND} -E remove -f ${WILL_REMOVE})
at least it reloads files :)
however, sometimes i need to run cmake 2 or 3 times to see new configuration at visual studio (can be virtual box, cmake or visual studio bug - have no idea about it).
But, anyway, after 2 or 3
cmake ..
It WORKS!!!!
Despite the CMake FAQ, looks like there is something still a bit unimplemented for this feature request. There is even an open issue for it:
http://www.cmake.org/Bug/view.php?id=5811
Monitor that bug in the CMake bug tracker to be notified as things are updated.

Resources