cmake_minimum_required(VERSION 2.6) 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 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/makeparcels.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}) foreach(file_to_configure ${files_to_configure}) configure_file("${base_dir}/${file_to_configure}.in" "${base_dir}/${file_to_configure}" @ONLY) endforeach() file(READ "${base_dir}/infrastructure/buildenv-testmain-template.cpp" test_template) 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}") 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() 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}) 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}") 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))$") else() set(dependencies "${dependencies} lib_common") endif() 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}) 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() 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") add_test(NAME ${test_name} COMMAND ${PERL_EXECUTABLE} ${base_dir}/runtest.pl.in ${test_name} $ 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() if(module_name MATCHES "^(bin|test)_") # We need to install binaries in specific places so that test # runner can find them: install(FILES "$" CONFIGURATIONS Debug DESTINATION "${base_dir}/debug/${module_dir}" RENAME "${bin_name}${CMAKE_EXECUTABLE_SUFFIX}") install(FILES "$" 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) 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() #include(ExternalProject) #ExternalProject_Add(pcre # PREFIX "../pcre" # BUILD_COMMAND "${CMAKE_EXECUTABLE # 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(/wd4996 /wd4291) # target_link_libraries(qdbm PRIVATE /IGNORE:LNK4006) set_property(TARGET qdbm PROPERTY CMAKE_STATIC_LINKER_FLAGS /IGNORE:LNK4006) endif(MSVC) target_link_libraries(lib_common PUBLIC ws2_32 gdi32) # 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}) # 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}) # 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}") # Define the location of the Perl executable, needed by testbackupstorefix cmake_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}")