# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ## The contents of this file should only be processed once. include_guard(GLOBAL) file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/cargo_home) ## Find the absolute path to the rust build tools. find_program(CARGO_BUILD_TOOL NAMES cargo REQUIRED) find_program(RUSTC_BUILD_TOOL NAMES rustc REQUIRED) if(APPLE) find_program(LIPO_BUILD_TOOL NAMES lipo arm64-apple-darwin${CMAKE_SYSTEM_VERSION}-lipo x86_64-apple-darwin${CMAKE_SYSTEM_VERSION}-lipo REQUIRED ) endif() # Figure out Rust's host architecture execute_process(OUTPUT_VARIABLE RUSTC_VERSION_RAW COMMAND ${RUSTC_BUILD_TOOL} --version --verbose) if(RUSTC_VERSION_RAW MATCHES "host: ([^\n]+)") set(RUSTC_HOST_ARCH ${CMAKE_MATCH_1} CACHE STRING "Rustlang host architecture") else() message(FATAL_ERROR "Failed to find rustc host arch") endif() ## Create a config.toml to inherit the toolchain. function(__rust_build_toolchain_config) cmake_parse_arguments(RUST_CONFIG "" "FILENAME" "ARCH;RUSTFLAGS;ENV" ${ARGN}) if(NOT RUST_CONFIG_FILENAME) set(RUST_CONFIG_FILENAME ${CMAKE_BINARY_DIR}/cargo_home/config.toml) endif() foreach(ARCH ${RUST_CONFIG_ARCH}) list(APPEND RUST_CONFIG_ENV CC_${ARCH}=${CMAKE_C_COMPILER}) list(APPEND RUST_CONFIG_ENV CXX_${ARCH}=${CMAKE_CXX_COMPILER}) list(APPEND RUST_CONFIG_ENV AR_${ARCH}=${CMAKE_AR}) endforeach() # Encode the environment configuration into a cargo.toml file. file(WRITE ${RUST_CONFIG_FILENAME} "# Auto generated by: ${CMAKE_CURRENT_LIST_FILE}\n[env]\n") foreach(ENTRY ${RUST_CONFIG_ENV}) string(FIND ${ENTRY} "=" NAME_LENGTH) if(NAME_LENGTH GREATER 0) # Wrap the value in quotations math(EXPR VALUE_START "${NAME_LENGTH} + 1") string(SUBSTRING ${ENTRY} 0 ${NAME_LENGTH} NAME) string(SUBSTRING ${ENTRY} ${VALUE_START} -1 VALUE) file(APPEND ${RUST_CONFIG_FILENAME} ${NAME}=\"${VALUE}\"\n) endif() endforeach() # Note: This would need to be set externally on the command line. if(RUST_VENDOR_DIR) file(REAL_PATH ${RUST_VENDOR_DIR} RUST_CONFIG_VENDOR_DIR BASE_DIRECTORY ${CMAKE_SOURCE_DIR}) if(IS_DIRECTORY RUST_CONFIG_VENDOR_DIR) file(APPEND ${RUST_CONFIG_FILENAME} [source.vendored-sources]\n) file(APPEND ${RUST_CONFIG_FILENAME} directory=\"${RUST_CONFIG_VENDOR_DIR}\"\n) file(APPEND ${RUST_CONFIG_FILENAME} [source.crates-io]\n) file(APPEND ${RUST_CONFIG_FILENAME} replace-with=\"vendored-sources\"\n\n) endif() endif() # Encode some build settings too. file(APPEND ${RUST_CONFIG_FILENAME} "\n[build]\n") file(APPEND ${RUST_CONFIG_FILENAME} "rustc=\"${RUSTC_BUILD_TOOL}\"\n") # We can't reliably set rustflags in the config because they get easily # replaced by conflicing environments or configs, so create a rust wrapper # to pass them to rustc for us when one of the target architectures is set. if(RUST_CONFIG_RUSTFLAGS) list(JOIN RUST_CONFIG_ARCH " " RUST_CONFIG_TARGETS) configure_file( ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/rustlang-wrapper.sh.in ${CMAKE_BINARY_DIR}/cargo_home/rustc-wrapper.sh @ONLY ) file(CHMOD ${CMAKE_BINARY_DIR}/cargo_home/rustc-wrapper.sh PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE ) file(APPEND ${RUST_CONFIG_FILENAME} "rustc-wrapper=\"${CMAKE_BINARY_DIR}/cargo_home/rustc-wrapper.sh\"\n") endif() endfunction() if(ANDROID) get_filename_component(ANDROID_TOOLCHAIN_ROOT_BIN ${CMAKE_C_COMPILER} DIRECTORY) if(CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7-a") set(RUSTC_ANDROID_ARCH armv7-linux-androideabi) set(RUSTC_ANDROID_LINKER ${ANDROID_TOOLCHAIN_ROOT_BIN}/armv7a-linux-androideabi${ANDROID_NATIVE_API_LEVEL}-clang) else() set(RUSTC_ANDROID_ARCH ${CMAKE_SYSTEM_PROCESSOR}-linux-android) set(RUSTC_ANDROID_LINKER ${ANDROID_TOOLCHAIN_ROOT_BIN}/${RUSTC_ANDROID_ARCH}${ANDROID_NATIVE_API_LEVEL}-clang) endif() set(RUSTC_ANDROID_ARCH ${RUSTC_ANDROID_ARCH} CACHE STRING "Rust target android architecture") __rust_build_toolchain_config( FILENAME ${CMAKE_BINARY_DIR}/cargo_home/config.toml RUSTFLAGS "-Clinker=${RUSTC_ANDROID_LINKER}" ARCH ${RUSTC_ANDROID_ARCH}) elseif(IOS) __rust_build_toolchain_config( FILENAME ${CMAKE_BINARY_DIR}/cargo_home/config.toml RUSTFLAGS -Clinker=${CMAKE_LINKER} -Clinker-flavor=ld ARCH aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim) # Ensure that the host architecture uses /usr/bin/cc for linking. file(APPEND ${CMAKE_BINARY_DIR}/cargo_home/config.toml "\n[target.${RUSTC_HOST_ARCH}]\n") file(APPEND ${CMAKE_BINARY_DIR}/cargo_home/config.toml "linker=\"/usr/bin/cc\"\n") elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") __rust_build_toolchain_config( FILENAME ${CMAKE_BINARY_DIR}/cargo_home/config.toml RUSTFLAGS -Clinker=${CMAKE_LINKER} -Clinker-flavor=ld ARCH aarch64-apple-darwin x86_64-apple-darwin ENV "CFLAGS_aarch64-apple-darwin=-target arm64-apple-darwin" "CFLAGS_x86_64-apple-darwin=-target x86_64-apple-darwin" MACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} ) elseif(MSVC) __rust_build_toolchain_config( FILENAME ${CMAKE_BINARY_DIR}/cargo_home/config.toml ARCH x86_64-pc-windows-msvc ENV CFLAGS_x86_64-pc-windows-msvc=${CMAKE_C_FLAGS} CXXFLAGS_x86_64-pc-windows-msvc=${CMAKE_CXX_FLAGS} ) file(APPEND ${CMAKE_BINARY_DIR}/cargo_home/config.toml "\n[target.x86_64-pc-windows-msvc]\n") file(APPEND ${CMAKE_BINARY_DIR}/cargo_home/config.toml "linker=\"${CMAKE_LINKER}\"\n") else() __rust_build_toolchain_config(FILENAME ${CMAKE_BINARY_DIR}/cargo_home/config.toml) endif() ## For the Ninja generator, setup a job pool for Cargo targets, which share a ## common lock on the package repository, and build aggressively in parallel ## anyways. get_property(HAS_CARGO_POOL GLOBAL PROPERTY JOB_POOLS) list(FILTER HAS_CARGO_POOL INCLUDE REGEX "^cargo=") if(NOT HAS_CARGO_POOL) set_property(GLOBAL APPEND PROPERTY JOB_POOLS cargo=1) endif() ### Helper function to get the rust library filename with extension. # # Sets the variable "RUST_LIBRARY_FILENAME" with the value. function(get_rust_library_filename SHARED CRATE_NAME) if(${SHARED}) set(RUST_LIBRARY_FILENAME ${CMAKE_SHARED_LIBRARY_PREFIX}${CRATE_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX} PARENT_SCOPE) else() set(RUST_LIBRARY_FILENAME ${CMAKE_STATIC_LIBRARY_PREFIX}${CRATE_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX} PARENT_SCOPE) endif() endfunction() ### Helper function to build Rust static libraries. # # Accepts the following arguments: # ARCH: Rust target architecture to build with --target ${ARCH} # BINARY_DIR: Binary directory to output build artifacts to. # PACKAGE_DIR: Soruce directory where Cargo.toml can be found. # LIBRARY_FILE: Filename of the expected library to be built. # CARGO_ENV: Environment variables to pass to cargo # SHARED: Whether or not we are building a shared library. Defaults to "false". # # This function generates commands necessary to build static archives # in ${BINARY_DIR}/${ARCH}/debug/ and ${BINARY_DIR}/${ARCH}/release/ # and it is up to the caller of this function to link the artifacts # into their targets as necessary. # # This function is intended to be used internally by add_rust_library, # you should consider using that instead. # function(build_rust_archives) cmake_parse_arguments(RUST_BUILD "" "ARCH;BINARY_DIR;PACKAGE_DIR;CRATE_NAME" "CARGO_ENV;SHARED" ${ARGN}) list(APPEND RUST_BUILD_CARGO_ENV CARGO_HOME=${CMAKE_BINARY_DIR}/cargo_home) if(NOT DEFINED RUST_BUILD_SHARED) message(FATAL_ERROR "Mandatory argument SHARED was not found") endif() if(NOT RUST_BUILD_CRATE_NAME) message(FATAL_ERROR "Mandatory argument CRATE_NAME was not found") endif() if(NOT RUST_BUILD_ARCH) message(FATAL_ERROR "Mandatory argument ARCH was not found") endif() if(NOT RUST_BUILD_BINARY_DIR) set(RUST_BUILD_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) endif() if(NOT RUST_BUILD_PACKAGE_DIR) set(RUST_BUILD_PACKAGE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) endif() ## Some files that we will be building. file(MAKE_DIRECTORY ${RUST_BUILD_BINARY_DIR}) get_rust_library_filename(${RUST_BUILD_SHARED} ${RUST_BUILD_CRATE_NAME}) ## For iOS simulator targets, find the SDKROOT of the simulator matching the ## iOS platform SDK. if((RUST_BUILD_ARCH STREQUAL "aarch64-apple-ios-sim") OR (RUST_BUILD_ARCH STREQUAL "x86_64-apple-ios")) execute_process(OUTPUT_VARIABLE IOS_SDK_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND xcrun --sdk ${CMAKE_OSX_SYSROOT} --show-sdk-version) execute_process(OUTPUT_VARIABLE IOS_SIMULATOR_SDKROOT OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND xcrun --sdk iphonesimulator${IOS_SDK_VERSION} --show-sdk-path) list(APPEND RUST_BUILD_CARGO_ENV SDKROOT=${IOS_SIMULATOR_SDKROOT}) elseif(APPLE AND CMAKE_OSX_SYSROOT) if (IS_DIRECTORY ${CMAKE_OSX_SYSROOT}) list(APPEND RUST_BUILD_CARGO_ENV "SDKROOT=${CMAKE_OSX_SYSROOT}") else() execute_process(OUTPUT_VARIABLE RUST_BUILD_SDKROOT OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND xcrun --sdk ${CMAKE_OSX_SYSROOT} --show-sdk-path) list(APPEND RUST_BUILD_CARGO_ENV "SDKROOT=${RUST_BUILD_SDKROOT}") endif() endif() if((CMAKE_GENERATOR MATCHES "Ninja") OR (CMAKE_GENERATOR MATCHES "Makefiles") OR XCODE) ## If the generator supports it, we can improve build times by setting # a DEPFILE to let CMake know when the library needs building and when # we can skip it. set(RUST_BUILD_DEPENDENCY_FILE ${CMAKE_STATIC_LIBRARY_PREFIX}${RUST_BUILD_CRATE_NAME}.d ) cmake_policy(PUSH) cmake_policy(SET CMP0116 NEW) ## Outputs for the release build add_custom_command( OUTPUT ${RUST_BUILD_BINARY_DIR}/${ARCH}/release/${RUST_LIBRARY_FILENAME} DEPFILE ${RUST_BUILD_BINARY_DIR}/${ARCH}/release/${RUST_BUILD_DEPENDENCY_FILE} JOB_POOL cargo WORKING_DIRECTORY ${RUST_BUILD_PACKAGE_DIR} COMMAND ${CMAKE_COMMAND} -E env ${RUST_BUILD_CARGO_ENV} ${CARGO_BUILD_TOOL} build --lib --release --target ${ARCH} --target-dir ${RUST_BUILD_BINARY_DIR} ) ## Outputs for the debug build add_custom_command( OUTPUT ${RUST_BUILD_BINARY_DIR}/${ARCH}/debug/${RUST_LIBRARY_FILENAME} DEPFILE ${RUST_BUILD_BINARY_DIR}/${ARCH}/debug/${RUST_BUILD_DEPENDENCY_FILE} JOB_POOL cargo WORKING_DIRECTORY ${RUST_BUILD_PACKAGE_DIR} COMMAND ${CMAKE_COMMAND} -E env ${RUST_BUILD_CARGO_ENV} ${CARGO_BUILD_TOOL} build --lib --target ${ARCH} --target-dir ${RUST_BUILD_BINARY_DIR} ) ## Reset our policy changes cmake_policy(POP) else() ## For all other generators, set a non-existent output file to force # the command to be invoked on every build. This ensures that the # library stays up todate with the sources, and relies on cargo to # rebuild if necessary. ## Outputs for the release build add_custom_command( OUTPUT ${RUST_BUILD_BINARY_DIR}/${ARCH}/release/${RUST_LIBRARY_FILENAME} ${RUST_BUILD_BINARY_DIR}/${ARCH}/release/.noexist WORKING_DIRECTORY ${RUST_BUILD_PACKAGE_DIR} COMMAND ${CMAKE_COMMAND} -E env ${RUST_BUILD_CARGO_ENV} ${CARGO_BUILD_TOOL} build --lib --release --target ${ARCH} --target-dir ${RUST_BUILD_BINARY_DIR} ) ## Outputs for the debug build add_custom_command( OUTPUT ${RUST_BUILD_BINARY_DIR}/${ARCH}/debug/${RUST_LIBRARY_FILENAME} ${RUST_BUILD_BINARY_DIR}/${ARCH}/debug/.noexist WORKING_DIRECTORY ${RUST_BUILD_PACKAGE_DIR} COMMAND ${CMAKE_COMMAND} -E env ${RUST_BUILD_CARGO_ENV} ${CARGO_BUILD_TOOL} build --lib --target ${ARCH} --target-dir ${RUST_BUILD_BINARY_DIR} ) endif() endfunction() ### Helper function to create a linkable target from a Rust package. # # This function takes one mandatory argument: TARGET_NAME which # sets the name of the CMake target to produce. # # Accepts the following optional arguments: # ARCH: Rust target architecture(s) to build with --target ${ARCH} # BINARY_DIR: Binary directory to output build artifacts to. # PACKAGE_DIR: Soruce directory where Cargo.toml can be found. # CRATE_NAME: Name of the staticlib crate we want to build. # CARGO_ENV: Environment variables to pass to cargo. # DEPENDS: Additional files on which the target depends. # SHARED: Whether or not we are building a shared library. Defaults to "false". # FW_NAME: Standalone dylibs need to be wrapped in a framework for distribtuion. Required when building shared lib for iOS. # function(add_rust_library TARGET_NAME) cmake_parse_arguments(RUST_TARGET "" "BINARY_DIR;PACKAGE_DIR;CRATE_NAME" "ARCH;CARGO_ENV;DEPENDS;SHARED;FW_NAME" ${ARGN}) if(NOT RUST_TARGET_SHARED) set(RUST_TARGET_SHARED 0) endif() if(${RUST_TARGET_SHARED} AND IOS AND NOT RUST_TARGET_FW_NAME) message(FATAL_ERROR "A framework name must be provided when building a shared Rust library for iOS.") endif() if(IOS AND RUST_TARGET_FW_NAME) set(FW_INFO_PLIST_FILE_PATH ${CMAKE_SOURCE_DIR}/scripts/cmake/Info.plist.${RUST_TARGET_FW_NAME}) if(NOT EXISTS ${FW_INFO_PLIST_FILE_PATH}) message(FATAL_ERROR "An Info.plist.${RUST_TARGET_FW_NAME} file must exist to support creation of ${FW_NAME} framework.") endif() endif() if(${RUST_TARGET_SHARED}) add_library(${TARGET_NAME} SHARED IMPORTED GLOBAL) else() add_library(${TARGET_NAME} STATIC IMPORTED GLOBAL) endif() if(NOT RUST_TARGET_CRATE_NAME) ## TODO: I would like to pull this from the package manifest. error("Mandatory argument CRATE_NAME was not found") endif() if(NOT RUST_TARGET_BINARY_DIR) set(RUST_TARGET_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) endif() if(NOT RUST_TARGET_PACKAGE_DIR) set(RUST_TARGET_PACKAGE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) endif() # Guess the target architecture if not set. if(NOT RUST_TARGET_ARCH) if((CMAKE_SYSTEM_NAME STREQUAL "Darwin") AND CMAKE_OSX_ARCHITECTURES) # Special case for MacOS universal binaries. foreach(OSXARCH ${CMAKE_OSX_ARCHITECTURES}) string(REPLACE "arm64" "aarch64" OSXARCH ${OSXARCH}) list(APPEND RUST_TARGET_ARCH "${OSXARCH}-apple-darwin") endforeach() elseif(NOT CMAKE_CROSSCOMPILING) set(RUST_TARGET_ARCH ${RUSTC_HOST_ARCH}) elseif(CMAKE_C_COMPILER_TARGET) # If set, the C compiler triple makes a reasonable guess. set(RUST_TARGET_ARCH ${CMAKE_C_COMPILER_TARGET}) else() # TODO: We could write something here for Android and IOS maybe message(FATAL_ERROR "Unable to determine rust target architecture when cross compiling.") endif() endif() get_rust_library_filename(${RUST_TARGET_SHARED} ${RUST_TARGET_CRATE_NAME}) ## Build the rust library file(s) foreach(ARCH ${RUST_TARGET_ARCH}) build_rust_archives( ARCH ${ARCH} BINARY_DIR ${RUST_TARGET_BINARY_DIR} PACKAGE_DIR ${RUST_TARGET_PACKAGE_DIR} CRATE_NAME ${RUST_TARGET_CRATE_NAME} CARGO_ENV ${RUST_TARGET_CARGO_ENV} SHARED ${RUST_TARGET_SHARED} ) if(RUST_TARGET_DEPENDS) add_custom_command(APPEND OUTPUT ${RUST_TARGET_BINARY_DIR}/${ARCH}/release/${RUST_LIBRARY_FILENAME} DEPENDS ${RUST_TARGET_DEPENDS} ) add_custom_command(APPEND OUTPUT ${RUST_TARGET_BINARY_DIR}/${ARCH}/debug/${RUST_LIBRARY_FILENAME} DEPENDS ${RUST_TARGET_DEPENDS} ) endif() # Keep track of the expected library artifacts. list(APPEND RUST_TARGET_RELEASE_LIBS ${RUST_TARGET_BINARY_DIR}/${ARCH}/release/${RUST_LIBRARY_FILENAME}) list(APPEND RUST_TARGET_DEBUG_LIBS ${RUST_TARGET_BINARY_DIR}/${ARCH}/debug/${RUST_LIBRARY_FILENAME}) endforeach() if(APPLE) if (${RUST_TARGET_SHARED} AND IOS) add_custom_command( OUTPUT ${RUST_TARGET_BINARY_DIR}/unified/release/${RUST_TARGET_FW_NAME}.framework DEPENDS ${RUST_TARGET_RELEASE_LIBS} WORKING_DIRECTORY ${RUST_TARGET_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E make_directory unified/release/${RUST_TARGET_FW_NAME}.framework COMMAND ${CMAKE_COMMAND} -E copy ${FW_INFO_PLIST_FILE_PATH} unified/release/${RUST_TARGET_FW_NAME}.framework/Info.plist COMMAND ${LIPO_BUILD_TOOL} -create ${RUST_TARGET_RELEASE_LIBS} -output unified/release/${RUST_TARGET_FW_NAME}.framework/${RUST_TARGET_FW_NAME} COMMAND install_name_tool -id @rpath/${RUST_TARGET_FW_NAME}.framework/${RUST_TARGET_FW_NAME} unified/release/${RUST_TARGET_FW_NAME}.framework/${RUST_TARGET_FW_NAME} ) add_custom_command( OUTPUT ${RUST_TARGET_BINARY_DIR}/unified/debug/${RUST_TARGET_FW_NAME}.framework DEPENDS ${RUST_TARGET_DEBUG_LIBS} WORKING_DIRECTORY ${RUST_TARGET_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E make_directory ${RUST_TARGET_BINARY_DIR}/unified/debug/${RUST_TARGET_FW_NAME}.framework COMMAND ${CMAKE_COMMAND} -E copy ${FW_INFO_PLIST_FILE_PATH} unified/debug/${RUST_TARGET_FW_NAME}.framework/Info.plist COMMAND ${LIPO_BUILD_TOOL} -create ${RUST_TARGET_DEBUG_LIBS} -output unified/debug/${RUST_TARGET_FW_NAME}.framework/${RUST_TARGET_FW_NAME} COMMAND install_name_tool -id @rpath/${RUST_TARGET_FW_NAME}.framework/${RUST_TARGET_FW_NAME} unified/debug/${RUST_TARGET_FW_NAME}.framework/${RUST_TARGET_FW_NAME} ) add_custom_target(${TARGET_NAME}_builder DEPENDS ${RUST_TARGET_BINARY_DIR}/unified/$,debug,release>/${RUST_TARGET_FW_NAME}.framework ) set_target_properties(${TARGET_NAME} PROPERTIES IMPORTED_LOCATION ${RUST_TARGET_BINARY_DIR}/unified/release/${FW_NAME}.framework/${FW_NAME} IMPORTED_LOCATION_DEBUG ${RUST_TARGET_BINARY_DIR}/unified/debug/${FW_NAME}.framework/${FW_NAME} ) else() add_custom_command( OUTPUT ${RUST_TARGET_BINARY_DIR}/unified/release/${RUST_LIBRARY_FILENAME} DEPENDS ${RUST_TARGET_RELEASE_LIBS} COMMAND ${CMAKE_COMMAND} -E make_directory ${RUST_TARGET_BINARY_DIR}/unified/release COMMAND ${LIPO_BUILD_TOOL} -create -output ${RUST_TARGET_BINARY_DIR}/unified/release/${RUST_LIBRARY_FILENAME} ${RUST_TARGET_RELEASE_LIBS} ) add_custom_command( OUTPUT ${RUST_TARGET_BINARY_DIR}/unified/debug/${RUST_LIBRARY_FILENAME} DEPENDS ${RUST_TARGET_DEBUG_LIBS} COMMAND ${CMAKE_COMMAND} -E make_directory ${RUST_TARGET_BINARY_DIR}/unified/debug COMMAND ${LIPO_BUILD_TOOL} -create -output ${RUST_TARGET_BINARY_DIR}/unified/debug/${RUST_LIBRARY_FILENAME} ${RUST_TARGET_DEBUG_LIBS} ) add_custom_target(${TARGET_NAME}_builder DEPENDS ${RUST_TARGET_BINARY_DIR}/unified/$,debug,release>/${RUST_LIBRARY_FILENAME} ) set_target_properties(${TARGET_NAME} PROPERTIES IMPORTED_LOCATION ${RUST_TARGET_BINARY_DIR}/unified/release/${RUST_LIBRARY_FILENAME} IMPORTED_LOCATION_DEBUG ${RUST_TARGET_BINARY_DIR}/unified/debug/${RUST_LIBRARY_FILENAME} ) endif() else() ## For all other platforms, only build the first architecture list(GET RUST_TARGET_ARCH 0 RUST_FIRST_ARCH) add_custom_target(${TARGET_NAME}_builder DEPENDS ${RUST_TARGET_BINARY_DIR}/${RUST_FIRST_ARCH}/$,debug,release>/${RUST_LIBRARY_FILENAME} ) set_target_properties(${TARGET_NAME} PROPERTIES IMPORTED_LOCATION ${RUST_TARGET_BINARY_DIR}/${RUST_FIRST_ARCH}/release/${RUST_LIBRARY_FILENAME} IMPORTED_LOCATION_DEBUG ${RUST_TARGET_BINARY_DIR}/${RUST_FIRST_ARCH}/debug/${RUST_LIBRARY_FILENAME} ) endif() set_target_properties(${TARGET_NAME}_builder PROPERTIES FOLDER "Libs") if (ANDROID AND RUST_TARGET_SHARED) set_target_properties(${TARGET_NAME} PROPERTIES IMPORTED_NO_SONAME TRUE ) endif() add_dependencies(${TARGET_NAME} ${TARGET_NAME}_builder) set_property(TARGET ${TARGET_NAME} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS}) endfunction()