Only rerun bindgen when its dependencies change
This took a bit of wrangling to get the depfiles working, but I
eventually figured it out. ninja -d explain is very useful.
Fixed: 597
Change-Id: I909a4c9418e9dc954e3d328da8f3a825e62544e4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/59005
Reviewed-by: Bob Beck <bbe@google.com>
Auto-Submit: David Benjamin <davidben@google.com>
Commit-Queue: Bob Beck <bbe@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a1fb153..aac5f0d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -17,6 +17,7 @@
include(sources.cmake)
include(cmake/go.cmake)
+include(cmake/paths.cmake)
include(cmake/perlasm.cmake)
enable_language(C)
diff --git a/cmake/go.cmake b/cmake/go.cmake
index 61a01f5..966ad32 100644
--- a/cmake/go.cmake
+++ b/cmake/go.cmake
@@ -34,10 +34,7 @@
else()
# Ninja expects the target in the depfile to match the output. This is a
# relative path from the build directory.
- string(LENGTH "${CMAKE_BINARY_DIR}" root_dir_length)
- math(EXPR root_dir_length "${root_dir_length} + 1")
- string(SUBSTRING "${CMAKE_CURRENT_BINARY_DIR}" ${root_dir_length} -1 target)
- set(target "${target}/${dest}")
+ binary_dir_relative_path(${dest} target)
set(depfile "${CMAKE_CURRENT_BINARY_DIR}/${dest}.d")
add_custom_command(OUTPUT ${dest}
diff --git a/cmake/paths.cmake b/cmake/paths.cmake
new file mode 100644
index 0000000..43ebc40
--- /dev/null
+++ b/cmake/paths.cmake
@@ -0,0 +1,11 @@
+# binary_dir_relative_path sets outvar to
+# ${CMAKE_CURRENT_BINARY_DIR}/${cur_bin_dir_relative}, but expressed relative to
+# ${CMAKE_BINARY_DIR}.
+#
+# TODO(davidben): When we require CMake 3.20 or later, this can be replaced with
+# the built-in cmake_path(RELATIVE_PATH) function.
+function(binary_dir_relative_path cur_bin_dir_relative outvar)
+ string(LENGTH "${CMAKE_BINARY_DIR}/" root_dir_length)
+ string(SUBSTRING "${CMAKE_CURRENT_BINARY_DIR}/${cur_bin_dir_relative}" ${root_dir_length} -1 result)
+ set(${outvar} ${result} PARENT_SCOPE)
+endfunction()
diff --git a/rust/bssl-sys/CMakeLists.txt b/rust/bssl-sys/CMakeLists.txt
index c11510b..5e5f446 100644
--- a/rust/bssl-sys/CMakeLists.txt
+++ b/rust/bssl-sys/CMakeLists.txt
@@ -2,48 +2,51 @@
add_library(rust_wrapper STATIC rust_wrapper.c)
target_link_libraries(rust_wrapper crypto)
+# Generate architecture-specific wrappers. bindgen must be called from
+# ${CMAKE_BINARY_DIR}, with the output path as a relative path. bindgen writes
+# the depfile using the same syntax as the command-line argument, and ninja
+# requires a path relative to the top-level build directory.
+set(wrapper src/wrapper_${RUST_BINDINGS}.rs)
+binary_dir_relative_path(${wrapper} wrapper_relative)
+binary_dir_relative_path(${wrapper}.d depfile_relative)
-# Generate architecture-specific wrappers.
-set(WRAPPER_TARGET ${CMAKE_BINARY_DIR}/rust/bssl-sys/src/wrapper_${RUST_BINDINGS}.rs)
-set(COMMAND ${BINDGEN_EXECUTABLE} wrapper.h
- -o ${WRAPPER_TARGET}
- --no-derive-default
- --enable-function-attribute-detection
- --use-core
- --default-macro-constant-type=signed
- --rustified-enum=point_conversion_form_t
- # These regexes need to accept both / and \ to handle Windows file
- # path differences, due a bindgen issue. See
- # https://crbug.com/boringssl/595. Ideally, we would write [/\\],
- # but there are many layers of escaping here. First, CMake
- # interprets backslashes. Then CMake generates a Ninja or Make file.
- # That, in turn, launches passes inputs to the shell on POSIX, and
- # does something else on Windows.
- #
- # It is unlikely that every layer here has sufficiently well-defined
- # escaping and correctly handled the next layer's escaping. On top
- # of that, we'd likely need to detect Windows vs POSIX hosts and
- # change the input. Instead, just use [[:punct:]] which is more
- # permissive than necessary, but we only need to exclude unwanted
- # libc heaaders.
- #
- # If bindgen ever supports some file-based config (see
- # https://github.com/rust-lang/rust-bindgen/issues/2508), we can
- # switch to that.
- --allowlist-file=".*[[:punct:]]include[[:punct:]]openssl[[:punct:]].*\\.h"
- --allowlist-file=".*[[:punct:]]rust_wrapper\\.h"
- -- # these are LLVM arg passthroughs
- -I../../include
- # https://doc.rust-lang.org/nightly/rustc/platform-support.html
- --target=${RUST_BINDINGS})
-
-add_custom_target(
- bindgen_rust_${RUST_BINDINGS}
- ALL
- ${COMMAND}
- BYPRODUCTS ${WRAPPER_TARGET}
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+add_custom_command(
+ OUTPUT ${wrapper}
+ COMMAND ${BINDGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/wrapper.h
+ -o ${wrapper_relative}
+ --depfile=${depfile_relative}
+ --no-derive-default
+ --enable-function-attribute-detection
+ --use-core
+ --default-macro-constant-type=signed
+ --rustified-enum=point_conversion_form_t
+ # These regexes need to accept both / and \ to handle Windows file
+ # path differences, due a bindgen issue. See
+ # https://crbug.com/boringssl/595. Ideally, we would write [/\\], but
+ # there are many layers of escaping here. First, CMake interprets
+ # backslashes. Then CMake generates a Ninja or Make file. That, in
+ # turn, uses the shell on POSIX, and does something else on Windows.
+ #
+ # It is unlikely that every layer here has sufficiently well-defined
+ # escaping and correctly handled the next layer's escaping. On top of
+ # that, we'd likely need to detect Windows vs POSIX hosts and change
+ # the input. Instead, just use [[:punct:]] which is more permissive
+ # than necessary, but we only need to exclude unwanted libc headers.
+ #
+ # If bindgen ever supports some file-based config (see
+ # https://github.com/rust-lang/rust-bindgen/issues/2508), we can
+ # switch to that.
+ --allowlist-file=".*[[:punct:]]include[[:punct:]]openssl[[:punct:]].*\\.h"
+ --allowlist-file=".*[[:punct:]]rust_wrapper\\.h"
+ -- # these are LLVM arg passthroughs
+ -I${PROJECT_SOURCE_DIR}/include
+ # https://doc.rust-lang.org/nightly/rustc/platform-support.html
+ --target=${RUST_BINDINGS}
+ DEPENDS wrapper.h
+ DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/${wrapper}.d
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
+add_custom_target(bssl_sys ALL DEPENDS ${wrapper})
# move files into build directory
configure_file("src/lib.rs" "src/lib.rs")