Adding static dependency in CMake - cmake

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

Linking problems with yaml-cpp

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

Issues with linking GLFW to the executable with CMake

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})

CMake, shared library linking fail

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.

CMake-generated Makefile does not contain target

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

CMake install: installing configuration files

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.