Reputation: 3997
I know how to pass compiler options using the cmake
command:
set(CMAKE_CXX_FLAGS "-Wall -Wno-dev -Wl,-rpath=/home/abcd/libs/")
Is there also a way to pass the options from the command line that will override the CMakeLists.txt options? Something like:
cmake -Wl,-rpath=/home/abcd/newlibs/ path/to/CMakeLists.txt
or
cmake -D CMAKE_CXX_FLAGS="-Wno-dev -Wl,-rpath=/home/abcd/libs/" path/to/CMakeLists.txt
My main problem is that I want to know how to append flags and how to override existing compiler flags from the command line.
Upvotes: 108
Views: 175269
Reputation: 884
To append flags after those set via CMAKE_CXX_FLAGS_DEBUG
from CMakeLists.txt
, you can build a cmake DEB or RPM package with this patch:
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -900,6 +900,9 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
flags += cmStrCat(' ', modmapFlags);
}
+ if (auto extra = mf->GetSafeDefinition(cmStrCat("CMAKE_EXTRA_FLAGS_", lang)); extra.size())
+ flags += cmStrCat(' ', extra);
+
vars.Flags = flags.c_str();
vars.DependencyFile = rule.DepFile.c_str();
git clone https://github.com/Kitware/CMake -b release
cd CMake
./bootstrap --parallel=`nproc`
sed -i 's/set(CPACK_GENERATOR.*/set(CPACK_GENERATOR "DEB")/' CPackConfig.cmake
make -j`nproc` package
Upvotes: 1
Reputation: 61
Look:
cmake \
-DCMAKE_C_FLAGS_INIT:STRING="<your special cflags for all variants of build type>" \
-DCMAKE_CXX_FLAGS_INIT:STRING="<your special cxxflags>" \
-DCMAKE_ASM_FLAGS_INIT:STRING="<your special asmflags>" \
-DCMAKE_EXE_LINK_FLAGS_INIT:STRING="<your special ldflags>" \
-S "<path to folder with root CMakeLists.txt>" \
-B "<path to folder for build>"
In CMakeCache.txt
created variables CMAKE_C_FLAGS
and others with yours special compiler options. If you want also to redefine compiler flags for release then just add for example -DCMAKE_C_FLAGS_RELEASE:STRING="-O2 -g -DNODEBUG"
. And in command line pushed next flags:
gcc <flags from CMAKE_C_FLAGS_INIT> <flags from CMAKE_C_FLAGS_RELEASE> ...
Upvotes: 0
Reputation: 736
I simply use the $ENV() operator to get the environment variable, for example in a CMakeLists.txt:
add_compile_options($ENV{MY_CXXFLAG})
The only problem is that $ENV() is only read on in the configuration stage, so CMake does not see the environment setting on the current build stage. But reconfiguring is triggered by changed CMake files, so I just use touch
to simulate a change. Here is an example of a command line:
touch CMakeLists.txt && MY_CXXFLAG="-D DEBUG" cmake --build build --config Debug
or what other options do you use. With this simple example, there are still some quirks with the flag string of the environment variable, e.g., more than one option. But it shouldn't be a big problem with string handling in CMakeLists.txt to beautify this.
Upvotes: -1
Reputation: 5223
Most of the answers here are valid, but I have also stumbled on how to pass
CMAKE_CXX_FLAGS
and add an include directory with a space in it (Windows).
Apparently, if you run that argument from the command line, you need to be extra careful with quotation (see also here).
cmake ... -DCMAKE_CXX_FLAGS="-fms-compatibility-version=19.00 --target=i686--windows -X -I """C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um""" "
So if the include path contains spaces, and that needs to be quoted, but you need also to quote CMAKE_CXX_FLAGS
, which ends up with starting quotation with a single quote character ("
), and whenever you need a quote, you place three quotation characters instead. ("""
)
That's a bit odd in overall, and it took a while to figure this out.
Upvotes: 1
Reputation: 11580
My answer aims to prove one thing:
Command line options like CMAKE_C_FLAGS
and CMAKE_CXX_FLAGS
always append and never overwrite.
Here it comes.
hello_world
#include <stdio.h>
int main(int argc, char* argv[]) {
printf("Hello World!\n");
#ifdef DEFINED_IN_CMAKELISTS
printf("You are here because you defined DEFINED_IN_CMAKELISTS in CMakeLists and it is not overwritten.\n");
#else
printf("You are here because CLI CMAKE_C_FLAGS overwrote DEFINED_IN_CMAKELISTS, or you have NOT defined DEFINED_IN_CMAKELISTS.\n");
#endif
#ifdef DEFINED_IN_CLI
printf("You are here because you defined DEFINED_IN_CLI when running cmake -DCMAKE_C_FLAGS.\n");
#else
printf("You are here because you have NOT defined DEFINED_IN_CLI when running cmake -DCMAKE_C_FLAGS.\n");
#endif // #ifdef DEFINED_IN_CLI
return 0;
}
cmake_minimum_required(VERSION 3.4.1 FATAL_ERROR)
project(Hello)
set(HELLO_SRCS Hello.c)
add_executable(Hello ${HELLO_SRCS})
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDEFINED_IN_CMAKELISTS")
$ mkdir _build && cd _build && cmake ..
-- The C compiler identification is AppleClang 11.0.3.11030032
-- The CXX compiler identification is AppleClang 11.0.3.11030032
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/me/Desktop/_dev/playground/cmake/hello_world/_build
$ make
Scanning dependencies of target Hello
[ 50%] Building C object CMakeFiles/Hello.dir/Hello.c.o
[100%] Linking C executable Hello
[100%] Built target Hello
$ ./Hello
Hello World!
You are here because you defined DEFINED_IN_CMAKELISTS in CMakeLists and it is not overwritten.
You are here because you have NOT defined DEFINED_IN_CLI when running cmake -DCMAKE_C_FLAGS.
$ cmake -DCMAKE_C_FLAGS="-DDEFINED_IN_CLI" ..
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/me/Desktop/_dev/playground/cmake/hello_world/_build
$ make
[ 50%] Building C object CMakeFiles/Hello.dir/Hello.c.o
[100%] Linking C executable Hello
[100%] Built target Hello
$ ./Hello
Hello World!
You are here because you defined DEFINED_IN_CMAKELISTS in CMakeLists and it is not overwritten.
You are here because you defined DEFINED_IN_CLI when running cmake -DCMAKE_C_FLAGS.
From the above test, you can see that even without hard-appending using something like
-DCMAKE_C_FLAGS="${CMAKE_C_FLAGS} -DDEFINED_IN_CLI"
, CMake still appends the CLI options to what's already in CMakeLists.txt
.
Upvotes: 40
Reputation: 42842
Yes, you can append compiler and linker options. But there are two things you have to differentiate in CMake: the first call to generate the build environment and all consecutive calls for regenerating that build environment after changes to your CMakeLists.txt
files or dependencies.
Here are some of the possibilities (excluding the more complex toolchain variants):
The initial content from the cached CMAKE_CXX_FLAGS
variable is a combination of CMAKE_CXX_FLAGS_INIT
set by CMake itself during OS/toolchain detection and whatever is set in the CXXFLAGS
environment variable. So you can initially call:
cmake -E env CXXFLAGS="-Wall" cmake ..
Later, CMake would expect that the user modifies the CMAKE_CXX_FLAGS
cached variable directly to append things, e.g., by using an editor like ccmake
commit with CMake.
You can easily introduce your own build type like ALL_WARNINGS
. The build type specific parts are appended:
cmake -DCMAKE_CXX_FLAGS_ALL_WARNINGS:STRING="-Wall" -DCMAKE_BUILD_TYPE=ALL_WARNINGS ..
The linker options are more or less equivalent to the compiler options. Just that CMake's variable names depend on the target type (EXE
, SHARED
or MODULE
).
The CMAKE_EXE_LINKER_FLAGS_INIT
, CMAKE_SHARED_LINKER_FLAGS_INIT
or CMAKE_MODULE_LINKER_FLAGS_INIT
do combine with the evironment variable LDFLAGS
to CMAKE_EXE_LINKER_FLAGS
, CMAKE_SHARED_LINKER_FLAGS
and CMAKE_MODULE_LINKER_FLAGS
.
So you can e.g call:
cmake -E env LDFLAGS="-rpath=/home/abcd/libs/" cmake ..
See above.
Build type-specific parts are appended:
cmake -DCMAKE_SHARED_LINKER_FLAGS_MY_RPATH:STRING="-rpath=/home/abcd/libs/" -DCMAKE_BUILD_TYPE=MY_RPATH ..
Just be aware that CMake does provide a special variable to set complier/linker flags in a platform independent way. So you don't need to know the specific compiler/linker option.
Here are some examples:
CMAKE_CXX_STANDARD
CMAKE_POSITION_INDEPENDENT_CODE
CMAKE_BUILD_RPATH
CMAKE_INSTALL_RPATH_USE_LINK_PATH
Unfortunately, there is none for the compiler's warning level (yet)
Upvotes: 91
Reputation: 2398
Use:
cmake -D CMAKE_CXX_FLAGS="-Wno-dev -Wl,-rpath=/home/abcd/libs/" path/to/CMakeLists.txt
This should work. The problem is that if you find_package()
some package that also changes the CMAKE_CXX_FLAGS
, then it would not only partially work.
Upvotes: 19
Reputation: 81
Perhaps this would work -
cmake -DCMAKE_CXX_FLAGS="$(CMAKE_CXX_FLAGS) -DYOUR_CUSTOM_DEFINE=1" <rest of original cmake cmdline>
like Tomaz mentioned above. -m
Upvotes: 7