I'm using CLion with CMake. I have my own static library "libxxx.a".
I'm trying to link it this way in CMakeLists.txt:
target_link_libraries(myProject ./lib/libxxx.a)
And this way I'm including library to my main.cpp.
#include "xxx.h".
But I have error fatal error: xxx.h: No such file or directory.
What should I do?
CMake include a prebuilt static library
As a sketch you need your project to look something like this
project( myProject )
set( SOURCE_FILES main.cpp )
add_library( myLibrary STATIC IMPORTED )
set_property( TARGET myLibrary PROPERTY IMPORTED_LOCATION /path/to/lib/libxxx.a )
include_directories( /path/to/headers/ )
add_executable( myProject ${SOURCE_FILES} )
target_link_libraries( myProject myLibrary )
You might be able to replace include_directories with:
set_property( TARGET myLibrary PROPERTY INCLUDE_DIRECTORIES /path/to/headers/ )
A better way to go is to compile the static library from source and then use
target_include_directories( myLibrary PUBLIC /path/to/headers/ )
And then they get handled automatically.
Related
I am building a lib that is wrapping a third party lib. Both the third party lib and the wrapper lib are build using cmake with the add_library function with the STATIC keyword. However when I try to build a executable that uses this wrapper lib, I get undefined references to the third party lib. Here is the code:
Third party lib spdlog.cmake:
include(FetchContent)
FetchContent_Declare(
spdlog
GIT_REPOSITORY https://github.com/gabime/spdlog.git
GIT_TAG v1.11.0
)
FetchContent_MakeAvailable(spdlog)
This lib can be build in different ways, but I have checked that we use the line add_library(spdlog STATIC ${SPDLOG_SRCS} ${SPDLOG_ALL_HEADERS})
Then the wrapper lib utils.cmake:
cmake_minimum_required (VERSION 3.1)
project (Utils)
# set C++20
set (CMAKE_CXX_STANDARD 20)
include(cmake/spdlog.cmake)
file(GLOB SRCS src/*.cpp)
file(GLOB HDRS include/*.h)
add_library(Utils STATIC ${SRCS} ${HDRS})
target_include_directories(Utils PUBLIC include)
target_link_libraries(Utils PRIVATE spdlog)
I link here using PRIVATE since we do not expose spdlog in the headers of this lib.
Then the executable cmake. Actually the wrapper lib is a separate project and the (static) lib that is created and its header files are is copied to a folder (Libs/Utils/lib and Libs/Utils/include) of the executable project.
cmake_minimum_required (VERSION 3.1)
project (Foo)
# Find Utils
set(UTILS_DIR "${PROJECT_SOURCE_DIR}/Libs/Utils")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${UTILS_DIR}/cmake/")
find_package(UTILS REQUIRED)
file(GLOB SRCS src/*.cpp)
add_executable(Foo ${SRCS})
target_include_directories(Foo PUBLIC ${UTILS_INCLUDE_DIRS})
target_link_libraries(Foo ${UTILS_LIBRARIES})
Finally the find script for the Utils lib:
SET(UTILS_DEFINITIONS ${UTILS_DEFINITIONS})
IF (UTILS_INCLUDE_DIR)
# Already in cache, be silent
SET(UTILS_FIND_QUIETLY TRUE)
ENDIF (UTILS_INCLUDE_DIR)
set(UTILS_INCLUDE_DIR
${UTILS_DIR}/include
)
set(UTILS_STATIC_LIBRARY
${UTILS_DIR}/lib/libUtils.a
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(UTILS DEFAULT_MSG
UTILS_INCLUDE_DIR UTILS_STATIC_LIBRARY)
mark_as_advanced(UTILS_INCLUDE_DIR UTILS_STATIC_LIBRARY)
set(UTILS_LIBRARIES ${UTILS_STATIC_LIBRARY})
set(UTILS_INCLUDE_DIRS ${UTILS_INCLUDE_DIR})
The Utils lib builds fine, but when I build Foo, I get a lot of linker errors (the Logger.cpp is a file in Utils lib:
Logger.cpp:(.text+0x90): undefined reference to `spdlog::logger::sinks()
If I also copy the (static) lib of spdlog to libs folder and set UTILS_STATIC_LIBRARY to include this lib, it links. However since the spdlog is build statically I would assume that linking to the Utils lib would be enough.
Can somebody tell me what I am doing wrong?
I am trying to build a dbgsym package with cmake and cannot find any help anywhere. I've seen CPACK_DEBIAN_DEBUGINFO_PACKAGE but cannot use it in CMakeLists.txt since the version of CMake I am using does not have that.
I do have set(CMAKE_BUILD_TYPE Debug).
I want to be able to include debug symbols with the package.
The following CMakeLists.txt creates a debug symbol package. I didn't check if it's usable in gdb, though.
cmake_minimum_required(VERSION 3.13)
message( STATUS "Build type is " ${CMAKE_BUILD_TYPE} )
project( demonstrator
DESCRIPTION "Demonstrator"
VERSION 1.0.0
LANGUAGES CXX )
add_library( my_library SHARED )
target_sources( my_library
PRIVATE my_code.cpp )
target_include_directories( my_library
PUBLIC include )
set_target_properties ( my_library
PROPERTIES
PUBLIC_HEADER "include/my_code.hpp" )
install(
TARGETS my_library
ARCHIVE
DESTINATION lib
COMPONENT runtime
LIBRARY
DESTINATION lib
COMPONENT runtime
PUBLIC_HEADER
DESTINATION include
COMPONENT development
)
set( CPACK_PACKAGE_NAME ${PROJECT_NAME} )
set( CPACK_PACKAGE_CONTACT "Contact name" )
set( CPACK_PACKAGE_VERSION ${PROJECT_VERSION} )
set( CPACK_PACKAGE_DESCRIPTION_SUMMARY "Description" )
set( CPACK_GENERATOR DEB )
set( CPACK_DEB_COMPONENT_INSTALL ON )
set( CPACK_DEBIAN_PACKAGE_DEPENDS "" )
set( CPACK_DEBIAN_RUNTIME_DEBUGINFO_PACKAGE ON )
include( CPack )
You might be interested in this ticket regarding a bug in CMake regarding debug symbol creation.
I have a cmake project which is a static library that i have to share with other teams in my company but just the .lib file and not the source code.
This library depends on Boost.
Now i build the library and transfer the install folder onto another pc (exe_pc) and use it in a exe project (this exe also depends on boost).
Now at compile time i get a linking error saying that E:/Development/vcpkg/installed/x64-windows/lib/boost_system-vc140-mt.lib cannot be opened.
so i open and check the generated LibTargets.cmake and it contains absolute paths of boost library for pc on which the library was built.
# The installation prefix configured by this project.
set(_IMPORT_PREFIX "C:/Program Files/cpp_licensing")
# Create imported target Licensing::liblicensing
add_library(Licensing::liblicensing STATIC IMPORTED)
set_target_properties(Licensing::liblicensing PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "_LICENSING_DEBUG=0"
INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
INTERFACE_LINK_LIBRARIES "\$<\$<NOT:\$<CONFIG:DEBUG>>:E:/Development/vcpkg/installed/x64-windows/lib/boost_system-vc140-mt.lib>;\$<\$<CONFIG:DEBUG>:E:/Development/vcpkg/installed/x64-windows/debug/lib/boost_system-vc140-mt-gd.lib>;\$<\$<NOT:\$<CONFIG:DEBUG>>:E:/Development/vcpkg/installed/x64-windows/lib/boost_filesystem-vc140-mt.lib>;\$<\$<CONFIG:DEBUG>:E:/Development/vcpkg/installed/x64-windows/debug/lib/boost_filesystem-vc140-mt-gd.lib>;cryptopp-static;wbemuuid"
)
LibLicensingTargets-release.cmake
et_target_properties(Licensing::liblicensing PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX"
IMPORTED_LOCATION_RELEASE "C:/Program Files/cpp_licensing/lib/licensing.lib"
)
list(APPEND _IMPORT_CHECK_TARGETS Licensing::liblicensing )
list(APPEND _IMPORT_CHECK_FILES_FOR_Licensing::liblicensing "C:/Program Files/cpp_licensing/lib/licensing.lib" )
The user is supposed to have boost installed, the only problem i have is that because absolute paths are used in targets file user has to manually change them on his pc in the targets file.
what changes do i make to cmake so that the libraries built folder can be shared. How do i distribute a library built using cmake ??
Here is the cmake for the library project
cmake_minimum_required(VERSION 3.10)
project(liblicensing)
message("~~ Project: " ${PROJECT_NAME})
set(LIB_NAME "${PROJECT_NAME}")
set(PROJECT_VERSION 1.0)
include_directories(
${PROJECT_SOURCE_DIR}/include
)
if (WIN32)
find_package(Boost REQUIRED system filesystem)
find_package(cryptopp REQUIRED)
find_package(unofficial-date REQUIRED)
include_directories(
${Boost_INCLUDE_DIR}
)
else()
find_package(date REQUIRED)
endif ()
file(GLOB_RECURSE HEADER_FILES include/*.h include/*.hpp)
file(GLOB_RECURSE SOURCES src/*.cpp)
add_library(${LIB_NAME} STATIC ${SOURCES} ${HEADER_FILES} )
set_target_properties(
${LIB_NAME}
PROPERTIES
OUTPUT_NAME "licensing"
POSITION_INDEPENDENT_CODE ON
CXX_STANDARD 14
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO
LINKER_LANGUAGE CXX
)
if (MSVC)
set_target_properties(${LIB_NAME} PROPERTIES DEBUG_POSTFIX "_d")
endif()
add_library(Licensing::liblicensing ALIAS ${LIB_NAME})
set(INSTALLATION_DIR "${CMAKE_INSTALL_PREFIX}")
set(CMAKE_INSTALL_LIBDIR "${INSTALLATION_DIR}/lib")
set(CMAKE_INSTALL_BINDIR "${INSTALLATION_DIR}/bin")
set(CMAKE_INSTALL_INCLUDEDIR "include")
set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/${LIB_NAME})
target_include_directories(${LIB_NAME}
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
if (WIN32)
target_link_libraries(
${LIB_NAME}
${Boost_LIBRARIES}
cryptopp-static
wbemuuid
)
else()
target_link_libraries(
${LIB_NAME}
cryptopp
boost_system
boost_filesystem
)
endif ()
if(CMAKE_BUILD_TYPE MATCHES Debug)
target_compile_definitions(${LIB_NAME} PUBLIC _LICENSING_DEBUG=1)
elseif(CMAKE_BUILD_TYPE MATCHES Release)
target_compile_definitions(${LIB_NAME} PUBLIC _LICENSING_DEBUG=0)
endif()
# Expose Projects's public includes to other subprojects through cache variable.
set(${PROJECT_NAME}_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/include CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE)
###############
# Installation
##
install(TARGETS ${LIB_NAME}
EXPORT LibLicensingTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
# INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${LIB_NAME}
FILES_MATCHING PATTERN "*.h*")
install(EXPORT LibLicensingTargets
FILE LibLicensingTargets.cmake
NAMESPACE Licensing::
DESTINATION ${INSTALL_CONFIGDIR}
)
#####################
# ConfigVersion file
##
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/LibLicensingConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY AnyNewerVersion
)
configure_package_config_file(
${CMAKE_CURRENT_LIST_DIR}/CMake/LibLicensingConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/LibLicensingConfig.cmake
INSTALL_DESTINATION ${INSTALL_CONFIGDIR}
)
## Install all the helper files
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/LibLicensingConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/LibLicensingConfigVersion.cmake
DESTINATION ${INSTALL_CONFIGDIR}
)
Not an entire answer but too much for a comment:
If you inspect your file LibLicensingTargets.cmake closely, you see that cryptopp-static and wbemuuid are not resolved down to the library level.
Looking at how you reference Boost you use the oldstyle version (${Boost_LIBRARIES}) that resolves down to the library level.
Try instead to use the targets provided by FindBoost.cmake module as follows:
if (WIN32)
target_link_libraries(
${LIB_NAME}
Boost::system
Boost::filesystem
cryptopp-static
wbemuuid
)
else()
target_link_libraries(
${LIB_NAME}
cryptopp
Boost::system
Boost::filesystem
)
endif()
Another thing that puzzles me is why you added the ALIAS:
add_library(Licensing::liblicensing ALIAS ${LIB_NAME})
This ALIAS is properly created in the LibLicensingTargets.cmake file, so you do not need to create it on your own.
Another thing is, that you are giving your INSTALL command absolute paths. To make the package entirely relocatable you need to use relative paths (relative to the CMAKE_INSTALL_PREFIX, the installation directory).
The following commands should therefore be changed to:
set(CMAKE_INSTALL_LIBDIR "lib")
set(CMAKE_INSTALL_BINDIR "bin")
set(CMAKE_INSTALL_INCLUDEDIR "include")
set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/${LIB_NAME})
If you further add the line:
export(TARGETS liblicensing NAMESPACE LibLicensing:: FILE LibLicensingTargets.cmake)
to your CMakeLists.txt, outside projects are able to import target from your build tree folder as of liblicensing was installed therein. See the CMake documentation of the export command.
I have a C++ project with this structure:
-- ProjectFolder
-- Project_Prototype1
-- Project_Prototype2
Project_Prototype1 has a CMakeLists file with this content:
cmake_minimum_required(VERSION 2.8)
project( Neuromarketing-RF )
find_package( Boost 1.58.0 REQUIRED COMPONENTS filesystem system )
include_directories( ${Boost_INCLUDE_DIRS} include src/external )
find_package( OpenCV 3 REQUIRED )
file(GLOB FACETRACKER_HEADERS "external/FaceTracker/include/FaceTracker/*.h")
file(GLOB FACETRACKER_SRC "external/FaceTracker/src/lib/*.cc")
file(GLOB SOURCES "src/*cpp")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin/")
add_executable( Neuromarketing-RF ${FACETRACKER_SRC} ${SOURCES} )
target_link_libraries( Neuromarketing-RF ${OpenCV_LIBS} ${Boost_LIBRARIES} )
target_compile_features( Neuromarketing-RF PRIVATE cxx_range_for )
Prototype1 is using an external library called FaceTracker .
In the Prototype2 I wanna access a file from Prototype1 but I don't want to redefine all dependencies from Prototype1 on Prototype2 CMakeLists (FaceTracker, Boost, etc...).
How can I write the Prototype2 CMakeLists to use Prototype1 without redefining everything manually?
Here is my current CMakeLists.txt for Prototype2:
cmake_minimum_required (VERSION 2.6)
project (Neuromarketing-CNN)
find_package(OpenCV REQUIRED)
find_package(Boost 1.58.0 REQUIRED COMPONENTS filesystem system)
add_subdirectory("../Neuromarketing-RF" "../Neuromarketing-RF/bin" )
file ( GLOB NM_RF_SRC "../Neuromarketing-RF/src/*.cpp" )
include_directories(include ../Neuromarketing-RF/include ${Boost_INCLUDE_DIRS} )
file(GLOB SOURCES "src/*.cpp")
add_executable (bin/Neuromarketing-CNN ${SOURCES} ${NM_RF_SRC} )
target_link_libraries(bin/Neuromarketing-CNN ${OpenCV_LIBS} ${Boost_LIBRARIES} )
target_compile_features( bin/Neuromarketing-CNN PRIVATE cxx_range_for )
The easiest way would be to create a file containing all the dependencies common to both CMakeList.txt files and use include(). For instance have a file names ProjectFolder/my-includes.cmake that contains the relevant find_package() statements, and in both CMakeList.txt files add a line
include ("../my-includes.cmake")
Everything defined in the included file is available to the including file.
Been looking around all day for a solution but no joy.
I have a CMake solution with 2 projects. The one is a static library which links to boost, and the other is an executable which links to boost and my own static library.
Problem is: In Linux it compiles fine with gcc. But in VS2008 I get the following type of linker errors for program_options only.
libboost_program_options-vc90-mt-gd-1_46_1.lib(options_description.obj) : error LNK2005: "public: class boost::program_options::options_description_easy_init & __thiscall boost::program_options::options_description_easy_init::operator()(char const *,char const *)" (??Roptions_description_easy_init#program_options#boost##QAEAAV012#PBD0#Z) already defined in boost_program_options-vc90-mt-gd-1_46_1.lib(boost_program_options-vc90-mt-gd-1_46_1.dll)
Looks like it's linking to both the static lib and the dll lib...but why?
So I have a solution directory with a CMakeFile like this:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT( BBlockTools )
SET( TopDir ${CMAKE_CURRENT_SOURCE_DIR} )
ADD_SUBDIRECTORY( Utilities )
ADD_SUBDIRECTORY( BBlockFixer )
And then the two project directories. Utilities is a static library and is created by following CMakeFile:
PROJECT( Utilities )
SET(Boost_USE_STATIC_LIBS ON)
FIND_PACKAGE(Boost COMPONENTS system program_options REQUIRED)
LINK_DIRECTORIES ( ${Boost_LIBRARY_DIRS} )
INCLUDE_DIRECTORIES ( ${Boost_INCLUDE_DIRS} )
SET( src_h Utilities.h )
SET( src_cpp Utilities.cpp )
ADD_LIBRARY( Utilities STATIC ${src_h} ${src_cpp} )
TARGET_LINK_LIBRARIES( Utilities
${Boost_SYSTEM_LIBRARY}
${Boost_PROGRAM_OPTIONS_LIBRARY}
${Boost_LIBRARIES}
)
And the second project created by this CMakeFile:
PROJECT( BBlockFixer )
SET(Boost_USE_STATIC_LIBS ON)
FIND_PACKAGE(Boost COMPONENTS system filesystem program_options REQUIRED)
LINK_DIRECTORIES ( ${BBlockTools_BINARY_DIR}/Utilities/Debug ${Boost_LIBRARY_DIRS} )
INCLUDE_DIRECTORIES ( ${TopDir} ${Boost_INCLUDE_DIRS} )
SET( src_cpp fixerMain.cpp )
ADD_EXECUTABLE( BBlockFixer ${src_cpp} )
TARGET_LINK_LIBRARIES( BBlockFixer
Utilities
${Boost_FILESYSTEM_LIBRARY}
${Boost_PROGRAM_OPTIONS_LIBRARY}
${Boost_SYSTEM_LIBRARY}
${Boost_LIBRARIES}
)
I'm new to CMake so I might be doing something very bad but I really can't find out what's going on. I started playing around with the VS Project(Fixer) like removing the link input to program_options which fixes the problem(until I run cmake again). But I think that isn't the solution since from how it looks it's linking both to the dll lib and to the static lib for some reason...
I tried removing ${Boost_PROGRAM_OPTIONS_LIBRARY} from BBlockFixer from TARGET_LINK_LIBRARIES and program_options from FIND_PACKAGE but doesnt help.
From what I understand in CMake my BBlockFixer inherits the links to program_options from my static lib which should be all fine. But where did this boost_program_options-vc90-mt-gd-1_46_1.lib(boost_program_options-vc90-mt-gd-1_46_1.dll) get linked into my project?
Any help would be appreciated because I'm becoming desperate. It can't really be that hard...
PS. this TopDir I set is so that I can include the .h file from the Utilities. But I'm sure there must be a cleaner way to do it or?
My guess is that you are still auto-linking: On MSVC, boost uses some pragma's to automically instruct the compiler to link to the necessary libraries and there is then no need to specify all the link-targets manually to the linker. Of course, this bites with the dependency-resolution of CMake and you specifying target_link_libraries manually.
Take a look at my answer to a similar question where I suggested the following extra definition to disable auto-linking:
add_definition( -DBOOST_ALL_NO_LIB )
You may need to add the following when linking dynamically and depending on the Boost version and the components:
add_definitions( -DBOOST_ALL_DYN_LINK )
Note also that you specify the Boost components you want in the find_package() call and then specify them again manually in your target_link_libraries() call. Depending a bit on your need, you could also replace this with
target_link_libraries( ${Boost_LIBRARIES} )