Skip to content

Commit

Permalink
Refactor and extend FindRust.cmake
Browse files Browse the repository at this point in the history
Export additional build context to Rust-based builds, and eliminate some of the
duplicated logic when bulding a macOS univeral binary.
  • Loading branch information
shutton committed Jan 23, 2024
1 parent 94b83af commit 2df7d5c
Showing 1 changed file with 67 additions and 27 deletions.
94 changes: 67 additions & 27 deletions cmake/FindRust.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,11 @@ function(cargo_vendor)
# This will allow us to package vendored dependencies in source tarballs
# for online builds when we run `cpack --config CPackSourceConfig.cmake`
message(STATUS "Running `cargo vendor` to collect dependencies for ${ARGS_TARGET}. This may take a while if the local crates.io index needs to be updated ...")

make_directory(${CMAKE_SOURCE_DIR}/.cargo)

get_cargo_local_dir_env(_cargo_local_dir_env)

execute_process(
COMMAND ${CMAKE_COMMAND} -E env "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" ${cargo_EXECUTABLE} vendor "${CMAKE_SOURCE_DIR}/.cargo/vendor"
WORKING_DIRECTORY "${ARGS_SOURCE_DIRECTORY}"
Expand Down Expand Up @@ -221,6 +225,26 @@ directory = \".cargo/vendor\"
endif()
endfunction()

# Export the project name (including upstream project) and maintainer mode
# status for use by build scripts
function(get_cargo_extra_env OUTPUT)
set(_result "PROJECT_NAME=${PROJECT_NAME}")
list(APPEND _result "CMAKE_PROJECT_NAME=${CMAKE_PROJECT_NAME}")
list(APPEND _result "MAINTAINER_MODE=${MAINTAINER_MODE}")
# Propagate any additional Rust compiler flags
list(APPEND _result "RUSTFLAGS=${RUSTFLAGS}")
set("${OUTPUT}" "${_result}" PARENT_SCOPE)
endfunction()

# From within another function, set environment variables pointing to local
# directories as specified by the arguments to that function
function(get_cargo_local_dir_env OUTPUT)
# Specify the destination directory for build products
set(_env "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}")
list(APPEND _env "CARGO_INCLUDE_DIRECTORIES=\"${ARGS_INCLUDE_DIRECTORIES}\"")
set(${OUTPUT} "${_env}" PARENT_SCOPE)
endfunction()

function(add_rust_executable)
set(options)
set(oneValueArgs TARGET SOURCE_DIRECTORY BINARY_DIRECTORY)
Expand All @@ -238,10 +262,14 @@ function(add_rust_executable)
list(APPEND MY_CARGO_ARGS "--target-dir" ${ARGS_BINARY_DIRECTORY})
list(JOIN MY_CARGO_ARGS " " MY_CARGO_ARGS_STRING)

get_cargo_extra_env(_cargo_extra_env)
get_cargo_local_dir_env(_cargo_local_dir_env)

# Build the executable.
add_custom_command(
OUTPUT "${OUTPUT}"
COMMAND ${CMAKE_COMMAND} -E env "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "CARGO_INCLUDE_DIRECTORIES=\"${ARGS_INCLUDE_DIRECTORIES}\"" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS}
COMMAND ${CMAKE_COMMAND} -E env "${_cargo_extra_env}" "${_cargo_local_dir_env}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS}
COMMAND_EXPAND_LISTS
WORKING_DIRECTORY "${ARGS_SOURCE_DIRECTORY}"
DEPENDS ${EXE_SOURCES}
COMMENT "Building ${ARGS_TARGET} in ${ARGS_BINARY_DIRECTORY} with:\n\t ${cargo_EXECUTABLE} ${MY_CARGO_ARGS_STRING}")
Expand Down Expand Up @@ -288,39 +316,47 @@ function(add_rust_library)
list(APPEND MY_CARGO_ARGS "--target-dir" ${ARGS_BINARY_DIRECTORY})
list(JOIN MY_CARGO_ARGS " " MY_CARGO_ARGS_STRING)

# Build the library and generate the c-binding
if("${CMAKE_OSX_ARCHITECTURES}" MATCHES "^(arm64;x86_64|x86_64;arm64)$")
get_cargo_extra_env(_cargo_extra_env)
get_cargo_local_dir_env(_cargo_local_dir_env)

if(RUST_COMPILER_TARGET STREQUAL "universal-apple-darwin")
foreach(arch IN LISTS CMAKE_OSX_ARCHITECTURES)
if(arch STREQUAL "arm64")
# Convert to rustc's designation
set(arch "aarch64")
endif()

# Form the path of this compiled library for later collection by
# `lipo`, and for providing a target dependency for the final output.
set(this_output "${ARGS_BINARY_DIRECTORY}/${arch}-apple-darwin/${CARGO_BUILD_TYPE}/lib${ARGS_TARGET}.a")
list(APPEND lipo_inputs "${this_output}")

add_custom_command(
OUTPUT "${this_output}"
COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=build" "${_cargo_extra_env}" "${_cargo_local_dir_env}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --target=${arch}-apple-darwin
COMMAND_EXPAND_LISTS
WORKING_DIRECTORY "${ARGS_SOURCE_DIRECTORY}"
DEPENDS ${LIB_SOURCES}
COMMENT "Building ${ARGS_TARGET} for ${arch} in ${ARGS_BINARY_DIRECTORY} with: ${cargo_EXECUTABLE} ${MY_CARGO_ARGS_STRING}")
endforeach()

# `lipo` will provide the Universal binary
add_custom_command(
OUTPUT "${OUTPUT}"
COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=build" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "MAINTAINER_MODE=${MAINTAINER_MODE}" "CARGO_INCLUDE_DIRECTORIES=\"${ARGS_INCLUDE_DIRECTORIES}\"" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --target=x86_64-apple-darwin
COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=build" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "MAINTAINER_MODE=${MAINTAINER_MODE}" "CARGO_INCLUDE_DIRECTORIES=\"${ARGS_INCLUDE_DIRECTORIES}\"" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --target=aarch64-apple-darwin
COMMAND ${CMAKE_COMMAND} -E make_directory "${ARGS_BINARY_DIRECTORY}/${RUST_COMPILER_TARGET}/${CARGO_BUILD_TYPE}"
COMMAND lipo -create ${ARGS_BINARY_DIRECTORY}/x86_64-apple-darwin/${CARGO_BUILD_TYPE}/lib${ARGS_TARGET}.a ${ARGS_BINARY_DIRECTORY}/aarch64-apple-darwin/${CARGO_BUILD_TYPE}/lib${ARGS_TARGET}.a -output "${OUTPUT}"
COMMAND lipo -create ${lipo_inputs} -output "${OUTPUT}"
COMMAND_EXPAND_LISTS
WORKING_DIRECTORY "${ARGS_SOURCE_DIRECTORY}"
DEPENDS ${LIB_SOURCES}
COMMENT "Building ${ARGS_TARGET} in ${ARGS_BINARY_DIRECTORY} with: ${cargo_EXECUTABLE} ${MY_CARGO_ARGS_STRING}")
elseif("${CMAKE_OSX_ARCHITECTURES}" MATCHES "^(arm64)$")
add_custom_command(
OUTPUT "${OUTPUT}"
COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=build" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "MAINTAINER_MODE=${MAINTAINER_MODE}" "CARGO_INCLUDE_DIRECTORIES=\"${ARGS_INCLUDE_DIRECTORIES}\"" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --target=aarch64-apple-darwin
WORKING_DIRECTORY "${ARGS_SOURCE_DIRECTORY}"
DEPENDS ${LIB_SOURCES}
COMMENT "Building ${ARGS_TARGET} in ${ARGS_BINARY_DIRECTORY} with: ${cargo_EXECUTABLE} ${MY_CARGO_ARGS_STRING}")
elseif("${CMAKE_OSX_ARCHITECTURES}" MATCHES "^(x86_64)$")
add_custom_command(
OUTPUT "${OUTPUT}"
COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=build" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "MAINTAINER_MODE=${MAINTAINER_MODE}" "CARGO_INCLUDE_DIRECTORIES=\"${ARGS_INCLUDE_DIRECTORIES}\"" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --target=x86_64-apple-darwin
COMMAND ${CMAKE_COMMAND} -E make_directory "${ARGS_BINARY_DIRECTORY}/${RUST_COMPILER_TARGET}/${CARGO_BUILD_TYPE}"
WORKING_DIRECTORY "${ARGS_SOURCE_DIRECTORY}"
DEPENDS ${LIB_SOURCES}
COMMENT "Building ${ARGS_TARGET} in ${ARGS_BINARY_DIRECTORY} with: ${cargo_EXECUTABLE} ${MY_CARGO_ARGS_STRING}")
DEPENDS ${lipo_inputs}
COMMENT "Composing universal binary in ${ARGS_BINARY_DIRECTORY}")
else()
add_custom_command(
OUTPUT "${OUTPUT}"
COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=build" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "MAINTAINER_MODE=${MAINTAINER_MODE}" "CARGO_INCLUDE_DIRECTORIES=\"${ARGS_INCLUDE_DIRECTORIES}\"" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS}
COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=build" "${_cargo_extra_env}" "${_cargo_local_dir_env}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS}
COMMAND_EXPAND_LISTS
WORKING_DIRECTORY "${ARGS_SOURCE_DIRECTORY}"
DEPENDS ${LIB_SOURCES}
COMMENT "Building ${ARGS_TARGET} in ${ARGS_BINARY_DIRECTORY} with: ${cargo_EXECUTABLE} ${MY_CARGO_ARGS_STRING}")
COMMENT "Building ${ARGS_TARGET} for ${arch} in ${ARGS_BINARY_DIRECTORY} with: ${cargo_EXECUTABLE} ${MY_CARGO_ARGS_STRING}")
endif()

# Create a target from the build output
Expand Down Expand Up @@ -367,17 +403,21 @@ function(add_rust_test)
list(JOIN MY_CARGO_ARGS " " MY_CARGO_ARGS_STRING)

if(ARGS_PRECOMPILE_TESTS)
list(APPEND ARGS_PRECOMPILE_ENVIRONMENT "CARGO_CMD=test" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}")
list(APPEND ARGS_PRECOMPILE_ENVIRONMENT "CARGO_CMD=test" "PROJECT_NAME=${PROJECT_NAME}" "CMAKE_PROJECT_NAME=${CMAKE_PROJECT_NAME}" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}")
add_custom_target(${ARGS_NAME}_tests ALL
COMMAND ${CMAKE_COMMAND} -E env ${ARGS_PRECOMPILE_ENVIRONMENT} ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --color always --no-run
DEPENDS ${ARGS_PRECOMPILE_DEPENDS}
WORKING_DIRECTORY ${ARGS_SOURCE_DIRECTORY}
)
endif()

get_cargo_extra_env(_cargo_extra_env)
get_cargo_local_dir_env(_cargo_local_dir_env)

add_test(
NAME ${ARGS_NAME}
COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=test" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --color always
COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=test" "${_cargo_extra_env}" "${_cargo_local_dir_env}" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --color always
COMMAND_EXPAND_LISTS
WORKING_DIRECTORY ${ARGS_SOURCE_DIRECTORY}
)
endfunction()
Expand Down

0 comments on commit 2df7d5c

Please sign in to comment.