put external project into a cPack - cmake

I try to setup a cMake project which create a package containing the output of multiple external projects. So the idea is, that I use this cMake project to create packages for the deployment.
Now the problem is, that when I use the cMakeLists shown bellow, the output of the external project is not included in the package. Just the internal one is in the package.
The install sequence of the external project seems to work, at least the output is in the install directory. It seams, that the package command doesn't see the binaries and for that reason dosn't put them into the zip archive.
Does anyone know, how to put the output of the external project into the package?
By the way: the external project is also cMake based. It contains a install step but no package step.
cmake_minimum_required (VERSION 3.12)
project(PackedBinaries
VERSION 0.0.42
)
set(GLOBAL_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/temp)
include(ExternalProject)
# Builds external projects.
ExternalProject_Add(
myExternalProject
GIT_REPOSITORY "..."
GIT_TAG "master"
UPDATE_COMMAND ""
PATCH_COMMAND ""
SOURCE_DIR "${PROJECT_BINARY_DIR}/repo"
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${GLOBAL_OUTPUT_PATH}
TEST_COMMAND ""
)
# Additional executable
add_executable(myInternalProject hello.c)
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "..." FORCE)
set(CPACK_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "..." FORCE)
endif()
install(TARGETS myInternalProject)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/temp DESTINATION "${CMAKE_BINARY_DIR}/install")
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
set(CPACK_PACKAGE_VERSION_PATCH "0")
set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY ${PROJECT_NAME})
set(CPACK_GENERATOR "ZIP")
# Must be after the last CPACK macros
include(CPack)

Related

Passing variables and their values from one ExternalProject dependency to another using cmake (in the context of zlib and libpng)

I am still at the beginning of my journey regarding ExternalProject. I have two projects used by my main project as dependencies: libpng and zlib. The former depends on the latter.
Inside the official CMakeLists.txt of libpng I see that there is the option PNG_BUILD_ZLIB, which you have to disable if you want to use a custom version of zlib. Currently my two externals look like this:
ExternalProject_Add(zlib
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/deps/zlib
INSTALL_DIR ${CMAKE_INSTALL_PREFIX}
DOWNLOAD_DIR ""
TMP_DIR ${DEPS_TMP}/zlib
STAMP_DIR ${DEPS_STAMP}/zlib
LOG_DIR ${DEPS_LOG}/zlib
BINARY_DIR ${DEPS_BUILD}/zlib
SOURCE_DIR ${DEPS}/zlib
INSTALL_COMMAND "${CMAKE_COMMAND}" -E echo "Skipping install step for dependency zlib"
INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}
BUILD_ALWAYS OFF
)
# Set zlib variables required by libpng
ExternalProject_Get_property(zlib BINARY_DIR)
ExternalProject_Get_property(zlib SOURCE_DIR)
set(zlib_DIR "${BINARY_DIR}/Debug" CACHE PATH "zlib dir" FORCE)
set(ZLIB_ROOT ${SOURCE_DIR} CACHE PATH "zlib root" FORCE) # ${zlib_DIR}
set(ZLIB_INCLUDE_DIRS ${SOURCE_DIR} CACHE PATH "zlib include dir" FORCE)
if(WIN32)
set(ZLIB_LIBRARY ${zlib_DIR}/zlibd.dll CACHE FILEPATH "zlib dynamic library" FORCE)
set(ZLIB_LIBRARIES ${zlib_DIR}/zlibd.dll CACHE FILEPATH "zlib dynamic library" FORCE)
else()
set(ZLIB_LIBRARY ${zlib_DIR}/libzlibd.so CACHE FILEPATH "zlib dynamic library" FORCE)
set(ZLIB_LIBRARIES ${zlib_DIR}/libzlibd.so CACHE FILEPATH "zlib dynamic library" FORCE)
endif()
ExternalProject_Add(libpng
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/deps/png
DEPENDS zlib
INSTALL_DIR ${CMAKE_INSTALL_PREFIX}
DOWNLOAD_DIR ""
TMP_DIR ${DEPS_TMP}/png
STAMP_DIR ${DEPS_STAMP}/png
LOG_DIR ${DEPS_LOG}/png
BINARY_DIR ${DEPS_BUILD}/png
SOURCE_DIR ${DEPS}/libpng
INSTALL_COMMAND "${CMAKE_COMMAND}" -E echo "Skipping install step for dependency libpng"
INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}
BUILD_ALWAYS OFF
CMAKE_ARGS
"-DPNG_BUILD_ZLIB=1" # Use zlib built as a dependency of this project
"-DPNG_SHARED=1"
"-DPNG_STATIC=0"
"-DPNG_TESTS=0"
"-DPNG_EXECUTABLES=0"
"-DPNG_HARDWARE_OPTIMIZATIONS=1"
"-DPNG_DEBUG=0"
)
where
${DEPS} points at a directory where currently every dependency's source code resides and is manually downloaded using git submodules commands
${DEPS_xyz} points at a ExternalProject directory for a specific purpose (logs, stamps, build files, temporary files etc.) and all are placed inside the build directory of the whole project.
The problem I am having is that I am failing at passing the include directory to libpng and this results in the header zlib.h not being found during the build step for that dependency. Apparently
set(ZLIB_INCLUDE_DIRS ${SOURCE_DIR} CACHE PATH "zlib include dir" FORCE)
isn't really passed to the dependency (but in itself it is pointing at the correct path on the filesystem where the header file is included).
Do I have to add the include directory as a CMAKE_ARGS entry or is there some other easier way?
I also checked here but the suggested solution (I just passed the stuff directly into my CMAKE_ARGS)
CMAKE_ARGS
"-DPNG_BUILD_ZLIB=1" # Use zlib built as a dependency of this project
"-DZLIB_INCLUDE_DIRS=\"${${ZLIB_INCLUDE_DIRS}}\"" # Pass the ZLIB_INCLUDE_DIRS to the dependency using the value of the variable set above
"-DPNG_SHARED=1"
"-DPNG_STATIC=0"
"-DPNG_TESTS=0"
"-DPNG_EXECUTABLES=0"
"-DPNG_HARDWARE_OPTIMIZATIONS=1"
"-DPNG_DEBUG=0"
doesn't work.

CMakeLists.txt not in root directory, can't do an automatic build

I have an issue with a repository not having its CMakeLists in the root directory, namely https://github.com/lz4/lz4
The CMakeLists.txt is in the subfolder contrib/cmake_unofficial.
I already checked similar questions on SO (Is it possible to have cmake build file (CMakeLists.txt) not in root in CLion, cmake - CMakeLists.txt is not in root folder (but is included in source)), but they only provide alternatives, and not a solution applicable to my situation.
Heres the cmake module I came up with:
if(ENABLE_LZ4)
message(STATUS "Using LZ4.")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DENABLE_LZ4")
# Enable ExternalProject CMake module
include(ExternalProject)
set(LZ4_SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/lz4)
set(LZ4_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/lib)
# Download and install lz4
ExternalProject_Add(
lz4
GIT_REPOSITORY https://github.com/lz4/lz4.git
GIT_TAG dev
SOURCE_DIR ${LZ4_SOURCE_DIR}
BINARY_DIR ${LZ4_BINARY_DIR}
INSTALL_COMMAND ""
CMAKE_ARGS
${LZ4_SOURCE_DIR}/contrib/cmake_unofficial
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
)
# Get lz4 source and binary directories from CMake project
ExternalProject_Get_Property(lz4 source_dir binary_dir)
# Create a liblz4 target to be used as a dependency by the program
add_library(liblz4 IMPORTED SHARED GLOBAL)
add_dependencies(liblz4 lz4)
include_directories(
${LZ4_SOURCE_DIR}/lib
)
set(LZ4_LIB ${LZ4_BINARY_DIR}/liblz4.so)
else()
message(STATUS "Not using LZ4.")
set(LZ4_LIB "")
endif()
Here the complete error output:
[ 0%] Performing update step for 'lz4'
Current branch dev is up to date.
[ 1%] Performing configure step for 'lz4'
CMake Error: The source directory "/****/build/lz4" does not appear to contain CMakeLists.txt.
Specify --help for usage, or press the help button on the CMake GUI.
CMakeFiles/lz4.dir/build.make:105: recipe for target 'lz4-prefix/src/lz4-stamp/lz4-configure' failed
make[2]: *** [lz4-prefix/src/lz4-stamp/lz4-configure] Error 1
CMakeFiles/Makefile2:72: recipe for target 'CMakeFiles/lz4.dir/all' failed
make[1]: *** [CMakeFiles/lz4.dir/all] Error 2
Makefile:94: recipe for target 'all' failed
make: *** [all] Error 2
I tried adding the path 'contrib/cmake_unofficial' to the CMAKE_ARGS variable (as seen in the module above), but it does not work (seems to be ignored?).
I also tried using PATCH_COMMAND to copy the CMakeLists.txt to the root before the build starts, but the relative paths of the file get messed up.
In other words, i need the cmake command to be called to build the library to be : cmake contrib/cmake_unofficial.
I also tried using CONFIGURE_COMMAND for this, but keep getting a file not found error for some reason (even though the path is correct).
The module has some other issues too, but I'm only interested in the non-root CMakeLists.
Thanks in advance!
ExternalProject separates download and source directories:
DOWNLOAD_DIR - a directory where downloading step is performed
SOURCE_DIR - a directory used as a source one when configuration step is performed
When use git for extract the project, note that git clone is called from the download directory, where it creates new directory with a project sources.
set(LZ4_DOWNLOAD_DIR ${CMAKE_CURRENT_BINARY_DIR}/lz4)
# Set a source dir based on the download one.
set(LZ4_SOURCE_DIR ${LZ4_DOWNLOAD_DIR}/lz4/contrib/cmake_unofficial)
set(LZ4_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/lib)
# Download and install lz4
ExternalProject_Add(
lz4
DOWNLOAD_DIR ${LZ4_DOWNLOAD_DIR} # Set download directory explicitely
GIT_REPOSITORY https://github.com/lz4/lz4.git
GIT_TAG dev
SOURCE_DIR ${LZ4_SOURCE_DIR}
BINARY_DIR ${LZ4_BINARY_DIR}
...
)
Probably not the correct way to do it, but this seems to work for me.
I used the CONFIGURE_COMMAND to call cmake on the correct directory.
Then use BUILD_COMMAND to call make
So essentially, it breaks down to this:
ExternalProject_Add(
lz4
GIT_REPOSITORY https://github.com/lz4/lz4.git
GIT_TAG dev
SOURCE_DIR ${LZ4_SOURCE_DIR}
BINARY_DIR ${LZ4_BINARY_DIR}
CONFIGURE_COMMAND cmake ${LZ4_SOURCE_DIR}/contrib/cmake_unofficial
BUILD_COMMAND make
INSTALL_COMMAND ""
CMAKE_ARGS
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
)

cmake's ExternalProject_Add: how to set source, build and install directories

I want to use ExternalProject_Add function to install cmake enabled projects. I need to control the building and installation processes. More specifically, I want that cmake build and install in specific directories.
There is an option to select a path where to put the source directory: SOURCE_DIR. Is there something equivalent for BUILD_DIR and INSTALL_DIR? I did not see anything alike.
There is a PREFIX option:
Root dir for entire project
What does it mean exactly? An how does cmake's ExternalProject_Add do the installation?
Edit:
This work, but I have no control over source directory and it does not install the library:
ExternalProject_Add(
wjelement-project
GIT_REPOSITORY "https://github.com/netmail-open/wjelement.git"
GIT_TAG "v1.2"
UPDATE_COMMAND ""
PATCH_COMMAND ""
TEST_COMMAND ""
INSTALL_COMMAND ""
#SOURCE_DIR "${MY_SOURCE_ROOT}/wjelement"
BINARY_DIR "${MY_BUILD_DIR}/wjelement"
INSTALL_DIR "${CCT_INSTALL_DIR}/wjelement"
)
If I uncomment SOURCE_DIR, it does not clone from GIT_CLONE but try to get source from SOURCE_DIR (and it fails because that's not what I expected...)
If I comment INSTALL_COMMAND "", then it try to install in C:/Program Files/wjelement, the default (apparently) and not in INSTALL_DIR
default path for source files seem to be ${CMAKE_BINARY_DIR}/wjelement-project-prefix/src
Another Stackoverflow question report problem (or at least non intuitive behavior) with INSTALL_DIR.

CMake External Project not Downloading

I am using CMake 3.5.1 with CLion, and I am attempting to download and install an external project from a URL. My CMakeLists.txt include:
include(ExternalProject)
set(EXTERNAL ${PROJECT_SOURCE_DIR}/external)
ExternalProject_Add(eigen_test
PREFIX ${EXTERNAL}/eigen
DOWNLOAD_DIR ${EXTERNAL}/eigen/download
SOURCE_DIR ${EXTERNAL}/eigen/src
BINARY_DIR ${EXTERNAL}/eigen/build
INSTALL_DIR ${EXTERNAL}/eigen/install
URL http://bitbucket.org/eigen/eigen/get/3.2.4.tar.gz
URL_MD5 4d0d77e06fef87b4fcd2c9b72cc8dc55
CONFIGURE_COMMAND cd <BINARY_DIR> && cmake -D CMAKE_INSTALL_PREFIX=$<INSTALL_DIR> <SOURCE_DIR>
)
When building, this directory structure is is created inside ${PROJECT_SOURCE_DIR}/external/
Although the cmake files exist to download and extract the project, these actions never occur. What am I doing wrong here?
I don't see a reason to pollute your project by downloading and building the library in ${PROJECT_SOURCE_DIR}, I always do that in ${CMAKE_BINARY_DIR}.
The eigen library uses CMakeLists.txt, it will work seamlessly as external project, you don't have to extensively configure each step. So CONFIGURE_COMMAND can be removed and the install prefix set with CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=...
This is the simplified and working configuration:
include(ExternalProject)
set(EXTERNALS_DIR ${CMAKE_BINARY_DIR}/external)
ExternalProject_Add(eigen_test
PREFIX ${EXTERNALS_DIR}
URL http://bitbucket.org/eigen/eigen/get/3.2.4.tar.gz
URL_MD5 4d0d77e06fef87b4fcd2c9b72cc8dc55
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTERNALS_DIR}/installed
)
How to use the library:
Add ${EXTERNALS_DIR}/installed/include to include directories
Build the eigen_test target

cmake external projects command seems to ignore INSTALL_DIR

First off, I'm relatively new to cmake. I'm trying to use cmake to build a project with a single external dependency. I specify the INSTALL_DIR for the external project to be CMAKE_INSTALL_PREFIX, so it installs to the same place as the parent project. But when I run make, it ignores it and tries to install to /usr/local/lib.
Here's my CMakeList.txt:
cmake_minimum_required( VERSION 2.8 )
include( ExternalProject )
project( capture )
add_library( capture SHARED capture.cc )
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" )
ExternalProject_Add( proj_exceptions
GIT_REPOSITORY /home/user/workspace/exceptions
INSTALL_DIR ${CMAKE_INSTALL_PREFIX}
)
add_library( exceptions SHARED IMPORTED )
set_property( TARGET exceptions
PROPERTY IMPORTED_LOCATION ${CMAKE_INSTALL_PREFIX}/lib/libexceptions.so
)
add_dependencies( exceptions proj_exceptions )
include_directories( ${CMAKE_INSTALL_PREFIX}/include )
target_link_libraries( capture exceptions )
install( TARGETS capture DESTINATION lib )
install( FILES capture.h DESTINATION include )
CMakeLists.txt for the external project looks like this:
cmake_minimum_required( VERSION 2.8 )
project( exceptions )
add_library( exceptions SHARED exceptions.cc )
install( TARGETS exceptions DESTINATION lib )
install( FILES exceptions.hh DESTINATION include )
It clones and builds the external project just fine, but it chokes on the install step:
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/lib/libexceptions.so
CMake Error at cmake_install.cmake:42 (file):
file INSTALL cannot copy file
"/home/user/workspace/capture/build/proj_exceptions-prefix/src/proj_exceptions-build/libexceptions.so"
to "/usr/local/lib/libexceptions.so".
Makefile:66: recipe for target 'install' failed
As you can see, the install configuration is empty. Looking through the generated config for the external project, I found this in cmake_install.cmake:
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "/usr/local")
endif()
So, it seems that passing INSTALL_DIR to ExternalProject_Add doesn't set the install prefix. The install step succeeds, if I instead use:
ExternalProject_Add( proj_exceptions
GIT_REPOSITORY /home/djones/workspace/exceptions
CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}"
)
So what's the purpose of INSTALL_DIR then?
You're right for the purpose of INSTALL_DIR, but you may have missed some steps.
According the cmake 2.8 doc about external project:
Install Step
The INSTALL_DIR is underneath the calling project’s
binary directory. Use INSTALL_DIR to specify a different location.
Note that in addition to setting INSTALL_DIR, you also have to pass
-DCMAKE_INSTALL_PREFIX or --prefix to the CMake or configure command. It is not used automatically in the configure step since not all
projects follow this convention.
# [INSTALL_DIR dir]
You can refer to the install directory in your configure command, for
example:
CONFIGURE_COMMAND SOURCE_DIR/configure --prefix=INSTALL_DIR
# [INSTALL_COMMAND cmd...]
CMake-based projects use ‘cmake--build’ to build the install target.
Other projects use ‘make install’. Use INSTALL_COMMAND to customize
the install step. Use INSTALL_COMMAND “” to omit the install step. The
install command executes with the working directory set to
.
So try to update your cmake command, or use the custom INSTALL_COMMAND feature.