@@ -89,12 +89,13 @@ function(rust_cargo_application)
89
89
90
90
# TODO: Make sure RUSTFLAGS is not set.
91
91
92
- if (CONFIG_DEBUG )
93
- set (RUST_BUILD_TYPE "debug" )
94
- set (rust_build_type_arg "" )
92
+ # choose debug/release build based on Kconfig choice
93
+ if (CONFIG_RUST_CARGO_PROFILE_RELEASE )
94
+ message (STATUS "Cargo build profile: release" )
95
+ set (RUST_BUILD_TYPE release )
95
96
else ()
96
- set ( RUST_BUILD_TYPE "release " )
97
- set (rust_build_type_arg "--release" )
97
+ message ( STATUS "Cargo build profile: dev " )
98
+ set (RUST_BUILD_TYPE debug )
98
99
endif ()
99
100
set (BUILD_LIB_DIR "${CMAKE_CURRENT_SOURCE_DIR} /${RUST_TARGET} /${RUST_BUILD_TYPE} " )
100
101
@@ -178,7 +179,7 @@ ${config_paths}
178
179
DT_AUGMENTS= "${DT_AUGMENTS} "
179
180
BINARY_DIR_INCLUDE_GENERATED= "${BINARY_DIR_INCLUDE_GENERATED} "
180
181
cargo build
181
- ${rust_build_type_arg}
182
+ --profile $< IF: $< BOOL: ${CONFIG_RUST_CARGO_PROFILE_RELEASE} > ,release,dev >
182
183
183
184
# Override the features according to the shield given. For a general case,
184
185
# this will need to come from a variable or argument.
@@ -194,6 +195,7 @@ ${config_paths}
194
195
${CARGO_EXTRA_FLAGS}
195
196
COMMENT "Building Rust application"
196
197
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
198
+ USES_TERMINAL
197
199
)
198
200
199
201
# Be sure we don't try building this until all of the generated headers have been generated.
@@ -261,3 +263,118 @@ ${config_paths}
261
263
# Add an empty file so that this will build. The main will come from the rust library.
262
264
target_sources (app PRIVATE $CACHE{RUST_MODULE_DIR} /main.c ${WRAPPER_FILE} )
263
265
endfunction ()
266
+
267
+ # Function to build a Rust library using cargo, to be integrated into a C-based
268
+ # Zephyr application.
269
+ #
270
+ # In contrast to the rust_cargo_application function, which builds an entire
271
+ # Zephyr application from primarily Rust source files, this function is designed
272
+ # to build a standalone Rust crate into a library that can be integrated into a
273
+ # Zephyr application whose source code base is primarily written in C.
274
+ #
275
+ # A library built with this function will typically provide a C API through a
276
+ # Foreign Function Interface (FFI) whose C header files will be automatically
277
+ # generated from the Rust source code by the cbindgen tool, therefore use of
278
+ # this function requires the cbindgen tool to be installed on the build host.
279
+ #
280
+ # The caller must specify the following arguments:
281
+ #
282
+ # LIBRARY_NAME <library-name> - the name of the library
283
+ # CRATE_PATH <crate-path> - path to the root of the Rust crate to build
284
+ #
285
+ # The caller may optionally specify the following argument:
286
+ #
287
+ # MEMORY_PARTITION <memory-partition-name>
288
+ #
289
+ # which, if specified, will place any static global symbols built from the Rust
290
+ # sources into the specified memory partition, which can allow the symbols to be
291
+ # used from user mode threads.
292
+ #
293
+ # The function will add the specified library name into the build environment as
294
+ # a symbol that can be linked into the target Zephyr application using e.g.
295
+ # target_link_libraries.
296
+ #
297
+ # Usage:
298
+ # rust_cargo_library(LIBRARY_NAME <library-name>
299
+ # CRATE_PATH <crate-path>
300
+ # |MEMORY_PARTITION <memory-partition-name>|
301
+ # )
302
+ #
303
+ function (rust_cargo_library )
304
+ # parse function arguments
305
+ set (flags )
306
+ set (args LIBRARY_NAME CRATE_PATH MEMORY_PARTITION )
307
+ set (listArgs )
308
+ cmake_parse_arguments (arg "${flags} " "${args} " "${listArgs} " ${ARGN} )
309
+
310
+ # verify required arguments
311
+ if (NOT arg_LIBRARY_NAME )
312
+ message (FATAL_ERROR "[rust_cargo_library]: LIBRARY_NAME is a required argument" )
313
+ endif ()
314
+ if (NOT arg_CRATE_PATH )
315
+ message (FATAL_ERROR "[rust_cargo_library]: CRATE_PATH is a required argument" )
316
+ endif ()
317
+
318
+ # locate cbindgen executable
319
+ find_program (CBINDGEN_EXE cbindgen REQUIRED )
320
+
321
+ _rust_map_target ()
322
+ message (STATUS "Building Rust library ${arg_LIBRARY_NAME} for llvm target ${RUST_TARGET} " )
323
+
324
+ # choose debug/release build based on Kconfig choice
325
+ if (CONFIG_RUST_CARGO_PROFILE_RELEASE )
326
+ message (STATUS "Cargo build profile: release" )
327
+ set (RUST_BUILD_TYPE release )
328
+ else ()
329
+ message (STATUS "Cargo build profile: dev" )
330
+ set (RUST_BUILD_TYPE debug )
331
+ endif ()
332
+ set (BUILD_LIB_DIR ${CMAKE_CURRENT_SOURCE_DIR} /${RUST_TARGET}/${RUST_BUILD_TYPE} )
333
+
334
+ # library filename is based on arg_LIBRARY_NAME
335
+ set (CARGO_TARGET_DIR ${CMAKE_CURRENT_BINARY_DIR} /rust/target )
336
+ set (RUST_LIBRARY ${CARGO_TARGET_DIR} /${RUST_TARGET}/${RUST_BUILD_TYPE}/lib${arg_LIBRARY_NAME}.a )
337
+
338
+ # cbindgen header filename is based on arg_LIBRARY_NAME with _ replaced by -
339
+ string (REPLACE "_" "-" CBINDGEN_FILENAME "${arg_LIBRARY_NAME} -cbindgen.h" )
340
+ set (CBINDGEN_HEADER ${CMAKE_CURRENT_BINARY_DIR} /${CBINDGEN_FILENAME} )
341
+
342
+ # The library is built by invoking Cargo.
343
+ add_custom_target (
344
+ ${arg_LIBRARY_NAME} _builder
345
+ BYPRODUCTS ${RUST_LIBRARY} ${CBINDGEN_HEADER}
346
+
347
+ # build the library
348
+ COMMAND
349
+ cargo build
350
+ --profile $< IF:$< STREQUAL:${CONFIG_RUST_CARGO_PROFILE_RELEASE} ,y> ,release,dev>
351
+ --target ${RUST_TARGET}
352
+ --target-dir ${CARGO_TARGET_DIR}
353
+ ${CARGO_EXTRA_FLAGS}
354
+
355
+ # autogenerate the C header file using cbindgen
356
+ COMMAND
357
+ ${CMAKE_COMMAND}
358
+ -E env ${CBINDGEN_EXE}
359
+ --config cbindgen.toml
360
+ --output ${CBINDGEN_HEADER}
361
+ --lang c
362
+
363
+ WORKING_DIRECTORY ${arg_CRATE_PATH}
364
+ USES_TERMINAL
365
+ )
366
+
367
+ # Create a library target and add the location of the generated header file
368
+ # to its include path.
369
+ add_library (${arg_LIBRARY_NAME} STATIC IMPORTED GLOBAL )
370
+ add_dependencies (${arg_LIBRARY_NAME} ${arg_LIBRARY_NAME} _builder )
371
+ set_target_properties (${arg_LIBRARY_NAME} PROPERTIES IMPORTED_LOCATION ${RUST_LIBRARY} )
372
+ set_target_properties (${arg_LIBRARY_NAME} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR} )
373
+
374
+ # Place any statics from the rust library into the specified memory partition.
375
+ if (arg_MEMORY_PARTITION )
376
+ zephyr_append_cmake_library (${arg_LIBRARY_NAME} )
377
+ set (ZEPHYR_CURRENT_LIBRARY ${arg_LIBRARY_NAME} )
378
+ zephyr_library_app_memory (${arg_MEMORY_PARTITION} )
379
+ endif ()
380
+ endfunction ()
0 commit comments