I have a cmake setup that makes an executable and a shared library I'm using a non-standard install prefix and want to bake the RPATH into the executable. Reading a bunch of previous questions as well as the kitware wiki leads me to this:
Top CMakeLists.txt:
cmake_minimum_required( VERSION 3.14 )
project( cmakeprogram VERSION 1.0 )
add_executable( program program.cxx )
set( CMAKE_RPATH "${CMAKE_INSTALL_PREFIX}/lib" )
set( CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib" )
set( CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE )
add_subdirectory( lib )
target_include_directories( auxlib PUBLIC "${CMAKE_CURRECT_SOURCE_DIR}" )
target_link_libraries( program PUBLIC auxlib )
install( TARGETS program DESTINATION . )
Library:
cmake_minimum_required( VERSION 3.14 )
project( auxlib )
set( CMAKE_RPATH "${CMAKE_INSTALL_PREFIX}/lib" )
set( CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib" )
set( CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE )
add_library( auxlib SHARED
aux.cxx aux.h )
target_include_directories( auxlib PUBLIC "${CMAKE_CURRECT_SOURCE_DIR}" )
install( TARGETS auxlib DESTINATION lib )
Running ldd on the program (SuSe linux if it matters) in the build & isntall location respectively gives:
build
libauxlib.so => /stuff/build-publiclib/lib/libauxlib.so (0x00002ad64984c000)
prefix
libauxlib.so => not found
Yes, I have read https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling but 1. that seems to be about cmake 2.whatever and 2. still doesn't get me the correct solution.
It is not so obvious from the article, but variables CMAKE_INSTALL_RPATH and CMAKE_INSTALL_RPATH_USE_LINK_PATH should be set before creation of the target:
cmake_minimum_required( VERSION 3.14 )
project( cmakeprogram VERSION 1.0 )
# All further targets on installation will have given RPATH.
set( CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib" )
add_executable( program program.cxx )
add_subdirectory( lib )
Funny thing that even documentation of CMAKE_INSTALL_RPATH variable is misleading:
This is used to initialize the target property INSTALL_RPATH for all targets.
But description of the INSTALL_RPATH correctly specifies the situation:
This property is initialized by the value of the variable CMAKE_INSTALL_RPATH if it is set when a target is created.
Actually, in CMake initialization of the most target properties from variables follows the clause bolded above.
Related
I get this error, which I've been trying to understand for some time now but getting nowhere.
add_library cannot create target "Plugin" because another target
with the same name already exists. The existing target is a shared library created
in source directory "D:/CHAI3D/SOFA/src/applications/plugins/plugin".
See documentation for policy CMP0002 for more details.
Below is the CMakelists.txt added for reference. I tried to remove the unnecessary code. So far, I've tried allowing duplicate targets with set(ALLOW_DUPLICATE_CUSTOM_TARGETS TRUE)
But to no avail
cmake_minimum_required(VERSION 3.1)
project(Plugin VERSION 21.06.99)
# Policies
cmake_policy(SET CMP0079 NEW)
set(ALLOW_DUPLICATE_CUSTOM_TARGETS TRUE)
set (PLUGIN_VERSION ${PROJECT_VERSION})
set(HEADER_FILES
src/initPlugin.h
...
)
set(SOURCE_FILES
src/initPlugin.cpp
...
)
file(GLOB_RECURSE RESOURCE_FILES "*.md" "*.psl" "*.py" "*.pyscn" "*.scn" "*.ah")
add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES} ${RESOURCE_FILES} )
target_include_directories(${PROJECT_NAME} PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>")
set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-DSOFA_BUILD_PLUGIN")
target_link_libraries(${PROJECT_NAME} SofaCore SofaConstraint SofaSimpleFem SofaBaseMechanics SofaRigid SofaBaseVisual SofaOpenglVisual)
## Install rules for the library and headers; CMake package configurations files
sofa_create_package_with_targets(
PACKAGE_NAME ${PROJECT_NAME}
PACKAGE_VERSION ${PROJECT_VERSION}
TARGETS ${PROJECT_NAME} AUTO_SET_TARGET_PROPERTIES
INCLUDE_SOURCE_DIR "src"
INCLUDE_INSTALL_DIR ${PROJECT_NAME}
RELOCATABLE "plugins"
)
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY FOLDER "plugins")
I'm building my own library using this CMakeLists.txt :
PROJECT (AstroLib)
cmake_minimum_required(VERSION 3.0)
set(AALib_VERSION_MAJOR 1 CACHE STRING "major version" FORCE)
set(AALib_VERSION_MINOR 95 CACHE STRING "minor version" FORCE)
set(AALib_VERSION ${AALib_VERSION_MAJOR}.${AALib_VERSION_MINOR} CACHE STRING "version" FORCE)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)
include(GenerateExportHeader)
file(GLOB AALib_SRCS "AALIb/source/*.cpp")
file(GLOB AALib_Headers "AALIb/include/*.h" "AALIb/include/*.hpp")
message ("AALib_VERSION ${AALib_VERSION}")
message ("CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}")
message ("CMAKE_CURRENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}")
add_library (AALib STATIC ${AALib_SRCS})
target_include_directories(AALib PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/AALib/include>
$<INSTALL_INTERFACE:include>
PRIVATE AALib/source)
generate_export_header( AALib )
set_property(TARGET AALib PROPERTY VERSION ${AALib_VERSION})
install(TARGETS AALib EXPORT AALibConfig
LIBRARY DESTINATION "lib/${CMAKE_BUILD_TYPE}"
ARCHIVE DESTINATION "lib/${CMAKE_BUILD_TYPE}"
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/AALib_export.h" DESTINATION include COMPONENT Devel)
install(FILES ${AALib_Headers} DESTINATION include)
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/AALib/AALibConfigVersion.cmake"
VERSION ${AALib_VERSION}
COMPATIBILITY AnyNewerVersion
)
export(TARGETS AALib
FILE "${CMAKE_CURRENT_BINARY_DIR}/AALib/AALibConfig.cmake"
NAMESPACE Upstream::
)
install(EXPORT AALibConfig DESTINATION AALib/cmake)
set(FOO "rtatzera")
#configure_file(AALibTargets.cmake "${CMAKE_CURRENT_BINARY_DIR}/AALib/AALibConfig.cmake" COPYONLY)
set(ConfigPackageLocation lib/cmake/AALib)
message ("ConfigPackageLocation ${ConfigPackageLocation}")
install(EXPORT AALibConfig
FILE
AALibConfig.cmake
NAMESPACE
Upstream::
DESTINATION
${ConfigPackageLocation}
)
I run cmake-gui with this cmakelists.txt and I can build and install my library on my computer.
Now I want to use this lib in another project using this cmakelists.txt :
cmake_minimum_required(VERSION 3.0)
PROJECT (DataMeteo)
find_package(OpenCV REQUIRED)
find_package(AALib REQUIRED)
file(GLOB DataMeteo_SRCS
"*.h"
"*.cpp")
ADD_EXECUTABLE (DataMeteo ${DataMeteo_SRCS})
message ( "AALib = ${AAlib}")
if (OpenCV_FOUND AND AALib_FOUND)
target_link_libraries( DataMeteo PUBLIC ${AALIb_} ${OpenCV_LIBS})
else (OpenCV_FOUND AND AALib_FOUND)
message("OPENC not found or AALib NOT FOUND ")
endif (OpenCV_FOUND AND AALib_FOUND)
In VS project I can find all opencv libs and include but I cannot find include and lib of my own Library. There is no error when I run cmake-gui.
Where is error(s) in my code (cmakelists.txt)?
Configuration Windows 10 64 bits VS2017 CMake 3.11.0
I have a number of external dependencies I'd like to pull into my project with ExternalProject_Add. The trick is to export the include directories and resulting statically linked libraries in the cleanest way possible.
Is it possible to make FindBoost dependent on the ExternalProject_Add or at least make the project pull in the libraries and and headers using target_link_libraries?
Boost
include( ExternalProject )
set( boost_URL "http://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.tar.bz2" )
set( boost_SHA1 "9f1dd4fa364a3e3156a77dc17aa562ef06404ff6" )
set( boost_INSTALL ${CMAKE_CURRENT_BINARY_DIR}/third_party/boost )
set( boost_INCLUDE_DIR ${boost_INSTALL}/include )
set( boost_LIB_DIR ${boost_INSTALL}/lib )
ExternalProject_Add( external_boost
PREFIX boost
URL ${boost_URL}
URL_HASH SHA1=${boost_SHA1}
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ./bootstrap.sh
--with-libraries=filesystem
--with-libraries=system
--with-libraries=date_time
--prefix=<INSTALL_DIR>
BUILD_COMMAND
./b2 install link=static variant=release threading=multi runtime-link=static
INSTALL_COMMAND ""
INSTALL_DIR ${boost_INSTALL} )
set( boost_LIBRARY_SUFFIX .a )
add_library( boost::date_time STATIC IMPORTED )
set_property( TARGET boost::date_time PROPERTY IMPORTED_LOCATION ${boost_LIB_DIR}/libboost_date_time${boost_LIBRARY_SUFFIX} )
set_property( TARGET boost::date_time PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${boost_INCLUDE_DIR} )
add_dependencies( boost::date_time external_boost )
add_library( boost::system STATIC IMPORTED )
set_property( TARGET boost::system PROPERTY IMPORTED_LOCATION ${boost_LIB_DIR}/libboost_system${boost_LIBRARY_SUFFIX} )
set_property( TARGET boost::system PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${boost_INCLUDE_DIR} )
add_dependencies( boost::system external_boost )
add_library( boost::filesystem STATIC IMPORTED )
set_property( TARGET boost::filesystem PROPERTY IMPORTED_LOCATION ${boost_LIB_DIR}/libboost_filesystem${boost_LIBRARY_SUFFIX} )
set_property( TARGET boost::filesystem PROPERTY INTERFACE_LINK_LIBRARIES boost::system )
set_property( TARGET boost::filesystem PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${boost_INCLUDE_DIR} )
add_dependencies( boost::filesystem external_boost )
The ExternalProject_Add creates a target that will drive pulling an external project. This means that downloading, building and installing of an external project happens during a build step. As a consequence external project's properties are not known at configure step, so you cannot directly depend (or find_package) on it.
The solution is to use the so called super build. The idea is to use find_package in your project for dependencies as if they were installed on the system. Then you create another CMakeLists.txt which contains ExternalProject_Add instructions for all dependencies and for your project.
When you invoke cmake on super build's CMakeLists.txt it will only setup a build system for downloading and building all the projects but do nothing yet. When you invoke build, the projects are downloaded, configured, built and intstalled one by one. So when it comes to your project all dependencies will be already installed and the configure step will succeed.
Example of super build can be found here (I did not try it, but at least you can get the idea): https://github.com/Sarcasm/cmake-superbuild. Note, that last instruction in cmake/SuperBuild.cmake is ExternalProject_Add for main CMakeLists.txt (aka your project).
See also the CMake documentation at https://cmake.org/cmake/help/v3.10/module/ExternalProject.html for how to define dependencies on an ExternalProject level.
I am using Windows 7 and CMake 3.5 with Cross-Compiling. For compiling I use the IAR 78000 C-Compiler V3.34A/W32 (very old). The include files where added over include_directories() to INCLUDE_DIRECTORIES.
The Compiler needs:
C_INCLUDES = -IC:/foo/bar/
But CMake creats in the flags.make file only:
C_INCLUDES = -IC:/foo/bar (without Backslash at the end)
I tried:
get_directory_property(cmake_include_directories INCLUDE_DIRECTORIES)
set(include_dirs)
foreach(it ${cmake_include_directories})
set(include_dirs ${include_dirs} "${it}/")
endforeach()
set_directory_properties(PROPERTIES INCLUDE_DIRECTORIES "${include_dirs}")
#set_property(TARGET ${PROJECT_NAME}.hex PROPERTY INCLUDE_DIRECTORIES ${include_dirs})
message(STATUS "New Dir: ${include_dirs}")
But the values in include_dir will not override the values in INCLUDE_DIRECTORIES
Is it possible to change my INCLUDE_DIRECTORIES only for the C_INCLUDES, to have the desired format?
Update: The solution for my problem
get_directory_property(cmake_include_directories INCLUDE_DIRECTORIES)
foreach(iterationValue ${cmake_include_directories})
set(iterationValue ${iterationValue}////) # You need //// for one /!
target_include_directories(
${PROJECT_NAME} PRIVATE
${iterationValue}
)
endforeach()
Thank you
Here is my current settings for output :
set( EXECUTABLE_OUTPUT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/bin")
set( LIBRARY_OUTPUT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/bin")
set( RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin")
But for some reason I do not want (MSVS) put out files to bin/Release or Debug folders in my bin folder. Can I realize it using CMake somehow?
thank you
A similar question was asked a few months ago, where I advised the use of target properties and also referred to another answer. For MSVC you can completely specify the locations of executables, libraries, archives, etc. on a per-configuration basis.
E.g. using something like:
if ( MSVC )
set_target_properties( ${targetname} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${youroutputdirectory} )
set_target_properties( ${targetname} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_DEBUG ${youroutputdirectory} )
set_target_properties( ${targetname} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_RELEASE ${youroutputdirectory} )
# etc for the other available configuration types (MinSizeRel, RelWithDebInfo)
endif ( MSVC )
which will put all your libraries in a single output-directory ${youroutputdirectory}, whether it is in Debug or Release config.
use cmake -G 'Ninja' in msvc 2015+