Linking with cmake, icc and pthreads (linux) - c++

I am trying to compile a simple test project with the Intel C++ Compiler, CMake, and std::threads support.
If I do :
icpc -std=c++11 -lpthread source/main.cpp
Then the build and the program work fine.
But with CMake I get an error:
CMake Error at CMakeLists.txt:21 (TARGET_LINK_LIBRARIES):
Cannot specify link libraries for target "test" which is not built by
this project.
CMakeLists.txt is:
project(test)
set (CMAKE_CXX_FLAGS "-std=c++11")
set(SOURCE_LIST "source/main.cpp")
TARGET_LINK_LIBRARIES(${PROJECT_NAME} pthread)
add_executable (${PROJECT_NAME} ${SOURCE_LIST})
I am building in an environment set by the script supplied by icc (compilervars.sh) and CMake is called with the -DCMAKE_C_COMPILER=icc -DCMAKE_CXX_COMPILER=icpc options. It works if I'm not using threads.
What is wrong with my use of CMake?
Thanks!

Looking back the documentation for target_link_libraries, a target must be declared before being used:
The named <target> must have been created in the current directory by a command such as add_executable() or add_library().
BTW as stated in this answer, you should not set CMAKE_CXX_FLAGS explicitly, and prefer setting CMAKE_CXX_STANDARD and related variables:
project(test)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(SOURCE_LIST "source/main.cpp")
add_executable(${PROJECT_NAME} ${SOURCE_LIST})
target_link_libraries(${PROJECT_NAME} pthread)

The order is wrong: first declare your executable and let CMake know that it exists
add_executable (${PROJECT_NAME} ${SOURCE_LIST})
and afterwards add the link libraries
TARGET_LINK_LIBRARIES(${PROJECT_NAME} pthread)
From target_link_libraries's documentation:
The named must have been created in the current directory by a command such as add_executable() or add_library()

Related

pybind11 and another libs in one project [duplicate]

I want to be able to call my C++ code as a python package. To do this I am using pybind11 with CMakelists (following this example https://github.com/pybind/cmake_example). My problem is that I have to include GSL libraries in the compilation of the code, and these need an explicit linker -lgsl .
If I were just to compile and run the C++ without wrapping it with python, the following Cmakelists.txt file does the job
cmake_minimum_required(VERSION 3.0)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
project(myProject)
add_executable(
myexecutable
main.cpp
function1.cpp
)
find_package(GSL REQUIRED)
target_link_libraries(myexecutable GSL::gsl GSL::gslcblas)
but when using pybind11 the template I found doesn't allow the add_executable therefore target_link_libraries doesn't work.
I have trie this
project(myProject)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED YES) # See below (1)
# Set source directory
set(SOURCE_DIR "project")
# Tell CMake that headers are also in SOURCE_DIR
include_directories(${SOURCE_DIR})
set(SOURCES "${SOURCE_DIR}/functions.cpp")
# Generate Python module
add_subdirectory(lib/pybind11)
pybind11_add_module(namr ${SOURCES} "${SOURCE_DIR}/bindings.cpp")
FIND_PACKAGE(GSL REQUIRED)
target_link_libraries(GSL::gsl GSL::gslcblas)
but this produces errors in the building.
Any idea ?
Function pybind11_add_module creates a library target, which can be used for link added module with other libraries:
pybind11_add_module(namr ${SOURCES} "${SOURCE_DIR}/bindings.cpp")
target_link_libraries(namr PUBLIC GSL::gsl GSL::gslcblas)
This is explicitely stated in documentation:
This function behaves very much like CMake’s builtin add_library (in fact, it’s a wrapper function around that command). It will add a library target called <name> to be built from the listed source files. In addition, it will take care of all the Python-specific compiler and linker flags as well as the OS- and Python-version-specific file extension. The produced target <name> can be further manipulated with regular CMake commands.

CMake does not build the added sub-directory first

I am writing a C++ project that uses Poco Net library. I use CMake to configure the project.
I would like to add Poco as a sub-directory to my project so that it is built in my main project. Here is my shortened main CMakeLists.txt
cmake_minimum_required(VERSION 3.2)
project(FunProj)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()
message(STATUS "Building in ${CMAKE_BUILD_TYPE} mode...")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(HEADER_FILES IDataProvider.h DataProvider.h)
set(SOURCE_FILES main.cpp
DataProvider.cpp)
set(POCO_STATIC ON)
ADD_SUBDIRECTORY(poco)
include_directories(${CMAKE_SOURCE_DIR}/poco/Net/include)
include_directories(${CMAKE_SOURCE_DIR}/poco/Foundation/include)
link_directories(${CMAKE_CURRENT_BINARY_DIR}/poco/lib)
add_executable(FunProj ${SOURCE_FILES} ${HEADER_FILES})
target_link_libraries(${EXEC_NAME} PocoNet)
When I run cmake it configures everything including Poco but when I run make it does not compile the Poco libraries. It only compiles the main.o and DataProvider.o and then the linker fails with an error that libPocoNet.a does not exist.
What is the problem and how may one solve it?
Thank you.

Linux: a C++ library fails to link after recompiling

I had a https://github.com/simongog/sdsl-lite library installed on a remote Linux server. What I did was to create lib, include directories inside my home directory and then run the script as ./install.sh /my/home/dir, as indeed explained on the above page. I was able to do it once and successfully linked it to my other programs by using a CMakeLists.txt file as the one similar to the following:
cmake_minimum_required(VERSION 2.8)
set (CMAKE_CXX_STANDARD 14)
macro(use_cxx14)
if (CMAKE_VERSION VERSION_LESS "3.1")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O2 -mcmodel=large")
endif ()
else ()
set (CMAKE_CXX_STANDARD 14)
endif ()
endmacro(use_cxx14)
use_cxx14()
# Locate GTest
link_directories(/my/home/dir/)
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} /my/home/dir/)
list(APPEND CMAKE_PREFIX_PATH "/my/home/dir/")
list(APPEND CMAKE_LIBRARY_PATH /my/home/dir/lib/)
INCLUDE_DIRECTORIES(/my/home/dir/include)
LINK_DIRECTORIES(/my/home/dir/lib)
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
# Link runTests with what we want to test and the GTest and pthread library
add_executable(runTests rs_bitvector_test.cpp)
# SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
# SET(BUILD_SHARED_LIBRARIES OFF)
# SET(CMAKE_EXE_LINKER_FLAGS "-static")
target_link_libraries(runTests sdsl ${GTEST_LIBRARIES} pthread)
(the server was missing C++14 but the name remains, although really I use the C++11 option)
Now I've changed a source file inside the previously downloaded location of the library and recompiled it. And now linking stopped working. What could be the reason? During re-compilation, the remote server kept telling me about some "modification time in the future" and "build may be incomplete". Is that the reason? What can be done?
EDIT: based off the suggestions in the comments, I removed the build directory (analog of make clean) and replaced it with that from the directory of the original bundle. Now, the timstamps issue is gone, but the linking still fails.
Funnily, after noticing that sdsl detected g++ 7.3 during installation while cmake was compiling using 4.8, I used https://cmake.org/Wiki/CMake_FAQ#How_do_I_use_a_different_compiler.3F to set the compiler to g++ 7.3 (using Method 3 in the above link), and it finally worked (still some issues with GTest, but it is OK).

How to use FFTW library in cmake?

I have C++ code which uses FFTW 3.3.4. Ubuntu 16.04, cmake version 3.7.2
$ locate *fftw*.so
/usr/lib/libsfftw.so
/usr/lib/libsfftw_mpi.so
/usr/lib/libsfftw_threads.so
/usr/lib/libsrfftw.so
/usr/lib/libsrfftw_mpi.so
/usr/lib/libsrfftw_threads.so
/usr/lib/x86_64-linux-gnu/libfftw3.so
/usr/lib/x86_64-linux-gnu/libfftw3_mpi.so
/usr/lib/x86_64-linux-gnu/libfftw3_omp.so
/usr/lib/x86_64-linux-gnu/libfftw3_threads.so
/usr/lib/x86_64-linux-gnu/libfftw3f.so
/usr/lib/x86_64-linux-gnu/libfftw3f_mpi.so
/usr/lib/x86_64-linux-gnu/libfftw3f_omp.so
/usr/lib/x86_64-linux-gnu/libfftw3f_threads.so
/usr/lib/x86_64-linux-gnu/libfftw3l.so
/usr/lib/x86_64-linux-gnu/libfftw3l_mpi.so
/usr/lib/x86_64-linux-gnu/libfftw3l_omp.so
/usr/lib/x86_64-linux-gnu/libfftw3l_threads.so
/usr/lib/x86_64-linux-gnu/libfftw3q.so
/usr/lib/x86_64-linux-gnu/libfftw3q_omp.so
/usr/lib/x86_64-linux-gnu/libfftw3q_threads.so
$ locate fftw3.h
/usr/include/fftw3.h
I can compile it in this way:
g++ main.cpp -o main -lfftw3
but I have a problem with cmake.
This is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.5.1)
project (main)
SET(CMAKE_C_COMPILER gcc)
SET(CMAKE_CXX_COMPILER g++)
file(GLOB SOURCES "*.cpp")
SET(CMAKE_CXX_FLAGS "-lm -lfftw3")
SET(CMAKE_C_FLAGS "-lm -lfftw3")
INCLUDE_DIRECTORIES(/usr/include)
LINK_DIRECTORIES(/usr/lib/x86_64-linux-gnu)
add_library(fftw3 STATIC IMPORTED)
set(CMAKE_C_OUTPUT_EXTENSION_REPLACE 1)
set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1)
add_executable(main ${SOURCES})
cmake . && make
gives
undefined reference to `fftw_malloc'
and the same for the other fftw functions.
The command add_library will create a library in your project (CMake -
add_library). I assume that is not what you want.
The command: g++ main.cpp -o main -lfftw3 will link the executable to the fftw library. In CMake you can reproduce the linking with:
add_executable(main ${SOURCES})
target_link_libraries(main fftw3)
Docu: CMake - target_link_libraries
Notice: It is important that the add_executable command comes before the linking.
Have fun with FFTW :)
We delegate this to pkg-config:
find_package(PkgConfig REQUIRED)
pkg_search_module(FFTW REQUIRED fftw3 IMPORTED_TARGET)
include_directories(PkgConfig::FFTW)
link_libraries (PkgConfig::FFTW)
This works with cmake 3.11 (at least, it may work with earlier versions too).
NOTE: This doesn't work with fftw3_thread component because they don't have a separate .pc file. (see https://github.com/FFTW/fftw3/issues/180).
This may work to add the component (not tested, doesn't work in Macs --see comments--):
link_libraries (PkgConfig::FFTW -lfftw3_thread)
NOTE 2: I am pasting here #OlafWilkocx solution to get the thread component as well
cmake_minimum_required(VERSION 3.20)
...
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -fno-math-errno -ffinite-math-only") # clang
find_package(OpenMP REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(FFTW IMPORTED_TARGET REQUIRED fftw3)
if( NOT FFTW_ROOT AND DEFINED ENV{FFTWDIR} )
set( FFTW_ROOT $ENV{FFTWDIR} )
endif()
find_library(
FFTW_DOUBLE_THREADS_LIB
NAMES "fftw3_threads"
PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR}
)
if (FFTW_DOUBLE_THREADS_LIB)
set(FFTW_DOUBLE_THREADS_LIB_FOUND TRUE)
set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_DOUBLE_THREADS_LIB})
add_library(FFTW::DoubleThreads INTERFACE IMPORTED)
set_target_properties(FFTW::DoubleThreads
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES "${FFTW_DOUBLE_THREADS_LIB}"
)
else()
set(FFTW_DOUBLE_THREADS_LIB_FOUND FALSE)
endif()
include_directories(PkgConfig::FFTW)
add_executable(solver_step src/solver_step.cc)
target_link_libraries(solver_step PRIVATE OpenMP::OpenMP_CXX ${VTK_LIBRARIES} PkgConfig::FFTW ${FFTW_DOUBLE_THREADS_LIB})
NOTE 3
I am told that the line include_directories(PkgConfig::FFTW) is always incorrect and suggested to either only use link_libraries(PkgConfig::FFTW) or target_link_libraries(target_name PRIVATE PkgConfig::FFTW).
see here: Avoid bad include paths in CMake's pkg-config fallback

translate g++ code to clion environment

I am new in clion. on gcc i always use:
g++ bin/obj/main.o -o bin/main -lboost_filesystem -lboost_system -lcrypto
How to do it in clion?
It seems my CMakeList does not work:
cmake_minimum_required(VERSION 3.1)
project(motion_simulation)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.cpp)
add_executable(motion_simulation ${SOURCE_FILES})
link_libraries(lboost_filesystem)
link_libraries(lboost_system)
link_libraries(lcrypto)
Try including the keyword "CMake" into your search next time. This question is actually not CLion specific because CLion actually uses CMake as buildsystem.
CMake is very well documented, and you should be able to find a lot of answers regarding your problem.
You could first try to get rid of that "l":
link_libraries(boost_filesystem)
If that doesn't work you should take a look how the find_package() command works. http://www.cmake.org/Wiki/CMake:How_To_Find_Libraries
And here is a detailed explanation how to find Boost libs and include directory.
http://www.cmake.org/cmake/help/v3.0/module/FindBoost.html
As you are using CMake 3.1 you can use some more advanced features of CMake.
With CMAKE_CXX_STANDARD you can select which C++ version you want to use and CMake will select the corresponding compiler flags (see docs).
link_libraries is one possibility, but it has to be called before add_executable or add_library. The alternative is target_link_libraries which links only to a single target, but can also manage transitive dependencies (docs).
CMake comes with find_package modules for OpenSSL and Boost to find dependencies and with the option REQUIRED, you can ensure that they are found on the system. Boost also supports COMPONENTS to select which libraries you need.
In case you ever work on a system, where OpenSSL and Boost are not installed in /usr/, you can already use target_include_directories to specify where the headers for your executable is found. Like target_link_libraries, target_include_directories can work with transitive dependencies, in this case PRIVATE.
cmake_minimum_required(VERSION 3.1)
project(motion_simulation)
set(CMAKE_CXX_STANDARD 11)
find_package(Boost REQUIRED COMPONENTS filesystem system)
find_package(OpenSSL REQUIRED)
set(SOURCE_FILES main.cpp)
add_executable(motion_simulation ${SOURCE_FILES})
target_include_directories(motion_simulation PRIVATE ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR})
target_link_libraries( motion_simulation PRIVATE ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES})