diff --git a/cmake/modules/NativeExecutable.cmake b/cmake/modules/NativeExecutable.cmake --- a/cmake/modules/NativeExecutable.cmake +++ b/cmake/modules/NativeExecutable.cmake @@ -1,132 +1,102 @@ # Allow to easily build native executable. # Useful for cross compilation. -if(NOT DEFINED __IS_NATIVE_BUILD) - # Check if we are in a native build or not. - set(__IS_NATIVE_BUILD 0 CACHE INTERNAL "Indicate if this is a native build") -endif() - -if(__IS_NATIVE_BUILD AND CMAKE_CROSSCOMPILING) - message(FATAL_ERROR "A native build cannot be cross compiled") -endif() - -# It is imperative that NATIVE_BUILD_DIR be in the cache. -set(NATIVE_BUILD_DIR "${CMAKE_BINARY_DIR}/native" CACHE PATH "The path of the native build directory" FORCE) - # Only ninja support depfiles and this is a hard error with other generators # so we need a nice wrapper to handle this mess. include(CustomCommandWithDepFile) +function(absolute_paths ABSOLUTE_PATHS) + foreach(RELATIVE_PATH ${ARGN}) + get_filename_component(ABSOLUTE_PATH "${RELATIVE_PATH}" ABSOLUTE) + list(APPEND ABSOLUTE_PATH_LIST "${ABSOLUTE_PATH}") + endforeach() + list(JOIN ABSOLUTE_PATH_LIST " " ${ABSOLUTE_PATHS}) + set(${ABSOLUTE_PATHS} "${${ABSOLUTE_PATHS}}" PARENT_SCOPE) +endfunction() + function(add_native_executable NAME) - if(__IS_NATIVE_BUILD) - add_executable(${NAME} EXCLUDE_FROM_ALL ${ARGN}) - # Multi-configuration generators (VS, Xcode) append a per-configuration - # subdirectory to the specified directory unless the - # `RUNTIME_OUTPUT_DIRECTORY` property is defined using a generator - # expression. - # Since we don't care about the build configuration for native - # executables, we can simply drop this subdirectory. - # Doing so ensure that the path to the binary can always be retrieved. - set_target_properties(${NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/$<0:>" - ) - else() - set(NATIVE_TARGET "${NAME}") - file(RELATIVE_PATH RELATIVE_PATH "${CMAKE_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}") - if(RELATIVE_PATH) - string(PREPEND NATIVE_TARGET "${RELATIVE_PATH}/") - endif() - if("${CMAKE_GENERATOR}" MATCHES "Ninja") - set(TARGET "${NATIVE_TARGET}") - else() - set(TARGET "${NAME}") - endif() - - set(NATIVE_BINARY "${NATIVE_BUILD_DIR}/${NATIVE_TARGET}") - set(NATIVE_LINK "${CMAKE_CURRENT_BINARY_DIR}/native-${NAME}") - - configure_file( - "${CMAKE_SOURCE_DIR}/cmake/templates/NativeBuildRunner.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/build_native_${NAME}.sh" - ) - - # We create a symlink because cmake craps itself if the imported - # executable has the same name as the executable itself. - # https://cmake.org/pipermail/cmake/2019-May/069480.html - add_custom_command_with_depfile( - OUTPUT "${NATIVE_LINK}" - COMMENT "Building native ${NATIVE_TARGET}" - COMMAND "${CMAKE_CURRENT_BINARY_DIR}/build_native_${NAME}.sh" - DEPENDS - native-cmake-build - "${CMAKE_CURRENT_BINARY_DIR}/build_native_${NAME}.sh" - ${ARGN} - DEPFILE "${NATIVE_LINK}.d" - VERBATIM USES_TERMINAL - ) - - add_executable(${NAME} IMPORTED GLOBAL) - set_target_properties(${NAME} PROPERTIES IMPORTED_LOCATION "${NATIVE_BINARY}") - - # This obviously cannot depend on a file for some mysterious reasons only - # the cmake gods are aware of, so we need a phony custom target. - add_custom_target("build-native-${NAME}" DEPENDS "${NATIVE_LINK}") - add_dependencies(${NAME} "build-native-${NAME}") - endif() -endfunction(add_native_executable) - -function(native_target_include_directories) - if(__IS_NATIVE_BUILD) - target_include_directories(${ARGN}) - endif() -endfunction(native_target_include_directories) - -function(native_add_cmake_flags) - set_property(GLOBAL APPEND PROPERTY _NATIVE_BUILD_CMAKE_FLAGS ${ARGN}) -endfunction(native_add_cmake_flags) - -# Internal machinery -function(_gen_native_cmake_target) - message(STATUS "Configuring native build in ${NATIVE_BUILD_DIR}") - - get_property(ARGSLIST GLOBAL PROPERTY _NATIVE_BUILD_CMAKE_FLAGS) - - list(SORT ARGSLIST) - list(REMOVE_DUPLICATES ARGSLIST) - list(JOIN ARGSLIST " " ARGS) + cmake_parse_arguments( + "" + "" + "" + "INCLUDE_DIRS;SOURCES" + ${ARGN} + ) + + # Inherits from the caller directory include directories + get_property(DIRECTORY_INCLUDE_DIRECTORIES DIRECTORY PROPERTY INCLUDE_DIRECTORIES) + + # Since the CMakeLists file will be generated outside of the source tree, we + # need to use absolute paths. + absolute_paths(ABS_SOURCES ${_SOURCES}) + absolute_paths(ABS_INCLUDE_DIRS ${DIRECTORY_INCLUDE_DIRECTORIES} ${_INCLUDE_DIRS}) + + set(NATIVE_LIST_DIR "${CMAKE_BINARY_DIR}/native/${NAME}") + set(NATIVE_BUILD_DIR "${NATIVE_LIST_DIR}/build") + + # Needed for the depfile generation + file(RELATIVE_PATH RELATIVE_BINARY_DIR "${CMAKE_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}") + file(RELATIVE_PATH RELATIVE_NATIVE_BUILD_DIR "${CMAKE_BINARY_DIR}" "${NATIVE_BUILD_DIR}") + + configure_file( + "${CMAKE_SOURCE_DIR}/cmake/templates/NativeCMakeLists.txt.in" + "${NATIVE_LIST_DIR}/CMakeLists.txt" + ) file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/config") configure_file( "${CMAKE_SOURCE_DIR}/cmake/templates/NativeCmakeRunner.cmake.in" - "${CMAKE_BINARY_DIR}/config/run_native_cmake.sh" + "${CMAKE_BINARY_DIR}/config/run_native_cmake_${NAME}.sh" ) -endfunction(_gen_native_cmake_target) -function(_gen_native_cmake_hook VAR ACCESS) - # When CMAKE_CURRENT_LIST_DIR is set to empty, we execute everything. - if("${VAR}" STREQUAL "CMAKE_CURRENT_LIST_DIR" AND - "${CMAKE_CURRENT_LIST_DIR}" STREQUAL "" AND - "${ACCESS}" STREQUAL "MODIFIED_ACCESS") - _gen_native_cmake_target() - endif() -endfunction(_gen_native_cmake_hook) + set(NATIVE_BINARY "${NATIVE_BUILD_DIR}/${NAME}") + set(NATIVE_LINK "${CMAKE_CURRENT_BINARY_DIR}/native-${NAME}") -if(NOT __IS_NATIVE_BUILD AND NOT TARGET native-cmake-build) - # Set a hook to execute when everything is set. - variable_watch(CMAKE_CURRENT_LIST_DIR _gen_native_cmake_hook) + configure_file( + "${CMAKE_SOURCE_DIR}/cmake/templates/NativeBuildRunner.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/build_native_${NAME}.sh" + ) add_custom_command_with_depfile( OUTPUT "${NATIVE_BUILD_DIR}/CMakeCache.txt" - COMMENT "Preparing native build..." - COMMAND "${CMAKE_BINARY_DIR}/config/run_native_cmake.sh" - DEPENDS "${CMAKE_BINARY_DIR}/config/run_native_cmake.sh" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + COMMENT "Preparing native build for ${NAME}..." + COMMAND "${CMAKE_BINARY_DIR}/config/run_native_cmake_${NAME}.sh" + DEPENDS "${CMAKE_BINARY_DIR}/config/run_native_cmake_${NAME}.sh" DEPFILE "${NATIVE_BUILD_DIR}/CMakeFiles/CMakeCache.txt.d" VERBATIM USES_TERMINAL ) - add_custom_target(native-cmake-build DEPENDS "${NATIVE_BUILD_DIR}/CMakeCache.txt") + add_custom_target(native-cmake-build-${NAME} + DEPENDS "${NATIVE_BUILD_DIR}/CMakeCache.txt" + ) + + # We create a symlink because cmake craps itself if the imported + # executable has the same name as the executable itself. + # https://cmake.org/pipermail/cmake/2019-May/069480.html + add_custom_command_with_depfile( + OUTPUT "${NATIVE_LINK}" + COMMENT "Building native ${NAME}" + COMMAND "${CMAKE_CURRENT_BINARY_DIR}/build_native_${NAME}.sh" + DEPENDS + native-cmake-build-${NAME} + "${CMAKE_CURRENT_BINARY_DIR}/build_native_${NAME}.sh" + ${ABS_SOURCES} + DEPFILE "${NATIVE_LINK}.d" + VERBATIM USES_TERMINAL + ) + + add_executable(${NAME} IMPORTED GLOBAL) + set_target_properties(${NAME} PROPERTIES IMPORTED_LOCATION "${NATIVE_BINARY}") + + # This obviously cannot depend on a file for some mysterious reasons only + # the cmake gods are aware of, so we need a phony custom target. + add_custom_target("build-native-${NAME}" DEPENDS "${NATIVE_LINK}") + add_dependencies(${NAME} "build-native-${NAME}") - # Add the native directory to the list of file to cleanup. - set_property(DIRECTORY "${CMAKE_SOURCE_DIR}" APPEND PROPERTY ADDITIONAL_CLEAN_FILES "${NATIVE_BUILD_DIR}") -endif() + # Cleanup the native build directory. + set_property( + DIRECTORY "${CMAKE_SOURCE_DIR}" + APPEND PROPERTY ADDITIONAL_CLEAN_FILES + "${NATIVE_BUILD_DIR}" + ) +endfunction() diff --git a/cmake/templates/NativeBuildRunner.cmake.in b/cmake/templates/NativeBuildRunner.cmake.in --- a/cmake/templates/NativeBuildRunner.cmake.in +++ b/cmake/templates/NativeBuildRunner.cmake.in @@ -1,7 +1,6 @@ #!/bin/sh -cd "${NATIVE_BUILD_DIR}" -"${CMAKE_COMMAND}" --build "${NATIVE_BUILD_DIR}" --target "${TARGET}" +"${CMAKE_COMMAND}" --build "${NATIVE_BUILD_DIR}" "${CMAKE_COMMAND}" -E create_symlink "${NATIVE_BINARY}" "${NATIVE_LINK}" # Ok let's generate a depfile if we can. @@ -10,5 +9,5 @@ --build-dir "${NATIVE_BUILD_DIR}" \ --base-dir "${CMAKE_BINARY_DIR}" \ --ninja "${CMAKE_MAKE_PROGRAM}" \ - "${RELATIVE_PATH}/native-${NAME}" "${TARGET}" > "${NATIVE_LINK}.d" + "${RELATIVE_BINARY_DIR}/native-${NAME}" "${NAME}" > "${NATIVE_LINK}.d" fi diff --git a/cmake/templates/NativeCMakeLists.txt.in b/cmake/templates/NativeCMakeLists.txt.in new file mode 100644 --- /dev/null +++ b/cmake/templates/NativeCMakeLists.txt.in @@ -0,0 +1,7 @@ +# Copyright (c) 2020 The Bitcoin developers + +cmake_minimum_required(VERSION 3.16) +project(${NAME}) + +add_executable(${NAME} ${ABS_SOURCES}) +target_include_directories(${NAME} PRIVATE ${ABS_INCLUDE_DIRS}) diff --git a/cmake/templates/NativeCmakeRunner.cmake.in b/cmake/templates/NativeCmakeRunner.cmake.in --- a/cmake/templates/NativeCmakeRunner.cmake.in +++ b/cmake/templates/NativeCmakeRunner.cmake.in @@ -1,11 +1,9 @@ #!/bin/sh "${CMAKE_COMMAND}" -G"${CMAKE_GENERATOR}" \ - -S "${CMAKE_SOURCE_DIR}" \ + -S "${NATIVE_LIST_DIR}" \ -B "${NATIVE_BUILD_DIR}" \ - -D__IS_NATIVE_BUILD=1 \ - -DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM} \ - ${ARGS} + -DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM} # Ok let's generate a depfile if we can. if test "x${CMAKE_GENERATOR}" = "xNinja"; then @@ -13,7 +11,7 @@ --build-dir "${NATIVE_BUILD_DIR}" \ --base-dir "${CMAKE_BINARY_DIR}" \ --ninja "${CMAKE_MAKE_PROGRAM}" \ - native/CMakeCache.txt build.ninja \ + "${RELATIVE_NATIVE_BUILD_DIR}/CMakeCache.txt" build.ninja \ --extra-deps build.ninja \ > "${NATIVE_BUILD_DIR}/CMakeFiles/CMakeCache.txt.d" fi diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -50,18 +50,6 @@ set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE}) endif(CCACHE) -# Disable what we do not need for the native build. -include(NativeExecutable) -native_add_cmake_flags( - "-DBUILD_BITCOIN_WALLET=OFF" - "-DBUILD_BITCOIN_QT=OFF" - "-DBUILD_BITCOIN_ZMQ=OFF" - "-DENABLE_QRCODE=OFF" - "-DENABLE_UPNP=OFF" - "-DUSE_JEMALLOC=OFF" - "-DENABLE_CLANG_TIDY=OFF" -) - if(ENABLE_CLANG_TIDY) include(ClangTidy) endif() diff --git a/src/secp256k1/CMakeLists.txt b/src/secp256k1/CMakeLists.txt --- a/src/secp256k1/CMakeLists.txt +++ b/src/secp256k1/CMakeLists.txt @@ -307,12 +307,10 @@ set(USE_ECMULT_STATIC_PRECOMPUTATION 1) include(NativeExecutable) - native_add_cmake_flags( - "-DSECP256K1_ECMULT_WINDOW_SIZE=${SECP256K1_ECMULT_WINDOW_SIZE}" - "-DSECP256K1_ECMULT_GEN_PRECISION=${SECP256K1_ECMULT_GEN_PRECISION}" - "-DSECP256K1_USE_ASM=OFF" + add_native_executable(gen_context + SOURCES + src/gen_context.c ) - add_native_executable(gen_context src/gen_context.c) add_custom_command( OUTPUT src/ecmult_static_context.h diff --git a/src/univalue/CMakeLists.txt b/src/univalue/CMakeLists.txt --- a/src/univalue/CMakeLists.txt +++ b/src/univalue/CMakeLists.txt @@ -45,8 +45,12 @@ # Generate lib/univalue_escapes.h include(NativeExecutable) -add_native_executable(univalue_gen gen/gen.cpp) -native_target_include_directories(univalue_gen PUBLIC include) +add_native_executable(univalue_gen + SOURCES + gen/gen.cpp + INCLUDE_DIRS + include +) # Custom target to regenerate univalue_escapes.h add_custom_target(generate_univalue_escapes_h