Hmmm, that could be useful for those large C wrapper projects.
One approach might be to provide a test function that just takes the address to each proc so the compiler thinks it's used. Like this (untested) code:
proc someFFI*() {.importc: "$1"}
proc useSomeFFI*() =
someFFI()
proc testFFIs*(fns: varargs[typed, unsafeAddr]) =
for fnptr in fns:
discard # not sure if Nim will be smart enough to elide this, but you could do a null op, etc
when isMainModule:
testFFIs(useSomeFFI)
You could create a pragma of {.includeBuild.} to do by adding to a compile time list and doing similar.
I'd be up for adding such a pragma macro to cdecl as a useful edge for testing C FFI as I have projects I could use it on. Presuming there's no cleaner approach.
How much effort would it take to modify {.used.} and/or {.importc(pp).} to support this behavior?
Very little effort, I can guide you on Discord. But neither .used nor .importc are the right pragmas to do that, we should introduce a new one like .mangledExport.
Suggestions for even better names are welcome.
There are cases where macros use .used procs that should be optimized out. keep affects the backend, used the frontend and it seems to be wise not to conflate the two.
Simplicity is not about leaving features out nor about conflating features (C's static keyword is a prime example here), it's about keeping features simple and independent from each other.
Now you can argue that keep should imply used, but it really shouldn't: If you forget the export marker the lack of .used will remind you whereas most symbols in your use case already use keep.