When I set up an XCode project with CMake using cmake -G "Xcode", and open it in Xcode, the option to run is greyed out, and I can only build the project. Looking around revealed that this is probably because XCode sees it as a library and not an executable. How do I use cmake so that I can run the file after building it?
EDIT: Here's my CMakeLists.txt
# Get the exercise name from the current directory
get_filename_component(exercise ${CMAKE_CURRENT_SOURCE_DIR} NAME)
# Basic CMake project
cmake_minimum_required(VERSION 2.8.11)
# Name the project after the exercise
project(${exercise} CXX)
# Locate Boost libraries: unit_test_framework, date_time and regex
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost 1.55 REQUIRED COMPONENTS unit_test_framework date_time regex)
# gcc/clang won't enable C++11 features without this flag
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(GNU|Clang)")
set(CMAKE_CXX_FLAGS "-std=c++11")
endif()
# Configure to run all the tests?
if(${EXERCISM_RUN_ALL_TESTS})
add_definitions(-DEXERCISM_RUN_ALL_TESTS)
endif()
# Make an executable that runs the exercism unit tests against the implementation
function(exercism)
# Replace -'s with _'s to get a filename from the exercise name
string(REPLACE "-" "_" file ${exercise})
# Implementation could be only a header
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}.cpp)
set(exercise_cpp ${file}.cpp)
else()
set(exercise_cpp "")
endif()
# Build executable from sources and headers
add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h)
# We need boost includes
target_include_directories(${exercise} PRIVATE ${Boost_INCLUDE_DIRS})
# We need boost libraries
target_link_libraries(${exercise} ${Boost_LIBRARIES})
# Run the tests on every build
add_custom_command(TARGET ${exercise} POST_BUILD COMMAND ${exercise})
endfunction()
exercism()
This was included with a set of exercises that ask you to write files that pass the tests thrown at it using Boost. I'm not familiar with cmake but I need the Xcode project that it creates to be runnable.
I have been working on a similar project, and I find that my "Products" in XCode are all red and the "Run" command is greyed out.
If you look at the "Identity and Type" pane for your test executable product, you'll probably find that the path listed is not the actual output path.
I have made this match and the run command be enabled by tinkering with the build settings. The "Build Products Path" for the top-level project seems to determine what path is expected in the "Products" list. The "Build Products Path" for each individual target seems to determine where the product output actually goes. So by manually changing these until the expected and actual output match, you can enable your "Run" command.
There's probably an adjustment to the CMake file that will automate this, but I haven't figured out what it is yet.
Related
I am learning how to use ExternalProject to download header only libaries and link to my executable.
My workflow is following:
I download header library Eigen using ExtenalProject:
cmake -DGET_LIBS=ON -DBUILD_SHARED_LIBS=ON -DBUILD_MY_PROJECTS=OFF -G
"Visual Studio 17 2022" -A x64 .. && cmake --build . --config Release
Then I run the same CMakeLists a second time, but this time I disable ExternalProject and compile the executable that links the Eigen:
cmake -DGET_LIBS=OFF -DBUILD_SHARED_LIBS=OFF -DBUILD_MY_PROJECTS=ON
-G "Visual Studio 17 2022" -A x64 .. && cmake --build . --config Release
Question
Why I need to use both of these commands since in target_include_directories command I specify the same path as in include_directories?
In the code below I need two commands include_directories and target_include_directories.
I thought that it would be enough to use only target_include_directories, but without include_directories it wont work.
if (BUILD_MY_PROJECTS)
add_executable(my_exe main.cpp)
include_directories("${CMAKE_BINARY_DIR}/install/eigen/") #add directory of the header-only library without this the next line wort work
target_include_directories(my_exe INTERFACE "${CMAKE_BINARY_DIR}/install/eigen/")# link exe to exectable
endif ()
My full CMakeLists.txt is following:
project(superbuild LANGUAGES CXX)
cmake_minimum_required(VERSION 3.19)
########################################################################
# EIGEN
########################################################################
SET(GET_LIBS "" CACHE STRING "Set option to download dependencies")
if (GET_LIBS)
message(AUTHOR_WARNING ${GET_LIBS})
ExternalProject_Add(eigen
GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
GIT_TAG 3.4.0
CMAKE_ARGS
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/install/eigen #this does nothing...
SOURCE_DIR "${CMAKE_BINARY_DIR}/install/eigen" #install in my local build dir
#SOURCE_DIR ${CMAKE_INSTALL_PREFIX}
BUILD_COMMAND "" #do not build
INSTALL_COMMAND "" #do not install
)
endif ()
###############################################################################
#EXECUTABLES
###############################################################################
if (BUILD_MY_PROJECTS)
add_executable(my_exe main.cpp)
include_directories("${CMAKE_BINARY_DIR}/install/eigen/") #add directory of the header-only library without this the next line wort work
target_include_directories(my_exe INTERFACE "${CMAKE_BINARY_DIR}/install/eigen/")# link exe to exectable
endif ()
Tl;dr never use include_directories. Ever. Learn how property visibility works in CMake instead.
include_directories("${CMAKE_BINARY_DIR}/install/eigen/") #add directory of the header-only library without this the next line wort work
target_include_directories(my_exe INTERFACE "${CMAKE_BINARY_DIR}/install/eigen/")# link exe to exectable
In the code you supplied, include_directories is implicitly setting the INCLUDE_DIRECTORIES property on your my_exe target. Then the second line sets the INTERFACE_INCLUDE_DIRECTORIES property.
INCLUDE_DIRECTORIES is a list of include directories that must be passed to the compiler when building the target. INTERFACE_INCLUDE_DIRECTORIES is a list of include directories that must be passed to the compiler when building targets that link to this one. This doesn't make much sense for an executable
Slightly better would be to write:
target_include_directories(my_exe PRIVATE "${CMAKE_BINARY_DIR}/install/eigen/")
This will just populate INCLUDE_DIRECTORIES without touching the INTERFACE_ version. If you wanted both you could write PUBLIC instead of PRIVATE or INTERFACE. By definition, PUBLIC is just both of the others.
But this isn't a great dependency management strategy anyway... digging into the source tree guts of a project isn't scalable. It's also difficult to try different versions of Eigen without editing your build files.
I would just write:
cmake_minimum_required(VERSION 3.23)
project(example)
find_package(Eigen3 REQUIRED)
add_executable(my_exe main.cpp)
target_link_libraries(my_exe PRIVATE Eigen3::Eigen)
Use a proper package manager like vcpkg or Conan to handle downloading Eigen when it isn't available on the system.
I have the following simple CMake project. It's basically an executable which links dynamically to Qt Widgets (I'm using Qt just as an example). What I'm trying to figure out is whether it is possible to copy all the linked libraries (not only the ones built by the current project) to the executable output directory using CMake.
cmake_minimum_required(VERSION 3.12)
project(MyProject)
set(CMAKE_CXX_STANDARD 14)
set(QT_CMAKE_DIR "/Users/huser/Qt/5.11.1/clang_64/lib/cmake")
set(CMAKE_PREFIX_PATH ${CMAKE_MODULE_PATH} ${QT_CMAKE_DIR})
find_package(Qt5 REQUIRED COMPONENTS Widgets)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} PUBLIC Qt5::Widgets)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_LIST_DIR}/build)
The issue is that the output directory only contains the MyProject executable (which is the expected behaviour). However, if I were to distribute that executable to someone who doesn't have Qt installed, they would not be able to open it. Hence, I would like to bundle only the necessary libraries/ frameworks with the executable.
Running otool -L MyProject lists the dependencies:
MyProject:
#rpath/QtWidgets.framework/Versions/5/QtWidgets
#rpath/QtGui.framework/Versions/5/QtGui
#rpath/QtCore.framework/Versions/5/QtCore
/usr/lib/libc++.1.dylib
/usr/lib/libSystem.B.dylib
What I'm looking for is a common way through CMake to get these 3 frameworks copied in the output directory right after the build step. That would result in the following directory structure:
build/
MyProject
QtWidgets.framework
QtGui.framework
QtCore.framework
Any help would be greatly appreciated!
There are two aspects to consider:
the build tree
the install tree
The build tree is what you work with as a developer, the install tree is what is "created" after executing the install target or after extracting the content of a package.
To redistribute your Qt5 based project, I suggest you leverage two tools:
CPack: This allow to create generate packages or archives that can be distributed to users. These includes windows installers, .tar,gz, .dmg, ...
macdeployqt: Tools provided by Qt allowing to copy all libraries, plugins, ... required by your application.
Using the BundleUtilities would still require you to explicitly identify and install all Qt plugins. For more complex application, with dependencies other than Qt, is is indeed helpful but for a simple application, I would suggest to use the approach described below.
You will find below a modified version of your example including some suggestions regarding the best practices as well as the integration of CPack and macdeployqt.
After configuring and building project, building the Package target will create a MyProject-0.1.1-Darwin.dmg package.
Note that more would need to be done but that should give a good starting point.
Reading the following may also be helpful: https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/RPATH-handling
To configure the project, consider passing the variable -DQt5_DIR:PATH=/path/to/lib/cmake/Qt5 instead of hardcoding the path.
Assuming the sources or the project are in a directory named src, you would configure the project with:
mkdir build
cd build
cmake -DQt5_DIR:PATH=/Volumes/Dashboards/Support/Qt5.9.1/5.9.1/clang_64/lib/cmake/Qt5 ../src/
src/CMakeLists.txt:
cmake_minimum_required(VERSION 3.12)
project(MyProject)
set(CMAKE_CXX_STANDARD 14)
# Suggestions:
# (1) EXECUTABLE_OUTPUT_PATH is deprecated, consider
# setting the CMAKE_*_OUTPUT_DIRECTORY variables
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build)
set(CMAKE_MACOSX_BUNDLE 1)
set(CMAKE_INSTALL_RPATH "#executable_path/../Frameworks")
# Suggestions:
# (1) Do not hardcode path to Qt installation
# (2) Configure the project specifying -DQt5_DIR
# See https://blog.kitware.com/cmake-finding-qt5-the-right-way/
# (3) By convention, "REQUIRED" is added at the end
find_package(Qt5 COMPONENTS Widgets REQUIRED)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} PUBLIC Qt5::Widgets)
install(TARGETS ${PROJECT_NAME} DESTINATION . COMPONENT Runtime)
# Get reference to deployqt
get_target_property(uic_location Qt5::uic IMPORTED_LOCATION)
get_filename_component( _dir ${uic_location} DIRECTORY)
set(deployqt "${_dir}/macdeployqt")
if(NOT EXISTS ${deployqt})
message(FATAL_ERROR "Failed to locate deployqt executable: [${deployqt}]")
endif()
# Execute deployqt during package creation
# See https://doc.qt.io/qt-5/osx-deployment.html#macdeploy
install(CODE "set(deployqt \"${deployqt}\")" COMPONENT Runtime)
install(CODE [===[
execute_process(COMMAND "${deployqt}" "${CMAKE_INSTALL_PREFIX}/MyProject.app")
]===] COMPONENT Runtime)
set(CPACK_GENERATOR "DragNDrop")
include(CPack)
So I'm using CMake to build a C++ project (on Mac OS) and my project relies on a dylib (I'm using TBB https://www.threadingbuildingblocks.org/ but the specific library itself doesn't matter)
If I do a standard "cmake" and "make" it builds the executable where I want it and when I run my app, the dylib links correctly and everything works perfectly.
The problem comes in when I try to do a "make install" and try to run the resulting executable from the install directory. I get an "image not found" error:
dyld: Library not loaded: #rpath/libtbb.dylib
Referenced from:
/Users/MyName/Desktop/ProjectRoot/install/./MyApp
Reason: image not found
Interestingly, if I do a regular "make" without an install, and then manually copy over the executable to the install directory, then that will link against my dylib properly. I have no idea why that is.
My directory structure is as follows:
Root
CMakeLists.txt
Source/
Libraries/
tbb/
include/
lib/
libtbb.dylib
install/
...and my CMakeLists.txt file is below:
# Start of CMakeLists.txt
cmake_minimum_required(VERSION 3.3)
project (MyApp)
# Set C++ version and output paths
set (CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR})
set(CMAKE_MACOSX_RPATH 1)
set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/install")
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
# Find TBB
find_library (
TBB_LIBRARIES
NAMES tbb libtbb # what to look for
HINTS "${CMAKE_SOURCE_DIR}/Libraries/tbb/lib" # where to look
NO_DEFAULT_PATH # do not search system default paths
)
# Set Custom Include Files + TBB header files
include_directories(Source/Headers Libraries/tbb/include)
# Set Source Files
file(GLOB_RECURSE SRC_FILES "Source/*.cpp")
add_executable(MyApp ${SRC_FILES})
# Link Libraries
target_link_libraries(MyApp ${TBB_LIBRARIES})
# Set compile flags
set_target_properties(MyApp PROPERTIES CXX_STANDARD 14) #LINK_FLAGS "-Wl")
target_compile_features(MyApp PUBLIC cxx_std_14)
# Install executable
install(TARGETS MyApp DESTINATION .)
If I try to also add the following line, and install the dylib as well:
install(TARGETS ${TBB_LIBRARIES} DESTINATION lib)
then when I do a "make install" I get the following error instead:
install TARGETS given target
"/Users/MyName/Desktop/ProjectRoot/Libraries/tbb/lib/libtbb.dylib"
which does not exist in this directory.
So I just can't seem to get this install to work. How do I fix it so that both my executable and my library get installed in the right place and that my executable will be able to link against my library when run?
I have a little Hello, World style program which I'd like to work on more in end-to-end fashion using CMake. In this case it means I could download Boost libraries, compile them and finally compile my little Hello, World and link the Boost libraries to it.
The Directory layout looks like this currently
cmaketest
|- build //I would like to have here the CMake generated IDE files.
|- src
|- main.cpp
|- hello.cpp
|- hello.hpp
|- depends //I would like to have here the built Boost libraries and headers.
|- downloads //This contains the downloaded zip file.
|- temp //Temporary files.
I have the following CMakeLists.txt, and currently I generate the Visual Studio 2015 project files like so: cmake build -G "Visual Studio 14 2015 Win64". All good and well, I'll start the solution, CMake complains it can't find Boost, goes to download it starts to build (in the following code I've set to fetch a file previously acquired). But then after building for a while, the problems emerge...
The Boost files seem to appear in \cmaketest\CMakeFiles\build\Boost-prefix\src\Boost as the root. How could I these so they'd be built to \depends\boost (or to that effect) and how to include the libraries to be linked to the solution? This linking is a separate problem I have, I know how to include the headers from this strange directory, but it's not really what I want.
It looks like the VS IDE gives first warning the Boost headers aren't to be found (see the main program shortly) first and then starts the Boost build. Can this be avoided?
How to make the Boost library disappear from the VS solution? I.e. not to make a project of it, but just a dependency on headers and libraries?
Is there a built-in way to avoid downloading the Boost package if it is already on the disk? It looks like it will be retrieved in any event, and I've thought about checking the existence of the file.
The main.cpp (I suppose this is the relevant file in this case)
//The Boost headers are included just to check the linker.
#include "hello.hpp"
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/posix_time/posix_time_io.hpp>
#include <iostream>
using std::cout;
using std::endl;
int main()
{
hello helloer;
cout << helloer.greet("World here") << endl;
return EXIT_SUCCESS;
}
And then the CMakeLists.txt file.
cmake_minimum_required(VERSION 3.6 FATAL_ERROR)
set(CMAKE_VERBOSE_MAKEFILE ON)
project(Cmaketest)
if(POLICY CMP0042)
cmake_policy(SET CMP0042 NEW)
endif()
if(POLICY CMP0066)
cmake_policy(SET CMP0066 NEW)
endif()
# Default build type if none was specified.
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE)
message(STATUS "Setting build type to '${CMAKE_BUILD_TYPE} as none was specified.")
# Possible values of build type for CMake GUI.
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
# The path to extra modules.
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
# Setup build locations.
if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
endif()
set(CMAKE_CURRENT_BINARY_DIR
${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/build)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
include(ExternalProject)
include(ProcessorCount)
ProcessorCount(N)
if(NOT N EQUAL 0)
set(CMAKE_BUILD_FLAGS -j${N})
endif()
# set(BOOST_VERSION 1.63.0)
# Boost related settings:
# https://cmake.org/cmake/help/v3.6/module/FindBoost.html.
# Should one check the environment variables and flags here explicitly
# to remove the complaint about missing Boost library? Or should perhaps
# BOOST_ROOT be set? Point to what?
find_package(Boost)
if(NOT Boost_FOUND)
# It shouldn't hurt to enable extensive diagnostics, just in case.
# Also, a different set of files is downloaded for UNIX and WIN32
# due to file permissions and line-feeds (Windows should handle
# also Unix style line-feeds).
set(Boost_DETAILED_FAILURE_MSG on)
add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS})
set(Boost_Bootstrap_Command)
if(UNIX)
set(Boost_Url "http://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.tar.gz")
set(Boost_Sha1 "2cecf1848a813de55e5770f324f084c568abca0a")
set(Boost_Bootstrap_Command ./bootstrap.sh)
set(Boost_b2_Command ./b2)
elseif(WIN32)
set(Boost_Url "http://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.zip")
set(Boost_Sha1 "4364989afbe6b11f2d5e59df902c3ca4d7851824")
set(Boost_Bootstrap_Command bootstrap.bat)
set(Boost_b2_Command b2.exe)
endif()
set(Config_Libraries "chrono,filesystem,program_options,system,thread,test")
ExternalProject_Add(Boost
TMP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/temp"
DOWNLOAD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/downloads"
URL "${CMAKE_CURRENT_SOURCE_DIR}/downloads/boost_1_63_0.zip"
URL_HASH "SHA1=${Boost_Sha1}"
BUILD_IN_SOURCE 1
UPDATE_COMMAND ""
PATCH_COMMAND ""
CONFIGURE_COMMAND ${Boost_Bootstrap_Command} --without-icu --with_libraries=${Config_Libraries}
BUILD_COMMAND ${Boost_b2_Command}
# --prefix="${CMAKE_CURRENT_SOURCE_DIR}/depends"
--without-python
--address-model=64
--architecture=x64
--threading=multi
--link=static
--variant=release
--layout=tagged
--build-type=complete
-j${N}
INSTALL_COMMAND ""
# INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/depends"
#As it happens, these directories are currently empty...
# set(BOOST_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/depends/include/boost-1_63)
# set(Boost_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/depends/boost_1_63/include)
# set(Boost_LIBRARY ${CMAKE_CURRENT_SOURCE_DIR}/depends/boost_1_63/lib)
)
endif()
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
include_directories(${CMAKE_SOURCE_DIR}/src)
# Grabbing just all the test project files.
file(GLOB SOURCES "src/*.*")
add_executable(cmaketest ${SOURCES})
# TARGET_LINK_LIBRARIES(cmaketest ${Boost_LIBRARY})
I will attempt to give you some hints, to try to answer your questions.
1) With this snippet you should be able to have sources and built files in the right directories. I kept TMP_DIR "${Cmaketest_SOURCE_DIR}/temp" but in my project I don't use that line.
ExternalProject_Add(Boost
TMP_DIR "${Cmaketest_SOURCE_DIR}/temp"
DOWNLOAD_DIR "${Cmaketest_SOURCE_DIR}/downloads"
URL "${Cmaketest_SOURCE_DIR}/downloads/boost_1_63_0.zip"
URL_HASH "SHA1=${Boost_Sha1}"
SOURCE_DIR ${Cmaketest_SOURCE_DIR}/downloads/boost_1_63_0
BUILD_IN_SOURCE 1
UPDATE_COMMAND ""
PATCH_COMMAND ""
CONFIGURE_COMMAND ${Boost_Bootstrap_Command} --without-icu --with_libraries=${Config_Libraries}
BUILD_COMMAND ${Boost_b2_Command}
--prefix="${Cmaketest_SOURCE_DIR}/depends/boost_1_63_0"
--without-python
--address-model=64
--architecture=x64
--threading=multi
--link=static
--variant=release
--layout=tagged
--build-type=complete
-j${N}
INSTALL_COMMAND ${Boost_b2_Command} --prefix="${Cmaketest_SOURCE_DIR}/depends/boost_1_63_0" --without-python
--address-model=64
--architecture=x64
--threading=multi
--link=static
--variant=release
--layout=tagged
--build-type=complete
-j${N} install
INSTALL_DIR "${Cmaketest_SOURCE_DIR}/depends/boost_1_63_0"
)
set(BOOST_ROOT ${Cmaketest_SOURCE_DIR}/depends/boost_1_63_0)
set(Boost_LIBRARY ${Cmaketest_SOURCE_DIR}/depends/boost_1_63_0/lib)
set(Boost_INCLUDE_DIR ${Cmaketest_SOURCE_DIR}/depends/boost_1_63_0/include)
include_directories(${Boost_INCLUDE_DIR})
To notice that you were not calling "install" so once built in that "strange" directory, the files were not moved to the specified prefix. Notice also the use of ${Cmaketest_SOURCE_DIR} instead of the previous.
Try to print both and see if there's a difference.
2) To address the warning you get in case Boost is not found, you should write:
find_package(Boost QUIET)
3) To address this I guess you could not generate project files, i.e. instead of having
cmake build -G "Visual Studio 14 2015 Win64"
just have cmake . or cmake .. depending whether you will do an in-source or an out-of-source build. I suggest doing out-of-source builds, but that's your choice.
4) FindBoost.cmake (FindBoost.cmake) gives you the possibility to pass an arbitrary path to a Boost directory. You could use that at configuration to hint CMake to look for Boost in the location you give, e.g. you would call cmake in the following way:
cmake -DBOOST_ROOT=/path_to_cmaketest_dir/depends/boost_1_63_0 ..
and if your system might be picky you could specify all things:
cmake -DBOOST_ROOT=/path_to_cmaketest_dir/depends/boost_1_63_0 -DBOOST_LIBRARYDIR=/path_to_cmaketest_dir/depends/boost_1_63_0/lib DBOOST_INCLUDEDIR=/path_to_cmaketest_dir/depends/boost_1_63_0/include ..
Notice that in the last two snippets I assumed configuration of an out-of-source build.
Also notice that if you already installed or have the Boost package downloaded, using ${Cmaketest_SOURCE_DIR} in the snipped of code in 1) should solve also 4) so when it will not find Boost it will try to download but it will not, since now cmake should be able to see the file (.zip).
Please see CMaker_Boost, build the Boost with the CMake at a configure time. Now it is tested on the Linux and Android, gcc and clang. Other systems are not tested. I hope this helps.
I have the following situation: a Project A depends on a Project B, but both are built at the same time. Project A has to include the includes of project B and it needs also to link its libraries. Up to now I've tried this way:
ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/other_project other_project)
and then:
INCLUDE_DIRECTORIES(includ ${CMAKE_SOURCE_DIR}/other_project/include})
LIST(APPEND LINK_LIBS other_project)
in the CMakeLists.txt of Project A
but it doesn't seem to work, the compiler also gives me error when including the headers of Project B saying that they do not exist.
What is the right way to add dependencies in A? How should the CMakeLists.txt look like?
EDIT:
as suggested in the comments, this question was addressed in this, however I'd like to see an example of how to use it in a CMakeList.txt file.
The following is a simple example which builds zlib and then builds libxml2 which depends on the zlib we build. One thing to note, I quickly pulled this example from stuff I've done before. The libxml2 example uses make, thus will only actually build on a system which has it, e.g. Linux, Mac ...
Here is the proposed directory structure for this example ...
src/
-- CMakeLists.txt
CMake/
---- External_ZLib.cmake
---- External_libxml2.cmake
Dowloads/ ( no need to create this directory, CMake will do it for you )
build/ ( Out of source build to prevent littering source tree )
Files:
CMakeLists.txt
# Any version that supports ExternalProject should do
cmake_minimum_required( VERSION 3.1)
project(test_ext_proj)
set(test_ext_proj_CMAKE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/CMake")
set(CMAKE_MODULE_PATH ${test_ext_proj_CMAKE_DIR} ${CMAKE_MODULE_PATH})
set(test_ext_proj_BUILD_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/install)
set(test_ext_proj_DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Downloads CACHE PATH "Directory to store downloaded tarballs.")
include(ExternalProject)
include(External_ZLib)
include(External_libxml2)
External_ZLib.cmake:
set(ZLib_version 1.2.8)
set(ZLib_url "http://zlib.net/zlib-${ZLib_version}.tar.gz")
set(ZLib_md5 "44d667c142d7cda120332623eab69f40")
ExternalProject_Add(ZLib
URL ${ZLib_url}
URL_MD5 ${ZLib_md5}
PREFIX ${vision-tpl_BUILD_PREFIX}
DOWNLOAD_DIR ${test_ext_proj_DOWNLOAD_DIR}
INSTALL_DIR ${test_ext_proj_BUILD_INSTALL_PREFIX}
CMAKE_GENERATOR ${gen}
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX:PATH=${test_ext_proj_BUILD_INSTALL_PREFIX}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}
)
#This variable is required so other packages can find it.
set(ZLIB_ROOT ${test_ext_proj_BUILD_INSTALL_PREFIX} CACHE PATH "" FORCE)
External_libxml2.cmake:
set(libxml2_release "2.9")
set(libxml2_patch_version 0)
set(libxml2_url "ftp://xmlsoft.org/libxml2/libxml2-sources-${libxml2_release}.${libxml2_patch_version}.tar.gz")
set(libxml2_md5 "7da7af8f62e111497d5a2b61d01bd811")
#We need to state that we're dependent on ZLib so build order is correct
set(_XML2_DEPENDS ZLib)
#This build requires make, ensure we have it, or error out.
if(CMAKE_GENERATOR MATCHES ".*Makefiles")
set(MAKE_EXECUTABLE "$(MAKE)")
else()
find_program(MAKE_EXECUTABLE make)
if(NOT MAKE_EXECUTABLE)
message(FATAL_ERROR "Could not find 'make', required to build libxml2.")
endif()
endif()
ExternalProject_Add(libxml2
DEPENDS ${_XML2_DEPENDS}
URL ${libxml2_url}
URL_MD5 ${libxml2_md5}
PREFIX ${test_ext_proj_BUILD_PREFIX}
DOWNLOAD_DIR ${test_ext_proj_DOWNLOAD_DIR}
INSTALL_DIR ${test_ext_proj_BUILD_INSTALL_PREFIX}
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ./configure
--prefix=${test_ext_proj_BUILD_INSTALL_PREFIX}
--with-zlib=${ZLIB_ROOT}
BUILD_COMMAND ${MAKE_EXECUTABLE}
INSTALL_COMMAND ${MAKE_EXECUTABLE} install
)