CMake link an external library - cmake

First of all, I am newbie in CMake. I've just started work with it. I want to link an external library to my project. I use code which I take from CMake wiki (at the end of article). Here is my CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project(hello_world)
set(SOURCE_EXE main.cpp)
include_directories(foo)
add_library(foo STATIC IMPORTED)
set_property(TARGET foo PROPERTY IMPORTED_LOCATION /usr/lib/libfoo.a)
target_link_libraries(main foo)
And here is a text of error:
-- The C compiler identification is GNU 4.7.3
-- The CXX compiler identification is GNU 4.7.3
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
CMake Error at CMakeLists.txt:24 (target_link_libraries):
Cannot specify link libraries for target "main" which is not built by this
project.
-- Configuring incomplete, errors occurred!
How can I do it correctly?

It looks like you're just missing out an add_executable call. You need to add main as an executable target in your CMakeLists.txt:
set(SOURCE_EXE main.cpp)
add_executable(main ${SOURCE_EXE})
...
target_link_libraries(main foo)

Related

Define compiler and linker in CMAKE

I would like to use CMAKE to compile a special piece of code in C99 with language extensions. Therefore I have to use a "custom" compiler and linker /your/path/to/compiler and /your/path/to/linker. How can I define the compiler and the linker command used by CMAKE?
EDIT:
I tried to define the compiler and linker as suggested by Equod:
set(CMAKE_C_COMPILER /your/path/to/compiler)
set(CMAKE_CUSTOM_LINKER /your/path/to/linker)
set(CMAKE_C_LINK_EXECUTABLE
"<CMAKE_CUSTOM_LINKER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
But CMAKE is still not taking it:
-- Building for: Visual Studio 15 2017
-- Selecting Windows SDK version 10.0.14393.0 to target Windows 10.0.18363.
-- The C compiler identification is MSVC 19.16.27040.0
-- The CXX compiler identification is MSVC 19.16.27040.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Programms/VisualStudio/2017/Professional/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Programms/VisualStudio/2017/Professional/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: C:/your/path/to/source/build
What I forgot to mention before, I am working on a Windows machine and the executable of th compiler and linker is in the PATH.
EDIT:
Here is my CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(MyProject
VERSION 1.0
DESCRIPTION "This is MyProject"
LANGUAGES C
)
set(CMAKE_C_COMPILER my_compiler)
set(CMAKE_C_LINK_EXECUTABLE my_linker)
configure_file(include/myproject_config.h.in include/myproject_config.h)
set(HEADER_FILES include/main.h include/somefunc.h)
set(SOURCE_FILES src/main.c src/somefunc.c)
add_executable(MyProject ${HEADER_FILES} ${SOURCE_FILES})
target_include_directories(MyProject PUBLIC "${PROJECT_BINARY_DIR}" )
target_include_directories(MyProject PUBLIC "../include" )
P.S.: my_compiler and my_linker are in PATH of cmd and PowerShell.
EDIT:
I installed MinGW now. I have make in my PATH as well. I updated the CMakeLists.txt file above. The make command tries to compile the code now with:
my_compiler #CMakeFiles/MyProject.dir/includes_C.rsp -o CMakeFiles\MyProject.dir\src\main.c.obj -c "C:\mypath\main.c"
But this is not working because I need a command like:
my_compiler -I="../include" "C:\mypath\main.c"
What CMake commands do I need to configure such a behavior?
CMake as default C compiler uses CC environment variables. You can also specify a different compiler and linker setting CMake variables:
Compiler:
set(CMAKE_C_COMPILER /your/path/to/compiler)
Linker:
set(CMAKE_CUSTOM_LINKER /your/path/to/linker)
set(CMAKE_C_LINK_EXECUTABLE
"<CMAKE_CUSTOM_LINKER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
To better understand why linker settings are done in two steps I'd suggest taking a look at how those variables are managed internally by CMake:
CMake on github

Can't find CUDA_INCLUDE_DIRS in latest CMAKE [duplicate]

This question already has answers here:
Listing include_directories in CMake
(3 answers)
Closed 3 years ago.
Since in CMAKE 3.10, CUDA macro is supported by default (https://cmake.org/cmake/help/latest/module/FindCUDA.html).
But I can't find the variable CUDA_INCLUDE_DIRS
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(cmake_and_cuda LANGUAGES CXX CUDA)
message(${CUDA_INCLUDE_DIRS})
the errors are
-- The CXX compiler identification is GNU 5.4.0
-- The CUDA compiler identification is NVIDIA 10.0.130
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Check for working CUDA compiler: /usr/local/cuda/bin/nvcc
-- Check for working CUDA compiler: /usr/local/cuda/bin/nvcc -- works
-- Detecting CUDA compiler ABI info
-- Detecting CUDA compiler ABI info - done
CMake Error at CMakeLists.txt:7 (message):
message called with incorrect number of arguments
-- Configuring incomplete, errors occurred!
See also "/home/tumh/code-samples/posts/cmake/build/CMakeFiles/CMakeOutput.log".
Any idea?
Just use the ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}.
In all .cu src files, there is no need to manually add
include_directories(${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}),
because CMake will do it for you.
But for .cpp src files, if you need to include <cuda_runtime.h>, you must manually add
include_directories(${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES})
in your CMakeLists.txt.

CMake: How to add a subdirectory with the library?

I cannot force cmake to search the library in the subdirectory /usr/local/lib/db5.
To search for libraries I use the following script:
link_directories(/usr/local/lib/db5 /usr/local/lib /usr/lib)
set (LIBRARIES
c m util ssl pthread db)
foreach (LIBRARY ${LIBRARIES})
find_library ("${LIBRARY}_FOUND" ${LIBRARY})
message (STATUS "Check the ${LIBRARY} is installed: " ${${LIBRARY}_FOUND})
if ( "${${LIBRARY}_FOUND}" STREQUAL "${LIBRARY}_FOUND-NOTFOUND" )
message (STATUS "Adding library sources")
add_subdirectory (../${LIBRARY} lib/${LIBRARY})
endif ()
endforeach ()
The library is definitely present in the directory.
ogogon#:/usr/local/src/util# ls /usr/local/lib/db5
libdb_cxx-5.3.a libdb_cxx-5.3.so.0.0.0 libdb_cxx.so libdb_stl-5.3.so.0 libdb_stl.a libdb-5.3.so libdb-5.so
libdb_cxx-5.3.so libdb_cxx-5.so libdb_stl-5.3.a libdb_stl-5.3.so.0.0.0 libdb_stl.so libdb-5.3.so.0 libdb.a
libdb_cxx-5.3.so.0 libdb_cxx.a libdb_stl-5.3.so libdb_stl-5.so libdb-5.3.a libdb-5.3.so.0.0.0 libdb.so
Library search does not lead to success.
ogogon#ot:/usr/local/src/util# ./configure
-- The C compiler identification is Clang 6.0.0
-- The CXX compiler identification is Clang 6.0.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Check the c is installed: /usr/lib/libc.so
-- Check the m is installed: /usr/lib/libm.so
-- Check the util is installed: /usr/lib/libutil.so
-- Check the ssl is installed: /usr/lib/libssl.so
-- Check the pthread is installed: /usr/lib/libpthread.so
-- Check the db is installed: db_FOUND-NOTFOUND
-- Adding library sources
CMake Error at CMakeLists.txt:27 (add_subdirectory):
add_subdirectory given source "../db" which is not an existing directory.
-- Configuring incomplete, errors occurred!
See also "/usr/local/src/util/CMakeFiles/CMakeOutput.log".
If I remove the library db from the list - everything goes fine.
ogogon#ot:/usr/local/src/util# ./configure
-- The C compiler identification is Clang 6.0.0
-- The CXX compiler identification is Clang 6.0.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Check the c is installed: /usr/lib/libc.so
-- Check the m is installed: /usr/lib/libm.so
-- Check the util is installed: /usr/lib/libutil.so
-- Check the ssl is installed: /usr/lib/libssl.so
-- Check the pthread is installed: /usr/lib/libpthread.so
-- Configuring done
-- Generating done
-- Build files have been written to: /usr/local/src/util
What am I doing wrong? How do I solve this problem?
Now I solved this problem like this:
set (LIBPATHS /usr/local/lib/db5 /usr/local/lib /usr/lib libs5)
set (LIBRARIES
c m util db ssl pthread)
foreach (LIBRARY ${LIBRARIES})
find_library ("${LIBRARY}_FOUND" ${LIBRARY} PATHS ${LIBPATHS})
message (STATUS "Check the ${LIBRARY} is installed: " ${${LIBRARY}_FOUND})
if ( "${${LIBRARY}_FOUND}" STREQUAL "${LIBRARY}_FOUND-NOTFOUND" )
message (STATUS "Adding library sources")
add_subdirectory (../${LIBRARY} lib/${LIBRARY})
endif ()
endforeach ()
But, if the version of the Berkley DB library changes, the paths will have to be adjusted. Is there a way to write something like /usr/local/lib/db* ?

Finding GLib with CMake: target_include_directories called with invalid arguments

I have this following (minimal) CMakeLists.txt supposed to find GLib via pkg-config and add the libs to the foo target:
cmake_minimum_required(VERSION 2.10 FATAL_ERROR)
project(foo)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GLib REQUIRED glib-2.0)
add_executable(foo foo.cpp)
message(WARNING "libs:" ${GLIB_LIBRARIES})
message(WARNING "includes:" ${GLIB_INCLUDE_DIRS})
target_link_libraries(foo PUBLIC ${GLIB_LIBRARIES})
target_include_directories(foo PUBLIC ${GLIB_INCLUDE_DIRS})
No matter what I try, I get (note the Found glib-2.0 part):
-- The C compiler identification is GNU 7.3.0
-- The CXX compiler identification is GNU 7.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.1")
-- Checking for module 'glib-2.0'
-- Found glib-2.0, version 2.56.1
CMake Warning at CMakeLists.txt:6 (message):
libs:
CMake Warning at CMakeLists.txt:7 (message):
includes:
CMake Error at CMakeLists.txt:9 (target_include_directories):
target_include_directories called with invalid arguments
-- Configuring incomplete, errors occurred!
See also "/tmp/aaa/CMakeFiles/CMakeOutput.log".
and I cannot see, reading the CMake reference what arguments are invalid (note: this question is different from cmake target_include_directories called with invalid arguments). I also looked at CMake's FindPkgConfig documentation which gives glib as an example and I am not able to reproduce it (${GLIB_VERSION}). I tried GLIB_ and GLIB2_ prefixes and all I get is empty strings.
The messages show the variables are empty, though pkg-config reports values correctly:
$ pkg-config glib-2.0 --cflags --libs
-I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -lglib-2.0
The CMake version I have is 2.10.
Can someone shed light on the issue?
I think your problem is the casing of GLIB_INCLUDE_DIRS and GLIB_LIBRARIES. They should be GLib_INCLUDE_DIRS and GLib_LIBRARIES since you specified "GLib" as the first argument of pkg_check_modules. I'm guessing that the target_include_directories() doesn't like not getting any arguments after the
PUBLIC (although it works for me in cmake 3.5).

CMake collect and process all source files in top directory

I am trying to collect and process all source files in the top directory, to deal with the fact that variables are not passed to sub directories. I have cobbled together the following CMakeLists.txt files:
cmake_minimum_required(VERSION 2.8)
project(main)
enable_language(Fortran)
enable_testing()
set (CMAKE_Fortran_COMPILER ifort)
set (CMAKE_Fortran_FLAGS " -g -C -fixed")
set (CMAKE_Fortran95_FLAGS " -openmp ")
# function to collect all the sources from sub-directories
# into a single list
function(add_sources)
get_property(is_defined GLOBAL PROPERTY SRCS_LIST DEFINED)
if(NOT is_defined)
define_property(GLOBAL PROPERTY SRCS_LIST
BRIEF_DOCS "List of source files"
FULL_DOCS "List of source files to be compiled in one library")
endif()
# make absolute paths
set(SRCS)
foreach(s IN LISTS ARGN)
if(NOT IS_ABSOLUTE "${s}")
get_filename_component(s "${s}" ABSOLUTE)
endif()
list(APPEND SRCS "${s}")
endforeach()
# append to global list
set_property(GLOBAL APPEND PROPERTY SRCS_LIST "${SRCS}")
endfunction(add_sources)
add_sources(SRCS main.f95)
add_subdirectory(sub)
# preprocess sources
set(PREP_SRCS)
get_property(SRCS GLOBAL PROPERTY SRCS_LIST)
foreach(s IN LISTS SRCS)
file(RELATIVE_PATH rs "${CMAKE_CURRENT_SOURCE_DIR}" "${s}")
string(REGEX REPLACE "f95$" "f" o "${CMAKE_CURRENT_BINARY_DIR}/${rs}")
add_custom_command(
OUTPUT "${o}"
COMMAND ${CMAKE_COMMAND} -E copy "${s}" "${o}"
DEPENDS "${s}"
if(${s} MATCHES "f95$")
set_source_files_properties( ${o} PROPERTIES
COMPILE_FLAGS ${CMAKE_Fortran95_FLAGS})
endif(${s} MATCHES "f95$")
COMMENT "Creating ${o}"
VERBATIM
)
list(APPEND PREP_SRCS "${o}")
endforeach()
message(${PREP_SRCS})
add_executable(main ${PREP_SRCS})
SET_TARGET_PROPERTIES(main PROPERTIES LINKER_LANGUAGE Fortran)
SET_TARGET_PROPERTIES(main PROPERTIES
LINK_FLAGS " ")
and in sub/
add_sources(SRCS saxpy2.f95 saxpy_noomp.f)
which cmakes correctly:
[baron#ray:1034]$ cmake ..
-- The C compiler identification is AppleClang 7.0.2.7000181
-- The CXX compiler identification is AppleClang 7.0.2.7000181
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- The Fortran compiler identification is Intel 15.0.1.20141022
-- Check for working Fortran compiler: /opt/intel/composer_xe_2015.1.108/bin/intel64/ifort
-- Check for working Fortran compiler: /opt/intel/composer_xe_2015.1.108/bin/intel64/ifort -- works
-- Detecting Fortran compiler ABI info
-- Detecting Fortran compiler ABI info - done
-- Checking whether /opt/intel/composer_xe_2015.1.108/bin/intel64/ifort supports Fortran 90
-- Checking whether /opt/intel/composer_xe_2015.1.108/bin/intel64/ifort supports Fortran 90 -- yes
/Users/baron/teach/comps/ompstuff/new_new_cmake_test/build/SRCS/Users/baron/teach/comps/ompstuff/new_new_cmake_test/build/main.f/Users/baron/teach/comps/ompstuff/new_new_cmake_test/build/sub/SRCS/Users/baron/teach/comps/ompstuff/new_new_cmake_test/build/sub/saxpy2.f/Users/baron/teach/comps/ompstuff/new_new_cmake_test/build/sub/saxpy_noomp.f
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/baron/teach/comps/ompstuff/new_new_cmake_test/build
[baron#ray:1035]$ make
make[2]: *** No rule to make target `../)', needed by `sub/saxpy_noomp.f'. Stop.
make[1]: *** [CMakeFiles/main.dir/all] Error 2
make: *** [all] Error 2
[baron#ray:1036]$
but obviously something subtle is missing. TIA