1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
|
find_program(CARGO_EXECUTABLE cargo REQUIRED)
function(add_rust_cxx_library target)
set(one_value_args CRATE CXX_BRIDGE_SOURCE_FILE)
set(multi_value_args DEPENDS LIBRARIES INCLUDES)
cmake_parse_arguments(arg "" "${one_value_args}" "${multi_value_args}" ${ARGN})
if("${arg_CRATE}" STREQUAL "")
message(FATAL_ERROR "add_rust_cxx_library called without CRATE <value>")
endif()
if("${arg_CXX_BRIDGE_SOURCE_FILE}" STREQUAL "")
set(arg_CXX_BRIDGE_SOURCE_FILE "src/lib.rs")
endif()
set(rust_target_dir "${CMAKE_BINARY_DIR}/target")
if("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
set(rust_binary_dir "${rust_target_dir}/$ENV{DEB_HOST_RUST_TYPE}/release")
set(cargo_release_flag "--release")
else()
set(rust_binary_dir "${rust_target_dir}/$ENV{DEB_HOST_RUST_TYPE}/debug")
set(cargo_release_flag "")
endif()
set(cxxbridge_include_dir "${rust_target_dir}/$ENV{DEB_HOST_RUST_TYPE}/cxxbridge")
set(cxxbridge_header "${cxxbridge_include_dir}/${arg_CRATE}/${arg_CXX_BRIDGE_SOURCE_FILE}.h")
set(cxxbridge_source "${cxxbridge_include_dir}/${arg_CRATE}/${arg_CXX_BRIDGE_SOURCE_FILE}.cc")
set(crate_staticlib "${rust_binary_dir}/lib${arg_CRATE}.a")
add_custom_command(
OUTPUT ${cxxbridge_header} ${cxxbridge_source} ${crate_staticlib}
COMMAND ${CARGO_EXECUTABLE} build ${cargo_release_flag} --target-dir ${rust_target_dir} -p ${arg_CRATE}
DEPENDS ${arg_DEPENDS}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMENT "Building Rust crate ${arg_CRATE}")
add_library(${target}-rust STATIC IMPORTED)
set_target_properties(${target}-rust PROPERTIES
IMPORTED_LOCATION ${crate_staticlib})
add_library(${target}-cxxbridge STATIC
${cxxbridge_source} ${cxxbridge_header})
if(arg_INCLUDES)
foreach(inc_dir IN LISTS arg_INCLUDES)
target_include_directories(${target}-cxxbridge PRIVATE "${inc_dir}")
endforeach()
endif()
if(arg_LIBRARIES)
foreach(library ${arg_LIBRARIES})
target_include_directories(${target}-cxxbridge PRIVATE
"$<TARGET_PROPERTY:${library},INTERFACE_INCLUDE_DIRECTORIES>"
)
endforeach ()
endif()
add_library(${target} INTERFACE)
target_include_directories(${target} INTERFACE ${cxxbridge_include_dir})
if(arg_INCLUDES)
foreach(inc_dir IN LISTS arg_INCLUDES)
target_include_directories(${target} INTERFACE "${inc_dir}")
endforeach()
endif()
# rust-cxx generates symbols named like "cxxbridge1$foo", which
# triggers a warning in Clang.
check_cxx_compiler_flag(-Wdollar-in-identifier-extension SUPPORTS_DOLLAR_IN_ID_WARNING)
if(SUPPORTS_DOLLAR_IN_ID_WARNING)
target_compile_options(${target}-cxxbridge
PRIVATE -Wno-error=dollar-in-identifier-extension)
target_compile_options(${target}
INTERFACE -Wno-error=dollar-in-identifier-extension)
endif()
# As described in https://cxx.rs/build/other.html#linking-the-c-and-rust-together
# the Rust staticlib and cxxbridge generated code are
# interdependent. CMake's LINKGROUP:RESCAN generator will produce
# the required --start-group/--end-group link flags.
set(LIBRARIES)
foreach(library ${arg_LIBRARIES})
if (TARGET ${library})
get_target_property(libs ${library} INTERFACE_LINK_LIBRARIES)
if (libs)
list(APPEND LIBRARIES ${libs})
endif()
else()
list(APPEND LIBRARIES ${library})
endif()
endforeach ()
target_link_libraries(${target} INTERFACE $<LINK_GROUP:RESCAN,${target}-cxxbridge,${target}-rust,${LIBRARIES}>)
endfunction()
|