diff options
Diffstat (limited to 'infrastructure')
-rw-r--r-- | infrastructure/cmake/CMakeLists.txt | 289 | ||||
-rwxr-xr-x | infrastructure/cmake/getversion.pl | 13 | ||||
-rwxr-xr-x | infrastructure/travis-build.sh | 30 |
3 files changed, 305 insertions, 27 deletions
diff --git a/infrastructure/cmake/CMakeLists.txt b/infrastructure/cmake/CMakeLists.txt index 0838045a..fa364690 100644 --- a/infrastructure/cmake/CMakeLists.txt +++ b/infrastructure/cmake/CMakeLists.txt @@ -75,24 +75,31 @@ 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) - - +# 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/msvc/getversion.pl + COMMAND ${PERL_EXECUTABLE} ${base_dir}/infrastructure/cmake/getversion.pl + WORKING_DIRECTORY ${base_dir}/infrastructure RESULT_VARIABLE status - OUTPUT_VARIABLE command_output + OUTPUT_VARIABLE new_version_define ERROR_VARIABLE command_output) if(NOT status EQUAL 0) message(FATAL_ERROR "Failed to execute: " - "${PERL_EXECUTABLE} ${base_dir}/infrastructure/msvc/getversion.pl: " + "${PERL_EXECUTABLE} ${base_dir}/infrastructure/cmake/getversion.pl: " "status ${status}: ${command_output}") endif() +file(WRITE "${base_dir}/lib/common/BoxVersion.h.new" "${new_version_define}") +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() +file(READ "${base_dir}/infrastructure/buildenv-testmain-template.cpp" test_template) + # Parsing Makefile.extra files in CMake script is a pain, so the relevant rules for # code-generating Perl scripts are hard-coded here. @@ -322,19 +329,24 @@ endforeach() # 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>:-DBOX_RELEASE_BUILD>) +target_compile_definitions(lib_common PUBLIC $<$<CONFIG:Release>:BOX_RELEASE_BUILD>) -# Tell QDBM not to build itself as a DLL, because we want to link statically to it. -target_compile_definitions(qdbm PUBLIC -DQDBM_STATIC) +# Detect platform features and write BoxConfig.h.in. Reuse code from +# infrastructure/m4/boxbackup_tests.m4 where possible -# 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) +include(CheckIncludeFiles) +include(CheckFunctionExists) +include(CheckSymbolExists) +include(CheckLibraryExists) +include(CheckCXXSourceCompiles) -target_link_libraries(lib_common PUBLIC ws2_32 gdi32) +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() # Link to ZLib # http://stackoverflow.com/a/6174604/648162 @@ -406,6 +418,251 @@ if(READLINE_FOUND) 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(/wd4996 /wd4291) + 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}) diff --git a/infrastructure/cmake/getversion.pl b/infrastructure/cmake/getversion.pl new file mode 100755 index 00000000..67e1f8a5 --- /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 "#define BOX_VERSION \"$BoxPlatform::product_version\"\n"; + +exit 0; diff --git a/infrastructure/travis-build.sh b/infrastructure/travis-build.sh index aa9f62c2..72a187b3 100755 --- a/infrastructure/travis-build.sh +++ b/infrastructure/travis-build.sh @@ -5,17 +5,25 @@ set -x ccache -s -cd `dirname $0`/.. -./bootstrap -./configure CC="ccache $CC" CXX="ccache $CXX" "$@" -grep CXX config.status -make V=1 -./runtest.pl ALL $TEST_TARGET -# When making a release build, also check that we can build the default -# target and "parcels" (which is the same thing): -if [ "$TEST_TARGET" = "release" ]; then - make - make parcels +if [ "$BUILD" = 'cmake' ]; then + cd `dirname $0` + mkdir -p cmake/build + cd cmake/build + cmake --version + cmake -DCMAKE_BUILD_TYPE:STRING=$TEST_TARGET .. + make install + [ "$TEST" = "n" ] || ctest -C $TEST_TARGET -V +else + cd `dirname $0`/.. + ./bootstrap + ./configure CC="ccache $CC" CXX="ccache $CXX" "$@" + grep CXX config.status + make V=1 + ./runtest.pl ALL $TEST_TARGET + if [ "$TEST_TARGET" = "release" ]; then + make + make parcels + fi fi ccache -s |