I am trying to install and export the target defined by the following CMakeLists.txt in a Windows environment. It uses FetchContent to download a library from github. I can build the library with no problem and generate nfd.lib. My goal is to use this library in my other projects.
cmake_minimum_required(VERSION 3.24)
project(mynfd VERSION 1.0.0)
include(FetchContent)
FetchContent_Declare(nfd
GIT_REPOSITORY https://github.com/btzy/nativefiledialog-extended.git
GIT_TAG c++-version)
FetchContent_MakeAvailable(nfd)
At this point, nfd.lib is successfully built in _deps/nfd-build/src/nfd.lib.
When I add the following install commands to the CMakeLists.txt above, I run into issues.
# Installation
include(GNUInstallDirs)
install(TARGETS nfd
EXPORT ${PROJECT_NAME}Targets
FILE_SET HEADERS
PUBLIC_HEADER DESTINATION ${nfd_SOURCE_DIR}/src/include
)
install(EXPORT ${PROJECT_NAME}Targets
FILE ${PROJECT_NAME}Targets.cmake
NAMESPACE ${PROJECT_NAME}::
DESTINATION lib/cmake/${PROJECT_NAME})
I get the following error messages.
CMake Error in cmake-build-debug-visual-studio/_deps/nfd-src/src/CMakeLists.txt:
Target "nfd" INTERFACE_INCLUDE_DIRECTORIES property contains path:
"C:/Dev/myproject/src/test/cmake-build-debug-visual-studio/_deps/nfd-src/src/include/"
which is prefixed in the build directory.
CMake Error in cmake-build-debug-visual-studio/_deps/nfd-src/src/CMakeLists.txt:
Target "nfd" INTERFACE_INCLUDE_DIRECTORIES property contains path:
"C:/Dev/myproject/src/test/cmake-build-debug-visual-studio/_deps/nfd-src/src/include/"
which is prefixed in the build directory.Target "nfd"
INTERFACE_INCLUDE_DIRECTORIES property contains path:
"C:/Dev/myproject/src/test/cmake-build-debug-visual-studio/_deps/nfd-src/src/include/"
which is prefixed in the source directory.
How can I resolve this problem?
Related
I have been working on a Visual Studio 2019 project with the objective of porting the application to Centos 8. I'm using a CMake project in VS2019 with remote building on my Centos machine. Basically, all the files are transferred to the remote machine and the project is built. My project directory looks as
Child
| CMakeLists.txt
| source
|__public
| headers
| libs
Parent
| CMakeLists.txt
| source
Child generates a shared library (.so) and some public headers which are to be linked in Parent. The so files and public headers are present in the public directory of Child. The CMake files of both the files are as follows
Child/CMakeLists.txt
set(PROJECT_NAME "Child")
set(Header_Files
#set of public headers and source headers
)
set(Source_Files
#set of source files
)
set(ALL_FILES
${Header_Files}
${Source_Files}
)
if (UNIX)
#Target is an SO
add_library(${PROJECT_NAME} SHARED ${ALL_FILES})
set(BOOST_INCLUDEDIR "${CMAKE_HOME_DIRECTORY}/Boost")
set(BOOST_LIBRARYDIR "${CMAKE_HOME_DIRECTORY}/Boost/libs/linux64-clang-9.0.0/static/release")
find_package(Boost REQUIRED)
if (Boost_FOUND)
target_include_directories(${PROJECT_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES})
endif()
set(XercesC_INCLUDE_DIR "${CMAKE_HOME_DIRECTORY}/Xercesc/Linux-Clang-Release/include")
set(XercesC_LIBRARY "${CMAKE_HOME_DIRECTORY}/Xercesc/Linux-Clang-Release/lib64")
find_package(XercesC REQUIRED)
if (XercesC_FOUND)
target_include_directories(${PROJECT_NAME} PRIVATE ${XercesC_INCLUDE_DIR})
target_link_libraries(${PROJECT_NAME} "${CMAKE_HOME_DIRECTORY}/Xercesc/Linux-Clang-Release/lib64/libxerces-c.so")
endif()
endif()
Parent/CMakeLists.txt
set(PROJECT_NAME "Parent")
set(Header_Files
#set of headers
)
set(Source_Files
#set of source files
)
set(ALL_FILES
${Header_Files}
${Source_Files}
)
if (UNIX)
set(CHILD_HEADERS "${CMAKE_HOME_DIRECTORY}/Child/public/headers")
set(CHILD_LIB_DIR "${CMAKE_BINARY_DIR}/Child/libs")
link_directories(${CHILD_LIB_DIR})
add_executable(${PROJECT_NAME} ${ALL_FILES})
target_include_directories(${PROJECT_NAME} PRIVATE ${CHILD_HEADERS})
target_link_libraries(${PROJECT_NAME} PRIVATE Child)
#Copy libChild.so to Parent executable directory
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND
cp "${CHILD_LIB_DIR}/libChild.so"
"${CMAKE_CURRENT_BINARY_DIR}/libChild.so"
)
endif()
Problem
My objective is to have a build for my customer. Hence, I need to package all the executables and libs under a single zip folder. However, upon doing so I find the linker paths to have taken absolute path values of the sort
$ldd Parent
libChild.so => /root/.vs/Project/829a6827-2641-4552-a2fb-abec91ed47a2/out/build/Linux-Clang-Release/Child/libChild.so (0x00007f6934908000)
However, concerning my final build folder will be like this
Parent (executable)
libChild.so
libboost_regex...
libxerces... etc. etc.
I kinda want a relative path link to the same directory
libChild.so => ./libChild.so
Thus, when I export as a zip to another machine, it is unable to find the shared library. I have tried a couple of things (using other CMake functions) as well as copying the library into the executable directory first and then linking. However, it still links it as an absolute path which is likely to cause the same issue again. I have gone through the CMake documentation and perused through cmake-packages and relocatable packages but unable to fix the problem.
The issue can be resolved by placing these two statements in the CMake files for Project Child and Project Parent.
set(CMAKE_INSTALL_RPATH ".")
set(CMAKE_BUILD_WITH_INSTALL_RPATH true)
Details about what these variables mean can be found in the CMake documentation.
Although this resolves the issue at the moment, however, this is not the correct approach for creating builds for a customer, as pointed out here.
I have a project that is supposed to install a static library and all its dependencies. One of these dependencies is boost.
I have something like the following but it doesn't work:
cmake_minimum_required(VERSION 3.9.0)
project(install_test)
find_package(Boost REQUIRED COMPONENTS system)
set(Boost_USE_STATIC_LIBS TRUE)
add_executable(test src/main.cpp)
target_link_libraries(test Boost::boost)
add_dependencies(test Boost::boost)
install(TARGETS test DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(TARGETS Boost::boost DESTINATION ${CMAKE_INSTALL_LIBDIR})
Note: boost can be found, if I remove the latest install statement everything works.
How can do this?
Since the installation is likely to happen to the same machine (on wich your library is to be compiled), and the Boost library is already installed (since it can be found), you should export your library with its dependencies via Config.cmake file. All the dependencies are to be found via find_dependency (I do not think that you want to copy all the boost libraries). It will search for required packages on linking with your installed library.
${PROJECT_NAME}Config.cmake.in file
#PACKAGE_INIT#
include(CMakeFindDependencyMacro)
find_dependency(glad REQUIRED)
find_dependency(glm REQUIRED)
include("${CMAKE_CURRENT_LIST_DIR}/#targets_export_name#.cmake")
check_required_components(gl_traits)
CMakeLists.txt
#... define here sources and public headers
add_library(${PROJECT_NAME}
STATIC
${PUBLIC_HEADERS}
${SOURCES}
)
set_target_properties(${PROJECT_NAME}
PROPERTIES
OUTPUT_NAME ${PROJECT_NAME}
DEBUG_POSTFIX "_d"
)
target_link_libraries(${PROJECT_NAME}
PUBLIC
Boost::boost
)
target_include_directories(${PROJECT_NAME}
PUBLIC
$<INSTALL_INTERFACE:${INSTALL_INCLUDEDIR}/${PROJECT_NAME}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/${PROJECT_NAME}>
PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
)
set(targets_export_name ${PROJECT_NAME}Targets)
set(project_config ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake)
set(version_config ${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake)
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
${version_config}
VERSION
${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)
configure_package_config_file(
${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}Config.cmake.in
${project_config}
INSTALL_DESTINATION
${INSTALL_CMAKEDIR}
)
install(TARGETS
${PROJECT_NAME}
EXPORT
${targets_export_name}
ARCHIVE
DESTINATION ${INSTALL_LIBDIR}
COMPONENT lib
LIBRARY
DESTINATION ${INSTALL_LIBDIR}
COMPONENT lib
RUNTIME
DESTINATION ${INSTALL_BINDIR}
COMPONENT bin
)
install(EXPORT
${targets_export_name}
DESTINATION
${INSTALL_CMAKEDIR}
)
install(FILES ${PUBLIC_HEADERS} DESTINATION ${INSTALL_INCLUDEDIR}/${PROJECT_NAME} COMPONENT dev)
install(FILES
${project_config}
${version_config}
DESTINATION
${INSTALL_CMAKEDIR}
)
If you need to install target's files use $<TARGET_FILE:target_name>
I'm following the ROS-tutorial and I am facing the following behavior after creating my own package:
If try to execute any installed package (e.g. any_package), I get the following error:
[rosrun] Couldn't find executable named <any_package> below /opt/ros/kinetic/share/<any_package>
[rosrun] Found the following, but they're either not files
[rosrun] or not executable:
[rosrun] /opt/ros/kinetic/share/<any_package>
Any help?
EDIT:
If I execute catkin_find --without-underlays --libexec --share <any_package>, it gives me the following output:
Multiple packages found with the same name "my_package":
- my_new_package/my_package
- my_new_package/my_package_2
I assume that you have a tainted workspace.
I assume that you've just copied the my_package to my_package_2 without editing the package.xml file in my_package_2.
It is not really mentioned in the tutorial, since it assumes that you use the proper commands which creates a manifest file with a unique package name.
Just edit the name-tag as follows:
<name>my_package</name>
to
<name>my_package_2</name>
in the corresponding folder.
You have to make sure you edit CmakeLists.txt according to your compile version, c++ executable declaration & Specify libraries to link a library
Below are step step modification and then run catkin_make before running your project:
step 1
add_compile_options(-std=c++11)
step 2
## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
add_executable(${PROJECT_NAME}_node src/myproject_node.cpp)
step 3
## Specify libraries to link a library or executable target against
target_link_libraries(${PROJECT_NAME}_node
${catkin_LIBRARIES}
)
We are building an application on OS X, the build management being implemented in CMake.
In the CMakeLists.txt of the application, the target is added as:
add_executable(${PROJECT_NAME} MACOSX_BUNDLE
${${PROJECT_NAME}_HEADERS}
${${PROJECT_NAME}_SOURCES}
${${PROJECT_NAME}_RESOURCES}
main.mm
)
With ${PROJECT_NAME}_RESOURCES variable listing the xib and image files. We also set the target properties and configure the installation as follows:
set_target_properties(${PROJECT_NAME} PROPERTIES
VERSION "${VERSION}"
SOVERSION "${SOVERSION}"
RESOURCE "${${PROJECT_NAME}_RESOURCES}"
)
install(TARGETS ${PROJECT_NAME}
BUNDLE DESTINATION ${RUNTIME_OUTPUT_DIRECTORY}
)
Quoting the documentation (emphasis mine):
The PRIVATE_HEADER, PUBLIC_HEADER, and RESOURCE arguments cause
subsequent properties to be applied to installing a FRAMEWORK shared
library target’s associated files on non-Apple platforms. Rules
defined by these arguments are ignored on Apple platforms because the
associated files are installed into the appropriate locations inside
the framework folder.
So we would understand that specifing a RESOURCE argument to install() would be ignored in our situation. Yet CMake issues this message (in red):
INSTALL TARGETS - target Xxx has RESOURCE files but no RESOURCE
DESTINATION.
EDIT: Setting a value for RESOURCE DESTINATION in the install() command disables the message. In this case, the resources are still copied in the right place into the application bundle, but they are also copied into the provided value.
Is there at least a way to turn off this message without introducing copies that are useless on OS X ?
I started with the following directory structure:
project
exec
executable.exe
lib
src
include
config
<cmake-generated config file>
I created the library in the lib/src folder by using a CMakefile in the lib/src folder. The exe would compile.
Then, I moved my CMakeFile up to /lib, making sure to change the source file paths to /src/*
Now, when I try to compile, all my libraries compile and link fine, but when I try to link the executable, I get /usr/bin/ld: cannot find -lconfig.
Does anyone have any idea why this happens or how to fix it?
Here is some of my code:
./CMakeLists.txt:
include_directories(config)
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
ADD_SUBDIRECTORY(libs) #library sources
ADD_SUBDIRECTORY(exec) #executable sources
CONFIGURE_FILE(${core_SOURCE_DIR}/config/config.h.in
${core_SOURCE_DIR}/config/config.h)
./libs/CMakeLists.txt:
file(GLOB src ...)
file(GLOB header ...)
add_library(lib ${src} ${header})
./exec/CMakeLists:
add_executable(executable executable.cpp)
link_directories(${core_SOURCE_DIR}/lib) #not sure if this is required
target_link_libraries(executable ${lots_of_libs})
Every library in lots_of_libs can be found as a .a file in the lib directory
One problem, probably not risolutive, is this:
link_directories(${core_SOURCE_DIR}/lib) #not sure if this is required
should be:
link_directories(${PROJECT_BINARY_DIR}/lib)
or:
link_directories(${LIBRARY_OUTPUT_PATH})
Anyway, normally you wouldn't need to add to your link_directories the path to a library that is built within the project, even if you have specified a different LIBRARY_OUTPUT_PATH