c++qtcmakezlibquazip

Build zLib with CMake


I'm trying to build Zlib and quazip automatic with the rest of my project. I want to do it in a similar way as I add googletest to my project. zLib and Quazip shall be linked static to my App.

I want to to this because of CI/ CD reasons and if somebody else wants to build the project he do not have to worry about those dependencies (especially under windows)...

  1. Download it at configure time with CMake ExternalProject_Add
  2. add it on target level

My structure is like the following:

project/
├── CMakelists.txt (1)
├── sources/
│   ├── APP/
│   │   ├── CMakeLists.txt (2)
│   │   ├── thirdparty/
│   │   │   ├── CMakeLists.txt (3)
│   │   │   ├── zlib
│   │   │   │   ├── CMakeLists.txt.in
│   │   │   ├── quazip
│   │   │   │   ├── CMakeLists.txt.in
│   │   │   │   ├── CMakeListsBuild.txt.in

Thats complicated enough but let me show you what I do where...

(1) CMakeLists.txt

Noting special just adding all the packages together like APP

(2) CMakeLists.txt

cmake_minimum_required(VERSION 3.15.2)

project(Project VERSION 0.0.1)

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

#Add the needed Qt Components
find_package(Qt5 COMPONENTS
                            Core
                            Network
                            REQUIRED)

add_subdirectory(thirdparty) 

SET(INCLUDES
    ...
    )

SET(SOURCES
    ...
    )

target_compile_options(${PROJECT_NAME}  PUBLIC
                                        ...
                                        )

target_compile_definitions(${PROJECT_NAME} PUBLIC
                                                    QUAZIP_STATIC )

target_include_directories(${PROJECT_NAME} PRIVATE
    OtherIncludes
    "${QUAZIP_INCLUDE_DIR}"
    )

target_link_libraries(${PROJECT_NAME}
    Qt5::Network
    Qt5::Core
    SomeOtherDep
    quazip_static  <---- adding static targets here
    zlibstatic     <---- adding static targets here
    )

(3) CMakeLists.txt

# Download and unpack at configure time
configure_file(zlib/CMakeLists.txt.in zlib-download/CMakeLists.txt)

execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
    WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/zlib-download"
)
execute_process(COMMAND "${CMAKE_COMMAND}" --build .
    WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/zlib-download"
)

add_subdirectory("${CMAKE_BINARY_DIR}/zlib-src"
                 "${CMAKE_BINARY_DIR}/zlib-build"
)

# Download and unpack at configure time
configure_file(quazip/CMakeLists.txt.in quazip-download/CMakeLists.txt)

execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
    WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/quazip-download"
)
execute_process(COMMAND "${CMAKE_COMMAND}" --build .
    WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/quazip-download"
)

configure_file(quazip/CMakeListsBuild.txt.in ${CMAKE_BINARY_DIR}/quazip-src/CMakeLists.txt COPYONLY)

add_subdirectory("${CMAKE_BINARY_DIR}/quazip-src"
                 "${CMAKE_BINARY_DIR}/quazip-build"
)

set(QUAZIP_INCLUDE_DIR
                "${CMAKE_BINARY_DIR}/quazip-src/quazip" PARENT_SCOPE)

The two CMakeLists.txt.in have nearly the same Content...

cmake_minimum_required(VERSION 2.8.2)

include(ExternalProject)

project(quazip-download NONE)

ExternalProject_Add(quazip
    GIT_REPOSITORY git://github.com/stachenov/quazip.git
    GIT_TAG v0.8.1
    SOURCE_DIR "${CMAKE_BINARY_DIR}/quazip-src"
    BINARY_DIR "${CMAKE_BINARY_DIR}/quazip-build"
    CONFIGURE_COMMAND ""
    BUILD_COMMAND ""
    INSTALL_COMMAND ""
    TEST_COMMAND ""
)
cmake_minimum_required(VERSION 2.8.2)

include(ExternalProject)

project(zlib-download NONE)

ExternalProject_Add(zlib
    GIT_REPOSITORY git://github.com/madler/zlib.git
    GIT_TAG v1.2.11
    SOURCE_DIR "${CMAKE_BINARY_DIR}/zlib-src"
    BINARY_DIR "${CMAKE_BINARY_DIR}/zlib-build"
    CONFIGURE_COMMAND ""
    BUILD_COMMAND ""
    INSTALL_COMMAND ""
    TEST_COMMAND ""
)

Then there is the last CMakeListsBuild.txt.in in the quazip folder. I'm just editing the original one and feed the zlib dependencies directly in. It looks like this:

cmake_minimum_required(VERSION 2.6)
project(QuaZip)

...
EVERYTHING ORIGINAL 
...
# Use system zlib on unix and Qt ZLIB on Windows
# will be set from outside ZLIB_LIBRARIES ZLIB_INCLUDE_DIRS
--------------------ADDED BY ME REMOVED find_packages...
set(ZLIB_INCLUDE_DIRS   ${CMAKE_BINARY_DIR}/zlib-src
                        ${CMAKE_BINARY_DIR}/zlib-build)
if(UNIX)
    set(ZLIB_LIBRARIES
                    "${CMAKE_BINARY_DIR}/zlib-build/libz.a")
elseif(MINGW)
    set(ZLIB_LIBRARIES
                    "${CMAKE_BINARY_DIR}/zlib-build/libzlibstatic.a")
endif()


...
EVERYTHING ORIGINAL 
...

Question

Downloading and building the static lib of zlib works but I get the following error while compiling under linux.

/home/linuxmint/someDirectory/build/zlib-src/test/example.c:8:10: fatal error: zlib.h: No such file or directory
 #include "zlib.h"
          ^~~~~~~~
compilation terminated.
zlib-build/CMakeFiles/example.dir/build.make:75: recipe for target 'zlib-build/CMakeFiles/example.dir/test/example.o' failed
make[2]: *** [zlib-build/CMakeFiles/example.dir/test/example.o] Error 1
CMakeFiles/Makefile2:1355: recipe for target 'zlib-build/CMakeFiles/example.dir/all' failed
make[1]: *** [zlib-build/CMakeFiles/example.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....

This is the strange part I dont understand. If I have a look in the CMakeLists of zlib. (LINK) They add everything of of the source and binary folder to the include with this:

include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR})

So I don't understand why the example of zlib (and everything else which need zlib.h) can't be build... Perhabs somebody has a hint... Thanks...

Edit

If I install the headers with apt building works... But why ;) Since nowhere find_package is called...


Solution

  • Thanks to @squarekittles who pointed me in the right direction.

    In the CMakeLists.txt of zlib the include dir is specified as ${CMAKE_SOURCE_DIR}. This is of course the wrong directory...

    I added a additional CMakeLists.txt.in for zlib which will replace the original one. It's all the same only two lines are different:

    ...
    include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
                                                            ^~~~~~~~~~~~~ Added in
    
    
    #============================================================================
    # zlib
    #============================================================================
    
    set(ZLIB_PUBLIC_HDRS
        ${CMAKE_CURRENT_BINARY_DIR}/zconf.h
        ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h
    )     ^~~~~~~~~~~~~ Added in
    
    ...
    

    Now the examples compile... Also I needed to add the headers of zlib to my project did it by editing CMakeLists.txt (3)

    ...
    configure_file(zlib/CMakeListsBuild.txt.in ${CMAKE_BINARY_DIR}/zlib-src/CMakeLists.txt COPYONLY) <--- Replacing CMakeLists.txt for zlib
    ...
    
    set(QUAZIP_INCLUDE_DIR
                    "${CMAKE_BINARY_DIR}/quazip-src/quazip" 
                    ${ZLIB_INCLUDE_DIR} PARENT_SCOPE)
                      ^~~~~~~~~~~~ Added in
    ...