How can I list cmake default build option in command-line?
I need to build OpenCV libraries from source. Before that, I want to know what are the default build settings.
cmake -LAH
To list all option(...) and set(... CACHE ...) variables, including those marked as advanced, do:
cmake -LAH
where:
-L: list variables
-A: include advanced variables.
CMake has a few dozen advanced variables defined as default, and you can mark you own variables as advanced with mark_as_advanced). Some default CMake advanced variables include basic default compilation parameters such as:
CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++
CMAKE_CXX_FLAGS:STRING=
CMAKE_CXX_FLAGS_DEBUG:STRING=-g
If you are only interested in the main configuration options of some project, you will likely want to remove the -A as it would be mostly noise.
-H: include help strings. -H was previously mentioned at: https://stackoverflow.com/a/53075317/895245 consider upvoting that answer
Example
CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(ProjectName)
set(GREETING "hello" CACHE STRING "How to greet")
set(GREETING2 "hello2" CACHE STRING "Supersecret greeting")
mark_as_advanced(FORCE VAR GREETING2)
set(MYNOCACHE "mynocacheval")
option(WORLD "Print world or not?" ON)
If we run:
mkdir -p build
cd build
cmake -LAH ..
the output contains:
// How to greet
GREETING:STRING=hello
// Supersecret greeting
GREETING2:STRING=hello2
// How to greet
MSG:STRING=hello
// Supersecret greeting
MSG2:STRING=hello2
// Print world or not?
WORLD:BOOL=ON
plus a bunch of default defined CMake variables. If we remove -A we get only:
// Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel ...
CMAKE_BUILD_TYPE:STRING=debug
// Install path prefix, prepended onto install directories.
CMAKE_INSTALL_PREFIX:PATH=/usr/local
// How to greet
GREETING:STRING=hello
// How to greet
MSG:STRING=hello
// Print world or not?
WORLD:BOOL=ON
so we see that our advanced variable GREETING2 is not present. We also understand that CMake feels that two of their default variables are often useful to merit the non-advanced distinction:
CMAKE_BUILD_TYPE to control debug vs release: Debug vs Release in CMake
CMAKE_INSTALL_PREFIX to decide where to install the project output
Without -H we get just:
CMAKE_BUILD_TYPE:STRING=debug
CMAKE_INSTALL_PREFIX:PATH=/usr/local
GREETING:STRING=hello
MSG:STRING=hello
WORLD:BOOL=ON
Note that the values are the cached values, not the defaults. E.g. if we first set a cached value:
cmake -DGREETING=bye ..
then running again cmake -L .. gives:
CMAKE_BUILD_TYPE:STRING=debug
CMAKE_INSTALL_PREFIX:PATH=/usr/local
GREETING:STRING=bye
MSG:STRING=hello
WORLD:BOOL=ON
Better way to determine the exact build options: run a verbose build!
I think some of people coming to this question are trying to understand how CMake is building their things exactly.
While you could deduce much of that from cmake -LA, a better more direct and sure-fire way would be as per: Using CMake with GNU Make: How can I see the exact commands? to just build with with:
make VERBOSE=1
The output would then contain a line of type:
/usr/bin/cc -DGREETING=\"hello\" -DWORLD -MD -MT CMakeFiles/main.dir/main.c.o -MF CMakeFiles/main.dir/main.c.o.d -o CMakeFiles/main.dir/main.c.o -c /home/ciro/main.c
which makes it clear exactly what CMake is doing.
ccmake ncurses
ccmake is an nCurses Cmake UI. The advantage over cmake -L is that you can interactively set the values as you find them:
sudo apt-get install cmake-curses-gui
ccmake .
shows:
To see the advanced options from cmake-curses-gui you can just enter the t key as mentioned on the UI which toggles them on or off.
cmake-gui
This UI is a bit better than ccmake in terms of capabilities:
sudo apt install cmake-qt-gui
cmake-gui .
we have:
"Advanced" checkbox to show the advanced options
"Grouped" checkbox to group options. By default it produces two categories:
"CMAKE" for the "CMAKE" default options
"Ungrouped Entries" for your variables
Option groups are apparently generated automatically based on common option name prefixes: Creating groups of CMake options
Tested in Ubuntu 22.10, cmake 3.5.2.
You can do cmake -LAH too. The H flag will provide you help for each option.
I do not know of an direct way to do it.
A way around this is to edit the main CMakeLists.txt and print at the end of the file the settings you are interested. The Variables where the most important cmake setting are stored are listed here:
I always print these variables at the end of my CMakeLists.txt to see the settings.
MESSAGE(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
MESSAGE(STATUS "Library Type: " ${LIB_TYPE})
MESSAGE(STATUS "Compiler flags:" ${CMAKE_CXX_COMPILE_FLAGS})
MESSAGE(STATUS "Compiler cxx debug flags:" ${CMAKE_CXX_FLAGS_DEBUG})
MESSAGE(STATUS "Compiler cxx release flags:" ${CMAKE_CXX_FLAGS_RELEASE})
MESSAGE(STATUS "Compiler cxx min size flags:" ${CMAKE_CXX_FLAGS_MINSIZEREL})
MESSAGE(STATUS "Compiler cxx flags:" ${CMAKE_CXX_FLAGS})
Related
I find myself going against the grain configuring cmake paths with ccmake over and over again as with every change of for ex. compiler some of my library paths get lost.
In particular paths to (unlinked) lapack, lapacke, gsl get either lost or set to system defaults instead the ones I've installed with brew.
There has to be a way to tell cmake to "ignore" system libraries and instead look in homebrew paths (say. /opt/homebrew/lib, /opt/homebrew/include etc.).
I'd prefer not to link those libraries as this is not recommend and I'm not experienced in switching environments.
[EDIT] MRE:
git clone https://gitlab.physik.uni-muenchen.de/AG-Scrinzi/tRecX.git
cd tRecX
cmake . -DCMAKE_BUILD_TYPE=Parallel
make -j 8
I add the following to .bash_profile/.zshrc:
export LDFLAGS="-L/opt/homebrew/opt/lapack/lib -L/opt/homebrew/opt/lapack/lib"
export CPPFLAGS="-I/opt/homebrew/opt/lapack/include -I/opt/homebrew/opt/openblas/include"
export PKG_CONFIG_PATH="/opt/homebrew/opt/lapack/lib/pkgconfig /opt/homebrew/opt/openblas/lib/pkgconfig"
then I try:
cmake . -DCMAKE_PREFIX_PATH=/opt/homebrew -DCMAKE_FIND_FRAMEWORK=NEVER -DCMAKE_FIND_APPBUNDLE=NEVER -DCMAKE_FIND_USE_CMAKE_SYSTEM_PATH=FALSE -DCMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH=FALSE -DMPI_CXX_COMPILER=/opt/homebrew/bin/mpicxx -DMPI_C_COMPILER=/opt/homebrew/bin/mpicc -DCMAKE_CXX_COMPILER=/opt/homebrew/bin/g++-11 -DCMAKE_C_COMPILER=/opt/homebrew/bin/gcc-11
The most common solution is to just set CMAKE_PREFIX_PATH to /opt/homebrew. CMake will then look preferentially in /opt/homebrew for everything. Since you're on Apple, you might need to set CMAKE_FIND_FRAMEWORK and CMAKE_FIND_APPBUNDLE to LAST or NEVER, too.
You can skip the standard platform search paths by setting CMAKE_FIND_USE_CMAKE_SYSTEM_PATH to FALSE at the command line, in a preset, or in a toolchain file. You might also wish to disable looking at the PATH environment variable by setting CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH to FALSE.
Finally, if you're in a cross-compiling scenario or toolchain file, you can change the definition of the system directories by setting CMAKE_SYSROOT. Note that the sysroot will have to contain the language runtime libraries (e.g. glibc) and will be passed to the --sysroot flag (or equivalent). Just be aware of those effects, too.
All of this is documented here:
https://cmake.org/cmake/help/latest/command/find_package.html#search-procedure
https://cmake.org/cmake/help/latest/variable/CMAKE_FIND_FRAMEWORK.html#variable:CMAKE_FIND_FRAMEWORK
https://cmake.org/cmake/help/latest/variable/CMAKE_FIND_APPBUNDLE.html#variable:CMAKE_FIND_APPBUNDLE
The following homebrew.cmake toolchain file worked for me:
set(HOMEBREW_PREFIX "/usr/local"
CACHE PATH "Path to Homebrew installation")
set(CMAKE_C_COMPILER "${HOMEBREW_PREFIX}/bin/gcc-11")
set(CMAKE_CXX_COMPILER "${HOMEBREW_PREFIX}/bin/g++-11")
set(CMAKE_PREFIX_PATH
"${HOMEBREW_PREFIX}"
# These libraries are keg-only and not loaded into
# the root prefix by default (to avoid clashes).
"${HOMEBREW_PREFIX}/opt/lapack"
"${HOMEBREW_PREFIX}/opt/openblas"
"${HOMEBREW_PREFIX}/opt/gcc/lib/gcc/11"
)
list(TRANSFORM CMAKE_PREFIX_PATH APPEND "/include"
OUTPUT_VARIABLE CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES)
set(CMAKE_C_STANDARD_INCLUDE_DIRECTORIES "${CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES}")
set(CMAKE_FIND_FRAMEWORK NEVER)
set(CMAKE_FIND_APPBUNDLE NEVER)
set(CMAKE_FIND_USE_CMAKE_SYSTEM_PATH FALSE)
set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH FALSE)
I built with the following commands:
$ ls
tRecX homebrew.cmake
$ cmake -G Ninja -S tRecX -B tRecX-build \
-DCMAKE_TOOLCHAIN_FILE=$PWD/homebrew.cmake \
-DCBLAS=/usr/local/opt/openblas/lib/libblas.dylib \
-DCMAKE_EXE_LINKER_FLAGS="-Wl,-undefined,dynamic_lookup" \
-DCMAKE_SHARED_LINKER_FLAGS="-Wl,-undefined,dynamic_lookup" \
-DCMAKE_BUILD_TYPE=Parallel
[ ... output clipped ... ]
Boost found -- full functionality
Build "Parallel" with C++ flags -D_USE_BOOST_ -O3 -pthread -D_USE_FFTW_, return to default by -UCMAKE_BUILD_TYPE
Compiler: /usr/local/bin/g++-11, change by -DCMAKE_CXX_COMPILER=[path_to_complier]
-- Linking to libraries Boost::system;Boost::filesystem;/usr/local/lib/libfftw3.dylib;/usr/local/opt/gcc/lib/gcc/11/libgfortran.dylib;alglib;/usr/local/lib/libarpack.dylib;Boost::system;Boost::filesystem;/usr/local/opt/lapack/lib/liblapacke.dylib;/usr/local/opt/openblas/lib/libblas.dylib;/usr/local/opt/lapack/lib/liblapack.dylib;/usr/local/opt/lapack/lib/libblas.dylib;m
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/alexreinking/Development/tRecX-build
$ cmake --build tRecX-build
I had to set CBLAS manually because libblas.dylib provides the OpenBLAS CBLAS interface, but the build system specifically looks for a library named libcblas. There's no other option in this case.
The code and build have issues with its linking model and dependencies. I was able to paper over these by setting -Wl,-undefined,dynamic_lookup. However, note that this will just defer linker errors to runtime and might impose a large startup cost.
If you can make commits to the project, I would store these settings in a preset, maybe name it homebrew-parallel or something:
-DCMAKE_TOOLCHAIN_FILE=$PWD/homebrew.cmake \
-DCBLAS=/usr/local/opt/openblas/lib/libblas.dylib \
-DCMAKE_EXE_LINKER_FLAGS="-Wl,-undefined,dynamic_lookup" \
-DCMAKE_SHARED_LINKER_FLAGS="-Wl,-undefined,dynamic_lookup" \
-DCMAKE_BUILD_TYPE=Parallel
Then you could just run cmake --preset=homebrew-parallel
I introduced CMake to my project it replaced Make's makefiles. Anyhow I'm not able to find how to customize 'make help' output. This target is created automagically anyhow I would like to add some descriptions for particular targets. It is anyhow possible?
Overwriting help with add_custom_target results in:
See also "/tmp/20/CMakeFiles/CMakeOutput.log".
CMake Error at CMakeLists.txt:5 (add_custom_target):
The target name "help" is reserved or not valid for certain CMake features,
such as generator expressions, and may result in undefined behavior.
Instead of overwriting what cmake generates, write your own make wrapper one directory above the cmake one. Like so:
$ cd /your/project
$ ls
_build CMakeLists.txt source_file.c Makefile
$ cmake -S. -B./_build
... configure the project in ./_build builddir ...
$ make
cmake --build _build --target all
<builds the project>
$ make help
This is your help
With Makefile:
all:
cmake --build _build --target all
configure_for_some_configuration:
cmake -S. -B_build -DSOME_OPTION=true
help:
#echo 'This is your help'
.PHONY: help configure_for_some_configuration all
Remember that make is one of several of supported generators. I recommend Ninja for faster builds. Use cmake --build <the build dir> to abstractly build the project independently of the used generator.
I have a part of my CMakeLists.txt that sets the C++ standard:
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 11)
endif()
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
This seems to work fine... mostly. I have a build directory, which I set up via:
$ cmake -G Ninja -DCMAKE_CXX_COMPILER=$(which clang++) -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STANDARD=17 ../gw3
Built my project on clang, fixed a few things, normal work stuff. Then I wanted to check to see if I broke the gcc build, so, in the same directory, I ran:
$ cmake -G Ninja -DCMAKE_CXX_COMPILER=$(which g++) -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STANDARD=17 ../gw3
This emited:
-- Configuring done
You have changed variables that require your cache to be deleted.
Configure will be re-run and you may have to reset some variables.
The following variables have changed:
CMAKE_CXX_COMPILER= /path/to/bin/g++
CMAKE_CXX_COMPILER= /path/to/bin/g++
CMAKE_CXX_COMPILER= /path/to/bin/g++
CMAKE_CXX_COMPILER= /path/to/bin/g++
... like 20 more times ...
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 7.2.0
... more cmake stuff here ...
At this point though, CMAKE_CXX_STANDARD is set to 11 in the cache! Why? I set it on the command line to 17. If I rereun the same cmake command again (verbatim, just up-arrow, enter), then the CMAKE_CXX_STANDARD variable gets set to 17 as desired. What gives?
The conventional way to avoid this error is to set the compiler via an environmental variable, i.e:
$ CXX=clang++ cmake .. -DCMAKE_CXX_STANDARD=17
# ...
$ cat CMakeCache.txt | grep STANDARD
CMAKE_CXX_STANDARD:STRING=17
$ env CXX=g++ cmake .. -DCMAKE_CXX_STANDARD=17
# ...
$ cat CMakeCache.txt | grep STANDARD
CMAKE_CXX_STANDARD:STRING=17
CMake doesn't like it when you try to change CMAKE_CXX_COMPILER. From the FAQ:
I change CMAKE_C_COMPILER in the GUI but it changes back on the next configure step. Why?
Once a build tree is created with a given compiler it cannot be
changed. There are a variety of implementation reasons for this
policy.
I'm trying to play around with cmake to build a small C++-code.
I do not have yet g++
(I'm testing on a virtualbox OS)
When I call cmake .
I get the nasty error messages.
-- The C compiler identification is GNU 4.7.2
**-- The CXX compiler identification is unknown**
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
**CMake Error: your CXX compiler: "CMAKE_CXX_COMPILER-NOTFOUND" was not found. Please set CMAKE_CXX_COMPILER to a valid compiler path or name.
-- Configuring incomplete, errors occurred!**
Basically, this is OK. It says errors occurred, but it says too much than needed. I just want to get a precise and concise message saying "g++ ist not installed. INSTALL it please".
Is there a way to first check if g++ is installed and then give an appropriate message?
The output you gave shows that CMake attempting to be helpful to you. If it is too verbose for your taste, perhaps the simplest way to reduce it would be to capture it into a variable, then examine it.
You can save the sample CMake script below as detect_cxx_compiler.cmake, and invoke the script using cmake -P detect_cxx_compiler.cmake. The code is written in a manner intended to be helpful to CMake beginners, not for small size or processing efficiency.
cmake_minimum_required(VERSION 2.8.5 FATAL_ERROR)
cmake_policy(VERSION 2.8.5)
# This cmake script (when saved as detect_cxx_compiler.cmake) is invoked by:
#
# cmake -P detect_cxx_compiler.cmake
#
# It is written for clarity, not brevity.
# First make a new directory, so that we don't mess up the current one.
execute_process(
COMMAND ${CMAKE_COMMAND} -E make_directory detection_area
WORKING_DIRECTORY .
)
# Here, we generate a key file that CMake needs.
execute_process(
COMMAND ${CMAKE_COMMAND} -E touch CMakeLists.txt
WORKING_DIRECTORY detection_area
)
# Have CMake check the basic configuration. The output is
# actually in the form that you posted in your question, but
# instead of displaying it onscreen, we save it to a variable
# so that we can select only parts of it to print later.
execute_process(
COMMAND ${CMAKE_COMMAND} --check-system-vars
OUTPUT_VARIABLE the_output
OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY detection_area
)
# Eliminate the directory, including all of the files within it that
# CMake created.
execute_process(
COMMAND ${CMAKE_COMMAND} -E remove_directory detection_area
WORKING_DIRECTORY .
)
# Here, you have the entire message captured as a variable.
# Uncomment this next line to convince yourself of this.
#message(STATUS "the_output = |${the_output}|.")
# Here, we search the message to see if the C++ compiler was found or not,
# and print an arbitrary message accordingly.
string(FIND "${the_output}" "CMAKE_CXX_COMPILER-NOTFOUND" scan_result)
#message(STATUS "scan_result = |${scan_result}|.")
if(NOT(-1 EQUAL "${scan_result}"))
message(FATAL_ERROR "A C++ compiler was not detected.")
endif()
message(STATUS "A C++ compiler was detected.")
You should use GCC (Gnu Compiler Collection) frontend. You should install gcc-c++ or something similar package.
How can I list cmake default build option in command-line?
I need to build OpenCV libraries from source. Before that, I want to know what are the default build settings.
cmake -LAH
To list all option(...) and set(... CACHE ...) variables, including those marked as advanced, do:
cmake -LAH
where:
-L: list variables
-A: include advanced variables.
CMake has a few dozen advanced variables defined as default, and you can mark you own variables as advanced with mark_as_advanced). Some default CMake advanced variables include basic default compilation parameters such as:
CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++
CMAKE_CXX_FLAGS:STRING=
CMAKE_CXX_FLAGS_DEBUG:STRING=-g
If you are only interested in the main configuration options of some project, you will likely want to remove the -A as it would be mostly noise.
-H: include help strings. -H was previously mentioned at: https://stackoverflow.com/a/53075317/895245 consider upvoting that answer
Example
CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(ProjectName)
set(GREETING "hello" CACHE STRING "How to greet")
set(GREETING2 "hello2" CACHE STRING "Supersecret greeting")
mark_as_advanced(FORCE VAR GREETING2)
set(MYNOCACHE "mynocacheval")
option(WORLD "Print world or not?" ON)
If we run:
mkdir -p build
cd build
cmake -LAH ..
the output contains:
// How to greet
GREETING:STRING=hello
// Supersecret greeting
GREETING2:STRING=hello2
// How to greet
MSG:STRING=hello
// Supersecret greeting
MSG2:STRING=hello2
// Print world or not?
WORLD:BOOL=ON
plus a bunch of default defined CMake variables. If we remove -A we get only:
// Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel ...
CMAKE_BUILD_TYPE:STRING=debug
// Install path prefix, prepended onto install directories.
CMAKE_INSTALL_PREFIX:PATH=/usr/local
// How to greet
GREETING:STRING=hello
// How to greet
MSG:STRING=hello
// Print world or not?
WORLD:BOOL=ON
so we see that our advanced variable GREETING2 is not present. We also understand that CMake feels that two of their default variables are often useful to merit the non-advanced distinction:
CMAKE_BUILD_TYPE to control debug vs release: Debug vs Release in CMake
CMAKE_INSTALL_PREFIX to decide where to install the project output
Without -H we get just:
CMAKE_BUILD_TYPE:STRING=debug
CMAKE_INSTALL_PREFIX:PATH=/usr/local
GREETING:STRING=hello
MSG:STRING=hello
WORLD:BOOL=ON
Note that the values are the cached values, not the defaults. E.g. if we first set a cached value:
cmake -DGREETING=bye ..
then running again cmake -L .. gives:
CMAKE_BUILD_TYPE:STRING=debug
CMAKE_INSTALL_PREFIX:PATH=/usr/local
GREETING:STRING=bye
MSG:STRING=hello
WORLD:BOOL=ON
Better way to determine the exact build options: run a verbose build!
I think some of people coming to this question are trying to understand how CMake is building their things exactly.
While you could deduce much of that from cmake -LA, a better more direct and sure-fire way would be as per: Using CMake with GNU Make: How can I see the exact commands? to just build with with:
make VERBOSE=1
The output would then contain a line of type:
/usr/bin/cc -DGREETING=\"hello\" -DWORLD -MD -MT CMakeFiles/main.dir/main.c.o -MF CMakeFiles/main.dir/main.c.o.d -o CMakeFiles/main.dir/main.c.o -c /home/ciro/main.c
which makes it clear exactly what CMake is doing.
ccmake ncurses
ccmake is an nCurses Cmake UI. The advantage over cmake -L is that you can interactively set the values as you find them:
sudo apt-get install cmake-curses-gui
ccmake .
shows:
To see the advanced options from cmake-curses-gui you can just enter the t key as mentioned on the UI which toggles them on or off.
cmake-gui
This UI is a bit better than ccmake in terms of capabilities:
sudo apt install cmake-qt-gui
cmake-gui .
we have:
"Advanced" checkbox to show the advanced options
"Grouped" checkbox to group options. By default it produces two categories:
"CMAKE" for the "CMAKE" default options
"Ungrouped Entries" for your variables
Option groups are apparently generated automatically based on common option name prefixes: Creating groups of CMake options
Tested in Ubuntu 22.10, cmake 3.5.2.
You can do cmake -LAH too. The H flag will provide you help for each option.
I do not know of an direct way to do it.
A way around this is to edit the main CMakeLists.txt and print at the end of the file the settings you are interested. The Variables where the most important cmake setting are stored are listed here:
I always print these variables at the end of my CMakeLists.txt to see the settings.
MESSAGE(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
MESSAGE(STATUS "Library Type: " ${LIB_TYPE})
MESSAGE(STATUS "Compiler flags:" ${CMAKE_CXX_COMPILE_FLAGS})
MESSAGE(STATUS "Compiler cxx debug flags:" ${CMAKE_CXX_FLAGS_DEBUG})
MESSAGE(STATUS "Compiler cxx release flags:" ${CMAKE_CXX_FLAGS_RELEASE})
MESSAGE(STATUS "Compiler cxx min size flags:" ${CMAKE_CXX_FLAGS_MINSIZEREL})
MESSAGE(STATUS "Compiler cxx flags:" ${CMAKE_CXX_FLAGS})