Change CMake from linking dynamic library to static library [duplicate] - cmake

I want to statically link the libraries listed below:
set_target_properties(exec PROPERTIES LINK_SEARCH_START_STATIC 1)
set_target_properties(exec PROPERTIES LINK_SEARCH_END_STATIC 1)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
find_library(SODIUM_LIB libsodium.a REQUIRED)
find_library(SSL_LIB libssl.a REQUIRED)
find_library(CRYPTO_LIB libcrypto.a REQUIRED)
find_library(DL_LIB libdl.a REQUIRED)
message(${SODIUM_LIB})
message(${SSL_LIB})
message(${CRYPTO_LIB})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
target_link_libraries(
exec
${SODIUM_LIB}
${SSL_LIB}
${CRYPTO_LIB}
${DL_LIB}
I do not want to add -static to CMAKE_EXE_LINKER_FLAGS, because in that case everything is linked static. CMake finds the static libraries:
/usr/local/lib/libsodium.a
/usr/lib/x86_64-linux-gnu/libssl.a
/usr/lib/x86_64-linux-gnu/libcrypto.a
and it seems that everything is linked statically except libcrypto:
readelf -d exec
0x0000000000000001 (NEEDED) Shared library: [libcrypto.so.1.0.0]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x0000000000000001 (NEEDED) Shared library: [ld-linux-x86-64.so.2]
How can I link libcrypto statically to my executable?

The CMake documentation starting with version 3.4 on the FindOpenSSL page says:
Set OPENSSL_USE_STATIC_LIBS to TRUE to look for static libraries.
(Assuming if they are found they will be used)
Example:
cmake_minimum_required(VERSION 3.4)
project(Foo)
set(SOURCE_FILES main.cpp)
set(OPENSSL_USE_STATIC_LIBS TRUE)
find_package(OpenSSL REQUIRED)
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
target_link_libraries(${PROJECT_NAME} OpenSSL::Crypto)

Related

Using cmake.js with google test for testing a node.js addon

I am trying to test a node-js addon (built with cmake-js) with google test.
I am building on Mac OS.
The addon target builds and runs ok, but I have problems with the googletest target.
I am getting linking errors related to undefined V8 methods.
In CMakeLists.txt I printed (with message) the variables CMAKE_JS_SRC and CMAKE_JS_LIB and they are both empty. If CMAKE_JS_LIB is empty I don't see how target_link_libraries() should work to add the node/v8 library to my test executable...
If instead of using add_executable() I use add_library() the google_test target builds but of course I can not run it since it is not an executable anymore.
Can you help?
Below is my CMakeLists.txt:
make_minimum_required(VERSION 3.14)
include_directories(my_project)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_C_FLAGS "-Wno-pointer-sign -fno-signed-char -std=c99 -fpermissive")
set(CMAKE_CXX_FLAGS "-Wno-pointer-sign -fno-signed-char -std=c99 -fpermissive")
project (addon)
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.12.1
)
FetchContent_MakeAvailable(googletest)
include_directories(${CMAKE_JS_INC} "my_project/include/pkcs11/v2.40/")
file(GLOB SOURCE_FILES "my_project/*.c" "my_project/*.h" "my_project/*.cpp")
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")
target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB} )
## google_test
enable_testing()
file(GLOB TEST_FILES "test/*.cc" "test/utils/*.c")
add_executable(
my_project_google_test
${TEST_FILES)
)
target_include_directories(my_project_google_test
PRIVATE
test/utils/*.h
)
target_link_libraries(
my_project_google_test
PRIVATE
GTest::gtest_main
${CMAKE_JS_LIB}
)
include(GoogleTest)
gtest_discover_tests(my_project_google_test)
CMAKE_JS_LIB is empty everywhere except on Windows.
Install v8 from Homebrew if you haven't done it yet: brew install v8.
Link the app to v8
target_link_libraries(
my_project_google_test
PRIVATE
v8
)
Other v8 libraries can be required, you have not post all errors: v8_libbase v8_libplatform.

CMake imported shared library links with relative path, breaks install

I have a vendor library which needs to be included with my project's installer, I'm installing it with INSTALL(FILES ...). The library is stored along with the source, the problem is that the linked path (shown by readelf) is relative and that prefix doesn't get removed during installation, so instead of the dynamic linker searching for hhlib.so its looking for ../hhlib-linux-64bit/hhlib.so.
How can I get a working installed binary? Can I get the install step or CPack to remove this relative path to the library?
I've reduced the problem down to a simple example:
.
├── build
├── CMakeLists.txt
├── hhlib-linux-64bit
│   ├── hhlib.h
│   └── hhlib.so
└── use_hydroharp.c
cmake_minimum_required (VERSION 3.19)
# These sets have no effect on the issue
# use, i.e. don't skip the full RPATH for the build tree
#SET(CMAKE_SKIP_BUILD_RPATH FALSE)
# when building, don't use the install RPATH already
# (but later on when installing)
#SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
# the RPATH to be used when installing
#SET(CMAKE_INSTALL_RPATH "")
# don't add the automatically determined parts of the RPATH
# which point to directories outside the build tree to the install RPATH
#SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
enable_language(C)
# Find the header files
find_path(HydroHarp_INCLUDEDIR
NAMES hhlib.h
PATHS "${CMAKE_CURRENT_SOURCE_DIR}/hhlib-linux-64bit"
)
# Find the shared library
find_library(HydroHarp_LIBRARY
NAMES hhlib.so
HINTS "${CMAKE_CURRENT_SOURCE_DIR}/hhlib-linux-64bit"
)
if(HydroHarp_INCLUDEDIR AND HydroHarp_LIBRARY)
message("Found HyroHarp library")
# Get the containing folder for the library
get_filename_component(HydroHarp_LIBDIR ${HydroHarp_LIBRARY} DIRECTORY)
# Import the library
add_library(HydroHarp SHARED IMPORTED)
set_target_properties(HydroHarp PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${HydroHarp_INCLUDEDIR}
IMPORTED_LOCATION ${HydroHarp_LIBRARY}
)
# copy the library when installing
install(FILES ${HydroHarp_LIBRARY} TYPE LIB)
else()
message(WARNING "Failed to find HydroHarp")
endif()
project(extlink)
add_executable(${PROJECT_NAME} use_hydroharp.c)
target_link_libraries(${PROJECT_NAME} PRIVATE HydroHarp)
# install the library
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin
)
set(CPACK_GENERATOR DEB CACHE INTERNAL "")
SET(CPACK_PACKAGE_CONTACT "asdaksd#kjhk.com")
SET(CPACK_PACKAGE_VENDOR "asdfasd")
include(CPack)
Built with:
build$ cmake .. && make package
The program references the shared library with a relative path (which is fine for the build tree but not needed due to the RUNPATH):
build$ readelf -d extlink
Dynamic section at offset 0x2da8 contains 29 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [../hhlib-linux-64bit/hhlib.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000001d (RUNPATH) Library runpath: [/code/hhlib-linux-64bit:]
0x000000000000000c (INIT) 0x1000
...
but after make install it's still there and the RUNPATH has been removed:
build$ readelf -d /usr/bin/extlink
Dynamic section at offset 0x2da8 contains 28 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [../hhlib-linux-64bit/hhlib.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000c (INIT) 0x1000
I'm building on Ubuntu 20.04 with CMake 3.16.3 but also tested with the latest CMake version 3.19.4
At first I thought this issue provided a solution, but no combination of those RPATH variables fixes the problem.
After a nice, long scream into my favourite screaming pillow I had another think:
Adding the property IMPORTED_NO_SONAME removes the offending path but the linker fails to find it - even when the path is explicitly included with LINK_DIRECTORIES, why? Because the vendor library doesn't follow the naming convention!
Renaming the library to libhh.so and adding set_target_properties(HydroHarp PROPERTIES IMPORTED_NO_SONAME TRUE) fixes the issue. Don't ask me why.
The full working CMakeLists.txt:
cmake_minimum_required (VERSION 3.19)
enable_language(C)
# Find the header files
find_path(HydroHarp_INCLUDEDIR
NAMES hhlib.h
PATHS "${CMAKE_CURRENT_SOURCE_DIR}/hhlib-linux-64bit"
)
# Find the shared library
find_library(HydroHarp_LIBRARY
NAMES hh # <-- Note removed .so so standard extensions are searched
HINTS "${CMAKE_CURRENT_SOURCE_DIR}/hhlib-linux-64bit"
)
if(HydroHarp_INCLUDEDIR AND HydroHarp_LIBRARY)
message("Found HyroHarp library")
# Import the library
add_library(HydroHarp SHARED IMPORTED)
set_target_properties(HydroHarp PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${HydroHarp_INCLUDEDIR}
IMPORTED_NO_SONAME TRUE # <-- This lib wasn't built with an SONAME
IMPORTED_LOCATION ${HydroHarp_LIBRARY}
)
# copy the library when installing
install(FILES ${HydroHarp_LIBRARY} TYPE LIB)
else()
message(WARNING "Failed to find HydroHarp")
endif()
project(extlink)
add_executable(${PROJECT_NAME} use_hydroharp.c)
target_link_libraries(${PROJECT_NAME} PRIVATE HydroHarp)
# install the library
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin
)
set(CPACK_GENERATOR DEB CACHE INTERNAL "")
SET(CPACK_PACKAGE_CONTACT "asdaksd#adssd.com")
SET(CPACK_PACKAGE_VENDOR "asdfasd")
include(CPack)

cmake linker error with library installed in custom path

I have compiled and installed with CMake the library SDL_bgi to a custom prefix /custom/prefix/. This library uses SDL2.
Now I want to use it in another project with the structure below but I get a linker error when I compile with make:
/usr/bin/c++ CMakeFiles/test.dir/test.cpp.o -o test -Wl,-rpath,/custom/prefix/lib: /custom/prefix/lib/libSDL_bgi.so
/usr/bin/ld: /custom/prefix/lib/libSDL_bgi.so: undefined reference to `SDL_DestroyWindow'
/usr/bin/ld: /custom/prefix/lib/libSDL_bgi.so: undefined reference to `SDL_CreateRenderer'
I have also written the file cmake/modules/FindSDL_bgi.cmake so that may be wrong as well.
If I compile with the following command I can compile correctly:
g++ test.cpp -I . -lSDL_bgi -lSDL2 -I /custom/prefix/include/ -L /custom/prefix/lib/
What am I doing wrongly?
Project structure:
cmake/modules/FindSDL_bgi.cmake
src/test/CMakeLists.txt
src/test/test.cpp
CMakeLists.txt
Libraries:
/usr/lib/libSDL.so
/usr/include/SDL.h
/custom/prefix/lib/libSDL_bgi.so
/custom/prefix/include/graphics.h
/custom/prefix/include/SDL2/libSDL_bgi.h
cmake/modules/FindSDL_bgi.cmake:
# - Try to find LibXml2
# Once done this will define
# SDL_BGI_FOUND - System has LibXml2
# SDL_BGI_INCLUDE_DIRS - The LibXml2 include directories
# SDL_BGI_LIBRARIES - The libraries needed to use LibXml2
# Hardcoded for now
set(SDL_BGI_PATH
/custom/prefix/
)
set(SDL_BGI_SEARCH_PATHS
/usr
/usr/local
/opt
${SDL_BGI_PATH}
)
find_path(SDL_BGI_INCLUDE_DIR graphics.h
HINTS
$ENV{SDL2DIR}
PATH_SUFFIXES include
PATHS ${SDL2_SEARCH_PATHS}
)
find_library(SDL_BGI_LIBRARY
NAMES SDL_bgi
HINTS
$ENV{SDL2DIR}
PATH_SUFFIXES lib64 lib
PATHS ${SDL2_SEARCH_PATHS}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SDL_bgi REQUIRED_VARS SDL_BGI_LIBRARY SDL_BGI_INCLUDE_DIR)
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(programmi_kennedy)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules")
set(COMPAT_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/include/
)
find_package(SDL_bgi REQUIRED)
add_subdirectory(src/test)
src/CMakeLists.txt:
add_executable(test test.cpp)
target_include_directories(test PUBLIC ${SDL_BGI_INCLUDE_DIR})
target_link_libraries(test PRIVATE ${SDL_BGI_LIBRARY})
install(TARGETS test DESTINATION bin)
/custom/prefix/include/graphics.h:
#include <SDL2/SDL_bgi.h>
What I was missing is to link to SDL2 with find_package(SDL2 REQUIRED) and link to SDL2::SDL2. (I did try to link to ${SDL2_LIBRARIES} but the syntax is different now). Thanks to #KamilCuk to point me to the right direction.
EDIT:
I changed the FindBGI_sdl.cmake module in order to search for the dependencies (SDL2) and link against them using the INTERFACE keyword. In this way the target test can link only against SDL_bgi and have the dependencies resolved automatically.
src/CMakeLists.txt:
add_executable(test test.cpp)
target_link_libraries(test PRIVATE SDL_bgi::SDL_bgi)
install(TARGETS test DESTINATION bin)
cmake/modules/FindSDL_bgi.cmake:
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
FindSDL_bgi
-------
Finds the SDL_bgi library.
Imported Targets
^^^^^^^^^^^^^^^^
This module provides the following imported targets, if found:
``SDL_bgi::SDL_bgi``
The SDL_bgi library
Result Variables
^^^^^^^^^^^^^^^^
This will define the following variables:
``SDL_bgi_FOUND``
True if the system has the SDL_bgi library.
``SDL_bgi_VERSION``
The version of the SDL_bgi library which was found.
``SDL_bgi_INCLUDE_DIRS``
Include directories needed to use SDL_bgi.
``SDL_bgi_LIBRARIES``
Libraries needed to link to SDL_bgi.
Cache Variables
^^^^^^^^^^^^^^^
The following cache variables may also be set:
``SDL_bgi_INCLUDE_DIR``
The directory containing ``foo.h``.
``SDL_bgi_LIBRARY``
The path to the SDL_bgi library.
#]=======================================================================]
find_package(SDL2 REQUIRED)
find_package(PkgConfig)
pkg_check_modules(PC_SDL_bgi QUIET SDL_bgi)
find_path(SDL_bgi_INCLUDE_DIR
NAMES graphics.h
PATHS ${PC_SDL_bgi_INCLUDE_DIRS}
)
find_library(SDL_bgi_LIBRARY
NAMES SDL_bgi
PATHS ${PC_SDL_bgi_LIBRARY_DIRS}
)
set(SDL_bgi_VERSION ${PC_SDL_bgi_VERSION})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SDL_bgi
FOUND_VAR SDL_bgi_FOUND
REQUIRED_VARS
SDL_bgi_LIBRARY
SDL_bgi_INCLUDE_DIR
VERSION_VAR SDL_bgi_VERSION
)
if(SDL_bgi_FOUND AND NOT TARGET SDL_bgi::SDL_bgi)
add_library(SDL_bgi::SDL_bgi UNKNOWN IMPORTED)
set_target_properties(SDL_bgi::SDL_bgi PROPERTIES
IMPORTED_LOCATION "${SDL_bgi_LIBRARY}"
INTERFACE_COMPILE_OPTIONS "${PC_SDL_bgi_CFLAGS_OTHER}"
INTERFACE_INCLUDE_DIRECTORIES "${SDL_bgi_INCLUDE_DIR}"
)
target_link_libraries(SDL_bgi::SDL_bgi INTERFACE SDL2::SDL2)
endif()
mark_as_advanced(
SDL_bgi_INCLUDE_DIR
SDL_bgi_LIBRARY
SDL2_DIR
)
Useful references:
https://pabloariasal.github.io/2018/02/19/its-time-to-do-cmake-right/
https://cmake.org/cmake/help/v3.17/manual/cmake-developer.7.html

How to configure CMakeLists.txt for OpenMP?

I am building a python extension from c++ shared library.
This library is using some openmp pragma.
I would like to know how to configure CMakeLists.txt in order to include openmp ?
I have added the openmp flag -fopenmp
But I still have this error : undefined symbol: GOMP_critical_end
here is my CMakeLists.txt file
cmake_minimum_required(VERSION 3.10)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++lastest -pthread -fopenmp")
project (py_interface)
#find_library('gomp')
find_package(OpenMP REQUIRED)
find_package(Boost REQUIRED)
include_directories(/usr/include/python3.6/)
link_directories(/usr/local/lib)
set(SRC interface.cpp)
add_library(py_interface SHARED ${SRC})
target_link_libraries(py_interface PRIVATE OpenMP::OpenMP_CXX ${PYTHON_LIBRARIES} ${Boost_LIBRARIES})
set_property(TARGET py_interface PROPERTY POSITION_INDEPENDENT_CODE ON)

How to stop CMake from linking against libstdc++

I have a very simple CMakeLists.txt for a C++ project, which builds a shared library:
add_library(foo SHARED
${HDR_PUBLIC}
${SOURCES})
When linking the library, CMake automatically uses -lstdc++. How can I stop it from doing this?
You can add -stdlib=libc++ to compiler flags.
Simple example:
cmake_minimum_required(VERSION 2.8.4)
project(test)
set(CMAKE_VERBOSE_MAKEFILE TRUE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -v -stdlib=libc++")
add_executable(test main.cpp)
Give output:
"/usr/bin/ld" ... -o test ... -lc++ ...
By default:
cmake_minimum_required(VERSION 2.8.4)
project(test)
set(CMAKE_VERBOSE_MAKEFILE TRUE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -v")
add_executable(test main.cpp)
Link to stdc++:
"/usr/bin/ld" ... -o test ... -lstdc++ ...
[update]
If you don't need to link to c++ lib at all - use '-nodefaultlibs' as linker flag and '-nostdinc++' to compiler flag. You may need to link some default libraries, like '-lSystem'.
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
set_target_properties(yourtarget PROPERTIES LINKER_LANGUAGE C)
Source: http://cmake.3232098.n2.nabble.com/setting-LINKER-LANGUAGE-still-adds-lstdc-td7581940.html