0

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.

rbaleksandar
  • 8,713
  • 7
  • 76
  • 161
  • "Do I have to add the include directory as a CMAKE_ARGS entry or is there some other easier way?" - Yes, you need to pass `ZLIB_INCLIDE_DIRS` and `ZLIB_LIBRARIES` variables as a CMAKE_ARGS entries. Since you have already compute their values in your `CMakeLists.txt`, passing is straghtforward: `"-DZLIB_INCLIDE_DIRS=${ZLIB_INCLIDE_DIRS}" "-DZLIB_LIBRARIES=${ZLIB_LIBRARIES}"`. Not sure what do you want to achive by extra escaping `\"${${ZLIB_INCLUDE_DIRS}}\""`. – Tsyvarev Sep 10 '21 at 16:42
  • The problem is that these variables are filled during the configuration and not build step. So I am struggling to find a way to populate `ZLIB_LIBRARIES` with the actual `lib` file path. I have two options: 1)GLOB it thus allowing me to set it regardless of prefixes and suffixes (e.g. debug build on Win produces `zlibd.lib` but a release one on Win produces `zlib1.lib`) with a good regex or 2)write fixed names. 1) is a no go since I cannot glob files that are not there (hence requirement to run cmake and build multiple times. 2) is difficult since some libs contain version numbers. – rbaleksandar Sep 13 '21 at 11:33
  • @Tsyvarev `\"${${ZLIB_INCLUDE_DIRS}}\"` is a leftover from a previous experiment. – rbaleksandar Sep 13 '21 at 11:33

0 Answers0