summaryrefslogtreecommitdiff
path: root/infrastructure/cmake
diff options
context:
space:
mode:
Diffstat (limited to 'infrastructure/cmake')
-rw-r--r--infrastructure/cmake/.gitignore6
-rw-r--r--infrastructure/cmake/CMakeLists.txt744
-rw-r--r--infrastructure/cmake/FindReadline.cmake84
-rwxr-xr-xinfrastructure/cmake/build/bin_bbackupd.vcxproj.user8
-rwxr-xr-xinfrastructure/cmake/build/bin_bbstored.vcxproj.user8
-rwxr-xr-xinfrastructure/cmake/build/test_backupstore.vcxproj.user9
-rwxr-xr-xinfrastructure/cmake/build/test_backupstorefix.vcxproj.user7
-rwxr-xr-xinfrastructure/cmake/build/test_bbackupd.vcxproj.user8
-rwxr-xr-xinfrastructure/cmake/build/test_common.vcxproj.user7
-rwxr-xr-xinfrastructure/cmake/build/test_httpserver.vcxproj.user7
-rwxr-xr-xinfrastructure/cmake/build/test_raidfile.vcxproj.user7
-rwxr-xr-xinfrastructure/cmake/getversion.pl13
-rwxr-xr-xinfrastructure/cmake/msvc/bin_bbackupd.vcxproj.user8
-rwxr-xr-xinfrastructure/cmake/msvc/bin_bbstored.vcxproj.user8
-rwxr-xr-xinfrastructure/cmake/msvc/test_backupstore.vcxproj.user9
-rwxr-xr-xinfrastructure/cmake/msvc/test_backupstorefix.vcxproj.user7
-rwxr-xr-xinfrastructure/cmake/msvc/test_bbackupd.vcxproj.user8
-rwxr-xr-xinfrastructure/cmake/msvc/test_common.vcxproj.user7
-rwxr-xr-xinfrastructure/cmake/msvc/test_httpserver.vcxproj.user7
-rwxr-xr-xinfrastructure/cmake/msvc/test_raidfile.vcxproj.user7
-rw-r--r--infrastructure/cmake/windows/CMakeLists.txt137
21 files changed, 1106 insertions, 0 deletions
diff --git a/infrastructure/cmake/.gitignore b/infrastructure/cmake/.gitignore
new file mode 100644
index 00000000..b27d6b9f
--- /dev/null
+++ b/infrastructure/cmake/.gitignore
@@ -0,0 +1,6 @@
+*.vcxproj
+*.vcxproj.filters
+BoxBackup.sln
+CMakeCache.txt
+CMakeFiles
+cmake_install.cmake
diff --git a/infrastructure/cmake/CMakeLists.txt b/infrastructure/cmake/CMakeLists.txt
new file mode 100644
index 00000000..65f59eb8
--- /dev/null
+++ b/infrastructure/cmake/CMakeLists.txt
@@ -0,0 +1,744 @@
+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}/../..)
+
+set(files_to_configure
+ bin/bbackupd/bbackupd-config
+ bin/bbstored/bbstored-certs
+ bin/bbstored/bbstored-config
+ contrib/mac_osx/org.boxbackup.bbackupd.plist
+ contrib/mac_osx/org.boxbackup.bbstored.plist
+ contrib/solaris/bbackupd-manifest.xml
+ contrib/solaris/bbstored-manifest.xml
+ contrib/debian/bbackupd
+ contrib/debian/bbstored
+ contrib/redhat/bbackupd
+ contrib/redhat/bbstored
+ contrib/suse/bbackupd
+ contrib/suse/bbstored
+ contrib/solaris/bbackupd-smf-method
+ contrib/solaris/bbstored-smf-method
+ contrib/windows/installer/boxbackup.mpi
+ infrastructure/BoxPlatform.pm
+ infrastructure/makebuildenv.pl
+ infrastructure/makedistribution.pl
+ lib/bbackupquery/makedocumentation.pl
+ lib/common/BoxPortsAndFiles.h
+ lib/common/makeexception.pl
+ lib/raidfile/raidfile-config
+ lib/server/makeprotocol.pl
+ runtest.pl
+ test/backupstorefix/testfiles/testbackupstorefix.pl
+ test/bbackupd/testfiles/bbackupd.conf
+ test/bbackupd/testfiles/bbackupd-exclude.conf
+ test/bbackupd/testfiles/bbackupd-snapshot.conf
+ test/bbackupd/testfiles/bbackupd-symlink.conf
+ test/bbackupd/testfiles/bbackupd-temploc.conf
+ test/bbackupd/testfiles/extcheck1.pl
+ test/bbackupd/testfiles/extcheck2.pl
+ test/bbackupd/testfiles/notifyscript.pl
+ test/bbackupd/testfiles/syncallowscript.pl
+)
+
+# We need to substitute TARGET_PERL in test/bbackupd/testfiles/bbackupd.conf, so define it
+# as a variable before running configure_file().
+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}.out" @ONLY)
+ replace_file_if_different(
+ "${base_dir}/${file_to_configure}"
+ "${base_dir}/${file_to_configure}.out")
+endforeach()
+
+# 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)
+
+if(WIN32)
+ add_definitions(-DWIN32)
+endif()
+
+# Parsing Makefile.extra files in CMake script is a pain, so the relevant rules for
+# code-generating Perl scripts are hard-coded here.
+
+set(exception_files
+ lib/backupclient/ClientException.txt
+ lib/backupstore/BackupStoreException.txt
+ lib/common/CommonException.txt
+ lib/common/ConversionException.txt
+ lib/compress/CompressException.txt
+ lib/crypto/CipherException.txt
+ lib/httpserver/HTTPException.txt
+ lib/raidfile/RaidFileException.txt
+ lib/server/ServerException.txt
+ lib/server/ConnectionException.txt
+)
+
+foreach(exception_file ${exception_files})
+ string(REGEX MATCH "(.*)/(.*).txt" valid_exception_file ${exception_file})
+ if(NOT valid_exception_file)
+ message(FATAL_ERROR "invalid exception file: '${exception_file}'")
+ endif()
+
+ set(output_file "${base_dir}/${CMAKE_MATCH_1}/autogen_${CMAKE_MATCH_2}.cpp")
+ add_custom_command(OUTPUT "${output_file}"
+ MAIN_DEPENDENCY "${base_dir}/${exception_file}"
+ COMMAND ${PERL_EXECUTABLE} "${base_dir}/lib/common/makeexception.pl" "${CMAKE_MATCH_2}.txt"
+ WORKING_DIRECTORY "${base_dir}/${CMAKE_MATCH_1}")
+
+ string(REPLACE "/" "_" module_name ${CMAKE_MATCH_1})
+ set(${module_name}_extra_files ${${module_name}_extra_files} ${output_file})
+endforeach()
+
+set(protocol_files
+ lib/backupstore/BackupProtocol.txt
+ test/basicserver/TestProtocol.txt
+)
+
+foreach(protocol_file ${protocol_files})
+ string(REGEX MATCH "(.*)/(.*).txt" valid_protocol_file ${protocol_file})
+ if(NOT valid_protocol_file)
+ message(FATAL_ERROR "invalid protocol file: '${protocol_file}'")
+ endif()
+
+ set(output_file "${base_dir}/${CMAKE_MATCH_1}/autogen_${CMAKE_MATCH_2}.cpp")
+ add_custom_command(OUTPUT "${output_file}"
+ MAIN_DEPENDENCY "${base_dir}/${protocol_file}"
+ COMMAND ${PERL_EXECUTABLE} "${base_dir}/lib/server/makeprotocol.pl" "${CMAKE_MATCH_2}.txt"
+ WORKING_DIRECTORY "${base_dir}/${CMAKE_MATCH_1}")
+
+ string(REPLACE "/" "_" module_name ${CMAKE_MATCH_1})
+ set(${module_name}_extra_files ${${module_name}_extra_files} ${output_file})
+endforeach()
+
+set(documentation_files
+ lib/bbackupquery/Documentation.txt
+)
+
+foreach(documentation_file ${documentation_files})
+ string(REGEX MATCH "(.*)/(.*).txt" valid_documentation_file ${documentation_file})
+ if(NOT valid_documentation_file)
+ message(FATAL_ERROR "invalid documentation file: '${documentation_file}'")
+ endif()
+
+ set(output_file "${base_dir}/${CMAKE_MATCH_1}/autogen_${CMAKE_MATCH_2}.cpp")
+ add_custom_command(OUTPUT "${output_file}"
+ MAIN_DEPENDENCY "${base_dir}/${documentation_file}"
+ COMMAND ${PERL_EXECUTABLE} "${base_dir}/lib/bbackupquery/makedocumentation.pl"
+ WORKING_DIRECTORY "${base_dir}/${CMAKE_MATCH_1}")
+
+ string(REPLACE "/" "_" module_name ${CMAKE_MATCH_1})
+ 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 "^[^#]")
+foreach(module_dep ${module_deps})
+
+ string(REGEX MATCH "([^ ]+)[ ]*(.*)" valid_module_line ${module_dep})
+ if(valid_module_line)
+ if(DEBUG)
+ message(STATUS "found module: ${CMAKE_MATCH_1} -> ${CMAKE_MATCH_2}")
+ endif()
+
+ set(module_dir ${CMAKE_MATCH_1})
+ set(module_path ${base_dir}/${module_dir})
+ string(REPLACE "/" "_" module_name ${CMAKE_MATCH_1})
+ string(REPLACE "/" "_" dependencies "${CMAKE_MATCH_2}")
+
+ # 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()
+ 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}")
+
+ if(module_name MATCHES "^bin_")
+ string(REGEX MATCH "^bin_(.*)" valid_exe ${module_name})
+ set(bin_name ${CMAKE_MATCH_1})
+ 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})
+ set(bin_name ${module_name})
+
+ if(DEBUG)
+ message(STATUS "add test '${module_name}': '${module_files}'")
+ endif()
+
+ 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
+ ${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}'")
+ endif()
+ add_library(${module_name} STATIC ${module_files})
+ else()
+ message(FATAL_ERROR "Unsupported module type: " ${module_name})
+ endif()
+
+ target_compile_definitions(${module_name} PRIVATE -DBOX_MODULE="${module_name}")
+
+ if(dependencies)
+ string(REGEX REPLACE "[ ]+" ";" dependency_list "${dependencies}")
+
+ foreach(dependency ${dependency_list})
+ if(DEBUG)
+ message(STATUS "add dependency to '${module_name}': '${dependency}'")
+ endif()
+ add_dependencies(${module_name} ${dependency})
+ if(dependency MATCHES "^(lib_.*|qdbm)$")
+ # message(STATUS "add link library to '${module_name}': '${dependency}'")
+ target_link_libraries(${module_name} PUBLIC ${dependency})
+ endif()
+
+ # We can't make a binary depend on another binary, so we need to
+ # add the dependency's directory directly to our include path.
+ if(dependency MATCHES "^bin_")
+ get_property(dep_include_dirs
+ TARGET ${dependency}
+ PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
+ target_include_directories(${module_name}
+ PUBLIC ${dep_include_dirs})
+ endif()
+ endforeach()
+ endif()
+
+ target_include_directories(${module_name} PUBLIC ${module_path})
+ endif()
+endforeach()
+
+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()
+
+# 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>)
+
+# 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()
+
+# 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()
+
+ 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
+# 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
+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
+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)
diff --git a/infrastructure/cmake/FindReadline.cmake b/infrastructure/cmake/FindReadline.cmake
new file mode 100644
index 00000000..3ba4d21d
--- /dev/null
+++ b/infrastructure/cmake/FindReadline.cmake
@@ -0,0 +1,84 @@
+# https://github.com/bro/cmake/blob/master/FindReadline.cmake
+#
+# Copyright (c) 1995-2015, The Regents of the University of California
+# through the Lawrence Berkeley National Laboratory and the
+# International Computer Science Institute. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# (1) Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# (2) Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# (3) Neither the name of the University of California, Lawrence Berkeley
+# National Laboratory, U.S. Dept. of Energy, International Computer
+# Science Institute, nor the names of contributors may be used to endorse
+# or promote products derived from this software without specific prior
+# written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# Note that some files in the distribution may carry their own copyright
+# notices.
+
+# - Try to find readline include dirs and libraries
+#
+# Usage of this module as follows:
+#
+# find_package(Readline)
+#
+# Variables used by this module, they can change the default behaviour and need
+# to be set before calling find_package:
+#
+# Readline_ROOT_DIR Set this variable to the root installation of
+# readline if the module has problems finding the
+# proper installation path.
+#
+# Variables defined by this module:
+#
+# READLINE_FOUND System has readline, include and lib dirs found
+# Readline_INCLUDE_DIR The readline include directories.
+# Readline_LIBRARY The readline library.
+
+find_path(Readline_ROOT_DIR
+ NAMES include/readline/readline.h
+)
+
+find_path(Readline_INCLUDE_DIR
+ NAMES readline/readline.h
+ HINTS ${Readline_ROOT_DIR}/include
+)
+
+find_library(Readline_LIBRARY
+ NAMES readline
+ HINTS ${Readline_ROOT_DIR}/lib
+)
+
+if(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
+ set(READLINE_FOUND TRUE)
+else(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
+ FIND_LIBRARY(Readline_LIBRARY NAMES readline)
+ include(FindPackageHandleStandardArgs)
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS(Readline DEFAULT_MSG Readline_INCLUDE_DIR Readline_LIBRARY )
+ MARK_AS_ADVANCED(Readline_INCLUDE_DIR Readline_LIBRARY)
+endif(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
+
+mark_as_advanced(
+ Readline_ROOT_DIR
+ Readline_INCLUDE_DIR
+ Readline_LIBRARY
+)
diff --git a/infrastructure/cmake/build/bin_bbackupd.vcxproj.user b/infrastructure/cmake/build/bin_bbackupd.vcxproj.user
new file mode 100755
index 00000000..fa1f3d34
--- /dev/null
+++ b/infrastructure/cmake/build/bin_bbackupd.vcxproj.user
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LocalDebuggerCommandArguments>testfiles\bbackupd.conf</LocalDebuggerCommandArguments>
+ <LocalDebuggerWorkingDirectory>$(ProjectDir)\..\..\..\debug\test\bbackupd</LocalDebuggerWorkingDirectory>
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/infrastructure/cmake/build/bin_bbstored.vcxproj.user b/infrastructure/cmake/build/bin_bbstored.vcxproj.user
new file mode 100755
index 00000000..339cddee
--- /dev/null
+++ b/infrastructure/cmake/build/bin_bbstored.vcxproj.user
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LocalDebuggerCommandArguments>testfiles/bbstored.conf</LocalDebuggerCommandArguments>
+ <LocalDebuggerWorkingDirectory>$(ProjectDir)\..\..\..\debug\test\backupstorefix</LocalDebuggerWorkingDirectory>
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/infrastructure/cmake/build/test_backupstore.vcxproj.user b/infrastructure/cmake/build/test_backupstore.vcxproj.user
new file mode 100755
index 00000000..7d7b3158
--- /dev/null
+++ b/infrastructure/cmake/build/test_backupstore.vcxproj.user
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LocalDebuggerWorkingDirectory>$(ProjectDir)\..\..\..\debug\test\backupstore</LocalDebuggerWorkingDirectory>
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+ <LocalDebuggerCommandArguments>
+ </LocalDebuggerCommandArguments>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/infrastructure/cmake/build/test_backupstorefix.vcxproj.user b/infrastructure/cmake/build/test_backupstorefix.vcxproj.user
new file mode 100755
index 00000000..170fb496
--- /dev/null
+++ b/infrastructure/cmake/build/test_backupstorefix.vcxproj.user
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LocalDebuggerWorkingDirectory>$(ProjectDir)\..\..\..\debug\test\backupstorefix</LocalDebuggerWorkingDirectory>
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/infrastructure/cmake/build/test_bbackupd.vcxproj.user b/infrastructure/cmake/build/test_bbackupd.vcxproj.user
new file mode 100755
index 00000000..ebf8c6a3
--- /dev/null
+++ b/infrastructure/cmake/build/test_bbackupd.vcxproj.user
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LocalDebuggerCommandArguments>-e test_basics</LocalDebuggerCommandArguments>
+ <LocalDebuggerWorkingDirectory>$(ProjectDir)\..\..\..\debug\test\bbackupd</LocalDebuggerWorkingDirectory>
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/infrastructure/cmake/build/test_common.vcxproj.user b/infrastructure/cmake/build/test_common.vcxproj.user
new file mode 100755
index 00000000..e5854a80
--- /dev/null
+++ b/infrastructure/cmake/build/test_common.vcxproj.user
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LocalDebuggerWorkingDirectory>$(ProjectDir)\..\..\..\debug\test\common</LocalDebuggerWorkingDirectory>
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/infrastructure/cmake/build/test_httpserver.vcxproj.user b/infrastructure/cmake/build/test_httpserver.vcxproj.user
new file mode 100755
index 00000000..ac1512a8
--- /dev/null
+++ b/infrastructure/cmake/build/test_httpserver.vcxproj.user
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LocalDebuggerWorkingDirectory>$(ProjectDir)\..\..\..\debug\test\httpserver</LocalDebuggerWorkingDirectory>
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/infrastructure/cmake/build/test_raidfile.vcxproj.user b/infrastructure/cmake/build/test_raidfile.vcxproj.user
new file mode 100755
index 00000000..620aa4bb
--- /dev/null
+++ b/infrastructure/cmake/build/test_raidfile.vcxproj.user
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LocalDebuggerWorkingDirectory>$(ProjectDir)\..\..\..\debug\test\raidfile</LocalDebuggerWorkingDirectory>
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/infrastructure/cmake/getversion.pl b/infrastructure/cmake/getversion.pl
new file mode 100755
index 00000000..d7ca0333
--- /dev/null
+++ b/infrastructure/cmake/getversion.pl
@@ -0,0 +1,13 @@
+#!perl
+
+use File::Basename;
+$basedir = dirname($0)."/../..";
+
+-d $basedir or die "Base directory $basedir does not exist!";
+chdir $basedir or die "Failed to change to base directory: $basedir: $!";
+
+require "$basedir/infrastructure/BoxPlatform.pm.in";
+
+print "$BoxPlatform::product_version\n";
+
+exit 0;
diff --git a/infrastructure/cmake/msvc/bin_bbackupd.vcxproj.user b/infrastructure/cmake/msvc/bin_bbackupd.vcxproj.user
new file mode 100755
index 00000000..fa1f3d34
--- /dev/null
+++ b/infrastructure/cmake/msvc/bin_bbackupd.vcxproj.user
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LocalDebuggerCommandArguments>testfiles\bbackupd.conf</LocalDebuggerCommandArguments>
+ <LocalDebuggerWorkingDirectory>$(ProjectDir)\..\..\..\debug\test\bbackupd</LocalDebuggerWorkingDirectory>
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/infrastructure/cmake/msvc/bin_bbstored.vcxproj.user b/infrastructure/cmake/msvc/bin_bbstored.vcxproj.user
new file mode 100755
index 00000000..339cddee
--- /dev/null
+++ b/infrastructure/cmake/msvc/bin_bbstored.vcxproj.user
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LocalDebuggerCommandArguments>testfiles/bbstored.conf</LocalDebuggerCommandArguments>
+ <LocalDebuggerWorkingDirectory>$(ProjectDir)\..\..\..\debug\test\backupstorefix</LocalDebuggerWorkingDirectory>
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/infrastructure/cmake/msvc/test_backupstore.vcxproj.user b/infrastructure/cmake/msvc/test_backupstore.vcxproj.user
new file mode 100755
index 00000000..7d7b3158
--- /dev/null
+++ b/infrastructure/cmake/msvc/test_backupstore.vcxproj.user
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LocalDebuggerWorkingDirectory>$(ProjectDir)\..\..\..\debug\test\backupstore</LocalDebuggerWorkingDirectory>
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+ <LocalDebuggerCommandArguments>
+ </LocalDebuggerCommandArguments>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/infrastructure/cmake/msvc/test_backupstorefix.vcxproj.user b/infrastructure/cmake/msvc/test_backupstorefix.vcxproj.user
new file mode 100755
index 00000000..170fb496
--- /dev/null
+++ b/infrastructure/cmake/msvc/test_backupstorefix.vcxproj.user
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LocalDebuggerWorkingDirectory>$(ProjectDir)\..\..\..\debug\test\backupstorefix</LocalDebuggerWorkingDirectory>
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/infrastructure/cmake/msvc/test_bbackupd.vcxproj.user b/infrastructure/cmake/msvc/test_bbackupd.vcxproj.user
new file mode 100755
index 00000000..ebf8c6a3
--- /dev/null
+++ b/infrastructure/cmake/msvc/test_bbackupd.vcxproj.user
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LocalDebuggerCommandArguments>-e test_basics</LocalDebuggerCommandArguments>
+ <LocalDebuggerWorkingDirectory>$(ProjectDir)\..\..\..\debug\test\bbackupd</LocalDebuggerWorkingDirectory>
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/infrastructure/cmake/msvc/test_common.vcxproj.user b/infrastructure/cmake/msvc/test_common.vcxproj.user
new file mode 100755
index 00000000..e5854a80
--- /dev/null
+++ b/infrastructure/cmake/msvc/test_common.vcxproj.user
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LocalDebuggerWorkingDirectory>$(ProjectDir)\..\..\..\debug\test\common</LocalDebuggerWorkingDirectory>
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/infrastructure/cmake/msvc/test_httpserver.vcxproj.user b/infrastructure/cmake/msvc/test_httpserver.vcxproj.user
new file mode 100755
index 00000000..ac1512a8
--- /dev/null
+++ b/infrastructure/cmake/msvc/test_httpserver.vcxproj.user
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LocalDebuggerWorkingDirectory>$(ProjectDir)\..\..\..\debug\test\httpserver</LocalDebuggerWorkingDirectory>
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/infrastructure/cmake/msvc/test_raidfile.vcxproj.user b/infrastructure/cmake/msvc/test_raidfile.vcxproj.user
new file mode 100755
index 00000000..620aa4bb
--- /dev/null
+++ b/infrastructure/cmake/msvc/test_raidfile.vcxproj.user
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LocalDebuggerWorkingDirectory>$(ProjectDir)\..\..\..\debug\test\raidfile</LocalDebuggerWorkingDirectory>
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/infrastructure/cmake/windows/CMakeLists.txt b/infrastructure/cmake/windows/CMakeLists.txt
new file mode 100644
index 00000000..49a1ea4d
--- /dev/null
+++ b/infrastructure/cmake/windows/CMakeLists.txt
@@ -0,0 +1,137 @@
+cmake_minimum_required(VERSION 2.6)
+
+project(BoxBackup_Windows)
+
+set(boxbackup_dir ${CMAKE_SOURCE_DIR}/../../..)
+set_property(DIRECTORY PROPERTY EP_BASE .)
+set(install_dir ${CMAKE_BINARY_DIR}/install)
+
+# Automate the process of downloading, building and "installing" dependencies on Windows,
+# as used by AppVeyor.
+
+# Version of zlib to download, build, and compile Box Backup against:
+set(ZLIB_VERSION 1.2.11)
+# Hash of zlib-${ZLIB_VERSION}.tar.gz, to be verified after download:
+set(ZLIB_HASH SHA256=c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1)
+
+# Version of OpenSSL to download, build, and compile Box Backup against:
+set(OPENSSL_VERSION 1.1.0g)
+# Hash of openssl-${OPENSSL_VERSION}.tar.gz, to be verified after download:
+set(OPENSSL_HASH SHA256=de4d501267da39310905cb6dc8c6121f7a2cad45a7707f76df828fe1b85073af)
+
+# Version of PCRE to download, build, and compile Box Backup against:
+set(PCRE_VERSION 8.39)
+# Hash of pcre-${PCRE_VERSION}.tar.gz, to be verified after download:
+set(PCRE_HASH SHA256=ccdf7e788769838f8285b3ee672ed573358202305ee361cfec7a4a4fb005bbc7)
+
+# Version of Boost to download, unpack, and compile Box Backup against:
+set(BOOST_VERSION 1.62.0)
+# Hash of the Boost download file, to be verified after download:
+set(BOOST_HASH SHA1=5fd97433c3f859d8cbab1eaed4156d3068ae3648)
+
+include(ExternalProject)
+
+ExternalProject_Add(zlib
+ URL "http://zlib.net/zlib-${ZLIB_VERSION}.tar.gz"
+ URL_HASH ${ZLIB_HASH}
+ DOWNLOAD_NO_PROGRESS 1
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${install_dir} ${SUB_CMAKE_EXTRA_ARGS}
+ # We need to build both versions, debug and release, because cmake requires both to be
+ # present to generate its multi-configuration project files for Visual Studio/MSBuild.
+ INSTALL_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --target install --config Debug
+ COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --target install --config Release
+ STEP_TARGETS configure install
+)
+
+if(WIN32)
+ ExternalProject_Add(openssl
+ DEPENDS zlib
+ URL "https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz"
+ URL_HASH ${OPENSSL_HASH}
+ DOWNLOAD_NO_PROGRESS 1
+ CONFIGURE_COMMAND perl Configure debug-VC-WIN32 no-asm no-shared
+ --prefix=${install_dir}
+ --openssldir=etc
+ # Run tests before install, but don't make the main target depend on them, so that
+ # we don't have to run them whenever we build manually on Windows.
+ TEST_BEFORE_INSTALL 1
+ TEST_EXCLUDE_FROM_MAIN 1
+ # You would expect us to use nt.mak to compile a static library here, but mk1mf.pl uses the /MT[d]
+ # CRT in that case, which is incompatible with our dynamic runtime, /MD[d]. It seems that the libs
+ # built by ntdll.mak, which are compiled with /MD[d], are full libraries and not import libs,
+ # so we can link statically against them and still get a dynamic runtime.
+ BUILD_IN_SOURCE 1
+ BUILD_COMMAND nmake /s
+ TEST_COMMAND nmake /s test
+ INSTALL_COMMAND nmake /s install
+ )
+elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ ExternalProject_Add(openssl
+ DEPENDS zlib
+ URL "https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz"
+ URL_HASH ${OPENSSL_HASH}
+ DOWNLOAD_NO_PROGRESS 1
+ CONFIGURE_COMMAND perl Configure darwin64-x86_64-cc --prefix=${install_dir}
+ BUILD_IN_SOURCE 1
+ )
+else()
+ ExternalProject_Add(openssl
+ DEPENDS zlib
+ URL "https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz"
+ URL_HASH ${OPENSSL_HASH}
+ DOWNLOAD_NO_PROGRESS 1
+ CONFIGURE_COMMAND ./config --prefix=${install_dir}
+ BUILD_IN_SOURCE 1
+ )
+
+endif()
+
+ExternalProject_Add(pcre
+ # Temporarily use SVN repo until the PCRE_STATIC issue in 8.40 is fixed:
+ # https://vcs.pcre.org/pcre?view=revision&revision=1677
+ SVN_REPOSITORY svn://vcs.exim.org/pcre/code/trunk
+ SVN_REVISION -r 1677
+ DOWNLOAD_NO_PROGRESS 1
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${install_dir} ${SUB_CMAKE_EXTRA_ARGS}
+ -DPCRE_SUPPORT_LIBREADLINE=OFF
+ -DPCRE_SUPPORT_LIBBZ2=OFF
+ # We need to build both versions, debug and release, because cmake requires both to be
+ # present to generate its multi-configuration project files for Visual Studio/MSBuild.
+ INSTALL_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --target install --config Debug
+ COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --target install --config Release
+)
+
+string(REPLACE "." "_" BOOST_VERSION_UNDERSCORES ${BOOST_VERSION})
+ExternalProject_Add(boost
+ URL "http://downloads.sourceforge.net/project/boost/boost/${BOOST_VERSION}/boost_${BOOST_VERSION_UNDERSCORES}.tar.bz2"
+ URL_HASH ${BOOST_HASH}
+ # DOWNLOAD_NO_PROGRESS 1
+ # Disable automatic updating (untarring) as it's slow and not necessary
+ UPDATE_DISCONNECTED 1
+ CONFIGURE_COMMAND ${CMAKE_COMMAND} -E echo "No configure step needed"
+ BUILD_COMMAND ${CMAKE_COMMAND} -E echo "No build step needed"
+ INSTALL_COMMAND ${CMAKE_COMMAND} -E echo "No install step needed"
+)
+
+if(BOXBACKUP_VERSION)
+ list(APPEND boxbackup_cmake_args "-DBOXBACKUP_VERSION=${BOXBACKUP_VERSION}")
+endif()
+string(REPLACE ";" " " boxbackup_cmake_args "${boxbackup_cmake_args}")
+
+ExternalProject_Add(boxbackup
+ DEPENDS zlib openssl pcre boost
+ SOURCE_DIR ${boxbackup_dir}/infrastructure/cmake
+ CMAKE_ARGS
+ -DZLIB_ROOT=${install_dir}
+ -DOPENSSL_ROOT_DIR=${install_dir}
+ -DPCRE_ROOT=${install_dir}
+ -DBOOST_ROOT=${CMAKE_BINARY_DIR}/Source/boost
+ -DBOX_SUPPORT_READLINE=OFF
+ -DCMAKE_INSTALL_PREFIX=${install_dir}
+ -DAPPVEYOR_MODE=1
+ -DDEBUG=${DEBUG}
+ ${boxbackup_cmake_args}
+ ${SUB_CMAKE_EXTRA_ARGS}
+ INSTALL_COMMAND ${CMAKE_COMMAND} -E echo "No install step needed"
+ STEP_TARGETS configure build
+)