Custom CMake library - What have I done wrong? - c++

I am trying to install a custom library with CMake.
It consists of 2 'sub-libraries' and a main header file which includes the 'sub-libraries'.
I think it installs okay (The output looks like this:)
-- Configuring done
-- Generating done
-- Build files have been written to: /home/pi/Desktop/Projects/MaxLib/build
[ 20%] Building CXX object Geom/CMakeFiles/Geom.dir/Geom.cpp.o
[ 40%] Linking CXX shared library libGeom.so
[ 40%] Built target Geom
[ 60%] Building CXX object File/CMakeFiles/File.dir/File.cpp.o
[ 80%] Linking CXX shared library libFile.so
[ 80%] Built target File
[100%] Built target MaxLib
Install the project...
-- Install configuration: "Debug"
-- Installing: /usr/local/lib/libMaxLib.a
-- Installing: /usr/local/include/MaxLib.h
-- Installing: /usr/local/include/MaxLib/File.h
-- Installing: /usr/local/include/MaxLib/Geom.h
However, when I try to compile a program using it, I receive a number of "undefined reference to" errors. Where have I gone wrong?
The Main Header looks like:
#include "MaxLib/File.h"
#include "MaxLib/Geom.h"
It's CMakefile looks like this:
cmake_minimum_required(VERSION 3.5)
project(MaxLib)
add_library(${PROJECT_NAME}
"${CMAKE_CURRENT_SOURCE_DIR}/MaxLib.h"
)
add_subdirectory(File)
add_subdirectory(Geom)
target_link_libraries(${PROJECT_NAME} File)
target_link_libraries(${PROJECT_NAME} Geom)
# Install Library
install (TARGETS ${PROJECT_NAME}
LIBRARY DESTINATION lib)
# Install Main Header File
INSTALL(FILES "${CMAKE_CURRENT_SOURCE_DIR}/MaxLib.h" DESTINATION include) #
INSTALL(FILES ...) or install(DIRECTORY ...)
# Build list of header files to install from other directorys. Root == "."
set(HEADER_DIRS "File" "Geom")
## Add Source Files from the other directories
foreach(DIR ${HEADER_DIRS})
# Find all source files & append to list
if(DIR STREQUAL ".")
file(GLOB HEADER_FILES_IN_FOLDER *.h)
else()
file(GLOB HEADER_FILES_IN_FOLDER ${CMAKE_CURRENT_SOURCE_DIR}/${DIR}/*.h)
endif()
list(APPEND HEADER_FILES ${HEADER_FILES_IN_FOLDER})
endforeach()
# Install Header files
INSTALL(FILES ${HEADER_FILES} DESTINATION include/${PROJECT_NAME}) # INSTALL(FILES ...) or install(DIRECTORY ...)
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Wpedantic -g)
set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX)
The 'sub-libraries's CMakefiles look like this:
project(Geom)
add_library(${PROJECT_NAME} SHARED
${CMAKE_CURRENT_SOURCE_DIR}/Geom.cpp
)
target_include_directories(${PROJECT_NAME}
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
I am trying to include the library like this:
#include <MaxLib.h>
And I am adding -lMaxLib to its makefile
Edit:
A basic program like this:
#include <MaxLib.h>
int main() {
float y1 = MaxLib::Geom::CleanAngle(7654);
}
Will produce the undefined reference error:
/usr/bin/ld: warning: libFile.so, needed by //usr/local/lib/libMaxLib.so, not found (try using -rpath or -rpath-link) // This shows when add_library marked SHARED
/usr/bin/ld: warning: libGeom.so, needed by //usr/local/lib/libMaxLib.so, not found (try using -rpath or -rpath-link) // This shows when add_library marked SHARED
/home/pi/Desktop/Projects/TestProgram/main.cpp:43: undefined reference to `MaxLib::Geom::CleanAngle(double)'

Related

Boost.Test linker error by use with precompiled headers (PCH)

I have a linker error when using Boost.Test with precompiled header (PCH) that does not occur without PCH. I use the dynamically linked library as described in Usage variants.
How can I fix the error to use Boost.Test also with PCH?
The problem occurs at least with Fedora and boost 1.73 (has only dynamic libraries) and g++ 10/clang 11.
$ cmake ../ && make
-- Configuring done
-- Generating done
-- Build files have been written to: /home/.../boost_test_pch/build
[ 33%] Building CXX object CMakeFiles/boost_utf_pch.dir/test_driver.cpp.o
[ 66%] Building CXX object CMakeFiles/boost_utf_pch.dir/test.cpp.o
[100%] Linking CXX executable boost_utf_pch
[100%] Built target boost_utf_pch
vs.
$ cmake -DEDA_ENABLE_PCH=TRUE ../ && make
-- Configuring done
-- Generating done
-- Build files have been written to: /home/.../boost_test_pch/build
[ 25%] Building CXX object CMakeFiles/boost_utf_pch.dir/cmake_pch.hxx.gch
[ 50%] Building CXX object CMakeFiles/boost_utf_pch.dir/test_driver.cpp.o
cc1plus: warning: /home/.../boost_test_pch/build/CMakeFiles/boost_utf_pch.dir/cmake_pch.hxx.gch: not used because `BOOST_TEST_DYN_LINK' is defined [-Winvalid-pch]
[ 75%] Building CXX object CMakeFiles/boost_utf_pch.dir/test.cpp.o
[100%] Linking CXX executable boost_utf_pch
/usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/10/../../../../lib64/crt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/boost_utf_pch.dir/build.make:138: boost_utf_pch] Error 1
make[1]: *** [CMakeFiles/Makefile2:95: CMakeFiles/boost_utf_pch.dir/all] Error 2
make: *** [Makefile:103: all] Error 2
I can not do anything with the warning message before ...
Here the playground files:
CMakeLists.txt:
project(boost_utf_pch LANGUAGES CXX)
cmake_minimum_required(VERSION 3.18)
add_executable(${PROJECT_NAME} "")
find_package(Boost 1.73.0 REQUIRED COMPONENTS
unit_test_framework)
target_sources(${PROJECT_NAME} PRIVATE
test_driver.cpp test.cpp)
target_link_libraries(${PROJECT_NAME} PRIVATE
Boost::unit_test_framework)
set_source_files_properties(test_driver.cpp
APPEND PROPERTIES COMPILE_DEFINITIONS "BOOST_TEST_DYN_LINK")
option(EDA_ENABLE_PCH "Enable PCH" OFF)
if (EDA_ENABLE_PCH)
target_precompile_headers(${PROJECT_NAME} PRIVATE pch.hpp)
endif()
pch.hpp
#pragma once
#include <boost/test/unit_test.hpp>
test.cpp
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_SUITE( my_test )
BOOST_AUTO_TEST_CASE( test_case1 )
{
BOOST_TEST_WARN( sizeof(int) < 4U );
}
BOOST_AUTO_TEST_SUITE_END()
test_driver.cpp
#define BOOST_TEST_MODULE "Boost.UTF PCH Test Suite"
#include <boost/test/unit_test.hpp>
Alan Birtles got the hint into the right direction. I was not aware of the influence of the compiler switch BOOST_TEST_DYN_LINK for the single file in the context of PCH here. A definition for all files of the project in the style of:
target_compile_definitions(${PROJECT_NAME} PRIVATE
"BOOST_TEST_DYN_LINK")
incomprehensibly does not solve the problem. Only after setting the property SKIP_PRECOMPILE_HEADERS for driver 'main' it compiles and links as expected:
project(boost_utf_pch LANGUAGES CXX)
cmake_minimum_required(VERSION 3.18)
add_executable(${PROJECT_NAME} "")
find_package(Boost 1.73.0 REQUIRED COMPONENTS
unit_test_framework)
target_sources(${PROJECT_NAME} PRIVATE
test_driver.cpp test.cpp)
target_link_libraries(${PROJECT_NAME} PRIVATE
Boost::unit_test_framework)
set_source_files_properties(test_driver.cpp
APPEND PROPERTIES COMPILE_DEFINITIONS "BOOST_TEST_DYN_LINK")
set_source_files_properties(test_driver.cpp
PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
option(EDA_ENABLE_PCH "Enable PCH" ON)
if (EDA_ENABLE_PCH)
target_precompile_headers(${PROJECT_NAME} PRIVATE pch.hpp)
endif()

Cmake - fatal error U1073: don't know how to make a specific library

I am trying to build my project under Windows. On Linux it has no issues.
Here is my main CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(Vibranium_Core)
set(CMAKE_CXX_STANDARD 17)
set(FLATBUFFERS_MAX_PARSING_DEPTH 16)
set(FLATBUFFERS_LOCATION "E:/vcpkg/packages/flatbuffers_x86-windows")
set(Boost_USE_STATIC_LIBS ON)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0")
endif()
if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
execute_process(
COMMAND git rev-list --count HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND git rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND git log -1 --format=%h
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND git --no-pager log -1 --format=%ai
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_RELEASED_ON
OUTPUT_STRIP_TRAILING_WHITESPACE
)
else(EXISTS "${CMAKE_SOURCE_DIR}/.git")
set(GIT_BRANCH "")
set(GIT_COMMIT_HASH "")
endif(EXISTS "${CMAKE_SOURCE_DIR}/.git")
message(STATUS "VibraniumCore current branch: ${GIT_BRANCH}")
message(STATUS "VibraniumCore Version: ${GIT_VERSION}")
message(STATUS "VibraniumCore commit hash: ${GIT_COMMIT_HASH}")
message(STATUS "Released on: ${GIT_RELEASED_ON}")
message(STATUS "Generating version.h")
configure_file(
${CMAKE_SOURCE_DIR}/cmake/version.h.in
${CMAKE_SOURCE_DIR}/Source/Common/Version.h
)
find_package(Boost 1.72.0 COMPONENTS date_time serialization regex)
find_package(Threads)
add_definitions(-DGIT_COMMIT_HASH="${GIT_COMMIT_HASH}")
add_definitions(-DGIT_BRANCH="${GIT_BRANCH}")
add_definitions(-DGIT_VERSION="${GIT_VERSION}")
add_definitions(-DGIT_RELEASED_ON="${GIT_RELEASED_ON}")
include_directories(${Boost_INCLUDE_DIR})
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
message(STATUS "Target is 64 bits")
if (WIN32)
set(WINXXBITS Win64)
endif(WIN32)
else("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
message(STATUS "Target is 32 bits")
if (WIN32)
set(WINXXBITS Win32)
endif(WIN32)
endif("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
find_package(MySQL REQUIRED)
if(WIN32)
find_package(Flatbuffers REQUIRED
PATHS ${FLATBUFFERS_LOCATION})
else()
find_package(Flatbuffers REQUIRED
PATHS /usr/local/flatbuffers)
endif()
include_directories(${MYSQL_INCLUDE_DIR})
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Source/Common)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Source/Core/WorldServer)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Source/Core/AuthServer)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Source/ClientEmulator)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Source/Game)
add_subdirectory(Tests)
set_target_properties(VibraniumCoreTests PROPERTIES EXCLUDE_FROM_ALL TRUE)
set_target_properties(gtest PROPERTIES EXCLUDE_FROM_ALL TRUE)
set_target_properties(gmock PROPERTIES EXCLUDE_FROM_ALL TRUE)
set_target_properties(gtest_main PROPERTIES EXCLUDE_FROM_ALL TRUE)
set_target_properties(gmock_main PROPERTIES EXCLUDE_FROM_ALL TRUE)
set_target_properties(
Common WorldServer AuthServer ClientEmulator Game
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/lib"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
)
Here is AuthServer CMakeLists.txt:
add_executable(AuthServer
AuthServer.cpp
${PRIVATE_SOURCES}
../Database/Implementation/LoginDatabase.cpp
../Database/Implementation/LoginDatabase.h
../Database/Implementation/LoginDatabase/Accounts.h
../Database/Implementation/LoginDatabase/AccountRoles.h
../Database/Implementation/LoginDatabase/Accounts.cpp
../Database/Implementation/LoginDatabase/AccountRoles.cpp
../Memory/LoginMemory.h
../Memory/LoginMemory.cpp
AuthServer.h
Server/AuthServerOpcodes.cpp Server/AuthServerOpcodes.h)
target_include_directories(AuthServer PUBLIC ../Database ../Database/Implementation/LoginDatabase/ ../../Game)
target_link_libraries(AuthServer PUBLIC Common Game ${Boost_LIBRARIES})
if(NOT EXISTS ${CMAKE_BINARY_DIR}/bin/configs/)
message(STATUS "Configs folder will be created: ${CMAKE_BINARY_DIR}/bin/configs")
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/bin/configs/)
endif()
if(NOT EXISTS ${CMAKE_BINARY_DIR}/bin/configs/AuthServer.conf)
message(STATUS "New AuthServer Config file in will be installed in: ${CMAKE_BINARY_DIR}/bin/configs")
add_custom_command(
TARGET AuthServer POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/AuthServer.conf.dist
${CMAKE_BINARY_DIR}/bin/configs/AuthServer.conf)
endif()
Here is my Game library CMakeLists.txt:
add_library(
Game
SHARED
Accounts/AccountManager.cpp Accounts/AccountManager.h)
target_include_directories(Game PUBLIC /usr/local/mysql/connector-c++-/include)
target_include_directories(Game PUBLIC . ${MYSQL_LIBRARY})
target_include_directories(Game PUBLIC ../Core/AuthServer)
target_include_directories(Game PUBLIC ../Core/WorldServer)
target_link_libraries(Game PUBLIC ${MYSQL_CONNECTOR_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} Common)
When I try to build I get this output and error:
====================[ Build | AuthServer | Debug ]==============================
"C:\Program Files\JetBrains\CLion 2020.1.3\bin\cmake\win\bin\cmake.exe" --build E:\Vibranium-Core\cmake-build-debug --target AuthServer
Scanning dependencies of target Common
[ 4%] Building CXX object Source/Common/CMakeFiles/Common.dir/Config.cpp.obj
Config.cpp
[ 8%] Building CXX object Source/Common/CMakeFiles/Common.dir/Logger.cpp.obj
Logger.cpp
[ 13%] Building CXX object Source/Common/CMakeFiles/Common.dir/Database/MySQLConnection.cpp.obj
MySQLConnection.cpp
[ 17%] Building CXX object Source/Common/CMakeFiles/Common.dir/Database/MySQLTable.cpp.obj
MySQLTable.cpp
[ 21%] Building CXX object Source/Common/CMakeFiles/Common.dir/Banner.cpp.obj
Banner.cpp
[ 26%] Building CXX object Source/Common/CMakeFiles/Common.dir/Database/MySQLTableBase.cpp.obj
MySQLTableBase.cpp
[ 30%] Building CXX object Source/Common/CMakeFiles/Common.dir/Memory/Memory.cpp.obj
Memory.cpp
[ 34%] Building CXX object Source/Common/CMakeFiles/Common.dir/Server/Server.cpp.obj
Server.cpp
Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:
- add -D_WIN32_WINNT=0x0601 to the compiler command line; or
- add _WIN32_WINNT=0x0601 to your project's Preprocessor Definitions.
Assuming _WIN32_WINNT=0x0601 (i.e. Windows 7 target).
[ 39%] Building CXX object Source/Common/CMakeFiles/Common.dir/Server/Client.cpp.obj
Client.cpp
Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:
- add -D_WIN32_WINNT=0x0601 to the compiler command line; or
- add _WIN32_WINNT=0x0601 to your project's Preprocessor Definitions.
Assuming _WIN32_WINNT=0x0601 (i.e. Windows 7 target).
[ 43%] Building CXX object Source/Common/CMakeFiles/Common.dir/Server/Packet.cpp.obj
Packet.cpp
Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:
- add -D_WIN32_WINNT=0x0601 to the compiler command line; or
- add _WIN32_WINNT=0x0601 to your project's Preprocessor Definitions.
Assuming _WIN32_WINNT=0x0601 (i.e. Windows 7 target).
[ 47%] Building CXX object Source/Common/CMakeFiles/Common.dir/Server/Protocol/Opcodes.cpp.obj
Opcodes.cpp
[ 52%] Building CXX object Source/Common/CMakeFiles/Common.dir/Server/WorldSession.cpp.obj
WorldSession.cpp
[ 56%] Building CXX object Source/Common/CMakeFiles/Common.dir/Server/AuthSession.cpp.obj
AuthSession.cpp
[ 60%] Linking CXX shared library ..\..\bin\Common.dll
Creating library ..\..\bin\lib\Common.lib and object ..\..\bin\lib\Common.exp
Creating library ..\..\bin\lib\Common.lib and object ..\..\bin\lib\Common.exp
[ 60%] Built target Common
Scanning dependencies of target Game
[ 65%] Building CXX object Source/Game/CMakeFiles/Game.dir/Accounts/AccountManager.cpp.obj
AccountManager.cpp
Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:
- add -D_WIN32_WINNT=0x0601 to the compiler command line; or
- add _WIN32_WINNT=0x0601 to your project's Preprocessor Definitions.
Assuming _WIN32_WINNT=0x0601 (i.e. Windows 7 target).
[ 69%] Linking CXX shared library ..\..\bin\Game.dll
[ 69%] Built target Game
Scanning dependencies of target AuthServer
[ 73%] Building CXX object Source/Core/AuthServer/CMakeFiles/AuthServer.dir/AuthServer.cpp.obj
AuthServer.cpp
Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:
- add -D_WIN32_WINNT=0x0601 to the compiler command line; or
- add _WIN32_WINNT=0x0601 to your project's Preprocessor Definitions.
Assuming _WIN32_WINNT=0x0601 (i.e. Windows 7 target).
[ 78%] Building CXX object Source/Core/AuthServer/CMakeFiles/AuthServer.dir/__/Database/Implementation/LoginDatabase.cpp.obj
LoginDatabase.cpp
[ 82%] Building CXX object Source/Core/AuthServer/CMakeFiles/AuthServer.dir/__/Database/Implementation/LoginDatabase/Accounts.cpp.obj
Accounts.cpp
[ 86%] Building CXX object Source/Core/AuthServer/CMakeFiles/AuthServer.dir/__/Database/Implementation/LoginDatabase/AccountRoles.cpp.obj
AccountRoles.cpp
[ 91%] Building CXX object Source/Core/AuthServer/CMakeFiles/AuthServer.dir/__/Memory/LoginMemory.cpp.obj
LoginMemory.cpp
[ 95%] Building CXX object Source/Core/AuthServer/CMakeFiles/AuthServer.dir/Server/AuthServerOpcodes.cpp.obj
AuthServerOpcodes.cpp
NMAKE : fatal error U1073: don't know how to make 'bin\lib\Game.lib'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\bin\HostX64\x64\nmake.exe"' : return code '0x2'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\bin\HostX64\x64\nmake.exe"' : return code '0x2'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\bin\HostX64\x64\nmake.exe"' : return code '0x2'
Stop.
I have two questions:
Why I see this message Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. and how can I fix it? I see this only on Windows. On Linux it does not apepar.
How can I fix the error NMAKE : fatal error U1073: don't know how to make 'bin\lib\Game.lib' ?
P.S.
Here is what I have in the build dir:
EDITED:
I'm not sure about issue #2 upon second viewing. I'd have to have access to more of your codebase.
But I think I can answer #1.
#1.) This is a message from boost:
D_WIN32_WINNT compiler warning with Boost
To fix issue number 1 you should include a specific windows header file.
Add following line in your top source code. As was specified by user Hill in the post I linked.
#include <SDKDDKVer.h>
This will define _WIN32_WINNT appropriately.
Ideas to try and fix number #2.
Use a different generator. I don't recommmend Nmake because it is super slow anyway and gives less than stellar error messages. I'd recommend Visual Studio or Ninja.

CMake: Can't link simple project that uses shared zlib wrapper library

In my situation I have two CMake projects (built using MSYS Makefiles if that matters):
One is a shared library that uses Zlib and Libzip to provide zipping functionality to the library user, let's call it mylib.
Another is an app that uses mylib to do some zipping stuff. It doesn't have to worry about Zlib, Libzip or anything. Let's call it app.
I have created a bare-bones example below that demonstrates the bizarre issue I'm having. Simply put, app refuses to link when running make, but only if some Libzip code is left uncommented in mylib (which compiles and links fine, no matter what).
Zlib and Libzip source code is located in C:/Dev/Libs.
lib/CMakeLists.txt
cmake_minimum_required(VERSION 3.7)
# Set project
project(mylib)
set(LIBS_DIR "C:/Dev/Libs")
# Add mylib sources
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src")
file(GLOB_RECURSE SRCS "src/*.cpp")
add_library(mylib SHARED ${SRCS})
# Add Zlib
set(ZLIB_ROOT "${LIBS_DIR}/zlib-1.2.11")
include_directories(${ZLIB_ROOT})
target_include_directories(mylib PUBLIC ${ZLIB_ROOT})
file(GLOB ZLIB_SRCS "${ZLIB_ROOT}/*.c")
add_library(zlib STATIC ${ZLIB_SRCS})
# Add Libzip
set(LIBZIP_ROOT "${LIBS_DIR}/libzip-1.1.3")
include_directories("${LIBZIP_ROOT}/lib")
target_include_directories(mylib PUBLIC "${LIBZIP_ROOT}/lib")
file(GLOB LIBZIP_SRCS "${LIBZIP_ROOT}/lib/*.c")
add_library(libzip STATIC ${LIBZIP_SRCS})
set(LIBS_LINK zlib libzip)
set(LIBS_INSTALL zlib libzip)
set(LIBS_EXPORT zlib libzip)
target_link_libraries(mylib PUBLIC ${LIBS_LINK})
# https://rix0r.nl/blog/2015/08/13/cmake-guide/
# Define headers for this library. PUBLIC headers are used for
# compiling the library, and will be added to consumers' build
# paths.
target_include_directories(mylib PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<INSTALL_INTERFACE:include>
PRIVATE src)
# 'make install' to the correct locations (provided by GNUInstallDirs).
include(GNUInstallDirs)
install(TARGETS mylib ${LIBS_INSTALL} EXPORT mylibConfig
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) # This is for Windows
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
# This makes the project importable from the install directory
# Put config file in per-project dir (name MUST match), can also
# just go into 'cmake'.
install(EXPORT mylibConfig DESTINATION share/mylib/cmake)
# This makes the project importable from the build directory
export(TARGETS mylib ${LIBS_EXPORT} FILE mylibConfig.cmake)
lib/src/lib.hpp
#pragma once
namespace lib
{
int func();
}
lib/src/lib.cpp
#include "lib.hpp"
#define ZIP_STATIC
#include "zip.h"
int lib::func()
{
zip_source_t *src;
zip_error_t error;
src = zip_source_buffer_create(0, 1, 0, &error);
return 10;
}
app/CMakeLists.txt
cmake_minimum_required(VERSION 3.7)
project(app)
# Add app sources
file(GLOB_RECURSE SRCS "src/*.cpp")
add_executable(app ${SRCS})
# Add mylib
set(mylib_DIR "${CMAKE_CURRENT_BINARY_DIR}/../lib")
find_package(mylib REQUIRED)
configure_file("${mylib_DIR}/libmylib.dll" "libmylib.dll" COPYONLY)
target_link_libraries(app mylib)
app/src/app.hpp
#pragma once
#include <lib.hpp>
app/src/app.cpp
#include <iostream>
#include "app.hpp"
int main()
{
std::cout << lib::func() << std::endl;
return 0;
}
Output from building mylib
$ make
[ 13%] Built target zlib
[ 98%] Built target libzip
Scanning dependencies of target mylib
[ 99%] Building CXX object CMakeFiles/mylib.dir/src/lib.cpp.obj
[100%] Linking CXX shared library libmylib.dll
[100%] Built target mylib
Output from building app
$ make
Scanning dependencies of target app
[ 50%] Building CXX object CMakeFiles/app.dir/src/app.cpp.obj
[100%] Linking CXX executable app.exe
CMakeFiles/app.dir/objects.a(app.cpp.obj):app.cpp:(.text+0x17): undefined reference to `lib::func()'
collect2.exe: error: ld returned 1 exit status
make[2]: *** [app.exe] Error 1
make[1]: *** [CMakeFiles/app.dir/all] Error 2
make: *** [all] Error 2
If I comment src = zip_source_buffer_create(0, 1, 0, &error); in lib/src/lib.cpp, rebuild and then rebuild app:
$ make
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Dev/Builds/cmaketest/app
[ 50%] Linking CXX executable app.exe
[100%] Built target app
$ ./app
10
Which yields the expected result.
The issue must lie in the CMakeLists of app, since mylib builds fine without any linking errors. Or am I adding zlib/libzip incorrectly in mylib? I need to link to them statically and I couldn't get it to work with find_package.
Thanks!
Got it working after copying over the .dll.a file as well:
configure_file("${mylib_DIR}/libmylib.dll.a" "libmylib.dll.a" COPYONLY)
and prefixing all my methods in lib with the following:
__declspec(dllexport)

Can't link c++ libraries using CMAKE and make install

I am having a problem linking two libraries using CMake on linux (ubuntu). I have the following CMake setup.
cmake_minimum_required(VERSION 3.3)
project(lib1)
set(SOURCE_FILES
source_1.cpp)
# set library output directory
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ../build/)
# Base directory relative to which all includes are
set(BASE_DIR ../)
#include base directory
include_directories ("${BASE_DIR}")
# create a shared library
add_library(lib1 SHARED ${SOURCE_FILES})
# make install target
install(TARGETS lib1 DESTINATION /usr/local/lib)
For Library 2 we have
cmake_minimum_required(VERSION 3.3)
project(lib2)
set(SOURCE_FILES
source_2.cpp)
set(BASE_DIR ../)
#include base directory
include_directories ("${BASE_DIR}")
# create a shared library
add_library(lib2 SHARED ${SOURCE_FILES})
# include lib1 library
target_link_libraries(lib2 PUBLIC lib1)
install(TARGETS lib2 DESTINATION /usr/local/lib)
Running these with
cmake_minimum_required(VERSION 3.3)
project(all)
add_subdirectory(lib1)
add_subdirectory(lib2)
creates liblib1.so and liblib2.so. liblib2.so depends on liblib1.so (ldd liblib2.so gives the link to liblib1.so in the CMAKE_LIBRARY_OUTPUT_DIRECTORY directory.)
After running
make install
I get
-- Install configuration: "Release"
-- Up-to-date: /usr/local/lib/liblib1.so
-- Installing: /usr/local/lib/liblib2.so
-- Set runtime path of "/usr/local/lib/liblib2.so" to ""
and in /usr/local/lib liblib2.so is no longer linked to liblib1.so.
I tried many reworkings of my cmake file, (e.g. using :
set(CMAKE_INSTALL_RPATH "/usr/local/lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
but nothing seemed to help. Anyone can explain me how to get the libraries to link after make install?
I did run ldconfig manually, but no luck. /usr/local/lib is also part of ld.conf and I am running ubuntu 16.04.

CMake, OS X Wrong Python Version

I am trying to use / learn CMake to embed Python into a C++ application that uses Qt.
I am using FIND_PACKAGE in an attempt to get a non-system package installation (Anaconda Python 2.7.9) in. I can not get the compiler to see any version other than the system installation (version 2.7.5).
My CMakeLists.txt is:
#Minimum CMAKE version
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
#Name the project
PROJECT(embedpython)
#Set the version number
SET(embedpython_VERSION_MAJOR 0)
SET(embedpython_VERSION_MINOR 1)
SET(CMAKE_AUTOMOC ON)
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
FIND_PACKAGE(Qt4 4.8.6 REQUIRED QtGui QtCore)
QT4_WRAP_CPP(embedpython_HEADERS_MOC ${embedpython_HEADERS})
message(status "QT FOUND: ${Qt4_FOUND}")
FIND_PACKAGE(PythonLibs 2.7.9 REQUIRED)
message(status "libs found: ${PYTHONLIBS_FOUND}")
MESSAGE(STATUS "PYTHON_LIBRARIES: ${PYTHON_LIBRARIES}")
MESSAGE(STATUS "PYTHON_INCLUDE_PATH: ${PYTHON_INCLUDE_PATH}")
MESSAGE(STATUS "PYTHONLIBS_VERSION: ${PYTHONLIBS_VERSION_STRING}")
MESSAGE(STATUS "PYTHON_INCLUDE_DIRS: ${PYTHON_INCLUDE_DIRS}")
INCLUDE(${QT_USE_FILE})
ADD_DEFINITIONS(${QT_DEFINITIONS})
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
SET(embedpython_SOURCES
main.cpp
mainwindow.cpp
pythonutilsimpl.cpp
ipcepythonrunner.cpp)
SET(embedpython_HEADERS
mainwindow.h
pythonutilsimpl.h
ipcepythonutils.h
ipcepythonrunner.h)
ADD_EXECUTABLE(embedpython ${embedpython_SOURCES} ${embedpython_HEADERS_MOC})
TARGET_LINK_LIBRARIES(embedpython ${QT_LIBRARIES} ${PYTHON_LIBRARIES})
Which outputs:
cmpt:build user$ /Applications/CMake.app/Contents/bin/cmake .. && make
statusQT FOUND: TRUE
statuslibs found: TRUE
-- PYTHON_LIBRARIES: /home/me/anaconda/lib/libpython2.7.dylib
-- PYTHON_INCLUDE_PATH: /home/me/anaconda/include/python2.7
-- PYTHONLIBS_VERSION: 2.7.9
-- PYTHON_INCLUDE_DIRS: /home/me/anaconda/include/python2.7
-- Configuring done
-- Generating done
-- Build files have been written to: /home/me/Desktop/EmbedPython/build
Scanning dependencies of target embedpython_automoc
[ 16%] Automatic moc for target embedpython
Generating moc_mainwindow.cpp
[ 16%] Built target embedpython_automoc
Scanning dependencies of target embedpython
[ 33%] Building CXX object CMakeFiles/embedpython.dir/main.cpp.o
[ 50%] Building CXX object CMakeFiles/embedpython.dir/mainwindow.cpp.o
[ 66%] Building CXX object CMakeFiles/embedpython.dir/pythonutilsimpl.cpp.o
[ 83%] Building CXX object CMakeFiles/embedpython.dir/ipcepythonrunner.cpp.o
[100%] Building CXX object CMakeFiles/embedpython.dir/embedpython_automoc.cpp.o
Linking CXX executable embedpython
[100%] Built target embed python
Using ccmake, I have set PYTHON_INCLUDE_DIR and PYTHON_LIBRARY so that FIND_PACKAGE succeeds in finding Python 2.7.9.
Within the C++ I have a debug to print the python version and path. Without fail, this returns Python 2.7.5. What is required in the CMake file to get the version of Python at the PATH I am aiming for?