Issue
Problem
I am learning how to do C interop in bare metal Rust project. I have a simple C project that takes a struct and prints it. I compile it with arm-none-eabi-gcc to generate a libfoo.a and link it against my Rust project.
The Rust project is configure to use the arm gcc and linker in .cargo.config.toml
. I generate bindings with bindgen and call a C function through the binding.
I am having issue with getting the project to compile. When rust tries to link against the static C library, it complains about
error: linking with `arm-none-eabi-gcc` failed: exit status: 1
|
= note: LC_ALL="C" PATH="/Users/yuenton/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/bin:/Users/yuenton/.pyenv/shims:/Applica
tions/Simplicity Studio.app/Contents/Eclipse/developer/adapter_packs/commander/Commander.app/Contents/MacOS:/usr/local/opt/ruby/bin:/usr/local/lib/ruby/gems/2.7
.0/bin:/Applications/cov-analysis-macosx-2022-3-0/bin/:/Applications/SEGGER/JLink_V760h:
/usr/local/opt/gcc-arm-none-eabi-8-2019-q3-update/bin:/Users/yuenton/.toolbox/bin:/Users/yuenton/.nvm/versions/node/v14.20.0/bin:/Users/yuenton/bin:/usr/local/b
in:/opt/homebrew/bin:/opt/homebrew/sbin:/Users/yuenton/.local/share/nvim/mason/bin:/Users/yuenton/.pyenv/bin:/Applications/Simplicity Studio.app/Contents/Eclips
e/developer/adapter_packs/commander/Commander.app/Contents/MacOS:/usr/local/opt/ruby/bin:/usr/local/lib/ruby/gems/2.7.0/bin:/Applications/SEGGER/JLink_V760h:/usr/local/opt/gcc-arm-none-eabi-8-2019-q3-
update/bin:/Users/yuenton/.toolbox/bin:/Users/yuenton/.nvm/versions/node/v14.20.0/bin:/Users/yuenton/bin:/usr/local/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/us
r/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/
var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Users/yuen
ton/.cargo/bin:/Applications/kitty.app/Contents/MacOS:/usr/local/opt/fzf/bin" VSLANG="1033" "arm-none-eabi-gcc" "/var/folders/lm/n3lqn5fx2qsddzty2389rfgcfkmffy/
T/rustc5AOqmy/symbols.o" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/app-6d1120295b5167b4.44hpxx6ly2g0n
6p4.rcgu.o" "-Wl,--as-needed" "-L" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps" "-L" "/Volumes/workplac
e/playground/rust_embedded_with_c_interop/app/target/debug/deps" "-L" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/
debug/build/app-fca9b4a0fb47443d/out" "-L" "/usr/local/opt/arm-none-eabi-gcc/gcc/arm-none-eabi/lib" "-L" "./c_proj/build/" "-L" "/Volumes/workplace/playground/r
ust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/build/cortex-m-c1b153b4741594d3/out" "-L" "/Volumes/workplace/playground/rust_embedded_with_c_in
terop/app/target/thumbv7m-none-eabi/debug/build/cortex-m-rt-feabb8431baf6f6c/out" "-L" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/th
umbv7m-none-eabi/debug/build/cortex-m-semihosting-3928837b527a45a9/out" "-L" "/Users/yuenton/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/thumbv7m-
none-eabi/lib" "-Wl,-Bstatic" "-lfoo" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libcty-580a16e85c8469
02.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libcortex_m_rt-c96c0df2d2e53803.rlib" "/Volumes/wo
rkplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libr0-c044695858752b9f.rlib" "/Volumes/workplace/playground/rust_embedd
ed_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libcortex_m-4e3d1e159a5b50d2.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/ta
rget/thumbv7m-none-eabi/debug/deps/libaligned-433f80187af623df.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/d
ebug/deps/libas_slice-7cd7b96cd776cbe0.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libstable_dere
f_trait-d6be1c622a71e64c.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libgeneric_array-2fb71faed80
7ea2c.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libgeneric_array-fe72171b4f9ffd35.rlib" "/Volum
es/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libgeneric_array-b85e7f6fe2cef964.rlib" "/Volumes/workplace/playgr
ound/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libtypenum-271c16d2a2f77c26.rlib" "/Volumes/workplace/playground/rust_embedded_with_c
_interop/app/target/thumbv7m-none-eabi/debug/deps/libpanic_halt-4d0b3983ed02fa87.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/th
umbv7m-none-eabi/debug/deps/libcortex_m_semihosting-695180d6324c8ba4.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-
eabi/debug/deps/libcortex_m-09751e7d921baf68.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libembed
ded_hal-2809cd32091c3ba8.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libvoid-fb1bf4e02014cb07.rli
b" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libnb-56a04b5218fae863.rlib" "/Volumes/workplace/playgro
und/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libnb-f9897756642f2d1b.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_inter
op/app/target/thumbv7m-none-eabi/debug/deps/libvolatile_register-6c4b892b7612085e.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/t
humbv7m-none-eabi/debug/deps/libvcell-16cd54fe2c2cf158.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/dep
s/libbare_metal-cdf719ed4a7ace5b.rlib" "/Users/yuenton/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/thumbv7m-none-eabi/lib/librustc_std_workspace_c
ore-05bb5221ddab705b.rlib" "/Users/yuenton/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/thumbv7m-none-eabi/lib/libcore-43d826545f9dd0d1.rlib" "/Use
rs/yuenton/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/thumbv7m-none-eabi/lib/libcompiler_builtins-c59fdfa9b274eac2.rlib" "-Wl,-Bdynamic" "-Wl,--e
h-frame-hdr" "-Wl,-z,noexecstack" "-L" "/Users/yuenton/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/thumbv7m-none-eabi/lib" "-o" "/Volumes/workplac
e/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/app-6d1120295b5167b4" "-Wl,--gc-sections" "-no-pie" "-nodefaultlibs" "-Wl,-Tl
ink.x" "-nostartfiles"
= note: /usr/local/opt/gcc-arm-none-eabi-8-2019-q3-update/bin/../lib/gcc/arm-none-eabi/8.3.1/../../../../arm-none-eabi/bin/ld: /Volumes/workplace/playground/r
ust_embedded_with_c_interop/app/target/debug/deps/libfoo.a(foo.o): in function `print_hello_foo':
foo.c:(.text+0x4c): undefined reference to `printf'
collect2: error: ld returned 1 exit status
= note: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
= note: use the `-l` flag to specify native libraries to link
= note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scrip
ts.html#cargorustc-link-libkindname)
I tried linking against libc.a provided by arm-none-eabi to get a reference to the printf definition, but it introduces more undefined references
error: linking with `arm-none-eabi-gcc` failed: exit status: 1
|
= note: LC_ALL="C" PATH="/Users/yuenton/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/bin:/Users/yuenton/.pyenv/shims:/Applica
tions/Simplicity Studio.app/Contents/Eclipse/developer/adapter_packs/commander/Commander.app/Contents/MacOS:/usr/local/opt/ruby/bin:/usr/local/lib/ruby/gems/2.7
.0/bin:/Applications/cov-analysis-macosx-2022-3-0/bin/:/Applications/SEGGER/JLink_V760h:
/usr/local/opt/gcc-arm-none-eabi-8-2019-q3-update/bin:/Users/yuenton/.toolbox/bin:/Users/yuenton/.nvm/versions/node/v14.20.0/bin:/Users/yuenton/bin:/usr/local/b
in:/opt/homebrew/bin:/opt/homebrew/sbin:/Users/yuenton/.local/share/nvim/mason/bin:/Users/yuenton/.pyenv/bin:/Applications/Simplicity Studio.app/Contents/Eclips
e/developer/adapter_packs/commander/Commander.app/Contents/MacOS:/usr/local/opt/ruby/bin:/usr/local/lib/ruby/gems/2.7.0/bin:lpay/Applications/SEGGER/JLink_V760h:/usr/local/opt/gcc-arm-none-eabi-8-2019-q3-
update/bin:/Users/yuenton/.toolbox/bin:/Users/yuenton/.nvm/versions/node/v14.20.0/bin:/Users/yuenton/bin:/usr/local/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/us
r/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/
var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Users/yuen
ton/.cargo/bin:/Applications/kitty.app/Contents/MacOS:/usr/local/opt/fzf/bin" VSLANG="1033" "arm-none-eabi-gcc" "/var/folders/lm/n3lqn5fx2qsddzty2389rfgcfkmffy/
T/rustcjzQWtq/symbols.o" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/app-6d1120295b5167b4.44hpxx6ly2g0n
6p4.rcgu.o" "-Wl,--as-needed" "-L" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps" "-L" "/Volumes/workplac
e/playground/rust_embedded_with_c_interop/app/target/debug/deps" "-L" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/
debug/build/app-fca9b4a0fb47443d/out" "-L" "/usr/local/opt/arm-none-eabi-gcc/gcc/arm-none-eabi/lib" "-L" "./c_proj/build/" "-L" "/Volumes/workplace/playground/r
ust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/build/cortex-m-c1b153b4741594d3/out" "-L" "/Volumes/workplace/playground/rust_embedded_with_c_in
terop/app/target/thumbv7m-none-eabi/debug/build/cortex-m-rt-feabb8431baf6f6c/out" "-L" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/th
umbv7m-none-eabi/debug/build/cortex-m-semihosting-3928837b527a45a9/out" "-L" "/Users/yuenton/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/thumbv7m-
none-eabi/lib" "-Wl,-Bstatic" "-lfoo" "-lc" "-lc_nano" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libc
ty-580a16e85c846902.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libcortex_m_rt-c96c0df2d2e53803.r
lib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libr0-c044695858752b9f.rlib" "/Volumes/workplace/playg
round/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libcortex_m-4e3d1e159a5b50d2.rlib" "/Volumes/workplace/playground/rust_embedded_with
_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libaligned-433f80187af623df.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thu
mbv7m-none-eabi/debug/deps/libas_slice-7cd7b96cd776cbe0.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/de
ps/libstable_deref_trait-d6be1c622a71e64c.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libgeneric_
array-2fb71faed807ea2c.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libgeneric_array-fe72171b4f9ff
d35.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libgeneric_array-b85e7f6fe2cef964.rlib" "/Volumes
/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libtypenum-271c16d2a2f77c26.rlib" "/Volumes/workplace/playground/rus
t_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libpanic_halt-4d0b3983ed02fa87.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_inte
rop/app/target/thumbv7m-none-eabi/debug/deps/libcortex_m_semihosting-695180d6324c8ba4.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/targ
et/thumbv7m-none-eabi/debug/deps/libcortex_m-09751e7d921baf68.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/de
bug/deps/libembedded_hal-2809cd32091c3ba8.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libvoid-fb1
bf4e02014cb07.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libnb-56a04b5218fae863.rlib" "/Volumes/
workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libnb-f9897756642f2d1b.rlib" "/Volumes/workplace/playground/rust_embe
dded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/libvolatile_register-6c4b892b7612085e.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_int
erop/app/target/thumbv7m-none-eabi/debug/deps/libvcell-16cd54fe2c2cf158.rlib" "/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-no
ne-eabi/debug/deps/libbare_metal-cdf719ed4a7ace5b.rlib" "/Users/yuenton/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/thumbv7m-none-eabi/lib/librust
c_std_workspace_core-05bb5221ddab705b.rlib" "/Users/yuenton/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/thumbv7m-none-eabi/lib/libcore-43d826545f9
dd0d1.rlib" "/Users/yuenton/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/thumbv7m-none-eabi/lib/libcompiler_builtins-c59fdfa9b274eac2.rlib" "-Wl,-B
dynamic" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/Users/yuenton/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/thumbv7m-none-eabi/lib" "-o" "
/Volumes/workplace/playground/rust_embedded_with_c_interop/app/target/thumbv7m-none-eabi/debug/deps/app-6d1120295b5167b4" "-Wl,--gc-sections" "-no-pie" "-nodefa
ultlibs" "-Wl,-Tlink.x" "-nostartfiles"
= note: /usr/local/opt/gcc-arm-none-eabi-8-2019-q3-update/bin/../lib/gcc/arm-none-eabi/8.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/opt/arm-none-eabi-gc
c/gcc/arm-none-eabi/lib/libc.a(lib_a-sbrkr.o): in function `_sbrk_r':
sbrkr.c:(.text._sbrk_r+0x18): undefined reference to `_sbrk'
/usr/local/opt/gcc-arm-none-eabi-8-2019-q3-update/bin/../lib/gcc/arm-none-eabi/8.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/opt/arm-none-eabi-gc
c/gcc/arm-none-eabi/lib/libc.a(lib_a-writer.o): in function `_write_r':
writer.c:(.text._write_r+0x24): undefined reference to `_write'
/usr/local/opt/gcc-arm-none-eabi-8-2019-q3-update/bin/../lib/gcc/arm-none-eabi/8.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/opt/arm-none-eabi-gc
c/gcc/arm-none-eabi/lib/libc.a(lib_a-closer.o): in function `_close_r':
closer.c:(.text._close_r+0x18): undefined reference to `_close'
/usr/local/opt/gcc-arm-none-eabi-8-2019-q3-update/bin/../lib/gcc/arm-none-eabi/8.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/opt/arm-none-eabi-gc
c/gcc/arm-none-eabi/lib/libc.a(lib_a-fstatr.o): in function `_fstat_r':
fstatr.c:(.text._fstat_r+0x1c): undefined reference to `_fstat'
/usr/local/opt/gcc-arm-none-eabi-8-2019-q3-update/bin/../lib/gcc/arm-none-eabi/8.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/opt/arm-none-eabi-gc
c/gcc/arm-none-eabi/lib/libc.a(lib_a-isattyr.o): in function `_isatty_r':
isattyr.c:(.text._isatty_r+0x18): undefined reference to `_isatty'
/usr/local/opt/gcc-arm-none-eabi-8-2019-q3-update/bin/../lib/gcc/arm-none-eabi/8.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/opt/arm-none-eabi-gc
c/gcc/arm-none-eabi/lib/libc.a(lib_a-lseekr.o): in function `_lseek_r':
lseekr.c:(.text._lseek_r+0x24): undefined reference to `_lseek'
/usr/local/opt/gcc-arm-none-eabi-8-2019-q3-update/bin/../lib/gcc/arm-none-eabi/8.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/opt/arm-none-eabi-gc
c/gcc/arm-none-eabi/lib/libc.a(lib_a-readr.o): in function `_read_r':
readr.c:(.text._read_r+0x24): undefined reference to `_read'
/usr/local/opt/gcc-arm-none-eabi-8-2019-q3-update/bin/../lib/gcc/arm-none-eabi/8.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/opt/arm-none-eabi-gc
c/gcc/arm-none-eabi/lib/libc.a(lib_a-abort.o): in function `abort':
abort.c:(.text.abort+0x10): undefined reference to `_exit'
/usr/local/opt/gcc-arm-none-eabi-8-2019-q3-update/bin/../lib/gcc/arm-none-eabi/8.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/opt/arm-none-eabi-gc
c/gcc/arm-none-eabi/lib/libc.a(lib_a-signalr.o): in function `_kill_r':
signalr.c:(.text._kill_r+0x1c): undefined reference to `_kill'
/usr/local/opt/gcc-arm-none-eabi-8-2019-q3-update/bin/../lib/gcc/arm-none-eabi/8.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/opt/arm-none-eabi-gc
c/gcc/arm-none-eabi/lib/libc.a(lib_a-signalr.o): in function `_getpid_r':
signalr.c:(.text._getpid_r+0x4): undefined reference to `_getpid'
collect2: error: ld returned 1 exit status
= note: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
= note: use the `-l` flag to specify native libraries to link
= note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scrip
ts.html#cargorustc-link-libkindname)
I would expect that glib functions definition is automatically linked by the compiler and I shouldn't have to provided the libraries. Am I missing a step when setting up the C static library?
I'm confused how the native library is supposed to be linked when cross compiling with Rust for C libraries. Any help is greatly appreciated!
Project Setup
This is my C files
// foo.h
typedef struct {
int x;
float y;
char str[20];
} foo_s;
void print_hello_foo(const foo_s *foo);
// foo.c
#include "include/foo.h"
#include <stdio.h>
void print_hello_foo(const foo_s *foo) {
printf("foo says hello, x: %i, y: %f, str: %s\n", foo->x, foo->y, foo->str);
}
I have a cmake project that compiles it
// CMakeLists.txt
cmake_minimum_required(VERSION 3.23)
set(CMAKE_C_COMPILER_FORCED TRUE)
set(CMAKE_CXX_COMPILER_FORCED TRUE)
project(foo)
add_library(foo foo.c)
target_include_directories(foo PUBLIC include)
message(styuen "$(CMAKE_INSTALL_INCLUDEDIR)")
install(TARGETS foo PUBLIC_HEADER DESTINATION $(CMAKE_INSTALL_INCLUDEDIR)/foo)
// toolchain.cmake
set(CMAKE_SYSTEM_NAME Generic CACHE STRING "The operating system to target. Generic for cross-platform" FORCE)
set(CMAKE_SYSTEM_PROCESSOR arm CACHE STRING "The target CPU architecture" FORCE)
set(CMAKE_CROSSCOMPILING 1 CACHE STRING "" FORCE)
set(TOOLCHAIN_PREFIX arm-none-eabi-)
find_program(BINUTILS_PATH ${TOOLCHAIN_PREFIX}gcc NO_CACHE)
if (NOT BINUTILS_PATH)
message(FATAL_ERROR "ARM GCC toolchain not found")
endif ()
get_filename_component(ARM_TOOLCHAIN_DIR ${BINUTILS_PATH} DIRECTORY)
# Without that flag CMake is not able to pass test compilation check
if (${CMAKE_VERSION} VERSION_EQUAL "3.6.0" OR ${CMAKE_VERSION} VERSION_GREATER "3.6")
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
else ()
set(CMAKE_EXE_LINKER_FLAGS_INIT "--specs=nosys.specs")
endif ()
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc CACHE STRING "" FORCE)
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER} CACHE STRING "" FORCE)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++ CACHE STRING "" FORCE)
set(CMAKE_AR ${TOOLCHAIN_PREFIX}gcc-ar CACHE STRING "" FORCE)
set(CMAKE_RANLIB ${TOOLCHAIN_PREFIX}gcc-ranlib CACHE STRING "" FORCE)
set(CMAKE_LINKER ${TOOLCHAIN_PREFIX}/arm-none-eabi-ld CACHE STRING "" FORCE)
execute_process(COMMAND ${CMAKE_C_COMPILER} -print-sysroot
OUTPUT_VARIABLE ARM_GCC_SYSROOT OUTPUT_STRIP_TRAILING_WHITESPACE)
In my rust project I the following for build configuration
# .cargo/config.toml
[target.thumbv7m-none-eabi]
# uncomment this to make `cargo run` execute programs on QEMU
runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# uncomment ONE of these three option to make `cargo run` start a GDB session
# which option to pick depends on your system
runner = "arm-none-eabi-gdb -q -x openocd.gdb"
# runner = "gdb-multiarch -q -x openocd.gdb"
# runner = "gdb -q -x openocd.gdb"
rustflags = [
# Previously, the linker arguments --nmagic and -Tlink.x were set here.
# They are now set by build.rs instead. The linker argument can still
# only be set here, if a custom linker is needed.
# By default, the LLD linker is used, which is shipped with the Rust
# toolchain. If you run into problems with LLD, you can switch to the
# GNU linker by uncommenting this line:
"-C", "linker=arm-none-eabi-ld",
# If you need to link to pre-compiled C libraries provided by a C toolchain
# use GCC as the linker by uncommenting the three lines below:
"-C", "linker=arm-none-eabi-gcc",
"-C", "link-arg=-Wl,-Tlink.x",
"-C", "link-arg=-nostartfiles",
]
[build]
# Pick ONE of these default compilation targets
# target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+
target = "thumbv7m-none-eabi" # Cortex-M3
# target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU)
# target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)
# target = "thumbv8m.base-none-eabi" # Cortex-M23
# target = "thumbv8m.main-none-eabi" # Cortex-M33 (no FPU)
# target = "thumbv8m.main-none-eabihf" # Cortex-M33 (with FPU)
// build.rs
//! This build script copies the `memory.x` file from the crate root into
//! a directory where the linker can always find it at build time.
//! For many projects this is optional, as the linker always searches the
//! project root directory -- wherever `Cargo.toml` is. However, if you
//! are using a workspace or have a more complicated build setup, this
//! build script becomes required. Additionally, by requesting that
//! Cargo re-run the build script whenever `memory.x` is changed,
//! updating `memory.x` ensures a rebuild of the application with the
//! new memory settings.
//!
//! The build script also sets the linker flags to tell it which link script to use.
use cmake::Config;
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
fn main() {
// Put `memory.x` in our output directory and ensure it's
// on the linker search path.
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
File::create(out.join("memory.x"))
.unwrap()
.write_all(include_bytes!("memory.x"))
.unwrap();
println!("cargo:rustc-link-search={}", out.display());
// By default, Cargo will re-run a build script whenever
// any file in the project changes. By specifying `memory.x`
// here, we ensure the build script is only re-run when
// `memory.x` is changed.
println!("cargo:rerun-if-changed=memory.x");
println!(
"cargo:rustc-link-search=native=/usr/local/opt/arm-none-eabi-gcc/gcc/arm-none-eabi/lib"
);
println!("cargo:rustc-link-search=native=./c_proj/build/");
println!("cargo:rustc-link-lib=static=foo");
// println!("cargo:rustc-link-lib=static=c");
println!("cargo:rerun-if-changed=c_proj/include/foo.h");
println!("cargo:rerun-if-changed=c_proj/foo.c");
let bindings = bindgen::Builder::default()
.header("c_proj/include/foo.h")
.use_core()
.ctypes_prefix("cty")
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.generate()
.expect("Unable to generate bindings");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}
rust main.rs
#![no_std]
#![no_main]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
use cortex_m_semihosting::{debug, hprintln};
// pick a panicking behavior
use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch panics
// use panic_abort as _; // requires nightly
// use panic_itm as _; // logs messages over ITM; requires ITM support
// use panic_semihosting as _; // logs messages to the host stderr; requires a debugger
use cortex_m::asm;
use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
hprintln!("Hello, world!");
let foo = foo_s {
x: 3,
y: 3.14,
str_: [
116, 101, 115, 116, 105, 110, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
],
};
unsafe {
print_hello_foo(&foo);
}
// exit QEMU
// NOTE do not run this on hardware; it can corrupt OpenOCD state
debug::exit(debug::EXIT_SUCCESS);
loop {
// your code goes here
}
}
Solution
The library has platform dependencies that must be resolved by a platform specific porting layer that you need to provide. This is necessary because I/O and memory management are platform dependent.
For the Newlib C library that arm-none-eabi-gcc normally uses this is the "syscalls" layer.
Most syscalls can be implemented as non-functioning stubs. If you only need to support printf
then implementing write
for stdout
is sufficient.
If you use dynamic memory allocation also sbrk
.
If your application is multithreaded, then you should implement the re-entrant versions suffixed _r
.
Minimal implementations of these stubs are provided in the documentation. All you need do for example is create a C source syscalls.c, containing these stubs then compile and link it to your project. Some will need re-implementation to be functional, but that will allow your code to link.
In response to Carl Norum's comment, internally parts of newlib use dynamic allocation. That might be a good reason to override printf()
with a third-party "lightweight" implementation. To ensure it is supported you will need to have at least a small heap. Often the linker script will create a heap space (typically all space available after static allocation), that being the case then the following sbrk
implementation will provide a heap:
register char *stack_ptr asm("sp");
void *_sbrk(ptrdiff_t incr)
{
extern char end asm("end"); // Defined by the linker.
static char *heap_end;
char *prev_heap_end;
if (heap_end == NULL)
heap_end = &end;
prev_heap_end = heap_end;
if (heap_end + incr > stack_ptr)
{
errno = ENOMEM;
return (void *)-1;
}
heap_end += incr;
return (void *)prev_heap_end;
}
_sbrk_r()
if needed (multi-threaded code) would have a thread-local errno
(or just do not rely on errno
to be correct). Moreover in a multi-threaded environment you would need to override __malloc_lock()
and __malloc_unlock()
stubs to make dynamic memory allocation thread-safe.
Answered By - Clifford Answer Checked By - Cary Denson (WPSolving Admin)