I created a versioned MacOS framework with CMake and stumbled over the question where to install the package config files sample-config.cmake, sample-config-version.cmake, sample-exports.cmake, sample-exports-release.cmake.
The framework is versioned so the structure is roughly as follows:
<sample.framework>
|-- Headers # link to Versions/Current/Headers
|-- Resources # link to Versions/Current/Resources
+-- Versions
|-- Current # link to B
+-- B
|-- Headers
+-- Resources
|-- CMake
+-- Info.plist
I use CMakes CMakePackageConfigHelpers macros to generate a package config file from a template sample-config.cmake.in with the content
#PACKAGE_INIT#
include("${CMAKE_CURRENT_LIST_DIR}/sample-export.cmake")
CMake does not mention versioned frameworks and recommends to install the files into the directory Resources/CMake.
I did so by calling
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sample-config.cmake"
DESTINATION sample.framework/Resources/CMake
COMPONENT development
)
The generated file looks like this:
####### Expanded from #PACKAGE_INIT# by configure_package_config_file() #######
####### Any changes to this file will be overwritten by the next CMake run ####
####### The input file was sample-config.cmake.in ########
get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)
macro(set_and_check _var _file)
set(${_var} "${_file}")
if(NOT EXISTS "${_file}")
message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !")
endif()
endmacro()
macro(check_required_components _NAME)
foreach(comp ${${_NAME}_FIND_COMPONENTS})
if(NOT ${_NAME}_${comp}_FOUND)
if(${_NAME}_FIND_REQUIRED_${comp})
set(${_NAME}_FOUND FALSE)
endif()
endif()
endforeach()
endmacro()
include("${CMAKE_CURRENT_LIST_DIR}/sample-export.cmake")
Error:
There's a difference in the generated config file whether I install those files to Resources/CMake or to Versions/B/Resources/CMake although both point to the same directory.
When installing via the Resources link to Resources/CMake the call to set PACKAGE_PREFIX_DIR is generated as
`get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)`
but when installing via Versions/B/Resources/CMake it is generated as
`get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../../../" ABSOLUTE)`
As a consequence of this the package cannot be found by find_package(sample CONFIG) when installing to Versions/B/Resources/CMake.
Did anybody was facing this error before?
Thanks for any input on this.
Related
I would like to share an ExternalProject between different CMake projects. Imagine a structure like the following:
prj1
|- CMakeLists.txt
|- ...
prj2
|- CMakeLists.txt
|- ...
lib
|- ext
|- gtest
|- CMakeLists.txt
|- googletest
|_ actual_google_test_files
What I'm trying to obtain is telling CMakeLists.txt to use the gtest in lib/ext/gtest with ExternalProject, without re-building gtest everytime in place for each project.
Ideally, gtest gets built once in its folder and projects just use it. I tried using ExternalProject like explained here (http://kaizou.org/2014/11/gtest-cmake/) and including lib/ext/gtest/CMakeLists.txt in the projects, but gtest gets re-compiled for every user.
tldr: You should try to integrate google_test as "subproject" not as prebuilt and use a "meta" CMakeLists.txt...
Please read https://crascit.com/2015/07/25/cmake-gtest/
CMakeLists.txt.in:
cmake_minimum_required(VERSION 2.8.2)
project(googletest-download NONE)
include(ExternalProject)
ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG master
SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src"
BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)
CMakeLists.txt:
# Download and unpack googletest at configure time
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/googletest-download" )
execute_process(COMMAND "${CMAKE_COMMAND}" --build .
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/googletest-download" )
# Prevent GoogleTest from overriding our compiler/linker options
# when building with Visual Studio
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
# Add googletest directly to our build. This adds
# the following targets: gtest, gtest_main, gmock
# and gmock_main
add_subdirectory("${CMAKE_BINARY_DIR}/googletest-src"
"${CMAKE_BINARY_DIR}/googletest-build")
add_subdirectory(prj1)
add_subdirectory(prj2)
I have divided my program in 3 folders: build, include, and src.
Build is where I want all the files created from the Makefile to go, include contains a "file.h", and src contains a "file.c" and "main.c".
I have written this in the CMakeLists.txt file:
cmake_minimum_required (VERSION 3.5.1)
project(Listas_interlazadas)
include_directories(${include})
add_executable(ejec
src/main.c
src/listas.c
include/listas.h
)
Nonetheless, I believe I should somehow include the src folder. Also, how do I send all files to the build folder? From the terminal, right?
Thanks.
Your code need some minor reworks.
The command include_directories must point to an valid path
Add header files only in case they are not included in any of your source files
Assume the following structure of your project:
project
+--source
| +--CMakeLists.txt
| +--src
| | +--main.c
| | +--listas.c
| +--include
| +--listas.h
+--build
Reworked CMakeLists.txt
cmake_minimum_required (VERSION 3.5.1)
project(Listas_interlazadas)
include_directories(include)
add_executable(ejec
src/main.c
src/listas.c
)
Back to your questions:
Add the sources: You already inserted the required source files. See add_executable.
Copy sources to build folder: This is not necessary.
To build your project, you have to run cmake and make (or nmake on windows).
Steps:
Open a command shell
Move to the build folder
Run: cmake ../source
Run: make
Some important parts of a CMakeLists.txt
I have a library project whose hierarchy looks something like this:
Root:
+ src/
+ apple.cpp
+ bananas/
+ bananas.cpp
...
+ include/
+ apple.h
+ bananas/
+ bananas.h
...
I've been using Visual Studio to compile it and it works fine but now I want to diversify it by allowing the library to be compiled using CMake. I've created the following CMakeLists.txt file (located in Root):
cmake_minimum_required(VERSION 2.8) # Version 2.8 required
file(GLOB_RECURSE HEADERS # Fetch all of the Lib's Headers
${CMAKE_CURRENT_SOURCE_DIR}/include/*.h
${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp
)
file(GLOB_RECURSE SOURCES # Fetch all of the Lib's Srcs
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
)
add_library( # Create the Library from Srcs
HoneycombGameEngine ${SOURCES}
)
target_include_directories( # Add the Headers to the Lib
HoneycombGameEngine
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
It compiles with CMake and generates its files, however when I run make to actually compile the library, I get an error in the bananas.cpp file (first file it chooses to compile) that it cannot find the bananas.h header file. If it is relevant, the bananas.cpp include header statement looks like this:
#include "..\..\include\bananas\bananas.h"
I'm not exactly sure what I'm doing wrong, this my first time using CMake so I mostly wrote my CMakeLists file using bits and examples from the internet. Anything that could point me in the right direction and help me solve this issue is much appreciated.
You are only get all .h inside include directory.
Bananas.h is inside bananas directory. Then you have to use something like it:
file(GLOB_RECURSE HEADERS # Fetch all of the Lib's Headers
${CMAKE_CURRENT_SOURCE_DIR}/include/*.h
${CMAKE_CURRENT_SOURCE_DIR}/include/bananas/*.h
)
This is my CMakeLists.txt:
ADD_SUBDIRECTORY(third)
ADD_SUBDIRECTORY(utils)
ADD_SUBDIRECTORY(rpc)
But the directory 'rpc' will be compiled before directory 'utils', actually the 'rpc' is depends on 'utils', so I will get a link error.
How can I make the 'rpc' compiling after 'utils'?
Thanks.
When you use target_link_libraries() function and pass it other target name, CMake automatically sets this target as a dependency. You can also use add_dependencies() to specify dependencies manually.
Also note that order of sources compilation have nothing to do with your problem. Link errors (i guess, you are seeing "undefined reference" ones) are because you aren't linking your targets properly.
if the 'rpc' is depends on 'utils':
utils CMAKELISTS.txt
project(utils)
add_library (utils SHARED ${PROJECT_SOURCE_LIST})
rpc CMAKELISTS.txt
project(rpc)
add_library (rpc SHARED ${PROJECT_SOURCE_LIST})
# must add this command to scan dependencies of target rpc
add_dependencies (rpc utils)
target_link_libraries (${TEST_SOURCE_FILE_NAME} libutils.so)
I have the same question with you.
I have open source libs —— jthread and jrtplib. I want to build them by a main CmakeList.text so I make a folder like:
cpp
├─jrtplib
│ ├─src
│ └─CMakeFiles.txt
├─jthread
│ ├─src
│ └─CMakeFiles.txt
└─CMakeFiles.txt
and cpp/CMakeFiles.txt like:
cmake_minimum_required (VERSION 3.8)
set(JTHREAD_ENABLED 1)
# 包含子项目。
add_subdirectory ("jthread")
add_subdirectory ("jrtplib")
but build error, it build jrtplib first, I think "jr" > "jt", so build jrtplib first, and it can't find libjthread.so , so target_link_libraries error
I find a solution :
cmake_minimum_required (VERSION 3.8)
# ↓↓↓↓↓↓↓↓ attention ↓↓↓↓↓↓↓↓
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
# ↑↑↑↑↑↑↑↑ attention ↑↑↑↑↑↑↑↑
set(JTHREAD_ENABLED 1)
# copy jthread/src/*.h to C:/thirdParty/include/jthread
set(JTHREAD_INCLUDE_DIRS "C:/thirdParty/include")
set(JTHREAD_LIBRARIES "libjthread.so")
# 包含子项目。
add_subdirectory (jthread)
add_subdirectory (jrtplib)
set xx_OUTPUT_DIRECTORY can set library build in main cmake_build folder, so jrtplib can find libjthread.so .
build success ...
I am assuming that the project named "third" is independent however "utils" depends upon "rpc". Try the following code for a sequential build
ADD_SUBDIRECTORY(third)
ADD_SUBDIRECTORY(utils "${CMAKE_CURRENT_BINARY_DIR}/utils_build")
ADD_SUBDIRECTORY(rpc "${CMAKE_CURRENT_BINARY_DIR}/rpc_build")
this will make a "_build" directory in your given build directory. and will copy the binaries there. For more information try
cmake --help-command ADD_SUBDIRECTORY
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