Add a subproject by CMake - c++

Apache Arrow submodule is stored at thirdparty/apache_arrow/cpp, so my main CMakeLists.txt looks like
cmake_minimum_required(VERSION 3.0.0)
project(arrow_parcer VERSION 0.1.0)
add_subdirectory(src)
add_subdirectory(thirdparty/apache_arrow/cpp)
At the thirdparty/apache_arrow stored whole Apache Arrow project.
When I'm trying to build project, last output lines is follow:
[cmake] CMake Error: INSTALL(EXPORT) given unknown export "arrow_targets"
[cmake] Generating done
[cms-driver] Error during CMake configure: [cmake-server] Failed to compute build system.
Apache Arrow can be easily builded by CMakeLists.txt at /cpp folder, but why there is an error if I trying to include it by add_subdirectory?

Apache Arrow C++ is not meant to be built using add_subdirectory, instead you should use CMake's ExternalProject_Add facility to build it:
ExternalProject_Add(arrow_ep
URL "https://www.apache.org/dist/arrow/arrow-0.15.1/apache-arrow-0.15.1.tar.gz"
SOURCE_SUBDIR cpp)
Instead of using URL you can also use different providers like GIT_REPOSITORY, too.

If you don't really need to setup the installation, here is a hack-y way to do this. In the CMakeLists.txt adding arrow's source dir, you define your own install.
function(install)
endfunction()
add_subdirectory(${arrow_SOURCE_DIR}/cpp ${arrow_BINARY_DIR})

Related

How to have sub_directory use VCPKG in find_package() in CMake?

I'm trying to build PROJ from source. I don't have many of its dynamic dependencies on Centos 7, nor is it possible for me to obtain these dependencies through the system package manager.
In order to skirt these issues, I sought to use VCPKG. However VCPKG is in a lot of turmoil over PROJ and I cannot physically use any version past 7.2.x in VCPKG (I need newer features) and I can't load geo tiffs either (so most non trivial projections will straight up not work). So I can't use VCPKG and PROJ together at all.
However I can still comfortably get the dependencies required to run PROJ through VCPKG.
I tried to convert PROJ source into a subdirectory, however to my suprise it was still trying to use my system libraries despite -DCMAKE_TOOLCHAIN_FILE=... -DVCPKG_TARGET_TRIPLET=x64-linux being set.
I tried using the directory as a standalone library, but with the VCPKG variables set, and... it worked.
So I tried setting cache variables to see if somehow that wasn't propagated downwards, and it didn't work (error message same as below)
set(CMAKE_TOOLCHAIN_FILE "/home/user/Documents/vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE STRING "TEST")
set(VCPKG_TARGET_TRIPLET "x64-linux" CACHE STRING "TEST")
add_subdirectory(external/PROJ)
My project is setup like this:
- CMakeLists.txt
- main.cpp
- external
- PROJ
...
my cmake is like this:
cmake_minimum_required(VERSION 3.13)
project(test)
set(CMAKE_CXX_STANDARD 17)
add_subdirectory(external/PROJ)
add_executable(test main.cpp)
target_link_libraries(test PRIVATE PROJ::proj)
and I keep getting
-- Found Sqlite3: /usr/lib64/libsqlite3.so
-- Sqlite3 version: 3.7.17
CMake Error at external/PROJ/CMakeLists.txt:180 (message):
sqlite3 >= 3.11 required!
when PROJ is a subdirectory
and I get the correct thing:
-- Found Sqlite3: /home/user/Documents/vcpkg/installed/x64-linux/debug/lib/libsqlite3.a
-- Sqlite3 version: 3.36.0
when I don't use it as a sub-directory.
After the first project() call, it is much too late for CMAKE_TOOLCHAIN_FILE to do anything useful. Indeed, it won't even be read if it changes after the first project() call. Vcpkg, Conan, and the like must be used globally or not at all.
You could get away with writing something like this:
cmake_minimum_required(VERSION 3.21) # upgrade!! 3.13 is ancient
# Use vcpkg by default
if (EXISTS "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake")
set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
CACHE STRING "TEST")
set(VCPKG_TARGET_TRIPLET "x64-linux"
CACHE STRING "default vcpkg triplet")
endif ()
project(test)
set(CMAKE_CXX_STANDARD 17
CACHE STRING "C++ standard to use")
if (CMAKE_CXX_STANDARD LESS 17)
message(FATAL_ERROR "Must compile `test` with C++17 or newer")
endif ()
add_subdirectory(external/PROJ)
add_executable(test main.cpp)
target_link_libraries(test PRIVATE PROJ::proj)
It is customary to set the environment variable VCPKG_ROOT to point to your vcpkg installation.
After fiddling around with this answer and wondering why it still wasn't working, I tried making an exact copy of the current MCVE in a different directory. To my surprise, it worked, and even worked with out caching (normal CMake command line variables). When using PROJ as a sub_directory, it actually only exposes PROJ as a target. However, I was trying to use PROJ::proj, a target apparently made by VCPKG to link against their install. Well I had uninstalled that, and wasn't using it as a dependency. Despite that, left over files in a separate build folder apparently were messing with my install, my directory originally looked like this:
- CMakeLists.txt
- main.cpp
- external
- PROJ
- cmake-build-debug
- cmake-build-release
Well, VCPKG stores some meta information about package caches and such in these directories. But with out completely deleting the whole directory I was not able to get it to "forget" about this old install. What's more, it took deleting both directories to get it to "fully" forget about proj.
So I deleted these files, like this:
- CMakeLists.txt
- main.cpp
- external
- PROJ
And reset/reloaded the CMake cache and file, and re-generated those build directories.
After doing this, I no longer had to worry about this extra target.

find_package with specified version in configuration script name

I need to use mangrove (mongo ODM lib over mongo-c-driver and mongo-cxx-driver) and included this into my project as CMake ExternalProject_Add command, with a dependency on mongo-c-driver/mongo-cxx-driver
mongocxx generates CMake configuration scripts with a names like :
libmongocxx-config.cmake
libmongocxx-config-version.cmake
and no issues to find these by mangrove with that script:
set(LIBMONGOCXX_REQUIRED_VERSION 3.1.3)
set(LIBMONGOCXX_REQUIRED_ABI_VERSION v_noabi)
find_package(libmongocxx ${LIBMONGOCXX_REQUIRED_VERSION} REQUIRED)
However mongo-c-driver generates those scripts with a name which incudes ABI version into file names.
libmongoc-1.0-config.cmake
libmongoc-1.0-config-version.cmake
and similar CMake code:
set(LIBMONGOC_REQUIRED_VERSION 1.7.0)
set(LIBMONGOC_REQUIRED_ABI_VERSION 1.0)
find_package(LibMongoC ${LIBMONGOC_REQUIRED_VERSION} REQUIRED)
can't find out the scripts.
Of course, if I manually remove the version from file names, it can find those files, but I'd like to fix the problem in a script and on mangove side.
So the question about CMake techniques :
Is there an ability to specify the version of package which will automatically used by (inside CMake scripts names) find_package command to look for?
According to find_package documentation, the version is embedded inside the libmongocxx-config-version.cmake file.
This means that if you want to get the package libmongoc-1.0-config.cmake, you should use:
find_package(libmongoc-1.0 ${LIBMONGOC_REQUIRED_VERSION} REQUIRED)

How can i fix tbb on CMake

I have this problem.
CMake Error at CMakeLists.txt:14 (find_package): By not providing
"FindTBB.cmake" in CMAKE_MODULE_PATH this project has asked CMake to
find a package configuration file provided by "TBB", but CMake did
not find one.
I could not find a package configuration file provided by "TBB" with any of the following names:
TBBConfig.cmake
tbb-config.cmake
Add the installation prefix of "TBB" to CMAKE_PREFIX_PATH or set
"TBB_DIR" to a directory containing one of the above files. If
"TBB" provides a separate development package or SDK, be sure it has
been installed.
how can i fix this?
Here is my CMakeLists.txt
cmake_minimum_required(VERSION 3.9)
project(deneme)
set(CMAKE_CXX_STANDARD 11)
include("C:/yunus/Git/inteltbb/tbb/cmake/TBBBuild.cmake")
tbb_build(TBB_ROOT "C:/yunus/Git/inteltbb/tbb" CONFIG_DIR TBB_DIR)
find_package(TBB REQUIRED tbb)
add_executable(deneme main.cpp ToDo.cpp ToDo.h)
TBB does not come by default with a FindTBB.cmake module so the guidelines in the error message are a bit misleading.
If your project provides the corresponding FindTBB.cmake module you need to add the path to it and the path to the TBB installation to your CMake call, i.e.
cmake . -G "<your generator here>" -DTBB_DIR=<path to TBB installation> -DCMAKE_PREFIX_PATH=<path to FindTBB.cmake>
Otherwise you need to download a suitable FindTBB.cmake module e.g. https://github.com/schuhschuh/cmake-basis-modules/blob/develop/FindTBB.cmake
This one uses TBB_ROOT instead of TBB_DIR.
Edit:
Try the binary package integration of TBB first.
Comment the include(...) and the tbb_build(...) command and add
target_link_libraries(deneme ${TBB_IMPORTED_TARGETS})
to your CMakeLists.txt after the add_executable call. Then call
cmake . -G "<your generator here>" -DCMAKE_PREFIX_PATH=<path to your TBB installation>

CMake and external dependency

I'd like to add an external dependency to my project. The one I'm trying to add is the Leptonica library as a submodule.
My project has the following directory structure:
|root
CMakeLists.txt
|-bin
|-build
|-buildsystem
|-executable
|-leptonica
|--CMakeLists.txt
|--cmake
|---Configure.cmake
|-production
In my root CMakeLists.txt file I added ADD_SUBDIRECTORY(${ROOT_DIR}/leptonica)
Unfortunately, CMake is not searching for Configure.cmake in the proper directory:
CMake Error at leptonica/CMakeLists.txt:107 (include):
include could not find load file:
Configure
CMake Error: File
<root>/cmake/templates/LeptonicaConfig-version.cmake.in does not exist.
CMake Error at leptonica/CMakeLists.txt:113 (configure_file):
configure_file Problem configuring file
When I build the project by myself, everything goes fine. In my opinion, the problem is with CMAKE_SOURCE_DIR. When using add_subdirectory it has the value of ROOT CMake instead ROOT/leptonica, so it's searching the wrong paths - as you can see in Leptonica CMake, it's used to determinate paths of its files.
What should be the proper way to fix this - should I set CMAKE_SOURCE_DIR to ROOT/leptonica just before calling add_subdirectory and set it back when it's finished, or does some other, more elegant solutions exist?
Not every CMake project is suitable for inclusion via add_subdirectory.
Among those are projects which uses CMAKE_SOURCE_DIR or CMAKE_BINARY_DIR variables.
However, inclusion via ExternalProject_Add (optionally wrapped with execute_process) always works.
Modifying variable CMAKE_SOURCE_DIR (and CMAKE_BINARY_DIR too) is a bad idea: this variable should be changed only by CMake itself. Otherwise you may get weird errors.
Instead, you may replace (automatically, with some script) all references to the variable with another variable, which is not used in the project. This new variable you may safely set before stepping into the subproject.
${CMAKE_SOURCE_DIR} and ${CMAKE_BINARY_DIR} are set relative to the top-level CMakeLists.txt. If you need something relative to your current CMakeLists.txt (leptonica), use ${CMAKE_CURRENT_SOURCE_DIR} and ${CMAKE_CURRENT_BINARY_DIR}.
If you're having trouble finding a cmake file like LeptonicaConfig-version.cmake.in, try appending the appropriate directory to ${CMAKE_MODULE_DIR}.
list(APPEND ${CMAKE_MODULE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates)
I prefer to use ${CMAKE_CURRENT_SOURCE_DIR} over ${CMAKE_SOURCE_DIR} any day because using the latter will break your build if you try to integrate it into a super-build later. If I need to pass my current top-level directory to subdirectories, then I do the following and use that later down the chain.
set( LEPTONICA_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} )

CMake can not determine linker language for target: azurestorage error

I'm very new to C++ programming and having some trouble using CMake to add the azure-storage-cpp repository to my VS solution.
Here is the build error I am getting in VS, when I attempt to build the azure storage project.
CMake can not determine linker language for target: azurestorage
Here is my CMake entry:
ExternalProject_Add( azurestorage
PREFIX azurestorage
GIT_REPOSITORY https://github.com/Azure/azure-storage-cpp.git
GIT_TAG master
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../azurestorage
SOURCE_SUBDIR Microsoft.WindowsAzure.Storage)
I tried adding SET_TARGET_PROPERTIES(azurestorage PROPERTIES LINKER_LANGUAGE CXX) to my CMakeList.txt file but it doesn't help. I've also read on other forums that the repo needs to have a .cpp and .h file in the root directory for CMake to know which language. However since the azure-storage-cpp repo isn't mine, I don't have the ability to add such files.
I'm using VS2015 on Windows10
What am I doing wrong? Any and all help is appreciated.
I've given your example a try and the relevant error message is more to the top of CMake's output:
-- Unsupported Build Platform.
So if you want to add it, don't use ExternalProject_Add(). The library's included CMakeLists.txt is for Unix/Linux/OSX.
But it comes with an existing .vcproj for VS2015 which you can include into your project with include_external_msproject():
find_package(Git REQUIRED)
execute_process(
COMMAND "${GIT_EXECUTABLE}" clone https://github.com/Azure/azure-storage-cpp.git
)
set(NUGET_EXECUTABLE "${CMAKE_CURRENT_BINARY_DIR}/azure-storage-cpp/tools/NuGet.exe")
execute_process(
COMMAND "${NUGET_EXECUTABLE}" restore "azure-storage-cpp/Microsoft.WindowsAzure.Storage.v140.sln"
)
include_external_msproject(
azurestorage
"azure-storage-cpp/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.v140.vcxproj"
)