summaryrefslogtreecommitdiff
path: root/infrastructure/cmake/CMakeLists.txt
diff options
context:
space:
mode:
Diffstat (limited to 'infrastructure/cmake/CMakeLists.txt')
-rw-r--r--infrastructure/cmake/CMakeLists.txt618
1 files changed, 531 insertions, 87 deletions
diff --git a/infrastructure/cmake/CMakeLists.txt b/infrastructure/cmake/CMakeLists.txt
index a9bd549f..65f59eb8 100644
--- a/infrastructure/cmake/CMakeLists.txt
+++ b/infrastructure/cmake/CMakeLists.txt
@@ -1,17 +1,16 @@
cmake_minimum_required(VERSION 2.6)
+
+find_program(CCACHE_PROGRAM ccache)
+if(CCACHE_PROGRAM)
+ # Support Unix Makefiles and Ninja
+ set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
+endif()
+
project(BoxBackup)
enable_testing()
set(base_dir ${CMAKE_SOURCE_DIR}/../..)
-macro(cmake_to_native_path cmake_path native_path)
- if(WIN32)
- string(REPLACE "/" "\\" ${native_path} "${cmake_path}")
- else()
- set(${native_path} "${cmake_path}")
- endif()
-endmacro()
-
set(files_to_configure
bin/bbackupd/bbackupd-config
bin/bbstored/bbstored-certs
@@ -31,7 +30,6 @@ set(files_to_configure
contrib/windows/installer/boxbackup.mpi
infrastructure/BoxPlatform.pm
infrastructure/makebuildenv.pl
- infrastructure/makeparcels.pl
infrastructure/makedistribution.pl
lib/bbackupquery/makedocumentation.pl
lib/common/BoxPortsAndFiles.h
@@ -56,22 +54,64 @@ set(files_to_configure
include(FindPerl)
set(TARGET_PERL ${PERL_EXECUTABLE})
+function(replace_file_if_different dest_file source_file)
+ execute_process(
+ COMMAND "${CMAKE_COMMAND}" -E
+ copy_if_different "${source_file}" "${dest_file}")
+ execute_process(
+ COMMAND "${CMAKE_COMMAND}" -E
+ remove "${source_file}")
+endfunction()
+
+function(move_file_if_exists source_file dest_file)
+ if(EXISTS "${source_file}")
+ execute_process(
+ COMMAND "${CMAKE_COMMAND}" -E
+ rename "${source_file}" "${dest_file}")
+ endif()
+endfunction()
+
foreach(file_to_configure ${files_to_configure})
- configure_file("${base_dir}/${file_to_configure}.in" "${base_dir}/${file_to_configure}" @ONLY)
+ configure_file("${base_dir}/${file_to_configure}.in" "${base_dir}/${file_to_configure}.out" @ONLY)
+ replace_file_if_different(
+ "${base_dir}/${file_to_configure}"
+ "${base_dir}/${file_to_configure}.out")
endforeach()
-file(READ "${base_dir}/infrastructure/buildenv-testmain-template.cpp" test_template)
+# If BOXBACKUP_VERSION is defined when running CMake (as the AppVeyor config does), use it
+# as-is, since it contains the full version number, branch, and platform (Win32/Win64):
+if(BOXBACKUP_VERSION)
+ set(boxbackup_version ${BOXBACKUP_VERSION})
+ # Remove CPACK_SYSTEM_NAME from the default CPACK_PACKAGE_NAME, because it's already
+ # included in the CPACK_PACKAGE_VERSION:
+ set(CPACK_PACKAGE_FILE_NAME ${CMAKE_PROJECT_NAME}-${boxbackup_version})
+else()
+ # Work out the current Box version (requires Perl) and update lib/common/BoxVersion.h,
+ # but only if it has changed, to avoid unnecessary complete rebuilds due to timestamps.
+ execute_process(
+ COMMAND ${PERL_EXECUTABLE} ${base_dir}/infrastructure/cmake/getversion.pl
+ WORKING_DIRECTORY ${base_dir}/infrastructure
+ RESULT_VARIABLE status
+ OUTPUT_VARIABLE boxbackup_version
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_VARIABLE command_output)
+ if(NOT status EQUAL 0)
+ message(FATAL_ERROR "Failed to execute: "
+ "${PERL_EXECUTABLE} ${base_dir}/infrastructure/cmake/getversion.pl: "
+ "status ${status}: ${command_output}")
+ endif()
+endif()
+
+file(WRITE "${base_dir}/lib/common/BoxVersion.h.new"
+ "#define BOX_VERSION \"${boxbackup_version}\"\n")
+replace_file_if_different(
+ "${base_dir}/lib/common/BoxVersion.h"
+ "${base_dir}/lib/common/BoxVersion.h.new")
+add_definitions(-DBOX_CMAKE -DNEED_BOX_VERSION_H)
-execute_process(
- COMMAND ${PERL_EXECUTABLE} ${base_dir}/infrastructure/msvc/getversion.pl
- RESULT_VARIABLE status
- OUTPUT_VARIABLE command_output
- ERROR_VARIABLE command_output)
-if(NOT status EQUAL 0)
- message(FATAL_ERROR "Failed to execute: "
- "${PERL_EXECUTABLE} ${base_dir}/infrastructure/msvc/getversion.pl: "
- "status ${status}: ${command_output}")
+if(WIN32)
+ add_definitions(-DWIN32)
endif()
# Parsing Makefile.extra files in CMake script is a pain, so the relevant rules for
@@ -107,8 +147,8 @@ foreach(exception_file ${exception_files})
endforeach()
set(protocol_files
- lib/backupstore/backupprotocol.txt
- test/basicserver/testprotocol.txt
+ lib/backupstore/BackupProtocol.txt
+ test/basicserver/TestProtocol.txt
)
foreach(protocol_file ${protocol_files})
@@ -128,7 +168,7 @@ foreach(protocol_file ${protocol_files})
endforeach()
set(documentation_files
- lib/bbackupquery/documentation.txt
+ lib/bbackupquery/Documentation.txt
)
foreach(documentation_file ${documentation_files})
@@ -147,13 +187,15 @@ foreach(documentation_file ${documentation_files})
set(${module_name}_extra_files ${${module_name}_extra_files} ${output_file})
endforeach()
+set(testmain_template_cpp
+ "${base_dir}/infrastructure/buildenv-testmain-template.cpp"
+)
+set(release_or_debug_dir
+ "${base_dir}/$<$<CONFIG:Debug>:debug>$<$<CONFIG:Release>:release>$<$<CONFIG:RelWithDebInfo>:release>"
+)
+
file(STRINGS ${base_dir}/modules.txt module_deps REGEX "^[^#]")
-# qdbm, lib/common and lib/win32 aren't listed in modules.txt, so hard-code them.
-foreach(module_dep
- "qdbm"
- "lib/win32"
- "lib/common qdbm lib/win32"
- ${module_deps})
+foreach(module_dep ${module_deps})
string(REGEX MATCH "([^ ]+)[ ]*(.*)" valid_module_line ${module_dep})
if(valid_module_line)
@@ -165,16 +207,19 @@ foreach(module_dep
set(module_path ${base_dir}/${module_dir})
string(REPLACE "/" "_" module_name ${CMAKE_MATCH_1})
string(REPLACE "/" "_" dependencies "${CMAKE_MATCH_2}")
- file(GLOB module_files ${module_path}/*.c ${module_path}/*.cpp
- ${module_path}/*.h)
- set(module_files ${module_files} ${${module_name}_extra_files})
- # everything except qdbm, lib/common and lib/win32 implicitly depend on
- # lib/common, so express that dependency here.
- if(module_name MATCHES "^(qdbm|lib_(common|win32))$")
+ # We are replacing QDBM's normal build system, and we only want to include
+ # the modules that we actually need, to avoid warnings about duplicate
+ # definitions, and potential conflicts with Box Backup code in future, so
+ # we specify the C files to compile in explicitly.
+ if(module_name STREQUAL "qdbm")
+ file(GLOB module_files ${module_path}/depot.c ${module_path}/myconf.c)
else()
- set(dependencies "${dependencies} lib_common")
+ file(GLOB module_files ${module_path}/*.cpp ${module_path}/*.h)
endif()
+
+ set(module_files ${module_files} ${${module_name}_extra_files})
+
string(REGEX REPLACE "^ " "" dependencies "${dependencies}")
string(REGEX REPLACE " $" "" dependencies "${dependencies}")
@@ -184,7 +229,26 @@ foreach(module_dep
if(DEBUG)
message(STATUS "add executable '${module_name}': '${module_files}'")
endif()
+
add_executable(${module_name} ${module_files})
+ # Rename the output executable from bin_bbackupd(.exe) to bbackupd(.exe):
+ set_target_properties(${module_name} PROPERTIES
+ OUTPUT_NAME "${bin_name}")
+
+ # Use a custom post-build command instead of install(...) to install
+ # binaries ready for running tests, because we don't want "make install" to
+ # do this too, and absolute-path installations break the CPack generators.
+ add_custom_command(TARGET ${module_name} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ "$<TARGET_FILE:${module_name}>"
+ "${release_or_debug_dir}/${module_dir}/${bin_name}${CMAKE_EXECUTABLE_SUFFIX}"
+ VERBATIM)
+
+ # For "make install" and CPack generators:
+ install(TARGETS ${module_name} RUNTIME
+ CONFIGURATIONS Debug;Release
+ DESTINATION "."
+ COMPONENT Applications)
elseif(module_name MATCHES "^test_")
string(REGEX MATCH "^test_(.*)" valid_test ${module_name})
set(test_name ${CMAKE_MATCH_1})
@@ -194,13 +258,52 @@ foreach(module_dep
message(STATUS "add test '${module_name}': '${module_files}'")
endif()
- string(REPLACE "TEST_NAME" ${test_name} test_main "${test_template}")
- file(WRITE "${module_path}/_main.cpp" "${test_main}")
- add_executable(${module_name} ${module_files}
- "${module_path}/_main.cpp")
+ set(module_files ${module_files} "${testmain_template_cpp}")
+ add_executable(${module_name} ${module_files})
+
+ # Use a custom post-build command instead of install(...) to install
+ # binaries ready for running tests, because we don't want "make install" to
+ # do this too, and absolute-path installations break the CPack generators.
+ add_custom_command(TARGET ${module_name} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ "$<TARGET_FILE:${module_name}>"
+ "${release_or_debug_dir}/${module_dir}/${bin_name}${CMAKE_EXECUTABLE_SUFFIX}"
+ VERBATIM)
+
+ if(${APPVEYOR_MODE})
+ set(appveyor_runtest_pl_switch -a)
+ else()
+ set(appveyor_runtest_pl_switch)
+ endif()
+
+ if(WIN32)
+ set(test_command_internal "$<TARGET_FILE_NAME:${module_name}>")
+ else()
+ set(test_command_internal "./$<TARGET_FILE_NAME:${module_name}>")
+ endif()
+
+ target_compile_definitions(${module_name} PRIVATE
+ -DTEST_EXECUTABLE="${test_command_internal}")
add_test(NAME ${test_name}
- COMMAND ${PERL_EXECUTABLE} ${base_dir}/runtest.pl.in ${test_name}
- $<CONFIG> WORKING_DIRECTORY ${base_dir})
+ COMMAND ${PERL_EXECUTABLE} ${base_dir}/runtest.pl
+ ${appveyor_runtest_pl_switch} -c ${test_name}
+ $<$<CONFIG:Debug>:DEBUG>$<$<CONFIG:Release>:RELEASE>$<$<CONFIG:RelWithDebInfo>:RELEASE>
+ "$<TARGET_FILE:${module_name}>" "${test_command_internal}"
+ WORKING_DIRECTORY ${base_dir})
+
+ if(${APPVEYOR_MODE})
+ execute_process(COMMAND appveyor AddTest -Name ${test_name}
+ -Framework Custom -FileName "")
+ endif()
+
+ # It helps with debugging if the test depends on another step which
+ # prepares the target directory, and is always out of date.
+ add_custom_target(${module_name}-prepare
+ COMMAND ${PERL_EXECUTABLE} ${base_dir}/runtest.pl
+ -n -c ${test_name}
+ $<$<CONFIG:Debug>:DEBUG>$<$<CONFIG:Release>:RELEASE>$<$<CONFIG:RelWithDebInfo>:RELEASE>
+ "$<TARGET_FILE:${module_name}>" "${test_command_internal}"
+ WORKING_DIRECTORY ${base_dir})
elseif(module_name MATCHES "^(lib_.*|qdbm)$")
if(DEBUG)
message(STATUS "add library '${module_name}': '${module_files}'")
@@ -210,19 +313,6 @@ foreach(module_dep
message(FATAL_ERROR "Unsupported module type: " ${module_name})
endif()
- if(module_name MATCHES "^(bin|test)_")
- # We need to install binaries in specific places so that test
- # runner can find them:
- install(FILES "$<TARGET_FILE:${module_name}>"
- CONFIGURATIONS Debug
- DESTINATION "${base_dir}/debug/${module_dir}"
- RENAME "${bin_name}${CMAKE_EXECUTABLE_SUFFIX}")
- install(FILES "$<TARGET_FILE:${module_name}>"
- CONFIGURATIONS Release
- DESTINATION "${base_dir}/release/${module_dir}"
- RENAME "${bin_name}${CMAKE_EXECUTABLE_SUFFIX}")
- endif()
-
target_compile_definitions(${module_name} PRIVATE -DBOX_MODULE="${module_name}")
if(dependencies)
@@ -254,47 +344,401 @@ foreach(module_dep
endif()
endforeach()
-#include(ExternalProject)
-#ExternalProject_Add(pcre
-# PREFIX "../pcre"
-# BUILD_COMMAND "${CMAKE_EXECUTABLE
+if(WIN32)
+ install(FILES ${base_dir}/bin/bbackupd/win32/NotifySysAdmin.vbs
+ DESTINATION "." COMPONENT Extras)
+ install(FILES ${base_dir}/bin/bbackupd/win32/bbackupd.conf
+ DESTINATION "." COMPONENT Extras)
+else()
+ install(FILES ${base_dir}/bin/bbackupd/bbackupd-config
+ DESTINATION "." COMPONENT Extras)
+endif()
-# Tell QDBM not to build itself as a DLL, because we want to link statically to it.
-target_compile_definitions(qdbm PUBLIC -DQDBM_STATIC)
+# We can't do anything conditional on CMAKE_BUILD_TYPE because that's not valid for multi-configuration
+# generators such as MSVC. We need to use a generator expression instead.
+target_compile_definitions(lib_common PUBLIC $<$<CONFIG:Release>:BOX_RELEASE_BUILD>)
-# Silence some less-useful warnings
-if(MSVC)
- add_definitions(/wd4996 /wd4291)
- # target_link_libraries(qdbm PRIVATE /IGNORE:LNK4006)
- set_property(TARGET qdbm PROPERTY CMAKE_STATIC_LINKER_FLAGS /IGNORE:LNK4006)
-endif(MSVC)
+# Detect platform features and write BoxConfig.h.in. Reuse code from
+# infrastructure/m4/boxbackup_tests.m4 where possible
+
+include(CheckCXXCompilerFlag)
+include(CheckCXXSourceCompiles)
+include(CheckFunctionExists)
+include(CheckIncludeFiles)
+include(CheckLibraryExists)
+include(CheckSymbolExists)
+
+set(boxconfig_h_file "${CMAKE_BINARY_DIR}/BoxConfig.h.in")
+file(REMOVE "${boxconfig_h_file}")
+file(WRITE "${boxconfig_h_file}" "// Auto-generated by CMake. Do not edit.\n")
+
+if(WIN32)
+ target_link_libraries(lib_common PUBLIC ws2_32 gdi32)
+endif()
-target_link_libraries(lib_common PUBLIC ws2_32 gdi32)
+# On Windows we want to statically link zlib to make debugging and distribution easier,
+# but FindZLIB.cmake doesn't offer that as an option, so we have to go through some
+# contortions to "find" the correct library. ZLIB_ROOT is required in this case.
+if(WIN32)
+ if(NOT DEFINED ZLIB_ROOT)
+ message(FATAL_ERROR "You must set ZLIB_ROOT to point to include/zlib.h and lib/zlibstatic[d].lib on Windows")
+ endif()
-# Link to ZLib
-include_directories(${base_dir}/../zlib-win32/include)
-find_library(zlibstaticd_lib_path zlibstaticd ${base_dir}/../zlib-win32/lib)
-find_library(zlibstatic_lib_path zlibstatic ${base_dir}/../zlib-win32/lib)
-target_link_libraries(lib_compress PUBLIC debug ${zlibstaticd_lib_path})
-target_link_libraries(lib_compress PUBLIC optimized ${zlibstatic_lib_path})
+ message(STATUS "Searching for Zlib in: ${ZLIB_ROOT}")
+ find_path(ZLIB_INCLUDE_DIR zlib.h PATHS ${ZLIB_ROOT}/include NO_DEFAULT_PATH)
+ include_directories(${ZLIB_INCLUDE_DIR})
+ message(STATUS "Found Zlib headers: ${ZLIB_INCLUDE_DIR}")
+
+ # We must link against zlibstaticD if this is a debug build, otherwise
+ # we have a C runtime mismatch (/MD versus /MDd) and the application
+ # crashes at runtime.
+ find_library(ZLIB_LIBRARY_STATIC_DEBUG NAMES zlibstaticd
+ PATHS ${ZLIB_ROOT}/lib NO_DEFAULT_PATH)
+ find_library(ZLIB_LIBRARY_STATIC_RELEASE NAMES zlibstatic
+ PATHS ${ZLIB_ROOT}/lib NO_DEFAULT_PATH)
+
+ target_link_libraries(lib_compress PUBLIC
+ debug ${ZLIB_LIBRARY_STATIC_DEBUG}
+ optimized ${ZLIB_LIBRARY_STATIC_RELEASE})
+else()
+ find_package(ZLIB REQUIRED)
+ include_directories(${ZLIB_INCLUDE_DIRS})
+ target_link_libraries(lib_compress PUBLIC ${ZLIB_LIBRARIES})
+endif()
# Link to OpenSSL
-include_directories(${base_dir}/../openssl-win32/include)
-find_library(libeay32_lib_path libeay32 ${base_dir}/../openssl-win32/lib)
-find_library(ssleay32_lib_path ssleay32 ${base_dir}/../openssl-win32/lib)
-target_link_libraries(lib_crypto PUBLIC ${libeay32_lib_path} ${ssleay32_lib_path})
+# Workaround for incorrect library suffixes searched by FindOpenSSL:
+# https://gitlab.kitware.com/cmake/cmake/issues/17604
+if(WIN32 AND MSVC)
+ find_package(OpenSSL)
+ set(OPENSSL_SSL_LIBRARY ${SSL_EAY_RELEASE})
+ set(OPENSSL_CRYPTO_LIBRARY ${LIB_EAY_RELEASE})
+ set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} crypt32)
+ find_package_handle_standard_args(OpenSSL
+ REQUIRED_VARS
+ OPENSSL_SSL_LIBRARY
+ OPENSSL_CRYPTO_LIBRARY
+ OPENSSL_INCLUDE_DIR
+ VERSION_VAR
+ OPENSSL_VERSION
+ FAIL_MESSAGE
+ "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
+ )
+else()
+ find_package(OpenSSL REQUIRED)
+endif()
+include_directories(${OPENSSL_INCLUDE_DIR})
+target_link_libraries(lib_crypto PUBLIC ${OPENSSL_LIBRARIES})
# Link to PCRE
-include_directories(${base_dir}/../pcre-win32/include)
-target_compile_definitions(lib_common PUBLIC -DPCRE_STATIC)
-find_library(pcreposix_lib_path pcreposix ${base_dir}/../pcre-win32/lib)
-find_library(pcreposixd_lib_path pcreposixd ${base_dir}/../pcre-win32/lib)
-find_library(pcre_lib_path pcre ${base_dir}/../pcre-win32/lib)
-find_library(pcred_lib_path pcred ${base_dir}/../pcre-win32/lib)
-target_link_libraries(lib_common PUBLIC debug "${pcreposixd_lib_path}" optimized "${pcreposix_lib_path}")
-target_link_libraries(lib_common PUBLIC debug "${pcred_lib_path}" optimized "${pcre_lib_path}")
+if (WIN32)
+ if(NOT DEFINED PCRE_ROOT)
+ message(FATAL_ERROR "You must set PCRE_ROOT to point to include/pcreposix.h and lib/pcreposix[d].lib on Windows")
+ endif()
+
+ target_compile_definitions(lib_common PUBLIC -DPCRE_STATIC)
+ find_library(pcreposix_lib_path pcreposix ${PCRE_ROOT}/lib)
+ find_library(pcreposixd_lib_path pcreposixd ${PCRE_ROOT}/lib)
+ find_library(pcre_lib_path pcre ${PCRE_ROOT}/lib)
+ find_library(pcred_lib_path pcred ${PCRE_ROOT}/lib)
+ target_link_libraries(lib_common PUBLIC debug "${pcreposixd_lib_path}" optimized "${pcreposix_lib_path}")
+ target_link_libraries(lib_common PUBLIC debug "${pcred_lib_path}" optimized "${pcre_lib_path}")
+ include_directories(${PCRE_ROOT}/include)
+else()
+ find_package(PkgConfig REQUIRED)
+ pkg_check_modules(PCRE REQUIRED libpcreposix)
+ include_directories(${PCRE_INCLUDE_DIRS})
+ target_link_libraries(lib_common PUBLIC ${PCRE_LIBRARIES})
+
+ if(DEBUG)
+ message(STATUS "Linking PCRE libraries from ${PCRE_LIBRARY_DIRS}: ${PCRE_LIBRARIES}")
+ endif()
+endif()
+
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}")
+find_package(Readline)
+if(READLINE_FOUND)
+ include_directories(${Readline_INCLUDE_DIR})
+ target_link_libraries(lib_common PUBLIC ${Readline_LIBRARY})
+endif()
+
+set(boxconfig_cmake_h_dir "${base_dir}/lib/common")
+# Get the values of all directories added to the INCLUDE_DIRECTORIES property
+# by include_directory() statements, and save it in CMAKE_REQUIRED_INCLUDES
+# which check_include_files() uses to set the include file search path:
+get_property(CMAKE_REQUIRED_INCLUDES DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
+list(APPEND CMAKE_REQUIRED_INCLUDES "${boxconfig_cmake_h_dir}")
+# message(STATUS "CMAKE_REQUIRED_INCLUDES=${CMAKE_REQUIRED_INCLUDES}")
+
+# Save the original BoxConfig.cmake.h so that we can move it back later,
+# and not need to recompile everything.
+move_file_if_exists(
+ "${boxconfig_cmake_h_dir}/BoxConfig.cmake.h"
+ "${boxconfig_cmake_h_dir}/BoxConfig.cmake.h.bak")
+
+foreach(m4_filename boxbackup_tests.m4 ax_check_mount_point.m4 ax_func_syscall.m4)
+ file(STRINGS "${base_dir}/infrastructure/m4/${m4_filename}" m4_functions REGEX "^ *AC[_A-Z]+\\(.*\\)$")
+ foreach(m4_function ${m4_functions})
+ if(DEBUG)
+ message(STATUS "Processing m4_function: ${m4_function}")
+ endif()
+
+ string(REGEX MATCH .* ac_check_headers ${m4_function})
+ if(m4_function MATCHES "^ *AC_CHECK_HEADERS?\\(\\[([a-z./ ]+)\\](.*)\\)$")
+ if(DEBUG)
+ message(STATUS "Processing ac_check_headers: ${CMAKE_MATCH_1}")
+ endif()
+
+ # http://stackoverflow.com/questions/5272781/what-is-common-way-to-split-string-into-list-with-cmake
+ string(REPLACE " " ";" header_files ${CMAKE_MATCH_1})
+
+ foreach(header_file ${header_files})
+ list(APPEND detect_header_files ${header_file})
+ endforeach()
+ elseif(m4_function MATCHES "^ *AC_CHECK_FUNCS\\(\\[([a-z./_ ]+)\\](.*)\\)$")
+ if(DEBUG)
+ message(STATUS "Processing ac_check_funcs: ${CMAKE_MATCH_1}")
+ endif()
+
+ # http://stackoverflow.com/questions/5272781/what-is-common-way-to-split-string-into-list-with-cmake
+ string(REPLACE " " ";" function_names ${CMAKE_MATCH_1})
+
+ foreach(function_name ${function_names})
+ list(APPEND detect_functions ${function_name})
+ endforeach()
+ elseif(m4_function MATCHES "^ *AC_CHECK_DECLS\\(\\[([A-Za-z._/ ]+)\\](,,, ..#include <([^>]+)>..)?\\)$")
+ if(DEBUG)
+ message(STATUS "Processing ac_check_decls: ${CMAKE_MATCH_1} in ${CMAKE_MATCH_3}")
+ endif()
+
+ # http://stackoverflow.com/questions/5272781/what-is-common-way-to-split-string-into-list-with-cmake
+ string(REPLACE " " ";" decl_names "${CMAKE_MATCH_1}")
+ string(REPLACE " " ";" header_files "${CMAKE_MATCH_3}")
+
+ foreach(decl_name ${decl_names})
+ string(TOUPPER ${decl_name} platform_var_name)
+ string(REGEX REPLACE "[/.]" "_" platform_var_name ${platform_var_name})
+ check_symbol_exists("${decl_name}" "${header_files}" HAVE_DECL_${platform_var_name})
+ file(APPEND "${boxconfig_h_file}" "#cmakedefine01 HAVE_DECL_${platform_var_name}\n")
+ endforeach()
+ elseif(m4_function MATCHES "^ *AC_SEARCH_LIBS\\(\\[([A-Za-z._/ ]+)\\], \\[([A-Za-z._]+)\\]\\)$")
+ if(DEBUG)
+ message(STATUS "Processing ac_search_libs: ${CMAKE_MATCH_1} in ${CMAKE_MATCH_2}")
+ endif()
+
+ set(function_name ${CMAKE_MATCH_1})
+ # http://stackoverflow.com/questions/5272781/what-is-common-way-to-split-string-into-list-with-cmake
+ string(REPLACE " " ";" library_names "${CMAKE_MATCH_2}")
+
+ foreach(library_name ${library_names})
+ string(TOUPPER ${library_name} platform_var_name)
+ check_library_exists(${library_name} ${function_name} "" HAVE_LIB_${platform_var_name})
+ if(HAVE_LIB_${platform_var_name})
+ target_link_libraries(lib_common PUBLIC ${library_name})
+ endif()
+ endforeach()
+ elseif(m4_function MATCHES "^ *AC_CHECK_MEMBERS\\(\\[([A-Za-z._/ ]+)\\.([[A-Za-z_]+)\\](,,, ..(#include <([^>]+)>)..)?\\)$")
+ if(DEBUG)
+ message(STATUS "Processing ac_check_members: ${CMAKE_MATCH_1}.${CMAKE_MATCH_2} in ${CMAKE_MATCH_5}")
+ endif()
+
+ set(struct_name "${CMAKE_MATCH_1}")
+ set(member_name "${CMAKE_MATCH_2}")
+ set(include_file "${CMAKE_MATCH_5}")
+
+ string(TOUPPER "${struct_name}_${member_name}" platform_var_name)
+ string(REGEX REPLACE "[/. ]" "_" platform_var_name ${platform_var_name})
+
+ CHECK_CXX_SOURCE_COMPILES([=[
+ #include "BoxConfig.cmake.h"
+ #include <${include_file}>
+ int main()
+ {
+ ${struct_name} foo;
+ return sizeof(foo.${member_name}) > 0 ? 0 : 1;
+ }
+ ]=] "HAVE_${platform_var_name}")
+ file(APPEND "${boxconfig_h_file}" "#cmakedefine HAVE_${platform_var_name}\n")
+ endif()
+ endforeach()
+
+ # Build an intermediate version of BoxConfig.cmake.h for use in the following tests.
+ configure_file("${boxconfig_h_file}" "${boxconfig_cmake_h_dir}/BoxConfig.cmake.h")
+endforeach()
+
+list(APPEND detect_header_files mntent.h sys/mnttab.h sys/mount.h sys/param.h)
+
+foreach(header_file ${detect_header_files})
+ list(APPEND detect_header_files ${header_file})
+ string(TOUPPER ${header_file} platform_var_name)
+ string(REGEX REPLACE "[/.]" "_" platform_var_name ${platform_var_name})
+ check_include_files(${header_file} HAVE_${platform_var_name})
+ file(APPEND "${boxconfig_h_file}" "#cmakedefine HAVE_${platform_var_name}\n")
+endforeach()
+
+if(NOT HAVE_PCREPOSIX_H)
+ message(FATAL_ERROR "pcreposix.h not found at PCRE_ROOT/include: ${PCRE_ROOT}/include")
+endif()
+
+# PCRE is required, so unconditionally define this:
+set(HAVE_REGEX_SUPPORT 1)
+file(APPEND "${boxconfig_h_file}" "#cmakedefine HAVE_REGEX_SUPPORT\n")
+
+foreach(function_name ${detect_functions})
+ string(TOUPPER ${function_name} platform_var_name)
+ string(REGEX REPLACE "[/.]" "_" platform_var_name ${platform_var_name})
+ check_function_exists(${function_name} HAVE_${platform_var_name})
+ file(APPEND "${boxconfig_h_file}" "#cmakedefine HAVE_${platform_var_name}\n")
+endforeach()
+
+check_symbol_exists(dirfd "dirent.h" HAVE_DECL_DIRFD)
+file(APPEND "${boxconfig_h_file}" "#cmakedefine01 HAVE_DECL_DIRFD\n")
+
+# Emulate ax_check_mount_point.m4
+# These checks are run by multi-line M4 commands which are harder to parse/fake using
+# regexps above, so we hard-code them here:
+CHECK_CXX_SOURCE_COMPILES([=[
+ #include "BoxConfig.cmake.h"
+ #ifdef HAVE_SYS_PARAM_H
+ # include <sys/param.h>
+ #endif
+ #include <sys/mount.h>
+ int main()
+ {
+ struct statfs foo;
+ return sizeof(foo.f_mntonname) > 0 ? 0 : 1;
+ }
+ ]=] "HAVE_STRUCT_STATFS_F_MNTONNAME")
+file(APPEND "${boxconfig_h_file}" "#cmakedefine HAVE_STRUCT_STATFS_F_MNTONNAME\n")
+CHECK_CXX_SOURCE_COMPILES([=[
+ #include "BoxConfig.cmake.h"
+ #ifdef HAVE_SYS_PARAM_H
+ # include <sys/param.h>
+ #endif
+ #include <sys/mount.h>
+ int main()
+ {
+ struct statvfs foo;
+ return sizeof(foo.f_mntonname) > 0 ? 0 : 1;
+ }
+ ]=] "HAVE_STRUCT_STATVFS_F_MNTONNAME")
+file(APPEND "${boxconfig_h_file}" "#cmakedefine HAVE_STRUCT_STATVFS_F_MNTONNAME\n")
+if(HAVE_STRUCT_STATFS_F_MNTONNAME OR
+ HAVE_STRUCT_STATVFS_F_MNTONNAME OR
+ HAVE_STRUCT_MNTENT_MNT_DIR OR
+ HAVE_STRUCT_MNTTAB_MNT_MOUNTP)
+
+ set(HAVE_MOUNTS 1)
+ file(APPEND "${boxconfig_h_file}" "#cmakedefine HAVE_MOUNTS\n")
+endif()
+
+# Emulate ax_random_device.m4
+if(EXISTS /dev/urandom)
+ set(RANDOM_DEVICE /dev/urandom)
+elseif(EXISTS /dev/arandom)
+ set(RANDOM_DEVICE /dev/arandom)
+elseif(EXISTS /dev/random)
+ set(RANDOM_DEVICE /dev/random)
+endif()
+if(RANDOM_DEVICE)
+ set(HAVE_RANDOM_DEVICE TRUE)
+endif()
+file(APPEND "${boxconfig_h_file}" "#cmakedefine RANDOM_DEVICE \"${RANDOM_DEVICE}\"\n")
+file(APPEND "${boxconfig_h_file}" "#cmakedefine HAVE_RANDOM_DEVICE\n")
+
+# Build an intermediate version of BoxConfig.cmake.h for use in the following tests:
+configure_file("${boxconfig_h_file}" "${boxconfig_cmake_h_dir}/BoxConfig.cmake.h")
+
+foreach(struct_member_name "struct ucred.uid" "struct ucred.cr_uid")
+ string(REGEX MATCH "(.*)\\.(.*)" dummy_var ${struct_member_name})
+ set(struct_name "${CMAKE_MATCH_1}")
+ set(member_name "${CMAKE_MATCH_2}")
+
+ string(TOUPPER "${struct_name}_${member_name}" platform_var_name)
+ string(REGEX REPLACE "[/. ]" "_" platform_var_name ${platform_var_name})
+
+ CHECK_CXX_SOURCE_COMPILES([=[
+ #include "BoxConfig.cmake.h"
+
+ #ifdef HAVE_UCRED_H
+ # include <ucred.h>
+ #endif
+
+ #ifdef HAVE_SYS_PARAM_H
+ # include <sys/param.h>
+ #endif
+
+ #ifdef HAVE_SYS_UCRED_H
+ # include <sys/ucred.h>
+ #endif
+
+ #ifdef HAVE_SYS_SOCKET_H
+ # include <sys/socket.h>
+ #endif
+
+ int main()
+ {
+ ${struct_name} foo;
+ return sizeof(foo.${member_name}) > 0 ? 0 : 1;
+ }
+ ]=] "HAVE_${platform_var_name}")
+ file(APPEND "${boxconfig_h_file}" "#cmakedefine HAVE_${platform_var_name}\n")
+endforeach()
+set(CMAKE_REQUIRED_INCLUDES "")
+
+# Build the final version of BoxConfig.cmake.h, as a temporary file.
+configure_file("${boxconfig_h_file}" "${boxconfig_cmake_h_dir}/BoxConfig.cmake.h.new")
+
+# Move the original back into place, and then replace it with the
+# temporary one if different (which will force a rebuild of everything).
+move_file_if_exists(
+ "${boxconfig_cmake_h_dir}/BoxConfig.cmake.h.bak"
+ "${boxconfig_cmake_h_dir}/BoxConfig.cmake.h")
+replace_file_if_different(
+ "${boxconfig_cmake_h_dir}/BoxConfig.cmake.h"
+ "${boxconfig_cmake_h_dir}/BoxConfig.cmake.h.new")
+
+# Tell QDBM not to build itself as a DLL, because we want to link statically to it.
+target_compile_definitions(qdbm PUBLIC -DQDBM_STATIC)
+
+# Silence some less-useful warnings
+if(MSVC)
+ add_definitions(/wd4291 /wd4710 /wd4820 /wd4996)
+ set_property(TARGET qdbm PROPERTY CMAKE_STATIC_LINKER_FLAGS /IGNORE:LNK4006)
+endif(MSVC)
# Define the location of the Perl executable, needed by testbackupstorefix
-cmake_to_native_path("${PERL_EXECUTABLE}" perl_executable_native)
+file(TO_NATIVE_PATH "${PERL_EXECUTABLE}" perl_executable_native)
string(REPLACE "\\" "\\\\" perl_path_escaped ${perl_executable_native})
target_compile_definitions(test_backupstorefix PRIVATE -DPERL_EXECUTABLE="${perl_path_escaped}")
+
+# Configure test timeouts:
+# I've set the timeout to 4 times as long as it took to run on a particular run on Appveyor:
+# https://ci.appveyor.com/project/qris/boxbackup/build/job/xm10itascygtu93j
+set_tests_properties(common PROPERTIES TIMEOUT 20)
+set_tests_properties(crypto PROPERTIES TIMEOUT 10)
+set_tests_properties(compress PROPERTIES TIMEOUT 80)
+set_tests_properties(raidfile PROPERTIES TIMEOUT 32)
+set_tests_properties(basicserver PROPERTIES TIMEOUT 80)
+set_tests_properties(backupstore PROPERTIES TIMEOUT 1320)
+set_tests_properties(backupstorefix PROPERTIES TIMEOUT 180)
+set_tests_properties(backupstorepatch PROPERTIES TIMEOUT 320)
+set_tests_properties(backupdiff PROPERTIES TIMEOUT 32)
+set_tests_properties(bbackupd PROPERTIES TIMEOUT 1200)
+set_tests_properties(s3store PROPERTIES TIMEOUT 20)
+set_tests_properties(httpserver PROPERTIES TIMEOUT 40)
+
+set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Box Backup is an open source, completely automatic, on-line backup system")
+set(CPACK_PACKAGE_VENDOR "www.BoxBackup.org")
+set(CPACK_PACKAGE_DESCRIPTION_FILE "${base_dir}/README.md")
+set(CPACK_RESOURCE_FILE_LICENSE "${base_dir}/LICENSE.txt")
+set(CPACK_PACKAGE_VERSION ${boxbackup_version})
+set(CPACK_PACKAGE_INSTALL_DIRECTORY "Box Backup")
+set(CPACK_COMPONENTS_ALL Applications Extras)
+set(CPACK_GENERATOR "ZIP;NSIS")
+set(CPACK_NSIS_DISPLAY_NAME "Box Backup")
+set(CPACK_NSIS_HELP_LINK "http://www.boxbackup.org/")
+set(CPACK_NSIS_URL_INFO_ABOUT "http://www.boxbackup.org/")
+set(CPACK_NSIS_CONTACT "boxbackup@boxbackup.org")
+set(CPACK_NSIS_MODIFY_PATH ON)
+include(CPack)