I'm building a project that uses MPI.
Here's the CMakeLists.txt
if(__OPENNN_MPI__)
find_package(MPI)
if(MPI_FOUND)
message("Using MPI")
set(CMAKE_CXX_COMPILER mpicxx)
set(CMAKE_C_COMPILER mpicc)
set(CMAKE_CXX_COMPILE_FLAGS "${CMAKE_CXX_COMPILE_FLAGS} ${MPI_COMPILE_FLAGS}")
set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} ${MPI_LINK_FLAGS}")
add_definitions(-D__OPENNN_MPI__ )
endif()
endif()
What argument to cmake do I pass to enable this block of code.
My MPI Installation is in a custom path, say /path/to/MPI
Do I simply add the MPI path to my $PATH and run cmake . or is there a flag that I should set, like we would set -DCMAKE_INSTALL_PREFIX:PATH
To tell CMakes FindMPI about a custom installation, it is sufficient to make sure that your custom mpicc and mpicxx is in $PATH. Alternatively, you can supply them as such:
cmake -DMPI_C_COMPILER=/path/to/bin/mpicc -DMPI_CXX_COMPILER=/path/to/bin/mpicxx
CMake will pick up the rest based on the compiler wrappers. You should however not set CMAKE_C_COMPILER / CMAKE_CXX_COMPILER to the MPI compiler wrappers. Instead:
include_directories(SYSTEM ${MPI_INCLUDE_PATH})
And for each C++ target:
target_link_libraries(target ${MPI_CXX_LIBRARIES})
if(MPI_CXX_COMPILE_FLAGS)
set_target_properties(target PROPERTIES COMPILE_FLAGS "${MPI_CXX_COMPILE_FLAGS}")
endif()
if(MPI_CXX_LINK_FLAGS)
set_target_properties(target PROPERTIES LINK_FLAGS "${MPI_CXX_LINK_FLAGS}")
endif()
C targets similarly.
Related
I've installed esp-idf and I'm trying to compile example build_system/cmake/idf_as_lib
and I got the error in the ESP-IDF CMD which not allow me to compile that example. The same problem is in Visual Studio Code.
Probably I should set environment path CMAKE_C_COMPILER but I don't know what should I point.
I've installed CMAKE on my windows
My actual environment paths:
IDF_PYTHON_ENV_PATH -> C:\esp\tools.espressif\python_env\idf4.4_py3.8_env\Scripts\python.exe
IDF_TOOLS_PATH -> C:\esp\tools.espressif
IDF_PATH -> C:\esp\esp-idf
C:\esp\esp-idf\examples\build_system\cmake\idf_as_lib>idf.py build
Executing action: all (aliases: build)
Running cmake in directory c:\esp\esp-idf\examples\build_system\cmake\idf_as_lib\build
Executing "cmake -G Ninja -DPYTHON_DEPS_CHECKED=1 -DESP_PLATFORM=1 -DCCACHE_ENABLE=1 c:\esp\esp-idf\examples\build_system\cmake\idf_as_lib"...
-- The C compiler identification is unknown
CMake Error at CMakeLists.txt:3 (project):
No CMAKE_C_COMPILER could be found.
Tell CMake where to find the compiler by setting either the environment
variable "CC" or the CMake cache entry CMAKE_C_COMPILER to the full path to
the compiler, or to the compiler name if it is in the PATH.
-- Configuring incomplete, errors occurred!
See also "C:/esp/esp-idf/examples/build_system/cmake/idf_as_lib/build/CMakeFiles/CMakeOutput.log".
See also "C:/esp/esp-idf/examples/build_system/cmake/idf_as_lib/build/CMakeFiles/CMakeError.log".
cmake failed with exit code 1
CMakeList
cmake_minimum_required(VERSION 3.5)
project(idf_as_lib C)
if("${TARGET}" STREQUAL "esp32")
# Include for ESP-IDF build system functions
include($ENV{IDF_PATH}/tools/cmake/idf.cmake)
# Create idf::esp32 and idf::freertos static libraries
idf_build_process(esp32
# try and trim the build; additional components
# will be included as needed based on dependency tree
#
# although esptool_py does not generate static library,
# processing the component is needed for flashing related
# targets and file generation
COMPONENTS esp32 freertos esptool_py
SDKCONFIG ${CMAKE_CURRENT_LIST_DIR}/sdkconfig
BUILD_DIR ${CMAKE_BINARY_DIR})
else()
# Create stubs for esp32 and freertos, stub::esp32 and stub::freertos
add_subdirectory(stubs/esp32)
add_subdirectory(stubs/freertos)
add_subdirectory(stubs/spi_flash)
endif()
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(elf_file ${CMAKE_PROJECT_NAME}.elf)
add_executable(${elf_file} main.c)
# Link the static libraries to the executable
if("${TARGET}" STREQUAL "esp32")
target_link_libraries(${elf_file} idf::esp32 idf::freertos idf::spi_flash)
# Attach additional targets to the executable file for flashing,
# linker script generation, partition_table generation, etc.
idf_build_executable(${elf_file})
else()
target_link_libraries(${elf_file} stub::esp32 stub::freertos stub::spi_flash)
endif()
I am using the arm-linux-androideabi-g++ compiler. When I try to compile a simple "Hello, World!" program it compiles fine. When I test it by adding a simple exception handling in that code it works too (after adding -fexceptions .. I guess it is disabled by default).
This is for an Android device, and I only want to use CMake, not ndk-build.
For example - first.cpp
#include <iostream>
using namespace std;
int main()
{
try
{
}
catch (...)
{
}
return 0;
}
./arm-linux-androideadi-g++ -o first-test first.cpp -fexceptions
It works with no problem...
The problem ... I am trying to compile the file with a CMake file.
I want to add the -fexceptions as a flag. I tried with
set (CMAKE_EXE_LINKER_FLAGS -fexceptions ) or set (CMAKE_EXE_LINKER_FLAGS "fexceptions" )
and
set ( CMAKE_C_FLAGS "fexceptions")
It still displays an error.
Note: Given CMake evolution since this was answer was written in 2012, most of the suggestions here are now outdated/deprecated and have better alternatives.
Suppose you want to add those flags (better to declare them in a constant):
SET(GCC_COVERAGE_COMPILE_FLAGS "-fprofile-arcs -ftest-coverage")
SET(GCC_COVERAGE_LINK_FLAGS "-lgcov")
There are several ways to add them:
The easiest one (not clean, but easy and convenient, and works only for compile flags, C & C++ at once):
add_definitions(${GCC_COVERAGE_COMPILE_FLAGS})
Appending to corresponding CMake variables:
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
Using target properties, cf. doc CMake compile flag target property and need to know the target name.
get_target_property(TEMP ${THE_TARGET} COMPILE_FLAGS)
if(TEMP STREQUAL "TEMP-NOTFOUND")
SET(TEMP "") # Set to empty string
else()
SET(TEMP "${TEMP} ") # A space to cleanly separate from existing content
endif()
# Append our values
SET(TEMP "${TEMP}${GCC_COVERAGE_COMPILE_FLAGS}" )
set_target_properties(${THE_TARGET} PROPERTIES COMPILE_FLAGS ${TEMP} )
Right now I use method 2.
In newer versions of CMake you can set compiler and linker flags for a single target with target_compile_options and target_link_libraries respectively (yes, the latter sets linker options too):
target_compile_options(first-test PRIVATE -fexceptions)
The advantage of this method is that you can control propagation of options to other targets that depend on this one via PUBLIC and PRIVATE.
As of CMake 3.13 you can also use target_link_options to add linker options which makes the intent more clear.
Try setting the variable CMAKE_CXX_FLAGS instead of CMAKE_C_FLAGS:
set (CMAKE_CXX_FLAGS "-fexceptions")
The variable CMAKE_C_FLAGS only affects the C compiler, but you are compiling C++ code.
Adding the flag to CMAKE_EXE_LINKER_FLAGS is redundant.
The preferred way to specify toolchain-specific options is using CMake's toolchain facility. This ensures that there is a clean division between:
instructions on how to organise source files into targets -- expressed in CMakeLists.txt files, entirely toolchain-agnostic; and
details of how certain toolchains should be configured -- separated into CMake script files, extensible by future users of your project, scalable.
Ideally, there should be no compiler/linker flags in your CMakeLists.txt files -- even within if/endif blocks. And your program should build for the native platform with the default toolchain (e.g. GCC on GNU/Linux or MSVC on Windows) without any additional flags.
Steps to add a toolchain:
Create a file, e.g. arm-linux-androideadi-gcc.cmake with global toolchain settings:
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
set(CMAKE_CXX_FLAGS_INIT "-fexceptions")
(You can find an example Linux cross-compiling toolchain file here.)
When you want to generate a build system with this toolchain, specify the CMAKE_TOOLCHAIN_FILE parameter on the command line:
mkdir android-arm-build && cd android-arm-build
cmake -DCMAKE_TOOLCHAIN_FILE=$(pwd)/../arm-linux-androideadi-gcc.cmake ..
(Note: you cannot use a relative path.)
Build as normal:
cmake --build .
Toolchain files make cross-compilation easier, but they have other uses:
Hardened diagnostics for your unit tests.
set(CMAKE_CXX_FLAGS_INIT "-Werror -Wall -Wextra -Wpedantic")
Tricky-to-configure development tools.
# toolchain file for use with gcov
set(CMAKE_CXX_FLAGS_INIT "--coverage -fno-exceptions -g")
Enhanced safety checks.
# toolchain file for use with gdb
set(CMAKE_CXX_FLAGS_DEBUG_INIT "-fsanitize=address,undefined -fsanitize-undefined-trap-on-error")
set(CMAKE_EXE_LINKER_FLAGS_INIT "-fsanitize=address,undefined -static-libasan")
You can also add linker flags to a specific target using the LINK_FLAGS property:
set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " ${flag}")
If you want to propagate this change to other targets, you can create a dummy target to link to.
This worked for me when I needed a precompile definition named "NO_DEBUG":
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DNO_DEBUG")
Then from code
#ifdef NO_DEBUG
.....
With CMake 3.4+, APPEND can be used with the string command to add flags.
string(APPEND CMAKE_EXE_LINKER_FLAGS " -fexceptions")
Work on Ubuntu 16
I used g++ main.cpp -lpq command for compiler my small project. Now I use Clion and wanna do same what I do with g++. But I can't add compiler flags in cmake file and get compile error.
cmake_minimum_required(VERSION 3.5.1)
project(day_g)
set(CMAKE_CXX_FLAGS "-lpq")
add_definitions(-lpq)
message("CMAKE_CXX_FLAGS is ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES main.cpp)
add_executable(day_g ${SOURCE_FILES})
Also I run only cmake file and get CMAKE_CXX_FLAGS with -lpq flag.
CMAKE_CXX_FLAGS is -lpq
-- Configuring done
-- Generating done
How properly add compiler flags to cmake file?
Flag -l is for linker, not for compiler. This flag is used for link with libraries. CMake has special command target_link_libraries for that purpose:
target_link_libraries(day_g pq)
-lq is not a compiler flag (CFLAGS) but a linker flag.
To pass a library in a CMake project you should use:
target_link_libraries(target_name libraries...)
Note that if you specify 'q' as library the project will link with libq.a or, if you are on windows q.dll.
... in your CMakeLists.txt the correct line to add is:
target_link_libraries(day_g pq)
Note also that when you add a CFLAG you should also "remember" the previous ones that may be added by libraries or by your platform, ie:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
To check the exact flags cmake is passing to compiler or linker you can always run, from the build directory, the following command:
make VERBOSE=1
I'm writing a Python extension module in C++ using Boost.Python. However, I
would like to use a newer version of the Boost library than the system
installation offers. This newer version of boost is contained in
BOOST_ROOT=$HOME/opt/boost/1.55.0.
Following this guide on how
to use RPath in CMake I came up with the following CMakeLists.txt.
cmake_minimum_required(VERSION 2.8)
project("test")
set(PROJECT_DESC "Test Boost.Python")
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
add_definitions(-std=c++11 -Wall -Wextra -pedantic)
find_package(PythonInterp REQUIRED)
find_package(PythonLibsNew REQUIRED)
find_package(Boost COMPONENTS python REQUIRED)
message(STATUS "Using Boost installation in:")
message(STATUS " INCLUDE: ${Boost_INCLUDE_DIRS}")
message(STATUS " LIB: ${Boost_LIBRARIES}")
include_directories(
${PROJECT_SOURCE_DIR}
${PYTHON_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
)
macro(add_python_module _name _srccpp)
PYTHON_ADD_MODULE(${_name} ${_srccpp})
target_link_libraries(${_name} ${Boost_LIBRARIES})
endmacro()
add_python_module(ownership ownership.cpp)
Then I run the following commands to build the module
mkdir build; cd build
cmake -DCMAKE_INSTALL_PATH="$BOOST_ROOT/lib" ..
make
The status message after running cmake points to the right boost
installation. (The CMake boost module picks up the environment variable
$BOOST_ROOT) I.e. the CMake variable Boost_LIBARIES points to
$BOOST_ROOT/lib/libboost_python.so.
But, if I check which libraries would actually be used, the system libraries
are listed:
$ ldd ownership.so
# ...
libboost_python.so.1.53.0 => /usr/lib64/libboost_python.so.1.53.0 (0x00007f09abfc1000)
# ...
This is version 1.53, even though the status message above explicitely pointed
to 1.55.
What am I doing wrong? How can I get ldd to pick the library in
$BOOST_ROOT/lib/libboost_python.so.1.55.0?
First of all as I already mentioned in commens you don't need to use CMake RPATH-manipulations
options. Example: http://pastebin.com/UDyYbQ1d, output: standard and custom
Do you know of a way of convincing CMake otherwise even if LIBRARY_PATH is set
This issue is not related to CMake, it's compiler responsibility. Read this discussion.
Solution
You can clear LIBRARY_PATH if you set BOOST_ROOT variable explicitly. And you can check
environment variable in CMakeLists.txt to avoid this problem in future:
string(COMPARE NOTEQUAL "$ENV{LIBRARY_PATH}" "" library_path_warning)
if(library_path_warning)
message(
WARNING
"LIBRARY_PATH environment variable is not empty ($ENV{LIBRARY_PATH}) "
"This may cause dynamic linking errors!"
)
endif()
I need to add Boost libraries into my CMakeLists.txt. How do you do it or how do you add it?
Put this in your CMakeLists.txt file (change any options from OFF to ON if you want):
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost 1.45.0 COMPONENTS *boost libraries here*)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(progname file1.cxx file2.cxx)
target_link_libraries(progname ${Boost_LIBRARIES})
endif()
Obviously you need to put the libraries you want where I put *boost libraries here*. For example, if you're using the filesystem and regex library you'd write:
find_package(Boost 1.45.0 COMPONENTS filesystem regex)
You can use find_package to search for available boost libraries. It defers searching for Boost to FindBoost.cmake, which is default installed with CMake.
Upon finding Boost, the find_package() call will have filled many variables (check the reference for FindBoost.cmake). Among these are BOOST_INCLUDE_DIRS, Boost_LIBRARIES and Boost_XXX_LIBRARY variabels, with XXX replaced with specific Boost libraries. You can use these to specify include_directories and target_link_libraries.
For example, suppose you would need boost::program_options and boost::regex, you would do something like:
find_package( Boost REQUIRED COMPONENTS program_options regex )
include_directories( ${Boost_INCLUDE_DIRS} )
add_executable( run main.cpp ) # Example application based on main.cpp
# Alternatively you could use ${Boost_LIBRARIES} here.
target_link_libraries( run ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_REGEX_LIBRARY} )
Some general tips:
When searching, FindBoost checks the environment variable $ENV{BOOST_ROOT}. You can set this variable before calling find_package if necessary.
When you have multiple build-versions of boost (multi-threaded, static, shared, etc.) you can specify you desired configuration before calling find_package. Do this by setting some of the following variables to On: Boost_USE_STATIC_LIBS, Boost_USE_MULTITHREADED, Boost_USE_STATIC_RUNTIME
When searching for Boost on Windows, take care with the auto-linking. Read the "NOTE for Visual Studio Users" in the reference.
My advice is to disable auto-linking and use cmake's dependency handling: add_definitions( -DBOOST_ALL_NO_LIB )
In some cases, you may need to explicitly specify that a dynamic Boost is used: add_definitions( -DBOOST_ALL_DYN_LINK )
Adapting #LainIwakura's answer for modern CMake syntax with imported targets, this would be:
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost 1.45.0 COMPONENTS filesystem regex)
if(Boost_FOUND)
add_executable(progname file1.cxx file2.cxx)
target_link_libraries(progname Boost::filesystem Boost::regex)
endif()
Note that it is not necessary anymore to specify the include directories manually, since it is already taken care of through the imported targets Boost::filesystem and Boost::regex.
regex and filesystem can be replaced by any boost libraries you need.
May this could helpful for some people. I had a naughty error:
undefined reference to symbol '_ZN5boost6system15system_categoryEv'
//usr/lib/x86_64-linux-gnu/libboost_system.so.1.58.0: error adding symbols: DSO missing from command line
There were some issue of cmakeList.txt and somehow I was missing to explicitly include the "system" and "filesystem" libraries. So, I wrote these lines in CMakeLists.txt
These lines are written at the beginning before creating the executable of the project, as at this stage we don't need to link boost library to our project executable.
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
set(Boost_NO_SYSTEM_PATHS TRUE)
if (Boost_NO_SYSTEM_PATHS)
set(BOOST_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../3p/boost")
set(BOOST_INCLUDE_DIRS "${BOOST_ROOT}/include")
set(BOOST_LIBRARY_DIRS "${BOOST_ROOT}/lib")
endif (Boost_NO_SYSTEM_PATHS)
find_package(Boost COMPONENTS regex date_time system filesystem thread graph program_options)
find_package(Boost REQUIRED regex date_time system filesystem thread graph program_options)
find_package(Boost COMPONENTS program_options REQUIRED)
Now at the end of the file, I wrote these lines by considering "KeyPointEvaluation" as my project executable.
if(Boost_FOUND)
include_directories(${BOOST_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
add_definitions(${Boost_DEFINITIONS})
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(KeyPointEvaluation ${Boost_LIBRARIES})
target_link_libraries( KeyPointEvaluation ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${Boost_REGEX_LIBRARY} ${Boost_SYSTEM_LIBRARY})
endif()
Try as saying Boost documentation:
set(Boost_USE_STATIC_LIBS ON) # only find static libs
set(Boost_USE_DEBUG_LIBS OFF) # ignore debug libs and
set(Boost_USE_RELEASE_LIBS ON) # only find release libs
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost 1.66.0 COMPONENTS date_time filesystem system ...)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(foo foo.cc)
target_link_libraries(foo ${Boost_LIBRARIES})
endif()
Don't forget to replace foo to your project name and components to yours!
I agree with the answers 1 and 2. However, I prefer to specify each library separately. This makes the depencencies clearer in big projects.
Yet, there is the danger of mistyping the (case-sensitive) variable names.
In that case there is no direct cmake error but some undefined references linker issues later on, which may take some time to resolve. Therefore I use the following cmake function:
function(VerifyVarDefined)
foreach(lib ${ARGV})
if(DEFINED ${lib})
else(DEFINED ${lib})
message(SEND_ERROR "Variable ${lib} is not defined")
endif(DEFINED ${lib})
endforeach()
endfunction(VerifyVarDefined)
For the example mentioned above, this looks like:
VerifyVarDefined(Boost_PROGRAM_OPTIONS_LIBRARY Boost_REGEX_LIBRARY)
target_link_libraries( run ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_REGEX_LIBRARY} )
If I had written "BOOST_PROGRAM_OPTIONS_LIBRARY" there would have been an error triggered by cmake and not much later triggered by the linker.
Additional information to answers above for those still having problems.
Last version of Cmake's FindBoost.cmake may not content last
version fo Boost. Add it if needed.
Use -DBoost_DEBUG=0 configuration flag to see info on problems.
See for library naming format. Use Boost_COMPILER and Boost_ARCHITECTURE suffix vars if needed.
If you are using custome boost path, set CMAKE_PREFIX_PATH firstly. So, cmake can find your custome boost.
list(FIND CMAKE_PREFIX_PATH ${CUSTOME_BOOST_DEP_PREFIX} _INDEX)
if (_INDEX EQUAL -1)
list(APPEND CMAKE_PREFIX_PATH ${CUSTOME_BOOST_DEP_PREFIX})
# set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE)
endif ()
By the way, if you run above code in sub cmake file, should set CMAKE_PREFIX_PATH back to parent scope.
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE)
If you want find all components of boost, using below code.
find_package(Boost 1.76 COMPONENTS ALL)