Linking against a debug version of a library with CMake - c++

I've got some problems with linking against a debug version of my lib. I use CMake to make a library:
project(myLib)
...
add_library(myLib SHARED ${SOURCES})
I launch the build two times to get a release and a debug version of my lib. Then I add 'd' suffix to the name of the debug lib and have myLib.dll and myLibd.dll.
In my app I explicitly link against the debug dll:
project(myApp)
add_executable(myApp WIN32 ${SOURCES})
target_link_libraries(myApp myLibd.dll)
The build finishes successfully, but when I open the resulting exe file with Dependency Walker I get an unresolved dependency to myLib.dll file, even though the debug version (myLibd.dll) is located in the same folder.
So, why does my app try to use the release version of my lib at runtime? And how do I properly link against the debug version?

You should not rename the file manually. Use CMake's CMAKE_DEBUG_POSTFIX variable or the DEBUG_POSTFIX target property instead:
add_library(myLib SHARED ${SOURCES})
set_target_properties(mylib PROPERTIES DEBUG_POSTFIX "d")
[...]
add_executable(myApp WIN32 ${SOURCES})
target_link_libraries(myApp myLib)

Related

How to build a release version in CLion, c++ project

I have the following CMake file that CLion picked up automatically and created a run-debug profile for:
cmake_minimum_required(VERSION 3.23)
project(shadowgate)
set(CMAKE_CXX_STANDARD 20)
include_directories(I:/onedrive/SDL2/include libs)
link_directories(I:/onedrive/SDL2/lib/x64 libs)
#lua54.dll needs to be copied to windows/system32 folder
add_library(Lua STATIC IMPORTED GLOBAL)
set_target_properties(Lua PROPERTIES
IMPORTED_LOCATION "I:/onedrive/lua4/liblua54.a"
INTERFACE_INCLUDE_DIRECTORIES "I:/onedrive/lua4/include"
)
file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/libs/imgui/*.cpp)
add_executable(${PROJECT_NAME} ${SRC_FILES} )
#looks for a file with .lib extension
target_link_libraries(${PROJECT_NAME} SDL2main SDL2 SDL2_ttf SDL2_image SDL2_mixer Lua)
#AssetManager
add_custom_target(copy_assets
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/assets ${CMAKE_CURRENT_BINARY_DIR}/assets
)
add_dependencies(${PROJECT_NAME} copy_assets)
I don't see any options in CLion to copy this debug profile to a 'release' profile. I tried moving the executable to a seperate folder and add the needed .dll files next to it, but then it's still not finding the dlls.
How can I make a proper release of this project, where it will look for the .dll files in it's own directory?

cmake: forcing build type for a specific library fails

I have a c++ project made of several executables and libraries. I use cmake for the compilation. Also in debug mode, I add ā€œ_dā€ as postfix for the libraries (i.e.: libfoo_d.so).
Now, one of those libraries (say lib1) is so slow in debug mode that I want to always build it in release mode. So, in the CMakeLists.txt of lib1 I am forcing the CMAKE_BUILD_TYPE to Release:
set(CMAKE_BUILD_TYPE "Release")
This library has dependencies (say lib2). Of course, lib2 should still be compiled in debug mode and its name should be liblib2_d.so (I only want lib1 to be in release mode).
Unfortunately, when building (in debug mode), I get the following error message:
[build] make[3]: *** No rule to make target 'binaries/lib/liblib2.so', needed by 'binaries/lib/liblib1_d.so'. Stop.
Here is the CMakeLists.txt file for lib1:
cmake_minimum_required(VERSION 2.8.9)
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
project (lib1)
endif()
if (NOT TARGET lib2)
add_subdirectory(../lib2 lib2)
endif()
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/binaries/lib/)
set(CMAKE_BUILD_TYPE "Release")
include_directories(include)
include_directories(../lib2/include lib2)
add_library(lib1 SHARED src/src1.cpp include/lib1.h)
target_link_libraries(lib1 lib2)
I am using cmake version 3.18.4.
I have also uploaded here, a sample that shows the issue. Just unzip the content and run:
mkdir build && cd build && cmake --configure ../app -DCMAKE_BUILD_TYPE=Debug && cmake --build .
I don't know how to solve this. Please can you help me?

Require shared library with dependencies in cmake

I'm new to cmake, so I'm having trouble figuring out how to model the following:
My program requires a third party library that I only have access to in the form of headers and *.so files. It also ships many of its dependencies as *.so files. How do I make sure that everything compiles and links correctly, ideally in the "correct" cmake way?
I've tried this
cmake_minimum_required (VERSION 3.8)
project ("Test")
add_executable (MyApp "MyApp.cpp")
link_directories("/path/to/lib")
target_include_directories(MyApp PUBLIC "/path/to/headers")
This compiles but fails at the linking stage.
Then I tried
cmake_minimum_required (VERSION 3.8)
project ("Test")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
add_executable (MyApp "MyApp.cpp")
find_package(Library REQUIRED)
target_link_libraries(MyApp PUBLIC Library::Library)
And cmake/FindLibrary.cmake following https://pabloariasal.github.io/2018/02/19/its-time-to-do-cmake-right/ (truncated):
...
if(Library_FOUND AND NOT TARGET Library::Library)
add_library(Library::Library SHARED IMPORTED)
set_target_properties(Library::Library PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${Library_INCLUDE_DIR}"
)
set_target_properties(Library::Library PROPERTIES
IMPORTED_LOCATION "/path/to/library.so"
)
endif()
This compiles and links, but the required other *.so files are not found at runtime. I suppose I need to add them also as libraries somehow, although I don't want them to be exported in FindLibrary.cmake. How do I do this correctly?
You can use IMPORTED libraries:
add_library(externalLib SHARED IMPORTED GLOBAL)
set_property(TARGET externalLib PROPERTY IMPORTED_LOCATION "/path/to/lib.so")
target_include_directories(externalLib INTERFACE "/path/to/headers")
target_link_directories(externalLib INTERFACE /path/to/libs)
target_link_libraries(externalLib INTERFACE -ldep1 -ldep2)
Then you can just depend on it:
target_link_libraries(MyApp PRIVATE externalLib)

How to make ExternalProject_Add acting like ADD_SUBDIRECTORY command with cmake?

I'm creating a native library under Android Studio, and I'm hurting the following problem.
In my AndroidStudio project CMakeLists.txt, I have this:
cmake_minimum_required(VERSION 3.7.0)
add_library(native-lib
SHARED
src/main/cpp/native-lib.cpp )
IF(USE_EXTERNAL)
include(ExternalProject)
ExternalProject_Add(
project_mylib
DOWNLOAD_COMMAND ""
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/mylib/"
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}
)
add_dependencies(native-lib project_mylib)
ELSE()
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/mylib/)
ENDIF()
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
target_link_libraries(native-lib
${log-lib}
mylib
)
A self-made library is located in src/main/cpp/mylib/, with a CMakeLists.txt:
cmake_minimum_required(VERSION 3.7.0)
project(lib)
add_library(mylib SHARED lib.cpp)
INSTALL(TARGETS mylib
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
)
When I use the "traditional" add_subdirectory(...) everything goes well. But, if I use the ExternalProject_Add(...) version, linker is skipping the compiled libmylib.so library and so cannot link mylib to native-lib.
I have the following message: skipping incompatible /home/.../app/.externalNativeBuild/cmake/debug/arm64-v8a/lib/libmylib.so when searching for -lmylib
My guess is that all the flags set by AndroidStudio for the root CMakeLists.txt are not set when the ExternalProject is compile leading to an incompatible shared library.
So, I wonder if there is a way to compile a cmake ExternalProject like it was part of the root project (sharing the same compile flags etc) ?
Thanks for any advice

Linking with a static library through CMake

I am trying to use cmake to build my project. I want to link against libpng which is present in my system. This is my code:
cmake_minimum_required(VERSION 2.8.11)
project(main)
file(GLOB SOURCES *.c)
add_executable(sphstego ${SOURCES})
find_package(PNG REQUIRED)
include_directories(${PNG_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS})
target_link_libraries(main ${PNG_LIBRARY})
message(STATUS "PNG_LIBRARY: " ${PNG_LIBRARY}) # correct path to so file
My problem is that I want to link statically rather than dynamically. Furthermore, and although the variable set as PNG_LIBRARY is correctly set to /usr/local/lib/libpng.so, I get an error message when running my executable:
error while loading shared libraries: libpng16.so.16: cannot open shared object file: No such file or directory
Any suggestions on how to resolve this?