CMAKE with ROS to create external projects locally? - build

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!

Related

CMake - Alternate option to FetchContent when the source file already exists locally

I tried building the ORTools github package locally using cmake and it builds without any errors. However the environment which we are planning to ultimately use does not have an outbound network connection. The problem I see is that https://github.com/google/or-tools/blob/v9.4/cmake/dependencies/CMakeLists.txt performs a Git Clone to download the dependencies and add them. Since there is no outbound network access this step fails and I'm unable to build the dependency. To circumvent this we are planning to manually download the dependencies and add them to https://github.com/google/or-tools/blob/v9.4/cmake/dependencies/ folder.
I'm pretty new to CMake and I'm not sure what changes have to be made to accommodate this.
For example, what would the following snippet need to be changed to if I cloned Zlib v1.2.11 repository and added it to https://github.com/google/or-tools/blob/v9.4/cmake/dependencies/?
# ##############################################################################
# ZLIB
# ##############################################################################
if(BUILD_ZLIB)
message(CHECK_START "Fetching ZLIB")
list(APPEND CMAKE_MESSAGE_INDENT " ")
FetchContent_Declare(
zlib
GIT_REPOSITORY "https://github.com/madler/ZLIB.git"
GIT_TAG "v1.2.11"
PATCH_COMMAND git apply --ignore-whitespace "${CMAKE_CURRENT_LIST_DIR}/../../patches/ZLIB.patch")
FetchContent_MakeAvailable(zlib)
list(POP_BACK CMAKE_MESSAGE_INDENT)
message(CHECK_PASS "fetched")
endif()
Can FetchContent_Declare be used to point to a directory that already contains the source files? What's the alternative?
You could specify SOURCE_DIR parameter for FetchContent_Declare and omit download options:
FetchContent_Declare(
zlib
SOURCE_DIR <path/to/existing/directory>
PATCH_COMMAND git apply --ignore-whitespace "${CMAKE_CURRENT_LIST_DIR}/../../patches/ZLIB.patch"
)
This works in the same way as in ExternalProject_Add command, which options are accepted by FetchContent_Declare.

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)

Using Cmake to just do ./genMakefiles && make -j4

I'm trying to integrate CMake build on https://github.com/rgaufman/live555
It uses the traditional ./genMakefiles && make -j4 therefore I just need to create a CMakeLists.txt that does this, right?
I know the right way would be to add all the cpp files and build everything but it's not my project and I'm not going to maintain it so the best way for this case would be to just integrate like I'm suggesting
Here's my prototype:
cmake_minimum_required(VERSION 3.9)
project(live555)
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/live555
COMMAND ./genMakefiles linux
COMMENT "=================== Generating makefiles for linux"
COMMAND make -j4
COMMENT "=================== make..."
)
I didn't understand what is OUTPUT for. Isn't OUTPUT dictated by make -j4? Also, I did cmake . && make, see the output:
lz#vm:~/JSCam/src/jscam/live555$ cmake .
-- Configuring done
-- Generating done
-- Build files have been written to: /home/lz/JSCam/src/jscam/live555
lz#vm:~/JSCam/src/jscam/live555$ make
I can't either see the comments I added and files aren't being built.
In CMake, if you need to build some other project which you are "not going to maintain", ExternalProject_Add usually is a good choice:
The ExternalProject_Add function creates a custom target to drive download, update/patch, configure, build, install and test steps of an external project
Its usage is quite simple:
include(ExternalProject) # Include definition of 'ExternalProject_Add' function
ExternalProject_Add(live555 # Name of the target. Could be any
# Setup source directory
SOURCE_DIR <path-to-directory-with-external-project>
# Setup build directory. Here it is the same as source one.
BUILD_IN_SOURCE 1
# Configuration step
CONFIGURE_COMMAND ./genMakefiles linux
# Build step. It is actually `make`, but in a wise manner.
BUILD_COMMAND ${CMAKE_MAKE_COMMAND}
# Disable install step
INSTALL_COMMAND ""
)

cmake: external project update and a work offline

I was using external projects to keep libraries up to date for a long time
something like:
include(AddAsio)
and script AddAsio.cmake like this:
cmake_minimum_required(VERSION 2.8.8)
include(ExternalProject)
find_package(Git REQUIRED)
ExternalProject_Add(
asio
PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/include/ext
GIT_REPOSITORY https://github.com/chriskohlhoff/asio.git
GIT_TAG master
TIMEOUT 10
UPDATE_COMMAND ${GIT_EXECUTABLE} pull
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
LOG_DOWNLOAD ON
)
ExternalProject_Get_Property(asio source_dir)
set(ASIO_INCLUDE_DIR ${source_dir}/asio/include CACHE INTERNAL "Path to include folder for Asio")
include_directories(${INCLUDE_DIRECTORIES} ${ASIO_INCLUDE_DIR})
message("asio source dir" ${ASIO_INCLUDE_DIR})
there was no issue for a long time, however yesterday I've faced with a problem when my internet provider was not working and I tried to work offline.
this script tries to update (git pull, look at external project definition) each time of build, even all required headers do exist there. and breaks build process in case of no connection.
any idea how to keep this mechanism of components update but do not stop a building in case of libraries already exist locally?
AFAIK, there is no easy way to make an external project not to update by examining if certain files exist. However, you could set UPDATE_DISCONNECTED to an external project or set EP_UPDATE_DISCONNECTED property of a directory to disable update of external projects. Along with a build option, the process could be made dynamically. For example, you could build the following project without updating foo and bar by configuring with the command cmake -DBUILD_OFFLINE=ON
cmake_minimum_required (VERSION 2.8.11)
project (myrootproject C)
add_library(hello SHARED hello.c)
option(BUILD_OFFLINE "Build offline" OFF)
if (${BUILD_OFFLINE})
set_property(DIRECTORY ${myrootproject_SOURCE_DIR}
PROPERTY EP_UPDATE_DISCONNECTED 1)
endif()
include(ExternalProject)
ExternalProject_Add(foo
SVN_REPOSITORY svn://foobar.org/
)
ExternalProject_Add(bar
GIT_REPOSITORY https://github.com/blah/blah
)

CMake error with ExternalProject

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.