Configuration option to disable static inline on functions #986
Labels
No labels
bazel
bluetooth
board settings
boot_stage2
bug
build
c++
can't reproduce
clang
clib-interface
cmsis
code cleanliness
code size
compiler version issues
cyw43_driver
debug
discussion
documentation
duplicate
dynamic_clock
elf2uf2
enhancement
errata
filesystem
flash layout
floating point
FreeRTOS
hardware_adc
hardware_claim
hardware_clocks
hardware_dma
hardware_exception
hardware_flash
hardware_gpio
hardware_i2c
hardware_irq
hardware_pio
hardware_pwm
hardware_rcp
hardware_rtc
hardware_spi
hardware_sync
hardware_uart
hardware_vreg
hardware_watchdog
hardware_xosc
help wanted
host
IAR
installation
invalid
linker scripts
lto
lwip
mbedtls
missing API
needs reporter detail
networking
newlib
newlib-multicore
non-c
non-cmake
non-gcc
openocd
orphan PR
OS integration
pico_async_context
pico_base
pico_binary_info
pico_flash
picolibc
pico_lwip
pico_malloc
pico_multicore
pico_printf
pico_runtime
pico_stdio
pico_stdio_usb
pico_sync
pico_time
pico_util
pioasm
port
question
review
review2
rtos interop
runtime init
static library
svd
test
tinyusb
vscode
wifi integration
wontfix
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
gh-raspberrypi/pico-sdk#986
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Would it be possible to replace the
static inlines with a configurable attribute that can be disabled if necessary?Background
We are using a Rust library to implement the main logic. The lib defines a
pub extern "C" fn rust_entry()which gets called from the Cmainfunction and then takes over control and calls back into the Pico-SDK where necessary (e.g. formalloc/free, GPIO etc.)This concept works amazingly well – except for one problem: Since a lot of the SDK's functions are
static, we cannot link against them. Our current workaround is to implement a 1:1 C-wrapper for all thestaticfunctions we need – however this gets quite cumbersome over time.A possible naive solution could be sth. like
and then using
__pico_static_inlineon all functions (if it is not crucial that they are inlined of course).I know that our setup is probably a little bit exotic and I'm completely fine if this issue gets closed 😅
However IMO this could ease the burden to write an application in language-of-your-choice, because if you can link back against the SDK, you suddenly don't need an entire native toolchain/SDK in language-of-your-choice anymore to get stuff running.
I've never written any Rust myself, and I don't know enough about the C SDK to answer your question, but have you had a look at https://github.com/rp-rs ? ping @thejpster
Yes, I know about
rp-rs; nevertheless tyvm for the suggestion :DThere are a few reasons why we decided to stick with the official SDK if possible (e.g. pretty stable, quick bugfixes for breaking issues, has a lot of built-in features etc. – we found that even if another toolchain suits the needs we have now there is a significant risk that we well run into problems/missing features in the future).
I ran into a similar problem providing access to the SDK routines from BBC BASIC. My solution was to write some Python code which reads through the SDK header files and automatically generates wrapper code such as:
The stub_ functions are then callable. The BBC BASIC function look-up (SYS) hides the stub_ prefix from the user.
Since the wrapper functions are automatically generated they can be reproduced from the latest SDK at every build.
My problem is with LWIP which makes extensive use of C #define macros. These cannot be automatically stubbed as the parameter and return types are unknown.
@Memotech-Bill Uhh, this looks pretty nice – I'll definitively take a closer look at it, this could be a good workaround!
This is potentially useful for people who want to make a static lib of the SDK (although #882 also helps)
@Memotech-Bill , really nice idea, I am fighting the same issue with my freepascal port of the pico headers, I ended up re-implementing lots of the static inlines with pascal code.
My 2p: Rather than disabling static wholesale, it seems to make sense to go through the API and decide what is public (and hence something you are careful not to break without warning people) and what is internal only. The internal APIs should not have extern linkage (i.e. remain static), and the public API should have extern linkage (i.e. not be marked static).
If application developers rely on APIs that are internal only, you should consider stabilizing them and making them public.
If the issue is that the
static inlinefunctions are trivial things defined (and not just declared) in the header file (ugh), then this kind of macro is probably the right work-around (also, don't do that and consider enabling LTO instead).Yeah this is just referring to public API functions which happen to implemented inline for code size/speed reasons.
And now i give it more than a moments thought, having something to generate is better, because either
a) you remove the static as well as the inline, in which case you'll get multiple-definitions
b) you leave the static, and you get duplicate code, but also no public callable version
I'm a little bit torn between both options...
On one side, generating something is much easier and faster; on the other side – @thejpster has a point: Using
static inlinewithin headers for public APIs is non-idiomatic C and breaks FFI compatibility.Furthermore I'm wondering if
static inlineis necessary? Doing LTO is probably a much better approach and has the additional advantage that it can be tweaked for either performance or code size, whereasstatic inlinealways optimizes for performance.For those interested: As a stopgap I've created a tiny helper to generate no-
staticno-inlinebindings for thestatic inlinefunctions. It's a bit cursed because it uses regex to parse the headers, but it works surprisingly well 😅There are also pregenerated bindings in
generated/.