diff --git a/CMakeLists.txt b/CMakeLists.txt index 5efe400..f5be613 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,107 +13,46 @@ set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) +include(GNUInstallDirs) +include(FetchContent) +include(CMakePackageConfigHelpers) + ############################################################################## -# Build options for enabling/disabling demos and tests +# Build options ############################################################################## option(ZIPPER_BUILD_DEMOS "Build the demo applications" OFF) option(ZIPPER_BUILD_TESTS "Build the test applications" OFF) option(ZIPPER_SHARED_LIB "Build zipper as a shared library" OFF) +option(ZIPPER_USE_LOCAL_SUBMODULES "Use local submodules instead of FetchContent" OFF) ############################################################################## -# External dependencies +# Third-party dependencies ############################################################################## -# Force static libraries for dependencies -set(BUILD_SHARED_LIBS OFF) -# Configure zlib-ng -set(ZLIB_COMPAT ON CACHE BOOL "Enable zlib-ng compatibility") -set(ZLIB_ENABLE_TESTS OFF CACHE BOOL "Disable zlib-ng tests") -set(SKIP_INSTALL_ALL ON CACHE BOOL "Skip installation of zlib-ng") -add_subdirectory(external/zlib-ng) - -# Configure minizip with AES encryption support -# Define the CMP0077 policy to avoid warning with option() in external/minizip -if(POLICY CMP0077) - cmake_policy(SET CMP0077 NEW) -endif() -option(USE_AES "Enable AES encryption" ON) -add_subdirectory(external/minizip) -target_include_directories(minizip PUBLIC - $ -) +add_subdirectory(external) ############################################################################## -# Main library targets (static and shared) +# Main library targets ############################################################################## -# Common source files definition -set(ZIPPER_SOURCES - src/utils/Path.cpp - src/utils/Timestamp.cpp - src/utils/glob.cpp - src/Zipper.cpp - src/Unzipper.cpp -) # Compile as static or as shared library if(ZIPPER_SHARED_LIB) - add_library(zipper SHARED ${ZIPPER_SOURCES}) -else() - add_library(zipper STATIC ${ZIPPER_SOURCES}) -endif() - -# Add platform-specific dependencies -if(WIN32) - target_sources(zipper PRIVATE - src/utils/dirent.c - ) - - target_compile_definitions(zipper PRIVATE - # Prevent Windows' min/max macros from conflicting with std::min/max - NOMINMAX=ON - ) -endif() - -# Export symbols for Windows and DLLs. -if(WIN32 AND ZIPPER_SHARED_LIB) - set(CMAKE_CXX_VISIBILITY_PRESET hidden) - set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) - - # Include and setup for exporting symbols - include(GenerateExportHeader) - - # Generate export header for shared library symbols - generate_export_header(zipper - BASE_NAME zipper - EXPORT_MACRO_NAME ZIPPER_EXPORT - EXPORT_FILE_NAME zipper_export.h - ) - target_compile_definitions(zipper PRIVATE zipper_EXPORTS) - target_compile_definitions(zipper PUBLIC ZIPPER_EXPORT_DEFINED) + set(BUILD_SHARED_LIBS ON) else() - # For all other cases, undefine the macro - target_compile_options(zipper PRIVATE -UZIPPER_EXPORT_DEFINED) + set(BUILD_SHARED_LIBS OFF) endif() -# Include directories configuration -target_include_directories(zipper PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - src - external/minizip -) +add_library(zipper) +add_library(zipper::zipper ALIAS zipper) -# Public include directories -target_include_directories(zipper PUBLIC - $ - $ - $ +set_target_properties(zipper PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} ) -# Library dependencies -target_link_libraries(zipper PRIVATE - minizip - zlibstatic -) +# Main implementation in here +add_subdirectory(src) +add_subdirectory(include) ############################################################################## # Build demos if CMake option is enabled @@ -134,8 +73,8 @@ endif() ############################################################################## if(ZIPPER_BUILD_TESTS) message(STATUS "Building test applications") - add_subdirectory(tests) enable_testing() + add_subdirectory(tests) endif() ############################################################################## @@ -146,45 +85,43 @@ configure_file( ${CMAKE_CURRENT_BINARY_DIR}/zipper.pc @ONLY ) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zipper.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig +) ############################################################################## -# Installation rules +# CMake Package Configuration (for find_package support) ############################################################################## include(GNUInstallDirs) include(CMakePackageConfigHelpers) -# Configure version information for shared libraries -if(ZIPPER_SHARED_LIB) - set_target_properties(zipper PROPERTIES - VERSION ${PROJECT_VERSION} - SOVERSION ${PROJECT_VERSION_MAJOR} - ) -endif() - -install(TARGETS zipper - EXPORT zipperTargets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - NAMELINK_SKIP - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +# Export the installed targets +install(EXPORT zipperTargets + FILE zipperTargets.cmake + NAMESPACE zipper:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/zipper +) +# Export for build-tree targets also +export(EXPORT zipperTargets + FILE zipperTargets.cmake + NAMESPACE zipper:: ) -# For shared libraries, add NAMELINK installation -if(ZIPPER_SHARED_LIB) - install(TARGETS zipper - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - NAMELINK_ONLY - ) -endif() +configure_package_config_file( + ${CMAKE_CURRENT_SOURCE_DIR}/zipperConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/zipperConfig.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/zipper +) +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/zipperConfigVersion.cmake + COMPATIBILITY AnyNewerVersion +) -install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -if(WIN32 AND ZIPPER_SHARED_LIB) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zipper_export.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - ) -endif() -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zipper.pc - DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig +# Install the configuration files +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/zipperConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/zipperConfigVersion.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/zipper ) ############################################################################## diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt new file mode 100644 index 0000000..3dc4aa6 --- /dev/null +++ b/external/CMakeLists.txt @@ -0,0 +1,67 @@ +# Support for FetchContent/find_package integration using CMake 3.24 +set(fetch_content_extra_args) +if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.24) + list(APPEND fetch_content_extra_args + FIND_PACKAGE_ARGS CONFIG + ) +endif() + +# Declare the dependencies +# Some default options are overwritten to better support bundled buildings +option(WITH_GTEST "zipper: Override" OFF) +option(WITH_FUZZERS "zipper: Override" OFF) +option(WITH_BENCHMARKS "zipper: Override" OFF) +# TODO: Do without the ZLIB_COMPAT +option(ZLIB_COMPAT "zipper: Override" ON) +option(ZLIB_ENABLE_TESTS "zipper: Override" OFF) +option(SKIP_INSTALL_ALL "zipper: Override" ON) +FetchContent_Declare(zlib-ng + GIT_REPOSITORY https://github.com/zlib-ng/zlib-ng.git + GIT_TAG 2.2.4 + ${fetch_content_extra_args} +) + +option(USE_AES "zipper: Override" ON) +FetchContent_Declare(minizip + GIT_REPOSITORY https://github.com/Lecrapouille/minizip.git + GIT_TAG v1.2 + ${fetch_content_extra_args} +) + +# If we are asked to use submodules, override the paths to point to +# the submodule destination +if(ZIPPER_USE_LOCAL_SUBMODULES) + set(FETCHCONTENT_SOURCE_DIR_MINIZIP ${CMAKE_CURRENT_SOURCE_DIR}/minizip CACHE PATH + "zipper: Override (USE_LOCAL_SUBMODULES)" + ) + set(FETCHCONTENT_SOURCE_DIR_ZLIB-NG ${CMAKE_CURRENT_SOURCE_DIR}/zlib-ng CACHE PATH + "zipper: Override (USE_LOCAL_SUBMODULES)" + ) +endif() + +# Make all dependencies build as static libraries +# TODO: This can be scoped for each dependency, but requires +# reorganization of the folder structure or CMake 3.25 +set(BUILD_SHARED_LIBS OFF) + +# Do the actual add_subdirectory/find_package calls +FetchContent_MakeAvailable(minizip zlib-ng) + +# Additional compatibility support because the dependencies do not properly support +# FetchContent (gated by _SOURCE_DIR) or find_package is not compatible +if(minizip_SOURCE_DIR) + # Ugly hack to make sure #include works + execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/include) + execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink + ${minizip_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/include/minizip + ) + target_include_directories(minizip PUBLIC + $ + ) + add_library(MINIZIP::minizip ALIAS minizip) +endif() + +if(zlib-ng_SOURCE_DIR) + # TODO: after ZLIB_COMPAT is off, switch to zlib-ng + add_library(ZLIB::zlib ALIAS zlib) +endif() diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt new file mode 100644 index 0000000..3c96b4d --- /dev/null +++ b/include/CMakeLists.txt @@ -0,0 +1 @@ +install(DIRECTORY Zipper/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/Zipper) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..2bf6916 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,54 @@ +target_sources(zipper PRIVATE + Zipper.cpp + Unzipper.cpp +) +add_subdirectory(utils) + +# Export symbols for Windows and DLLs. +if(WIN32 AND ZIPPER_SHARED_LIB) + set(CMAKE_CXX_VISIBILITY_PRESET hidden) + set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) + + # Include and setup for exporting symbols + include(GenerateExportHeader) + + # Generate export header for shared library symbols + generate_export_header(zipper + BASE_NAME zipper + EXPORT_MACRO_NAME ZIPPER_EXPORT + EXPORT_FILE_NAME zipper_export.h + ) + target_compile_definitions(zipper PRIVATE zipper_EXPORTS) + target_compile_definitions(zipper PUBLIC ZIPPER_EXPORT_DEFINED) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zipper_export.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) +else() + # For all other cases, undefine the macro + target_compile_options(zipper PRIVATE -UZIPPER_EXPORT_DEFINED) +endif() + +# Include directories configuration +target_include_directories(zipper PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} +) + +# Public include directories +target_include_directories(zipper PUBLIC + $ + # for the zipper_export.h file. Is it needed though? + $ + $ +) + +# Library dependencies +target_link_libraries(zipper PRIVATE + MINIZIP::minizip + # TODO: Use the non-compat version + ZLIB::zlib +) + +install(TARGETS zipper + EXPORT zipperTargets +) diff --git a/src/Unzipper.cpp b/src/Unzipper.cpp index 6d6ac3f..cf10cf6 100644 --- a/src/Unzipper.cpp +++ b/src/Unzipper.cpp @@ -10,10 +10,10 @@ #include "utils/Path.hpp" #include "utils/glob.hpp" -#include "external/minizip/ioapi_mem.h" -#include "external/minizip/minishared.h" -#include "external/minizip/unzip.h" -#include "external/minizip/zip.h" +#include +#include +#include +#include #include #include diff --git a/src/Zipper.cpp b/src/Zipper.cpp index 1d6a7ac..a18339b 100644 --- a/src/Zipper.cpp +++ b/src/Zipper.cpp @@ -10,8 +10,8 @@ #include "utils/Path.hpp" #include "utils/Timestamp.hpp" -#include "external/minizip/ioapi_mem.h" -#include "external/minizip/zip.h" +#include +#include #include #include diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt new file mode 100644 index 0000000..86dcd70 --- /dev/null +++ b/src/utils/CMakeLists.txt @@ -0,0 +1,16 @@ +target_sources(zipper PRIVATE + Path.cpp + Timestamp.cpp + glob.cpp +) + +# Add platform-specific dependencies +if(WIN32) + target_sources(zipper PRIVATE + dirent.c + ) + target_compile_definitions(zipper PRIVATE + # Prevent Windows' min/max macros from conflicting with std::min/max + NOMINMAX=ON + ) +endif() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8dc74ae..142581b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,13 +9,21 @@ set(CMAKE_CXX_STANDARD 14) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # Download and configure GoogleTest +set(fetch_content_extra_args) +if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.24) + list(APPEND fetch_content_extra_args + FIND_PACKAGE_ARGS CONFIG + ) +endif() + include(FetchContent) FetchContent_Declare( - googletest + GTest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG v1.14.0 + ${fetch_content_extra_args} ) -FetchContent_MakeAvailable(googletest) +FetchContent_MakeAvailable(GTest) # Define the test sources file(GLOB TESTS_SOURCES "*.cpp") @@ -39,9 +47,9 @@ target_compile_definitions(zipper-tests PRIVATE # Link with the main library and Google Test target_link_libraries(zipper-tests PRIVATE zipper - gtest - gtest_main - gmock + GTest::gtest + GTest::gtest_main + GTest::gmock ) # Add the test to the CTest list diff --git a/zipperConfig.cmake.in b/zipperConfig.cmake.in index 3dc510e..42bbd4c 100644 --- a/zipperConfig.cmake.in +++ b/zipperConfig.cmake.in @@ -1,19 +1,14 @@ @PACKAGE_INIT@ # Zipper CMake Configuration File -# This file is configured during the build process to help find_package(zipper) work +# To use this simply use `target_link_libraries` against `zipper::zipper` -# Set the version -set(ZIPPER_VERSION @PROJECT_VERSION@) - -# Include the target definitions include("${CMAKE_CURRENT_LIST_DIR}/zipperTargets.cmake") -# Set the include directories -set_and_check(ZIPPER_INCLUDE_DIRS "@PACKAGE_INCLUDE_INSTALL_DIR@") -# Set the libraries -set(ZIPPER_LIBRARIES zipper::zipper) +# Deprecated variables, do not use! +# These are meant to be used purely for backwards compatibility with a potential +# FindZipper.cmake module. The names are provided as a best effort basis. -# Check that all required components are available -check_required_components(zipper) \ No newline at end of file +get_target_property(ZIPPER_INCLUDE_DIRS zipper::zipper INTERFACE_INCLUDE_DIRECTORIES) +set(ZIPPER_LIBRARIES zipper::zipper)