0

I'm trying to create a superbuild to compile the dependencies (zlib, nifticlib and boost) and then compile my project, depending on all these libraries.

Here is my CMakeLists:

cmake_minimum_required(VERSION 3.6)

project(CMakeTest)

#-----------------------------------------------------------------------------
# Build options
#-----------------------------------------------------------------------------

option(BUILD_MYPROJECT "Build MYPROJECT." ON)

#-----------------------------------------------------------------------------
# Git protocole option
#-----------------------------------------------------------------------------
option(USE_GIT_PROTOCOL "If behind a firewall turn this off to use http instead." OFF)

set(git_protocol "git")
if(NOT USE_GIT_PROTOCOL)
  set(git_protocol "https")
endif()

#-----------------------------------------------------------------------------
# Enable and setup External project global properties
#-----------------------------------------------------------------------------
include(ExternalProject)

if (NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Release CACHE STRING
    "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
    FORCE)
endif()

#-----------------------------------------------------------------------------
# Zlib
#-----------------------------------------------------------------------------

message(STATUS "Installing Zlib library.")

ExternalProject_Add(Zlib
  SOURCE_DIR "${PROJECT_BINARY_DIR}/deps/zlib"
  BINARY_DIR "${PROJECT_BINARY_DIR}/deps/zlib-build"
  INSTALL_DIR "${PROJECT_BINARY_DIR}/deps/zlib-install"
  GIT_REPOSITORY "${git_protocol}://github.com/madler/zlib.git"
  GIT_TAG "50893291621658f355bc5b4d450a8d06a563053d"
  CMAKE_ARGS
  -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
  -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
  -DCMAKE_BIN_DIR:PATH=<INSTALL_DIR>/bin
  -DINSTALL_INC_DIR:PATH=<INSTALL_DIR>/include
  -DINSTALL_LIB_DIR:PATH=<INSTALL_DIR>/lib
  -DINSTALL_MAN_DIR:PATH=<INSTALL_DIR>/share/man
  -DINSTALL_PKGCONFIG_DIR:PATH=<INSTALL_DIR>/share/pkgconfig)

if(WIN32)
  set(ZLIB_LIB_BASE_NAME "zlibstatic")
  set(ZLIB_LIB_NAME_RELEASE "${CMAKE_STATIC_LIBRARY_PREFIX}${ZLIB_LIB_BASE_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}")
  set(ZLIB_LIB_NAME_DEBUG "${CMAKE_STATIC_LIBRARY_PREFIX}${ZLIB_LIB_BASE_NAME}d${CMAKE_STATIC_LIBRARY_SUFFIX}")
elseif(UNIX)
  set(ZLIB_LIB_BASE_NAME "z")
  set(ZLIB_LIB_NAME_RELEASE "${CMAKE_STATIC_LIBRARY_PREFIX}${ZLIB_LIB_BASE_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}")
  set(ZLIB_LIB_NAME_DEBUG "${CMAKE_STATIC_LIBRARY_PREFIX}${ZLIB_LIB_BASE_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}")
else()
  # MacOSX
endif()

ExternalProject_Get_Property(Zlib install_dir)
set(ZLIB_LIBRARY_DIR ${install_dir}/lib)
set(ZLIB_INCLUDE_DIR ${install_dir}/include)
set(ZLIB_BINARY_DIR ${install_dir}/bin)

add_library(zlib STATIC IMPORTED)
set_target_properties(zlib PROPERTIES IMPORTED_LOCATION_DEBUG "${ZLIB_LIBRARY_DIR}/${ZLIB_LIB_NAME_DEBUG}")
set_target_properties(zlib PROPERTIES IMPORTED_LOCATION_RELEASE "${ZLIB_LIBRARY_DIR}/${ZLIB_LIB_NAME_RELEASE}")

#-----------------------------------------------------------------------------
# Niftilib
#-----------------------------------------------------------------------------

message(STATUS "Installing Nifti library.")

ExternalProject_Add(Nifticlib
  SOURCE_DIR "${PROJECT_BINARY_DIR}/deps/nifticlib"
  BINARY_DIR "${PROJECT_BINARY_DIR}/deps/nifticlib-build"
  INSTALL_DIR "${PROJECT_BINARY_DIR}/deps/nifticlib-install"
  GIT_REPOSITORY "${git_protocol}://gitlab.com/slckr/nifticlib.git"
  GIT_TAG "e26a94e947c210104223f9f49737392c742c1c5b"
  CMAKE_ARGS
  -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
  -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
  -DZLIB_INCLUDE_DIR:PATH=${ZLIB_INCLUDE_DIR}
  -DZLIB_LIBRARY_DEBUG:PATH=${ZLIB_LIBRARY_DIR}/${ZLIB_LIB_NAME_DEBUG}
  -DZLIB_LIBRARY_RELEASE:PATH=${ZLIB_LIBRARY_DIR}/${ZLIB_LIB_NAME_RELEASE}
  DEPENDS Zlib)

set(NIFTIIO_LIB_BASE_NAME "niftiio")
set(NIFTIIO_LIB_NAME "${CMAKE_STATIC_LIBRARY_PREFIX}${NIFTIIO_LIB_BASE_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}")

set(NIFTICDF_LIB_BASE_NAME "nifticdf")
set(NIFTICDF_LIB_NAME "${CMAKE_STATIC_LIBRARY_PREFIX}${NIFTICDF_LIB_BASE_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}")

set(ZNZ_LIB_BASE_NAME "znz")
set(ZNZ_LIB_NAME "${CMAKE_STATIC_LIBRARY_PREFIX}${ZNZ_LIB_BASE_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}")

ExternalProject_Get_Property(Nifticlib install_dir)
set(NIFTI_LIBRARY_DIR ${install_dir}/lib)
set(NIFTI_INCLUDE_DIR ${install_dir}/include/nifti)
set(NIFTI_BINARY_DIR ${install_dir}/bin)

add_library(niftiio STATIC IMPORTED)
set_target_properties(niftiio PROPERTIES IMPORTED_LOCATION "${NIFTI_LIBRARY_DIR}/${NIFTIIO_LIB_NAME}")

add_library(nifticdf STATIC IMPORTED)
set_target_properties(nifticdf PROPERTIES IMPORTED_LOCATION "${NIFTI_LIBRARY_DIR}/${NIFTICDF_LIB_NAME}")

add_library(znz STATIC IMPORTED)
set_target_properties(znz PROPERTIES IMPORTED_LOCATION "${NIFTI_LIBRARY_DIR}/${ZNZ_LIB_NAME}")

#-----------------------------------------------------------------------------
# Boost
#-----------------------------------------------------------------------------

message(STATUS "Installing Boost library.")

set(BOOST_BOOTSTRAP_COMMAND)
if(WIN32)
  set(BOOST_BOOTSTRAP_COMMAND bootstrap.bat)
  set(BOOST_B2_COMMAND b2.exe)
elseif(UNIX )
  set(BOOST_BOOTSTRAP_COMMAND ./bootstrap.sh)
  set(BOOST_B2_COMMAND ./b2)
else()
  # MacOSX
  set(BOOST_BOOTSTRAP_COMMAND ./bootstrap.sh)
  set(BOOST_B2_COMMAND ./b2)
endif()

set(BOOST_BUILD_TYPE variant=release)
if (${CMAKE_BUILD_TYPE} MATCHES Debug)
  set(BOOST_BUILD_TYPE variant=debug)
endif(${CMAKE_BUILD_TYPE} MATCHES Debug)

set(BOOST_INSTALL_DIR ${PROJECT_BINARY_DIR}/deps/boost-install)
ExternalProject_Add(boost
  SOURCE_DIR "${PROJECT_BINARY_DIR}/deps/boost"
  BUILD_IN_SOURCE 1
  GIT_REPOSITORY "${git_protocol}://github.com/boostorg/boost"
  GIT_TAG "5ec478a570bdc71c5d4854e7165a8b3f4fa82ad9"
  CONFIGURE_COMMAND ${BOOST_BOOTSTRAP_COMMAND}
  BUILD_COMMAND ${BOOST_B2_COMMAND} headers COMMAND ${BOOST_B2_COMMAND} install
    link=static
    ${BOOST_BUILD_TYPE}
    --prefix=${BOOST_INSTALL_DIR}
    --with-filesystem
    --with-program_options
    --with-system
    --with-thread
    -j8
  INSTALL_COMMAND ""
)

if(WIN32)
  set(BOOST_LIBRARY_DIR ${BOOST_INSTALL_DIR}/lib/boost)
  set(BOOST_INCLUDE_DIR ${BOOST_INSTALL_DIR}/include/boost-1_65)
else()
  set(BOOST_LIBRARY_DIR ${BOOST_INSTALL_DIR}/lib/boost)
  set(BOOST_INCLUDE_DIR ${BOOST_INSTALL_DIR}/include)
endif()

set(BOOST_SUBMODULES system;filesystem;program_options;thread)

#-----------------------------------------------------------------------------
# MyProject
#-----------------------------------------------------------------------------

message(STATUS "Installing MyProject library.")

if(BUILD_MYPROJECT)
  set(MYPROJECT_LIBS zlib;znz;nifticdf;niftiio)
  ExternalProject_Add(MYPROJECT
    SOURCE_DIR "${PROJECT_BINARY_DIR}/MyProject"
    BINARY_DIR "${PROJECT_BINARY_DIR}/MyProject-build"
    INSTALL_DIR "${PROJECT_BINARY_DIR}/MyProject-install"
    GIT_REPOSITORY "${git_protocol}://gitlab.com/slckr/MyProject.git"
    GIT_TAG "origin/multithread2"
    CMAKE_ARGS
    -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
    -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
    -DZLIB_INC_DIR:PATH=${ZLIB_INCLUDE_DIR}
    -DZLIB_LIB_DIR:PATH=${ZLIB_LIBRARY_DIR}
    -DNIFTI_INC_DIR:PATH=${NIFTI_INCLUDE_DIR}
    -DNIFTI_LIB_DIR:PATH=${NIFTI_LIBRARY_DIR}
    -DBOOST_INC_DIR:PATH=${BOOST_INCLUDE_DIR}
    -DBOOST_LIB_DIR:PATH=${BOOST_LIBRARY_DIR}
    -DBOOST_SUBMODULES:STRING=${BOOST_SUBMODULES}
    -DMYPROJECT_LIBS:STRING=${MYPROJECT_LIBS}
    DEPENDS Nifticlib boost)
endif()

The problem is when I try to link MyProject to nifticlib or boost, because the library name is different based on the platform (which I handled when importing libraries) the linking fails.

I pass the library directory and in MyProject CMakeLists, I do:

include_directories(${ZLIB_INC_DIR} ${NIFTI_INC_DIR} ${BOOST_INC_DIR})
link_directories(${ZLIB_LIB_DIR} ${NIFTI_LIB_DIR} ${BOOST_LIB_DIR})

target_link_libraries(MyProject zlib znz niftiio nifticdf)

but target_link_libraries fails, because zlib is not found (but I imported it in my superbuild). How can I tell MyProject to use the imported library of my superbuild?

Thank you.

RAM
  • 2,257
  • 2
  • 19
  • 41
whiteShadow
  • 369
  • 4
  • 19

1 Answers1

1

I think this https://crascit.com/2015/07/25/cmake-gtest/ could help you.

The main point of the method in the link is to build the external project during configuration time. This integrates the external project completly in your build and gives access to the targets.

Unfortunaly the example uses gtest to demonstrate the use but it is possible to use it for other dependencies.

perp
  • 11
  • 2
  • Yes, I saw that method, however, it seems more like a hack than a clean method. I think in the worst case scenario I can pass the library names into the CMAKE_ARGS of my project, but still not very clean. I don't understand why ExternalProject_Add can have dependencies, but only uses it for the build order, and do not pass all the variables of the dependency to the external project too. – whiteShadow May 03 '17 at 16:20