Repository navigation
Description
At the moment the config API gives you two options for passing args to clang, using Input.compilerOptions:
- Use the defaults, which work for 90% of cases
- Pass custom args, overwriting the defaults
The default params depend on:
- the host OS
- the target language specified in the config
- probably other config elements in future (especially with C++ support in the works)
- some non-trivial logic that attempts to find system headers
Often what users want is to add extra args to the defaults, not replace them. Users shouldn't have to replicate our complicated default arg logic. In my own configs, I often end up importing some of the internal utils that calculate the default args.
Option 1: Expose utils
The obvious solution would be to clean up and expose those internal utils. That's a bit fiddly because the args depend on elements from the config. There's no clean way of building that API, aside from asking the user to repeat themselves (eg specify the target language in both the config and this arg calculation util).
There are other options for this approach, but nothing particularly clean.
Option 2: Non-breaking API change
We could change List<String>? compilerOptions to allow adding to the defaults. For example, we could accept a sentinel string, like "DEFAULT_ARGS" that we replace with the defaults. Or we could make it a List<String?> and use null as the sentinel.
A less hacky solution would be to add another field to Input, like bool appendCompilerOptions, which means the compilerOptions are appended to the defaults instead of replacing them. Not as clean as I'd like, but this is the approach I lean towards.
The downside of these approaches is that the user still has to take all the defaults, or none of them (though they can override the defaults since later args overwrite earlier ones).
Option 3: Breaking API change
We could also consider changing compilerOptions from a List<String> to some sort of structured object. We would have fields for each arg we currently set, each of which is nullable, and if the field is null then the default is used. The object would also still have a List<String> for other options.
Activity
dcharkes commentedon Sep 14, 2026
Yeah option 1 seems bad because of the user having to repeat the config.
Option 2 and 3 both seem fine to me. E.g. they both have the workflow the user provides something and then they can look at the logs for the actual clang flags invocation and then iterate. I don't have a super strong preference.
Option 3 kind of has the issue that you can't really enumerate all arguments of clang, so you need a catch-all clause where users can add clang options we haven't structured. Then in the future if we add such an argument to the structured API the users might skip migrating to the structured API, so you end up with the overriding behavior from appending again.
If you want to go for option 2 with
"DEFAULT_ARGS", consider making the argumentList<String> compilerOptions = [r"$DEFAULT_ARGS"]as a way of documenting.vikramsingh920 commentedon Sep 15, 2026
hii @liamappelbe, I’d like to work on this issue.
Could you please assign this issue to me?
liamappelbe commentedon Sep 16, 2026
@vikramsingh920 Let's go with the
bool appendCompilerOptionsapproach. Seems to be the least worst option to me.vikramsingh920 commentedon Sep 16, 2026
Thanks @liamappelbe!
I’ll go with the
bool appendCompilerOptionsapproach and keep the changes focused on this issue.[ffigen] Add Input.appendCompilerOptions to append clang args to defa…
[ffigen] Add Input.appendCompilerOptions to append clang args to defa…