How to add C++REST SDK as a submodule with CMake? - cmake

I am trying to build a project with numerous dependencies such as Boost, OpenSSL, and C++ REST SDK. However, it is required that the source code is included in the project workspace and that the library is built from said source code.
The most consistently successful way I have found to achieve this is though the use of git submodule add <URL>, add_subdirectory, target_link_libraries, and some clever projects built for this purpose such as boost-cmake and openssl-cmake.
Take for example the following project structure:
prjct
| include/
| libs/
| | boost-cmake/
| | openssl-cmake/
| | cpprestsdk/
| src/
| tests/
| CMakeLists.txt
For which the top-level CMakeLists.txt would contain:
...
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/libs/boost-cmake)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/libs/openssl-cmake)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/libs/cpprestsdk)
target_link_libraries(${PROJECT_NAME_L}
PUBLIC
Boost::system
Boost::thread
Boost::log
Boost::program_options
Boost::chrono
ssl # OpenSSL::SSL
crypto # OpenSSL::Crypto
cpprestsdk::cpprest
)
...
However, in the case of the cpprestsdk library, I recieve the following error upon running cmake .. from build/:
CMake Error at CMakeLists.txt:55 (add_library):
Target "prjct" links to target "cpprestsdk::cpprest" but the target
was not found. Perhaps a find_package() call is missing for and IMPORTED
target, or an ALIAS target is missing?
How can I link and use the C++ REST SDK within these constraints?

Related

How to configure a subdirectory project in CMake in a way that find_package in another one is able to find it?

I am trying to build the netCDF C++ library as a dependency to my project on Windows 10 using MSVC shipped with VS2017 (I think v141 but not sure). Since some of the dependencies I will mention below require CMake > 3.12 I am forced to use CMake that is not shipped with VS2017. The problem is that netCDF C++ requires the netCDF C library (I guess the former is a wrapper for the latter), which in terms depends on the HDF5 library.
All can be found on github as CMake projects:
https://github.com/HDFGroup/hdf5
https://github.com/Unidata/netcdf-c
https://github.com/Unidata/netcdf-cxx4
Currently my project's structure is as follows:
MAIN PROJECT
|
*--- CMakeLists.txt
|
*--- examples (CMake subproject)
| |
| *---CMakeLists.txt
| |
| *--- example1 (CMake subproject, uses my_library)
| |
| *--- example2 (CMake subproject, uses my_library)
|
*--- deps (CMake subproject)
| |
| *--- CMakeLists.txt
| |
| *--- jsoncpp (CMake subproject, git clone)
| |
| *--- ...
| |
| *--- hdf5 (CMake subproject, git clone)
| |
| *--- netcdf-c (CMake subproject, git clone)
| |
| *--- netcdf-cxx4 (CMake subproject, git clone)
|
*--- my_library (CMake subproject, my own library that uses deps)
|
*--- my_binary (CMake subproject, my own executable that uses my_library and deps)
Until I started tinkering with netCDF I didn't have any issues. My deps CMakeLists.txt look like this:
add_subdirectory(sqlite3)
set(JSONCPP_WITH_EXAMPLE OFF CACHE BOOL "Compile JsonCpp example")
set(JSONCPP_WITH_TESTS OFF CACHE BOOL "Compile and (for jsoncpp_check) run JsonCpp test executables")
set(JSONCPP_WITH_POST_BUILD_UNITTEST OFF CACHE BOOL "Automatically run unit-tests as a post build step")
set(BUILD_STATIC_LIBS ON CACHE BOOL "Build jsoncpp_lib as a static library.")
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build jsoncpp_lib as a shared library.")
add_subdirectory(jsoncpp)
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libraries")
set(BUILD_CURL_EXE OFF CACHE BOOL "Build curl EXE")
add_definitions("-DCURL_STATICLIB")
if(WIN32)
set(ENABLE_UNICODE OFF CACHE BOOL "Set to ON to use the Unicode version of the Windows API functions")
endif()
add_subdirectory(curl)
add_subdirectory(hdf5)
add_subdirectory(netcdf-c) # ISSUE with find_package and hdf5
add_subdirectory(netcdf-cxx4)
The netcdf-c subproject has the following lines, which cause a problem for me:
IF(MSVC)
SET(SEARCH_PACKAGE_NAME ${HDF5_PACKAGE_NAME})
FIND_PACKAGE(HDF5 NAMES ${SEARCH_PACKAGE_NAME} COMPONENTS C HL CONFIG REQUIRED ${NC_HDF5_LINK_TYPE})
ELSE(MSVC)
FIND_PACKAGE(HDF5 COMPONENTS C HL REQUIRED)
ENDIF(MSVC)
From what I saw the same applies to netcdf-cxx4 so solving this can hopefully be applied to it too.
I do not want to touch anything inside the respective dependenies' folders (I plan on adding those as git submodules later on). Is there a way to instruct the underlying sub-project (just like a did for e.g. JSON++) where to look without installing anything from the project one level up? Possibly a useful note here is that I also don't have any install() calls.

CMake: add_subdirectory twice as a shared project

I've search the internet all over, but there is no simple answer for the issue.
I've read this: CMake: Attempted to add link library to target which is not built in this directory
But i don't want to put the target_link_libraries into the same cmake list, instead i want to leave the linkage commands inside each respective list because a library cmake list has to know which one library dependency it must be linked with.
Mine project's structure is this:
<main_exe> : /main
| : |
<main_lib> : +- /_3dparty
/ \ : | |
<lib_A> <lib_B> : | +- /lib_A/CMakeLists.txt
\ / : | +- /lib_B/CMakeLists.txt
<lib_X> : | +- /lib_X/CMakeLists.txt
: |
: +- /CMakeLists.txt
All 3 libraries are standalone and static, and i don't want to make them as a subdirectory to each other.
But when i tried to add_subdirectory with external binary directory from lib_A and lib_B respectively:
if (NOT TARGET lib_X)
add_subdirectory(${lib_X_ROOT} ${CMAKE_BUILD_ROOT}/_3dparty/lib_X)
endif()
add_dependencies(${PROJECT_NAME} lib_X)
target_link_libraries(${PROJECT_NAME}
PUBLIC
lib_X
)
, then the cmake throw an error:
Attempt to add link library "lib_X" to target "lib_B" which is not built in
this directory
Is there a way to put it to work w/o excessive ExternalProject_Add usage?
EDIT:
I reproduced the issue on the minimal example.
The library libB actually had slightly different structure:
/main
|
+- /_3dparty
| |
| +- /lib_A/CMakeLists.txt
| +- /lib_B
| | |
| | +- /libsubdir/CMakeLists.txt
| | +- /CMakeLists.txt
| |
| +- /lib_X/CMakeLists.txt
|
+- /CMakeLists.txt
That was the cause of the issue.
/CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(main_project)
set(CMAKE_BUILD_ROOT ${CMAKE_CURRENT_LIST_DIR}/_build)
set(CMAKE_LIBS_ROOT ${CMAKE_CURRENT_LIST_DIR}/_3dparty)
add_library(mainlib ${CMAKE_CURRENT_LIST_DIR}/main.cpp)
add_subdirectory(${CMAKE_LIBS_ROOT}/libA ${CMAKE_BUILD_ROOT}/_3party/libA)
add_subdirectory(${CMAKE_LIBS_ROOT}/libB ${CMAKE_BUILD_ROOT}/_3party/libB)
target_link_libraries(mainlib
PUBLIC
libA
libB
)
/_3dparty/libA/CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(libA_project)
add_library(libA STATIC ${CMAKE_CURRENT_LIST_DIR}/main.cpp)
add_subdirectory(${CMAKE_LIBS_ROOT}/libX ${CMAKE_BUILD_ROOT}/_3party/libX)
target_link_libraries(libA
PUBLIC
libX
)
/_3dparty/libB/CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(libB_project)
#add_library(libB STATIC ${CMAKE_CURRENT_LIST_DIR}/libsubdir/main.cpp)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/libsubdir) # the root cause of the issue
#add_subdirectory(${CMAKE_LIBS_ROOT}/libX ${CMAKE_BUILD_ROOT}/_3party/libX) # would be an error if add this twice
target_link_libraries(libB # <- the issue error is here
PUBLIC
libX
)
/_3dparty/libB/libsubdir/CMakeLists.txt
add_library(libB STATIC main.cpp)
/_3dparty/libX/CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(libX_project)
add_library(libX STATIC ${CMAKE_CURRENT_LIST_DIR}/main.cpp)
Output:
x:\_cmake_test\_out>cmake .. -G "Visual Studio 14 2015"
CMake Error at _3dparty/libB/CMakeLists.txt:11 (target_link_libraries):
Attempt to add link library "libX" to target "libB" which is not built in
this directory.
-- Configuring incomplete, errors occurred!
See also "X:/_cmake_test/_out/CMakeFiles/CMakeOutput.log".
If uncomment the add_library(libB ... and comment add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/libsubdir) then the issue disappears.
Any suggestions how to fix that w/o edit a 3dparty library?
Do not do add_subdirectory() in cmake-projects which are likely to be used as sub-directories itself.
Instead create a super-project which does all the add_subdirectory() at the same level (in the same CMakeLists.txt). The order is not important, CMake resolves the target-dependency (done via target_link_libraries()) once all CMakeLists.txt have been processed.
This is an approach I ended up using in all my projects. It has some disadvantages, for example unit-testing of each library might be difficult, but this is solvable with conditioning the tests with a variable.

CMake : Add subdirectories to custom target and adding custom target to VS solution

Using CMake, I am trying to this:
I need a custom build target (I know, I it can create it with custom_target), but I want it to get added to the visual studio solution. Now when I create a custom target I see the project file in the folder but it is not shown/added in the VS solution, when I open the VS solution in VS IDE.
I need to add subdirectories (which has CMakeLists.txt in them) to the custom target, so that these projects will get added to the custom target and when the custom target is build these projects will get build.
Basically another line of build like ALL_BUILD. When ALL_BUILD is build, only the projects (subdirectories) added to it will get build. When the custom target is build only the projects (subdirectories) added to the custom target will get build.
Is it possible to do something like this?
Thank you so much for your time and help!
--RC
You should be able to do that using add_custom_target and add_dependencies.
Say you have the following directory structure:
root
|--CMakeLists.txt
|--main.cc
|
|--one
| |--CMakeLists.txt
| |--main_one.cc
|
|--two
|--CMakeLists.txt
|--main_two.cc
Assuming you want the subdirectories "one" and "two" as the targets not included in ALL_BUILD, then the following should work:
Top-level CMakeLists.txt:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(test)
add_executable(primary main.cc)
add_subdirectory(one)
add_subdirectory(two)
add_custom_target(SecondaryAllBuild)
add_dependencies(SecondaryAllBuild one two)
CMakeLists.txt in "root/one" (for the CMakeLists.txt in "root/two", swap "one" for "two"):
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(secondary_one)
add_executable(one EXCLUDE_FROM_ALL main_one.cc)

developing an llvm pass with cmake out of llvm source directory

I am trying to develop an llvm pass under my project directory. For that, I follow the info in http://llvm.org/docs/CMake.html#developing-llvm-pass-out-of-source. I create my CMakeFiles appropriately as in this link and my final project directory is like;
|-- src
| |-- CMakeLists.txt
| |-- bigForPass
| | |-- CMakeLists.txt
| | |-- bigForPass.cpp
| | |-- merged.bc
| |-- build
I also linked my source files with llvm root directory without any problem.
Finally I make the build under the 'build' folder and my shared library is created successfully with no problems (under build/bin folder) with the name LLVMHello1.dylib.
However, when I try to run my pass over merged.bc file (which contains my llvm code) with the command
opt -load ../build/bin/LLVMHello1.dylib -bishe_insert <merged.bc> final.bc
I keep getting the error;
Error opening '../build/bin/LLVMHello1.dylib': dlopen(../build/bin/LLVMHello1.dylib, 9): Symbol not found: __ZTIN4llvm10ModulePassE
Referenced from: ../build/bin/LLVMHello1.dylib
Expected in: flat namespace
in ../build/bin/LLVMHello1.dylib
-load request ignored.
Any ideas and suggestions on this appreciated ?
Thanks a lot in advance.
from http://www.jiang925.com/node/28
Undefined Symbol: _ZTIN4llvm12FunctionPassE There is an inconsistency
between LLVM main build system and the cmake support for building
out-of-source. The LLVM binaries are built without runtime type info
"-fno-rtti". Therefore, the out-of-source passes have to be built the
same way otherwise opt will complain that symbol
"_ZTIN4llvm12FunctionPassE" is undefined.
To solve this problem, LLVM must be compile with RTTI enabled. Add
"-DLLVM_REQUIRES_RTTI=1" to cmake, or add "REQUIRES_RTTI=1" to make.
So I added SET(CMAKE_CXX_FLAGS "-Wall -fno-rtti") to CMakeLists.txt of my pass library and then it's working.

Add a dependency not in a subdirectory using CMake

Let's say there's following directory structure:
root
|
+--projects
| |
| +-test
| |
| +-CMakeFiles.txt
|
+--libs
|
+-testlib
|
+-CMakeFiles.txt
test contains CMakeFiles.txt and testlib also contains CMakeFiles.txt. "test" produces an executable and "testlib" produces a static library.
I want "test" to link with "testlib" without using symlinks and without moving "testlib" library into a subdirectory within "test".
Because "testlib" isn't a subdirectory of "test", I can't do
add_subdirectory("../../libs/testlib")
In test's CMakeFiles.txt - CMake will complain about "testlib" not being in the "test" subdirectory.
Also, because system has several different compilers, I can't simply install "testlib" libraries into some kind of central directory, so I want test to compile a local copy of testlib and link with it (i.e. as if testlib was a subdirectory). I also want the "test" project to automatically rebuild "testlib" if it has been changed.
So, how can I deal with it? I am using CMake 2.8.4 on Windows XP SP3.
You could either provide a top-level CMakeLists.txt in root, or provide a binary directory to the add_subdirectory command; e.g.
add_subdirectory("../../libs/testlib" "${CMAKE_CURRENT_BINARY_DIR}/testlib_build")
This creates a subdirectory called testlib_build in your current build directory which contains the generated project files for testlib, but not the source.
For further info, run
cmake --help-command ADD_SUBDIRECTORY
The only way I see to do this - create CMakeLists.txt in root and put the following code there:
add_subdirectory(projects/test)
add_subdirectory(lib/testlib)
When you have done this, you can do target_link_libraries(test testlib) in test/CMakeLists.txt, and it will be automatically rebuilt if you change something in testlib.