CMake error with ExternalProject - build

Two days ago, I added an External Project to compile a project using autotools. It was perfectly working until today...
I have a weird error:
CMake Error at
/usr/share/cmake-2.8/Modules/ExternalProject.cmake:710 (message): error: no download info
for 'libantlr3c' -- please specify existing SOURCE_DIR or one of URL, CVS_REPOSITORY and CVS_MODULE, SVN_REPOSITORY or DOWNLOAD_COMMAND
And one of these rules is actually specified (SOURCE_DIR):
cmake_minimum_required(VERSION 2.8)
# ...
include(ExternalProject)
ExternalProject_Add(
libantlr3c
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/libantlr3c-3.1.3
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/lib/libantlr3c-3.1.3/configure --prefix=${CMAKE_CURRENT_SOURCE_DIR}/lib/libantlr3c-3.1.3
PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/lib/libantlr3c-3.1.3
BUILD_COMMAND make
BUILD_IN_SOURCE 1
)
So this error hasn't any meaning... And it was perfectly working yesterday (nothing changed until now).
Any idea ?
Thank you!

This is a bug from the 2.8.0 version. Install the version 2.8.3 or superior...

I had a similar issue even with 2.8.6 and the documentation wasn't much help. I found an example online that gave me the hint I needed.
You need to use the URL argument, but there's a catch. If you just give it the path to the direcotry it assumes you're going to point it to an archive, not an directory. You have to prepend your path with "file://", for example:
ExternalProject_Add(
libantlr3c
URL file://${CMAKE_CURRENT_SOURCE_DIR}/lib/libantlr3c-3.1.3
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/libantlr3c-3.1.3
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/lib/libantlr3c-3.1.3/configure --prefix=${CMAKE_CURRENT_SOURCE_DIR}/lib/libantlr3c-3.1.3
PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/lib/libantlr3c-3.1.3
BUILD_COMMAND make
BUILD_IN_SOURCE 1
)
Now I just have to figure out (on my project) why it's looking for <project>-mkdir when it doesn't exist.

Related

How to add a header only library to a project with cmake build system?

I need to modify a C++ project to use Cereal library. The build system of this project is based on CMake. Since Cereal is a header only library and also uses CMake, I expect this to be a pretty simple task. I tried editing the CMakeLists.txt with:
include(ExternalProject)
ExternalProject_Add(cereal
GIT_REPOSITORY git#github.com:USCiLab/cereal.git
CMAKE_ARGS -DJUST_INSTALL_CEREAL=ON -DSKIP_PORTABILITY_TEST=ON -DBUILD_TESTS=OFF
PREFIX ${CMAKE_INSTALL_PREFIX})
but somehow cmake tries to install cereal under /usr/local. I appreciate any help that can point me in the right direction.
The proper way is always to link to the library:
target_link_libraries(your-executable PUBLIC cereal::cereal)
Since this library define a target, you can just use it so the include directories are automatically set to your target.
I am not sure if this is the best thing to do, but the following works. The trick is not to install anything and set include directory correctly.
include(ExternalProject)
ExternalProject_Add(cereal
GIT_REPOSITORY git#github.com:USCiLab/cereal.git
PREFIX cereal
SOURCE_DIR "${CMAKE_BINARY_DIR}/third-party/cereal"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
)
include_directories(
${CMAKE_BINARY_DIR}/third-party/cereal/include)

Is there an easy way of skip download_step if folder exists, in cmake ExternalProject_Add

I need the ExternalProject_Add in CMakeLists.txt to skip download_step for git downloads if there is already a folder with the repo cloned, like the update_step if you provide a GIT_TAG, but don't want to write a custom DOWNLOAD_COMMAND. Basically just need the project to build fully offline if the dependencies where added manually to the folder project.
For example:
ExternalProject_Add(civ
SOURCE_DIR ${PROJECT_SOURCE_DIR}/test
BUILD_COMMAND ${MAKE_EXE}
BINARY_DIR "./bin"
INSTALL_COMMAND ""
GIT_REPOSITORY "https://github.com/test/test"
GIT_TAG "v1.0"
LOG_DOWNLOAD on
CMAKE_ARGS
"-DTuberosumTools_DIR=${TUBEROSUMTOOLS_DIR}"
)
this, deletes test folder and clones it again every time the project is builded for the first time(if i manually delete build folder), i can build after that totally offline, but really need to use it offline always. Already tried to set a cache variable like:
set(FRESH_DOWNLOAD off CACHE BOOL "download a fresh copy of all dependencies")
include(ExternalProject)
ExternalProject_Add(civ
SOURCE_DIR ${PROJECT_SOURCE_DIR}/test
BUILD_COMMAND ${MAKE_EXE}
BINARY_DIR "./bin"
INSTALL_COMMAND ""
GIT_REPOSITORY "https://github.com/test/test"
GIT_TAG "v1.0"
if(NOT FRESH_DOWNLOAD)
DOWNLOAD_COMMAND ""
endif()
CMAKE_ARGS
"-DTuberosumTools_DIR=${TUBEROSUMTOOLS_DIR}"
)
to completly disable download unless indicated, but the if inside the call to ExternalProject_Add(), obviusly does not work, and using the if outside introduces extra code a little harder to mantain, and its ugly.
Any simple alternative is valid, thanks in advance.
When call a function or macro, CMake allows to substitute a variable, which contains several parameters at once. That is, you may conditionally define a variable which is responsible for DOWNLOAD step:
set(FRESH_DOWNLOAD off CACHE BOOL "download a fresh copy of all dependencies")
include(ExternalProject)
if (NOT FRESH_DOWNLOAD)
# Define the variable to disable DOWNLOAD step
set(civ_DOWNLOAD DOWNLOAD_COMMAND "")
else()
# Define an empty variable.
# This actually can be omitted since absent variable is treated as empty.
set(civ_DOWNLOAD)
endif()
ExternalProject_Add(civ
SOURCE_DIR ${PROJECT_SOURCE_DIR}/test
BUILD_COMMAND ${MAKE_EXE}
BINARY_DIR "./bin"
INSTALL_COMMAND ""
GIT_REPOSITORY "https://github.com/test/test"
GIT_TAG "v1.0"
${civ_DOWNLOAD} # IMPORTANT: Do not use double quotes here.
CMAKE_ARGS
"-DTuberosumTools_DIR=${TUBEROSUMTOOLS_DIR}"
)
You can try FetchContent and then ExternalProject with directory downloaded by FetchContent. Something like that:
include(FetchContent)
FetchContent_Declare(
mylib
GIT_REPOSITORY "git#github.com:username/mylib.git"
GIT_TAG <some sha>
)
FetchContent_MakeAvailable(mylib)
include(ExternalProject)
ExternalProject_Add(
mylib
SOURCE_DIR "_deps/mylib-src/"
CONFIGURE_COMMAND ""
INSTALL_COMMAND ""
BUILD_COMMAND "pwd"
)
Update/Patch Step Options:
Whenever CMake is re-run, by default the external project’s sources will be updated if the download method supports updates (e.g. a git repository would be checked if the GIT_TAG does not refer to a specific commit).
UPDATE_DISCONNECTED <bool>
When enabled, this option causes the update step to be skipped. It does not, however, prevent the download step. The update step can still be added as a step target (see ExternalProject_Add_StepTargets()) and called manually. This is useful if you want to allow developers to build the project when disconnected from the network (the network may still be needed for the download step though).
ref: https://cmake.org/cmake/help/latest/module/ExternalProject.html

Semicolon separated list to cmake command in cmake file

I am building amazon's aws-sdk-cpp in my application. So i am extracting the content from aws-sdk-cpp.tar.gz file and running as ExternalProject.
ExternalProject_Add(awssdk
PREFIX DIR
URL ${CMAKE_CURRENT_SOURCE_DIR}/${AWS_SDK_SRC_TAR}
BUILD_COMMAND ${CMAKE_COMMAND} cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_ONLY='dynamodb;kenisis' -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/Ext/Aws/CtcInstall/${CMAKE_INSTALL_PREFIX} -DENABLE_TESTING=OFF ${CMAKE_BINARY_DIR}/source
But, when i pass -DBUILD_ONLY='dynamodb;kenisis'(supported by aws cmake file), Build is failing. If i pass -DBUILD_ONLY=dynamodb only dynamodb related targets are getting generated. But i need kenisis related targets also. How can i pass that semicolon separated list in ExternalProject_Add.
Doing some testing myself - including the hint in #usr1234567's comment - I did run the following successfully (for easier reproduciblility I've put the Git address in the example):
ExternalProject_Add(
awssdk
PREFIX DIR
GIT_REPOSITORY https://github.com/aws/aws-sdk-cpp.git
CMAKE_CACHE_ARGS
-DCMAKE_BUILD_TYPE:String=${CMAKE_BUILD_TYPE}
-DBUILD_ONLY:String=dynamodb\\;kinesis
-DCMAKE_INSTALL_PREFIX:String=${CMAKE_BINARY_DIR}/Ext/Aws/CtcInstall
-DENABLE_TESTING:String=OFF
)
The awkward double backslashes are necessary because the ExternalProject_Add() itself is a CMake script function that goes through several loops of parameter extension.
Alternative
A more generic way would be to use a $<SEMICOLON> generator expression like this:
ExternalProject_Add(
awssdk
PREFIX DIR
GIT_REPOSITORY https://github.com/aws/aws-sdk-cpp.git
CMAKE_ARGS
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DBUILD_ONLY=dynamodb$<SEMICOLON>kinesis
-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/Ext/Aws/CtcInstall
-DENABLE_TESTING=OFF
)
Just for demonstration purposes I'm also using an alternative way of passing the arguments here.

cmake: retrieve library from git before using in a main cmakelists

I'm getting Catch library from github via additional cmakelists.txt which is included into main one:
cmake_minimum_required(VERSION 3.2)
project(MyProject)
add_subdirectory(ext/catch)
include_directories(${CATCH_INCLUDE_DIR} ${CXXOPTS_INCLUDE_DIR} src)
...
Where CmakeLists.txt for Catch is:
cmake_minimum_required(VERSION 2.8.8)
project(catch_builder CXX)
include(ExternalProject)
find_package(Git REQUIRED)
ExternalProject_Add(
catch
PREFIX ${CMAKE_CURRENT_SOURCE_DIR}
GIT_REPOSITORY https://github.com/philsquared/Catch.git
TIMEOUT 10
UPDATE_COMMAND ${GIT_EXECUTABLE} pull
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
LOG_DOWNLOAD ON
)
# Expose required variable (CATCH_INCLUDE_DIR) to parent scope
ExternalProject_Get_Property(catch source_dir)
set(CATCH_INCLUDE_DIR ${source_dir}/include CACHE INTERNAL "Path to include folder for Catch")
message(${CATCH_INCLUDE_DIR})
However, the building of main project is started earlier than Catch will be retrieved from Git.
How to fix this? What is wrong in my cmake script?
I think I had the same problem, what I did is:
Put AddCatch.cmake (The cmakelist of catch) in the CMAKE_MODULE_PATH
e.g.: set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
Remove the line: project(catch_builder CXX)
Replace add_subdirectory(ext/catch) by include(AddCatch)
And it should work just fine ;)
In your case, the download performed by ExternalProject_Add happens at _build_time, not when CMake is run, so the download won't have happened yet when add_subdirectory is called. With just a little bit of work, you can use CMake's ExternalProject_Add command to perform the download of Catch from github at CMake/configure time instead of at build time. This then means it will be present when you call add_subdirectory. There's an article here showing how to do this (it uses GoogleTest as the example and it links through to a fully generalised implementation you should be able to use directly for your situation). The general approach is that it creates a small script which is invoked via CMake's script mode to force the ExternalProject_Add call to happen immediately.

CMAKE with ROS to create external projects locally?

I am working with ROS and wanted to modify the ardrone driver of autonomy lab. Unfortunately I have problems to build external libraries with CMake.
The problem is following:
The compiling original CMakeLists includes an external project:
include(ExternalProject)
ExternalProject_Add(ardronelib
GIT_REPOSITORY git://github.com/AutonomyLab/ardronelib.git
GIT_TAG 2f987029c55531e4c0119c3600f9c57f935851ed
PREFIX ${CATKIN_DEVEL_PREFIX}
CONFIGURE_COMMAND echo "No configure"
BUILD_COMMAND make
INSTALL_COMMAND make install INSTALL_PREFIX=${CATKIN_DEVEL_PREFIX}/lib/
BUILD_IN_SOURCE 1
)
To modify this package, I downloaded it into my sourcefolder:
catkin_ws/src/my_project/
ardronelib/
src/ ...
launch/ ...
...
the ardronelib folder contains the makefile of the downloaded git project.
ardronelib/
ARDroneLib
.git
.travis.yml
LICENSE
Makefile
README.md
Basically I want to have the same libraries installed and linked as in the original version, but from this local folder.
My approach with:
include(ExternalProject)
ExternalProject_Add(ardronelib
SOURCE_DIR=${PROJECT_SOURCE_DIR}/ardronelib
PREFIX ${CATKIN_DEVEL_PREFIX}
CONFIGURE_COMMAND echo "No configure"
BUILD_COMMAND make
INSTALL_COMMAND make install INSTALL_PREFIX=${CATKIN_DEVEL_PREFIX}/lib/
BUILD_IN_SOURCE 1
)
and several other attempts didn't work. Any ideas how to build the project so that later I can use the locally build "ardronelib" within my project?
As the library is quite complex, the direct linking of the source files
would be to costly. Any ideas how I can use the same build structure, but instead of
GIT_REPOSITORY git://github.com/AutonomyLab/ardronelib.git
GIT_TAG 2f987029c55531e4c0119c3600f9c57f935851ed
us the local version:
${PROJECT_SOURCE_DIR}/ardronelib
I would be reaaally happy for any clues.
Thanks a lot in advance!