I've got an example project:
.
├── CMakeLists.txt
└── src
└── test1.f90
where test1.f90 uses a specific version of Lapack (therefore I can't use FindLAPACK).
I am trying to compile this using CMake:
cmake_minimum_required(VERSION 2.5)
project(TEST)
file(GLOB_RECURSE sources src/*.f90)
add_executable(cmake.x ${sources})
enable_language(Fortran)
set(CMAKE_Fortran_COMPILER_ID "IBM")
if(CMAKE_Fortran_COMPILER_ID MATCHES "IBM")
set(CMAKE_SHARED_LIBRARY_LINK_Fortran_FLAGS)
MESSAGE(STATUS "IBM")
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,-allow-multiple-definition ")
set(CMAKE_Fortran_COMPILER mpixlf2008_r)
set(debug "-C")
endif()
set(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} ${bounds}")
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${dialect}")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
MESSAGE( STATUS "cmake_module_path: " ${CMAKE_MODULE_PATH})
If I run make VERBOSE=1 this results in:
...
[100%] Building Fortran object CMakeFiles/cmake.x.dir/src/test1.o
mpixlf2008_r -c /work/jias12/jias1217/lapack_test/src/test1.f90 -o CMakeFiles/cmake.x.dir/src/test1.o
** main === End of Compilation 1 ===
1501-510 Compilation successful for file test1.f90.
Linking Fortran executable cmake.x
/usr/bin/cmake -E cmake_link_script CMakeFiles/cmake.x.dir/link.txt --verbose=1
mpixlf2008_r -Wl,-allow-multiple-definition CMakeFiles/cmake.x.dir/src/test1.o -o cmake.x
CMakeFiles/cmake.x.dir/src/test1.o:(.text+0x5c): undefined reference to `sgesv'
make[2]: *** [cmake.x] Error 1
make[2]: Leaving directory `/work/jias12/jias1217/lapack_test'
make[1]: *** [CMakeFiles/cmake.x.dir/all] Error 2
make[1]: Leaving directory `/work/jias12/jias1217/lapack_test'
make: *** [all] Error 2
This obviously doesn't work, because I didn't include LAPACK, which I then can do manually:
mpixlf2008_r -Wl,-allow-multiple-definition CMakeFiles/cmake.x.dir/src/test1.o -o cmake.x -L$LAPACK_LIB -L/bgsys/local/lib -llapack -lesslbg
Which works fine. How can I achieve this using CMake? I want to add -L$LAPACK_LIB -L/bgsys/local/lib -llapack -lesslbg to the linker after the *.o files. All I've managed is to add them as flags before the *.o files, which fails. I've look at a number of examples on the web, but I cannot find something which works in my case. This is the test1.f90.
This is in the folders:
> ls $LAPACK_LIB
libblas_extra.a libcblas.a liblapack.a liblapacke.a libtmglib.a
ls /bgsys/local/lib/
BGeic.pm BG.pm libesslbg.a libesslsmpbg.a
As Tsyvarev correctly mentioned:
What is wrong with target_link_libraries which links with the
libraries (meaning of flag -l) and link_directories which specifies
libraries search path (meaning of flag -L)?
Those hase to be called in the right order, which leads to:
cmake_minimum_required(VERSION 2.5)
project(TEST)
file(GLOB_RECURSE sources src/*.f90)
link_directories($ENV{LAPACK_LIB} /bgsys/local/lib)
enable_language(Fortran)
add_executable(cmake.x ${sources})
target_link_libraries(cmake.x lapack esslbg)
Related
I am trying to incorporate yaml-cpp into my project.
I have a "Demes" class where I need to parse a YAML file.
This is the relevant method in Demes.cpp:
#include "Demes.hpp"
void Demes::parse(const std::string& fileName)
{
YAML::Node test = YAML::LoadFile(fileName);
}
where Demes.hpp includes the yaml-cpp headers and declares the 'parse' method.
Building with make -VERBOSE=1 (as suggested by #Tsyvarev) gives:
[100%] Linking CXX executable momentspp
cd /home/gvbarroso/Devel/momentspp/build/src && /usr/bin/cmake -E cmake_link_script CMakeFiles/momentspp.dir/link.txt --verbose=1
/usr/bin/c++ -std=c++20 -Weffc++ -Wshadow -Wall -Wextra -ffast-math -O3 -march=native CMakeFiles/momentspp.dir/Log.cpp.o CMakeFiles/momentspp.dir/PolymorphismData.cpp.o CMakeFiles/momentspp.dir/SumStatsLibrary.cpp.o CMakeFiles/momentspp.dir/Drift.cpp.o CMakeFiles/momentspp.dir/Migration.cpp.o CMakeFiles/momentspp.dir/Mutation.cpp.o CMakeFiles/momentspp.dir/Recombination.cpp.o CMakeFiles/momentspp.dir/Epoch.cpp.o CMakeFiles/momentspp.dir/Model.cpp.o CMakeFiles/momentspp.dir/OptimizationWrapper.cpp.o CMakeFiles/momentspp.dir/Demes.cpp.o CMakeFiles/momentspp.dir/main.cpp.o -o momentspp -Wl,-rpath,/home/gvbarroso/.local/lib: /home/gvbarroso/.local/lib/libbpp-phyl3.so.1.0.0 /usr/lib/x86_64-linux-gnu/libboost_iostreams.so.1.74.0 /home/gvbarroso/.local/lib/libbpp-seq3.so.1.0.0 /home/gvbarroso/.local/lib/libbpp-core3.so.1.0.0
/usr/bin/ld: CMakeFiles/momentspp.dir/Demes.cpp.o: in function Demes::parse(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)': Demes.cpp:(.text+0x4c): undefined reference to YAML::LoadFile(std::__cxx11::basic_string<char, std::char_traits, std::allocator > const&)'
/usr/bin/ld: Demes.cpp:(.text+0x12c): undefined reference to `YAML::operator<<(std::ostream&, YAML::Node const&)'
collect2: error: ld returned 1 exit status
make[2]: *** [src/CMakeFiles/momentspp.dir/build.make:277: src/momentspp] Error 1
make[2]: Leaving directory '/home/gvbarroso/Devel/momentspp/build'
make[1]: *** [CMakeFiles/Makefile2:125: src/CMakeFiles/momentspp.dir/all] Error 2
make[1]: Leaving directory '/home/gvbarroso/Devel/momentspp/build'
make: *** [Makefile:156: all] Error 2
I am using CMake to build my project, but I am still fairly unfamiliar with it.
EDIT: I forgot to mention that I have two CMakeLists.txt files, one inside src and the other inside the external build.
The start of my CMakeLists.txt file in the external build is:
cmake_minimum_required (VERSION 3.5.0)
project (momentspp CXX)
SET(CMAKE_CXX_FLAGS "-std=c++20 -Weffc++ -Wshadow -Wall -Wextra -ffast-math -O3 -march=native")
And the part of it where I look for yaml-cpp is:
FIND_PACKAGE(yaml-cpp REQUIRED)
IF(yaml-cpp_FOUND)
INCLUDE_DIRECTORIES(${yaml-cpp_INCLUDE_DIRS})
SET(LIBS {yaml-cpp_LIBRARIES})
MESSAGE("-- yaml-cpp libraries found here:")
MESSAGE(" includes: ${yaml-cpp_INCLUDE_DIRS}")
ENDIF()
My full CMakeLists.txt file inside src is:
SET(momentspp_CPP
Log.cpp
PolymorphismData.cpp
SumStatsLibrary.cpp
Drift.cpp
Migration.cpp
Mutation.cpp
Recombination.cpp
Epoch.cpp
Model.cpp
OptimizationWrapper.cpp
Demes.cpp
main.cpp
)
ADD_EXECUTABLE (momentspp ${momentspp_CPP})
SET(momentspp-targets momentspp)
FOREACH (target ${momentspp-targets})
TARGET_LINK_LIBRARIES(${target} ${BPP_LIBS_SHARED} ${BOOST_LIBS_SHARED} ${EIGEN3_LIBS_SHARED} ${yaml-cpp_LIBS_SHARED})
TARGET_LINK_LIBRARIES (${target} ${LIBS})
ENDFOREACH (target)
INSTALL(TARGETS ${momentspp-targets} DESTINATION ${CMAKE_INSTALL_BINDIR})
and this was working prior to the inclusion of yaml-cpp.
This feels like a rather complicated CMake set-up, but I am copying and editing it from a previous project where someone else helped me with it.
How can I fix the linking issue?
I tried looking similar questions around here, but couldn't get their solutions to work for me (apparently those people where not using CMake to build their projects).
Thank you,
Gustavo
I am currently trying to link the GLFW library with my executable files in CLion. After hours of research and trial & error, I am stuck. I am using find_package() to locate my GLFW library. For some reason my FindGLFW.cmake file seems to correctly locate the library in /usr/local/lib/libglfw.a when using find_library(), but my CMakeLists.txt returns empty with find_package(). I don't really understand how that's possible. Could someone help me out?
CMakeLists.txt:
cmake_minimum_required(VERSION 3.15)
project(learnopengl)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMake)
find_package(glfw 3.3 REQUIRED)
message(STATUS "(CMakeLists.txt) GLFW: [${glfw}]")
if (NOT glfw)
message(SEND_ERROR "(CMakeLists) Did not find glfw_library")
endif()
add_executable(learnopengl src/main.cpp)
target_link_libraries(learnopengl glfw)
FindGLFW.cmake
find_library( GLFW_LIBRARY
NAMES
glfw3 glfw
PATHS
${GLFW_LOCATION}/lib
$ENV{GLFW_LOCATION}/lib
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/lib
NO_DEFAULT_PATH
DOC "The GLFW library"
)
message(STATUS "(FindGLFW.cmake) GLFW_INCLUDE_DIR: [${GLFW_INCLUDE_DIR}]")
message(STATUS "(FindGLFW.cmake) GLFW_LIB: [${GLFW_LIBRARY}]")
if (NOT GLFW_LIBRARY)
message(SEND_ERROR "(FindGLFW.cmake) Did not find glfw_library")
Output when running cmake ..
-- (FindGLFW.cmake) GLFW_INCLUDE_DIR: [/usr/local/include]
-- (FindGLFW.cmake) GLFW_LIB: [/usr/local/lib/libglfw3.a]
-- (CMakeLists.txt) GLFW: []
CMake Error at CMakeLists.txt:12 (message):
(CMakeLists) Did not find glfw_library
When I tried to directly include find_library() in my CMakeLists.txt instead, it did locate the library, but when I tried to link it with my executable, I got a linker error saying it couldn't locate the library:
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(learnopengl)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMake)
find_library( GLFW_LIBRARY
NAMES
glfw3 glfw
PATHS
${GLFW_LOCATION}/lib
$ENV{GLFW_LOCATION}/lib
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/lib
NO_DEFAULT_PATH
DOC "The GLFW library"
)
message(STATUS "(FindGLFW.cmake) GLFW_LIB: [${GLFW_LIBRARY}]")
if (NOT GLFW_LIBRARY)
message(SEND_ERROR "(CMakeLists.txt) Did not find glfw_library")
endif()
add_executable(learnopengl src/main.cpp)
target_link_libraries(learnopengl GLFW_LIBRARY)
Output:
~/dev/projects/opengl/learnopengl/build cmake ..
-- (CMakeLists.txt) GLFW_LIB: [/usr/local/lib/libglfw3.a]
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/Philipp/dev/projects/opengl/learnopengl/build
~/dev/projects/opengl/learnopengl/build cmake --build .
[ 50%] Linking CXX executable learnopengl
ld: library not found for -lGLFW_LIBRARY
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [learnopengl] Error 1
make[1]: *** [CMakeFiles/learnopengl.dir/all] Error 2
make: *** [all] Error 2
I would really appreciate some hints as to what I am doing wrong. I can't see why it wouldn't locate/link the library correctly.
Thank you!
In cmake, arguments are case sensitive, so find_package should be
find_package(GLFW 3.3 REQUIRED)
Linker problem can be found easily in the logs. You are trying to link -lGLFW_LIBRARY, however what you want to link is GLFW_LIBRARY's value, /usr/local/lib/libglfw3.a .
target_link_libraries(learnopengl ${GLFW_LIBRARY})
I'm currently getting used to cmake and I'm trying to compile a small project with a .so library linking.
My project is the following.
/
CMakeLists.txt
inc/
Als.h
src/
main.c
CMakeLists.txt
lib/
libals.so
build/
I'm compiling from the build directory with:
$ cmake ..
-- DIR:
-- Configuring done
-- Generating done
-- Build files have been written to: /home/julien/tmp/cmakeTest/build
And then:
$ make
Linking C executable cmakeTest
/usr/bin/ld: ne peut trouver -lals
collect2: error: ld returned 1 exit status
src/CMakeFiles/cmakeTest.dir/build.make:85: recipe for target 'src/cmakeTest' failed
make[2]: *** [src/cmakeTest] Error 1
CMakeFiles/Makefile2:75: recipe for target 'src/CMakeFiles/cmakeTest.dir/all' failed
make[1]: *** [src/CMakeFiles/cmakeTest.dir/all] Error 2
Makefile:76: recipe for target 'all' failed
make: *** [all] Error 2
The linker seems to be unable to find the libals.so file.
Here is the file /CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
PROJECT(cmaketest)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
INCLUDE_DIRECTORIES(
inc
)
ADD_SUBDIRECTORY(src)
get_directory_property(OUT_VAR LINK_DIRECTORIES)
message(STATUS "DIR: ${OUT_VAR}")
And here is the file /src/CMakeLists.txt:
PROJECT(cmakeTest)
FILE(
GLOB
${PROJECT_NAME}_Sources
*.c
)
INCLUDE_DIRECTORIES(
inc
inc
)
ADD_EXECUTABLE(
${PROJECT_NAME}
${${PROJECT_NAME}_Sources}
)
LINK_DIRECTORIES(
/home/julien/tmp/cmakeTest/lib/
)
TARGET_LINK_LIBRARIES(
${PROJECT_NAME}
als
pthread
)
Maybe I missed something but if I change the /src/CMakeLists.txt to:
PROJECT(cmakeTest)
FILE(
GLOB
${PROJECT_NAME}_Sources
*.c
)
INCLUDE_DIRECTORIES(
inc
inc
)
ADD_EXECUTABLE(
${PROJECT_NAME}
${${PROJECT_NAME}_Sources}
)
TARGET_LINK_LIBRARIES(
${PROJECT_NAME}
/home/julien/tmp/cmakeTest/lib/libals.so
pthread
)
The compilation is ok. Does someone know why the linker is unable to find libals.so when I'm giving him the good directory path to look in?
The LINK_DIRECTORIES functions seems not to be working.
Besides the solution you already have, and my solution in a comment, the problem you have with the CMake file shown is the order in which you invoke the CMake commands.
From the link_directories command reference:
The command will apply only to targets created after it is called.
[Emphasis mine]
You simply need to call link_directories before you call add_executable.
I'm using G++ MinGW for compiling. My Files :
main.cpp, linkedList.cpp, linkedList.h
My CMake file :
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
project (Tutorial)
set(CMAKE_CXX_FLAGS "-Wall -std=c++11")
enable_testing()
include_directories(include)
add_executable(Tutorial
main.cpp
linkedList.cpp
linkedList.h
)
add_test(Tutorial tutorial)
The exact compile error from generated Makefile :
mingw32-make[2]: *** No rule to make target '../linkedList.h', needed by 'CMakeFiles/Tutorial.dir/main.cpp.obj'. Stop.
mingw32-make[1]: *** [CMakeFiles/Tutorial.dir/all] Error 2
mingw32-make: *** [all] Error 2
Gist for CMake generated Makefile
You target is Tutorial, not ../LinkedList.h
Go to your build directory and execute
make Tutorial
I want CMake to make install rules for me which also automatically install configuration and other things. I looked at this question, but adding:
add_executable(solshare_stats.conf solshare_stats.conf)
to my CMakeLists.txt file only gave me warnings and errors:
CMake Error: CMake can not determine linker language for target:solshare_stats.conf
CMake Error: Cannot determine link language for target "solshare_stats.conf".
...
make[2]: *** No rule to make target `CMakeFiles/solshare_stats.conf.dir/build'. Stop.
make[1]: *** [CMakeFiles/solshare_stats.conf.dir/all] Error 2
make: *** [all] Error 2
How do I add configuration, init and/or logfiles to CMake install rules?
Here is my complete CMakeLists.txt file:
project(solshare_stats)
cmake_minimum_required(VERSION 2.8)
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST} )
add_executable(solshare_stats.conf solshare_stats.conf)
target_link_libraries(solshare_stats mysqlcppconn)
target_link_libraries(solshare_stats wiringPi)
if(UNIX)
if(CMAKE_COMPILER_IS_GNUCXX)
SET(CMAKE_EXE_LINKER_FLAGS "-s")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall -std=c++0x")
endif()
install(TARGETS solshare_stats DESTINATION /usr/bin COMPONENT binaries)
install(TARGETS solshare_stats.conf DESTINATION /etc/solshare_stats COMPONENT config)
endif()
The .conf file should be included in the add_executable where you define your executable target, not in a separate call:
add_executable(${PROJECT_NAME} ${SRC_LIST} solshare_stats.conf)
Then you need to use install(FILE ...) rather than install(TARGET ...):
install(TARGETS solshare_stats DESTINATION /usr/bin COMPONENT binaries)
install(FILES solshare_stats.conf DESTINATION etc/solshare_stats COMPONENT config)
By doing
add_executable(${PROJECT_NAME} ${SRC_LIST})
add_executable(solshare_stats.conf solshare_stats.conf)
you're saying you want to create 2 executables, one called "solshare_stats" and another called "solshare_stats.conf".
The second target's only source file is the actual file "solshare_stats.conf". Since none of the source files in this target have a suffix which gives an idea about the language (e.g ".cc" or ".cpp" implies C++, ".asm" implies assembler), no language can be deduced, hence the CMake error.