File: RustLibrary.cmake

package info (click to toggle)
mir 2.25.2-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 22,080 kB
  • sloc: cpp: 192,777; xml: 13,784; ansic: 8,207; python: 1,304; sh: 794; makefile: 258
file content (92 lines) | stat: -rw-r--r-- 3,522 bytes parent folder | download | duplicates (2)
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()