I have a code with multiple files, that uses the GSL Library. When I compile the code through the terminal with the command
g++ main.cpp -lm -lgsl -lgslcblas -o Exec
This compiles and gives the correct output and no errors.
However, when I try and build the code in CLion I get the error
undefined reference to `gsl_rng_uniform'
I have linked the various .cpp files in my code through the CMakeLists.txt, but I think, I have to something similar to the flags to link to GSL.
My CMakeLists.txt file is as follows currently (only the .cpp files are included in the source files, not the .h files):
cmake_minimum_required(VERSION 3.7)
project(Unitsv1)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES main.cpp
transition.cpp
random.cpp)
add_executable(Unitsv1 ${SOURCE_FILES})
I'm very new to C++, and can't seem to find any answers online.
Thanks
You haven't linked in the GSL libraries, so the linker won't find any of the symbols it provides. Something like this should get you most of the way there:
cmake_minimum_required(VERSION 3.7)
project(Unitsv1)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED YES) # See below (1)
set(SOURCE_FILES main.cpp
transition.cpp
random.cpp)
add_executable(Unitsv1 ${SOURCE_FILES})
find_package(GSL REQUIRED) # See below (2)
target_link_libraries(Unitsv1 GSL::gsl GSL::gslcblas)
If your code uses C++11, then you need the line at (1) to ensure you actually get C++11 support. Without CMAKE_CXX_STANDARD_REQUIRED YES, the CMAKE_CXX_STANDARD variable acts only as "Use it if it is available, or fall back to the closest standard the compiler can provide". You can find a detailed write-up here if you're curious.
The more important part for your question is at (2). The find_package() command looks for the GSL libraries, etc. and makes them available as import targets GSL::gsl and GSL::gslcblas. You then use target_link_libraries() to link your executable to them as shown. The CMake documentation explains how the find_package() side of things works in plenty of detail:
Start here: find_package()
Specifics for GSL: FindGSL module
Linking: target_link_libraries()
Related
When I was using Github Action CI, I found that no matter what method I used to link, there was no way to link pthread_create
But this error only appears in the Ubuntu environment, Windows, macOS are no problem
I tried:
Not Working
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)
add_executable(xxx xxx.c)
target_link_libraries(xxx PRIVATE Threads::Threads)
Not Working
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
You can view the compiled log here:
https://github.com/YuzukiTsuru/lessampler/runs/6640320037?check_suite_focus=true
If you read the build log carefully
/usr/bin/ld: CMakeFiles/GenerateAudioModelTest.dir/__/src/GenerateAudioModel.cpp.o: in function `GenerateAudioModel::GenerateModelFromFile()':
GenerateAudioModel.cpp:(.text+0x27aa): undefined reference to `pthread_create'
You notice the error has happened while linking the target GenerateAudioModelTest that is located in the directory test and CMakeLists.txt there does not have the compiler flags you shown. Just add -pthread in test/CMakeLists.txt.
This is a bad idea.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
Use
target_compile_options(GenerateAudioModelTest PRIVATE -pthread)
See What is the modern method for setting general compile flags in CMake?
Not Working
You did not link with Thread::Thread nor any library that the target links to.
https://github.com/YuzukiTsuru/lessampler/blob/a6bb7e7d7ac30b6b4043d4f717a2d4deb7fb7638/test/CMakeLists.txt#L22
Not Working
Flags have to be set before add_executable. Which means before all the add_subdirectories. And flags have directory scope. Use targe_compile_options.
https://github.com/YuzukiTsuru/lessampler/blob/master/src/CMakeLists.txt
Consider just making it one library, why so many, and so many CMakeLists.txt in every directory. If the tools are not so separate and you are never going to use them separately, just make it one library with one CMakeLists.txt that links with all the libraries.
I want to compile .cu and .cpp to .o files separately, then link them to executable. I have few simple files: cuda_func.cu. cuda_func.h and main.cpp. In main cpp I include cuda_func.h and run cuda_func(). I've come up with following cmake code:
project(cuda)
cmake_minimum_required(VERSION 2.8)
# CUDA PACKAGE
find_package(CUDA REQUIRED)
set(CUDA_SEPARABLE_COMPILATION ON)
set(CUDA_PROPAGATE_HOST_FLAGS OFF)
set(CUDA_HOST_COMPILER g++)
# COMPILE CU FILES
file(GLOB CUDA_FILES *.cu)
list( APPEND CUDA_NVCC_FLAGS "-gencode arch=compute_30,code=sm_30; -std=c++11")
CUDA_COMPILE(CU_O ${CUDA_FILES})
SET(CMAKE_EXE_LINKER_FLAGS "-L/usr/local/cuda/lib -lcudart")
# SETUP FOR CPP FILES
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
# COMPILE AND LINK
add_executable(main main.cpp ${CU_O})
But I get undefined reference to "cudaMemcpy" error. When I compile it by hand, using nvcc and g++ to get .o files and g++ finally to make executable it works fine. It seems like the cuda library isnt linked properly at the end. What should I do?
Cmake 3.8 added native support for CUDA (here is a document from NVIDIA that explains how to use it this way), you can simply add cuda as a language and the appropriate compiler will be used automatically for each file.
cmake_minimum_required (VERSION 3.8)
project(youProject LANGUAGES CXX CUDA)
add_executable(yourExecutable)
target_sources(yourExecutable <you can add c++ as well as cuda files here>)
// Or if you want to separate cuda and C++ more clearly, put your cuda code
// in a library and link to it (which obviously allows you to compile them separately)
add_library(yourCudaLib <you can add your cuda files here>)
target_link_libraries(yourProject PRIVATE yourCudaLib)
I'm trying to build my project on a cluster, so I don't have any influence on the environment (ie no sudo). On my local machine I can get it to work.
Here the problem:
My project contains cuda files as well as c++ code. The latter one requires a library that needs gcc/g++ >6 (maybe >5 would work as well, afaik std=c++14). The cuda code on the other hand, as of cuda 7.5 needs gcc < 5.
I've already got this issue done by using the g++ 6.2.0 as standard compiler and pass the other gcc with -ccbin /path/to/gcc-4.x.
So my code compiles fine, but the problem is that it also uses the boost library, which needs to be a newer version on the cluster to work with the gcc 6.2.0 than the one I locally use. This is also not the problem itself, as linking the correct one does work, BUT when doing so, the nvcc still links an older version of boost (that is compatible with the gcc-4.x) and thus resulting in having multiple boost library version linked. This leads to segmentation faults during run time, whenever a function of the old boost library is used.
So a solution I was thinking about would be first compiling the c++ files and then only the cuda files, kinda like a simple makefile target would do:
foo: foo-class.o
nvcc foo-class.o foo.cu -o foo
I'm currently unsure if this would solve the problem and if this is possible to do with cmake, but if that is not the case, is there a possibility to take care of the double linkage?
Minimal cmake file example of how mine currently looks:
cmake_minimum_required(VERSION 3.2)
project(foo)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
set(LINKER_FLAGS "-lboost_program_options -lboost_regex -lSDL2 -lSDL2main -lboost_system -lboost_filesystem")
set(ADDITIONAL_FLAGS "-g -Wno-error=switch")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 ${LINKER_FLAGS} ${ADDITIONAL_FLAGS}")
set(SOURCE_FILES
runtime/main.cpp
foo.cpp)
set(CUDA_FILES cuda/food.cu)
set(CUDA_ADDITIONAL_FLAGS "-ccbin /usr/bin/gcc --Wno-deprecated-gpu-targets")
set(CUDA_SDK_ROOT_DIR "/afs/crc.nd.edu/x86_64_linux/c/cuda/8.0/")
find_package(CUDA QUIET REQUIRED)
set(CUDA_PROPAGATE_HOST_FLAGS OFF)
set(CUDA_NVCC_FLAGS -g ${CUDA_ADDITIONAL_FLAGS})
FIND_PACKAGE(Boost COMPONENTS program_options filesystem system regex REQUIRED)
cuda_add_executable(isosurfaces ${SOURCE_FILES} ${CUDA_FILES})
include_directories(~/lib/include)
include_directories(${BOOST_ROOT}/incldue)
target_link_libraries(foo ~/lib/lib/libThorSerialize17.so)
Thanks for any help, I really appreciate it.
To improve the CMake file I would suggest to use the variables provided by the Boost find script instead of manual setting (that will however most likely not help with the issue itself, but good in general):
find_package(Threads)
# set(Boost_USE_STATIC_LIBS ON) # uncomment to try with static libs
FIND_PACKAGE(Boost REQUIRED COMPONENTS program_options filesystem system regex)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
target_link_libraries(isosurfaces
${Boost_LIBRARIES}
${CUDA_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
)
# remove -lboost_program_options -lboost_regex -lboost_system -lboost_filesystem
# from LINKER_FLAGS as provided better by ${Boost_LIBRARIES}
Regarding the issue itself with the different versions of Boost (if you really need to use Boost in the Cuda code for some reason), I'm afraid that will be quite difficult to get working in scope of a single executable. What you can do however, is to separate one of the modules (either the Cuda or the application code) to a separate shared library. That way it could work relatively straightforward, as the shared library can use a different Boost version than the rest of the application (you can experiment with using either static or shared Boost libraries, i.e. Boost_USE_STATIC_LIBS switched ON/OFF).
For example to create a shared library from the Cuda code you could do:
cuda_add_library(isosurfaces_cuda ${CUDA_FILES} SHARED)
add_executable(isosurfaces ${SOURCE_FILES})
target_link_libraries(isosurfaces
isosurfaces_cuda
${Boost_LIBRARIES}
${CUDA_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
)
Then it could probably work, provided that you do not use Boost in the interface between the Cuda code and the remaining C++ code.
It can also help to use the visibility attribute and hide all symbols by default, so that the Boost library symbols will not be exported from the Cuda shared library (or the other way around, if the library is created from the remaining C++ code). For that the "-fvisibility=hidden" compiler flag and "-Wl,--exclude-libs=ALL -Wl,--discard-all" linker flags can be used.
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})
I use this line to compile a simple program:
g++ main.cc -lntl -lm -lgmp
How do you include this into CMake?
find_package(NTL REQUIRED)
find_package(GMP REQUIRED)
Doesn't work. And gives the following error:
CMake Error at CMakeLists.txt:30 (find_package):
Could not find module FindNTL.cmake or a configuration file for package
NTL.
...
.
and
SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -std=c++0x -lntl -lm -lgmp)
Doesn't work either (but I think it's just wrong in general).
Thank you!
If ntl, m, and gmp libraries are usually installed to somewhere in the default path (e.g. /usr/ or /usr/local/), you could simply do something like:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(Test)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
add_executable(test main.cc)
target_link_libraries(test ntl m gmp)
This is probably closest to your original g++ command, but it isn't very robust however; if any of the libraries aren't found, you won't know about it until you try linking. If you want to fail at configure time (i.e. while running CMake), you could add find_library calls for each of the required libs, e.g.
find_library(NTL_LIB ntl)
if(NOT NTL_LIB)
message(FATAL_ERROR "ntl library not found. Rerun cmake with -DCMAKE_PREFIX_PATH=\"<path to lib1>;<path to lib2>\"")
endif()
You'd then have to change your target_link_libraries command to
target_link_libraries(test ${NTL_LIB} ${M_LIB} ${GMP_LIB})
You'd probably also then have to do a find_file for one of each lib's header files to find out the appropriate path to add via the include_directories command (which translates to -I for g++).
Note, it's important to put quotes around the extra CXX_FLAGS arguments, or CMake treats them like separate values in a list and inserts a semi-colon between the flags.
For further information about find_library, find_file, etc. run:
cmake --help-command find_library
cmake --help-command find_file
Regarding your error:
It doesn't look like there's a FindNTL.cmake module included with CMake. That means you'll have to either:
Write your own FindNTL.cmake,
Find another that somebody else has written,
Hack together a solution that:
Checks if NTL is installed
Provides link targets, relevant flags, etc.
From a (rather quick) Google search, it appears somebody has an NTL module for CMake. Since NTL use GMP, you will probably need the associated GMP module for CMake. It doesn't look like a fully-featured CMake module, but it also appears to be the best thing out there (again, it was a quick Google search, and I don't use NTL).
To use, you'll want to add some things to your CMakeLists.txt:
# Let CMake know where you've put the FindNTL.cmake module.
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build/CMake/Modules")
# Call the FindNTL module:
find_package(NTL REQUIRED)
SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -std=c++0x -lntl -lm -lgmp)
Yes, this is wrong. You don't want to be setting your CXX_FLAGS with linking directives. I would use:
SET ( CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -std=cxx0x )
to set the Cxx standard you want to use. To actually link to libraries, you'll want to:
Ensure that you've found the libraries (with the relevant find_package ( FOO ) lines)
Link those against your target, like this:
# Build the Foo executable. (Or library, or whatever)
add_executable (FooEXE ${Foo_SOURCES} )
target_link_libraries (FooEXE
${bar_LIBRARIES}
${baz_LIBRARY}
)
Please note! ${bar_LIBRARIES} and ${baz_LIBRARY} is not a typo; there's no standard way of setting the relevant libraries in the FindFOO.cmake modules, which is, in my opinion, an annoyance. If one doesn't work, try the other, or, worst case, have a look in the relevant FindFOO.cmake file (there's a bunch installed with CMake by default) to see what each one uses. With the link i provided, you can use ${NTL_LIB} and ${GMP_LIB}.