set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON)
# CMake generated files build/ CMakeCache.txt CMakeFiles/ Makefile cmake_install.cmake install_manifest.txt
It is often helpful to include the current directory for C++ projects. When using GCC directly, this can be done using -I.
, whereas for CMake you need to use the following statement:
target_include_directories(myexe PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
Remember to replace myexe
by the name of your executable target.
You are trying to build your CMake-based project using a CMakeLists.txt
like
cmake_minimum_required(VERSION 3.10) project(my_project) add_executable(my_project *.cpp)
You can’t use the glob pattern *.cpp
directly in add_executable()
. You need to use file(GLOB ...)
in order to set a variable, which you can then use in add_executable()
:
cmake_minimum_required(VERSION 3.10) project(my_project) file(GLOB SRC_FILES *.cpp) add_executable(my_project ${SRC_FILES})
In your CMakeLists.txt
, you want to add an include directory such as /usr/include/mylibrary
for the executable myexe
using code like:
target_include_directories( myexe /usr/include/mylib )
But when you try to configure the build using cmake .
or make
, you see an error message like
CMake Error at CMakeLists.txt:8 (target_include_directories): target_include_directories called with invalid arguments -- Configuring incomplete, errors occurred!
You need to add PUBLIC
between the target name (myexe
) and the include directory/directories:
target_include_directories( myexe PUBLIC /usr/include/mylib )
When building your conan package, you see this CMake error:
CMake Error at /usr/share/cmake-3.16/Modules/FindPackageHandleStandardArgs.cmake:146 (message): Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR (missing: OPENSSL_CRYPTO_LIBRARY OPENSSL_INCLUDE_DIR) Call Stack (most recent call first): /usr/share/cmake-3.16/Modules/FindPackageHandleStandardArgs.cmake:393 (_FPHSA_FAILURE_MESSAGE) /usr/share/cmake-3.16/Modules/FindOpenSSL.cmake:447 (find_package_handle_standard_args) ../_deps/curl-src/CMakeLists.txt:365 (find_package)
even though your conanfile.py
declares OpenSSL as a dependency:
class MyPackageConan(ConanFile): # ... requires = ("openssl/1.1.1l", )
Make sure that the project’s CMakeLists.txt
contains these lines:
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup()
Typically, the way to do this is to use this code which is automatically generated by conan new
:
# This small hack might be useful to guarantee proper /MT /MD linkage # in MSVC if the packaged project doesn't have variables to set it # properly tools.replace_in_file("hello/CMakeLists.txt", "PROJECT(HelloWorld)", '''PROJECT(HelloWorld) include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup()''')
in source()
like this:
def source(self): self.run("git clone https://github.com/conan-io/hello.git") # This small hack might be useful to guarantee proper /MT /MD linkage # in MSVC if the packaged project doesn't have variables to set it # properly tools.replace_in_file("hello/CMakeLists.txt", "PROJECT(HelloWorld)", '''PROJECT(HelloWorld) include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup()''')
Note that you need to replace both hello/CMakeLists.txt
with the correct filename (typically, just replace hello
by). Also, you need to replace both instances PROJECT(HelloWorld)
by the actual line from your CMakeLists.txt
in order for the replace command to work.
When trying to configure your CMake project using
find_package(Protobuf REQUIRED)
you see an error message like
CMake Error at /usr/share/cmake-3.16/Modules/FindThreads.cmake:49 (message): FindThreads only works if either C or CXX language is enabled Call Stack (most recent call first): /usr/share/cmake-3.16/Modules/FindProtobuf.cmake:420 (find_package) CMakeLists.txt:7 (find_package) -- Configuring incomplete, errors occurred!
You need to put your
project(MyProject)
line before the
find_package(Protobuf REQUIRED)
line. If you don’t have a project()
line, create one.
Add this to your CMakeLists.txt
:
# # Compile test suite # find_package(Boost COMPONENTS system filesystem unit_test_framework REQUIRED) add_executable(test_myprogram tests/MyTest.cpp ) target_include_directories(test_myprogram PUBLIC "${CMAKE_CURRENT_LIST_DIR}/include") target_compile_features(test_myprogram PRIVATE cxx_std_17) target_link_libraries(test_myprogram ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ) add_test(test_myprogram test_myprogram) # make "make test" run the test program add_custom_target(test DEPENDS myprogram COMMAND ./test_myprogram )
In order to build the program and the test, run
make
In order to run the tests, use
make test
When compiling your CMake-based C++
CMake Error at /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake:117 (find_package): Could not find a package configuration file provided by "boost_unit_test_framework" (requested version 1.71.0) with any of the following names: boost_unit_test_frameworkConfig.cmake boost_unit_test_framework-config.cmake Add the installation prefix of "boost_unit_test_framework" to CMAKE_PREFIX_PATH or set "boost_unit_test_framework_DIR" to a directory containing one of the above files. If "boost_unit_test_framework" provides a separate development package or SDK, be sure it has been installed. Call Stack (most recent call first): /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake:182 (boost_find_component) /usr/share/cmake-3.16/Modules/FindBoost.cmake:443 (find_package) OCCUtils/CMakeLists.txt:58 (find_package) -- Configuring incomplete, errors occurred!
The error message is trying to tell you that you don’t have the boost unit test
library installed (or CMake can’t find it).
On Ubuntu, for example, install it using
sudo apt -y install libboost-test-dev
On Windows you can install it using the prebuilt boost binaries for Windows.
When compiling your CMake-based C++
CMake Error at /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake:117 (find_package): Could not find a package configuration file provided by "boost_filesystem" (requested version 1.71.0) with any of the following names: boost_filesystemConfig.cmake boost_filesystem-config.cmake Add the installation prefix of "boost_filesystem" to CMAKE_PREFIX_PATH or set "boost_filesystem_DIR" to a directory containing one of the above files. If "boost_filesystem" provides a separate development package or SDK, be sure it has been installed. Call Stack (most recent call first): /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake:182 (boost_find_component) /usr/share/cmake-3.16/Modules/FindBoost.cmake:443 (find_package) CMakeLists.txt:58 (find_package)
The error message is trying to tell you that you don’t have the boost filesystem
library installed (or CMake can’t find it).
On Ubuntu, for example, install it using
sudo apt -y install libboost-filesystem-dev
On Windows you can install it using the prebuilt boost binaries for Windows.
This CMakeLists.txt
builds an executable called main
from main.cpp
:
add_executable(main main.cpp)
With automake/m4 in configure.ac
you use syntax like
AC_CHECK_FUNCS(atan2)
which defines HAVE_FDATASYNC
if the function is available.
In CMake, you can use check_symbol_exists()
for the same purpose like this:
cmake_minimum_required(VERSION 3.0) include(CheckSymbolExists) # Define executable add_executable(myexe main.c) # atan2 requires the math library to be linked list(APPEND CMAKE_REQUIRED_LIBRARIES m) check_symbol_exists(atan2 math.h HAVE_ATAN2) # Add compile definitions if we have the library if(HAVE_ATAN2) target_compile_definitions(myexe PRIVATE -DHAVE_ATAN2) endif()
Note that check_symbol_exists()
does not automatically add a preprocessor define but you have to do that manually (see the last block in the code shown above). While this might seem less comfortable at first, this approach provides you with much more flexibility on how to handle missing or available functions.
See the CMake check_symbol_exists()
documentation for more details.
cmake_minimum_required(VERSION 3.0) include(CheckSymbolExists) # Define executable add_executable(myexe main.c) # atan2 requires the math library to be linked list(APPEND CMAKE_REQUIRED_LIBRARIES m) check_symbol_exists(atan2 math.h HAVE_ATAN2) # Add compile definitions if we have the library if(HAVE_ATAN2) target_compile_definitions(myexe PRIVATE -DHAVE_ATAN2) endif()
If you have CMake code using check_symbol_exists(...)
like
list(APPEND CMAKE_REQUIRED_LIBRARIES m) check_symbol_exists(atan2 math.h HAVE_ATAN2)
but you get an error message like
CMake Error at CMakeLists.txt:8 (check_symbol_exists): Unknown CMake command "check_symbol_exists". -- Configuring incomplete, errors occurred!
you need to add
include(CheckSymbolExists)
near the top of your CMakeLists.txt
(before your first call to check_symbol_exists()
).
if
/else
/endif
looks like this in CMake:
if(myvar) message("if") else() message("else") endif()
Simply add these lines to the end of your CMakeLists.txt
and replace myTarget
by the name of your build target (usually the first argument to add_executable(...)
or add_library(...)
):
# Include boost find_package( Boost 1.30 COMPONENTS program_options REQUIRED ) target_include_directories( myTarget PRIVATE ${Boost_INCLUDE_DIR}) target_link_libraries( myTarget ${Boost_LIBRARIES} )
If you have multiple targets, copy & paste the last two lines for each target.
If you need a specific version of boost, replace 1.30
by the minimum version you need.
If you want to build an executable / library with debug symbols in CMake, run
cmake -DCMAKE_BUILD_TYPE=Debug . make
Conversely, if you want to build an executable / library in release mode, run
cmake -DCMAKE_BUILD_TYPE=Release . make
In order to configure CMake to use an alternate object file suffix (default: .o
on Linux) use these lines in your CMakeLists.txt
:
set(CMAKE_C_OUTPUT_EXTENSION ".rel") set(CMAKE_CXX_OUTPUT_EXTENSION ".rel")
This example changes the output extension from .o
to .rel
(which is required for the SDCC compiler). Be sure to replace ".rel"
by your desired output suffix.
Note that in order for these to take effect, you might need to completely remove CMakeCache.txt
, CMakeFiles
& cmake_install.cmake
:
rm -rf CMakeCache.txt CMakeFiles cmake_install.cmake
If you have been looking desperately for a working CMake example for the SDCC compiler for STM8 microcontrollers here’s my take on it:
cmake_minimum_required(VERSION 3.2) set(CMAKE_C_OUTPUT_EXTENSION ".rel") set(CMAKE_C_COMPILER sdcc) set(CMAKE_SYSTEM_NAME Generic) # No linux target etc # Prevent default configuration set(CMAKE_C_FLAGS_INIT "") set(CMAKE_EXE_LINKER_FLAGS_INIT "") project(STM8Blink C) SET(CMAKE_C_FLAGS "-mstm8 --std-c99") add_executable(main.ihx main.c) # Flash targets add_custom_target(flash ALL COMMAND stm8flash -c stlink -p stm8s105c6 -w main.ihx)
This will build main.ihx
from main.c
. main.ihx
is a Intel Hex file which can be directly flashed using stm8flash.
The last lines setup make flash
; you might need to use the correct microcontroller (stm8s105c6
in this example, run stm8flash -l
to show supported devices) and the correct flash adapter (stlink
, stlinkv2
, stlinkv21
, stlinkv3
or espstlink
).
The setup example shown here is for the STM8S eval board.
I suppose it can be easily modified for other microcontrollers, but I haven’t tried that so far.
You are trying to build a software that is using the CMake build system.
You are trying to run make
to build, but you see this error message:
make: *** No targets specified and no makefile found. Stop.
Before running make
, you need to configure your build using CMake.
The simplest way of doing that is to run
cmake .
Typically you only need to do that once for each project ; CMake will automatically detect changes to CMakeLists.txt
when you run make
.
After that, you can run make
again. If the build is successful, you’ll see a message like this:
[ 50%] Building CXX object CMakeFiles/main.dir/main.cpp.o [100%] Linking CXX executable main [100%] Built target main