ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
34.23k stars 2.5k forks source link

"multibuilds" - a plan to harmonize conditional compilation with compile errors, documentation, and IDEs #3028

Open andrewrk opened 5 years ago

andrewrk commented 5 years ago

Here are some problems to solve:

And so here is my plan: multibuilds - The idea of building not just the native target, not just a cross compiled target - but telling the compiler about the complete set of targets / build flags that are supported by the project. This gives the compiler the ability to assume that any branches not taken, are actually dead even across all the desired set of builds.

Zig is in a unique position to explore this concept, with its strong emphasis on cross compilation support.

What this looks like from an implementation perspective is roughly:

matklad commented 4 years ago

Hey, I've been working on IDEs for Rust for several year and would love to share my experience about IDEs vs conditional compilation (not that I have any insightful solutions).

What we are doing in rust-analyzer (in a small capacity at the moment) is the multibuild approach: we "instantiate" Rust crates several times with different cfg options. This in general swimmingly inside the compiler, but feels awkward at the boundary between the compilery parts and the IDE parts. Specifically, it is convenient in the IDE if you can unambiguously map source-level element (like function) to a semantic representation. With multibuild, the relationship is one-to-many, and you need some custom code to deal with it (which in the simple case would be just picking the "default" semantic repr). As an example of awkwardness, consider a function foo which has two arguments on unix and three arguments on windows. How do you render it in copmletion popup? Two items? One item with how many arguments? One multi-item with "overloads"?

Still, despite this being awkward, I don't know of a better solution for Rust style conditional compilation. However, I have a suspicion that it is possible to design conditional compilation language feature in such a way that IDE support comes naturally. Specifically, I think it should be possible to move conditional compilation from an early phase of compilation (just after parsing) to a much later phase (just before codegen). That is, I think it should be possible to make name resolution independent of the current set of cfg flags. An example of this approach is Kotlin multi-platform support:

Kotlin needs conditional compilation primarily because it targets JVM, native and JavaScript, and, to bind to platform functionality, you need a custom per-platform code. The way this feature works is roughly that you write a "header" file, which is shared between all platform, and you write an "implementation" file per platform.

Hope this is helpful!

Validark commented 2 years ago

As an example of awkwardness, consider a function foo which has two arguments on unix and three arguments on windows. How do you render it in completion popup? Two items? One item with how many arguments? One multi-item with "overloads"?

I think the IDE should render it based on the code context. If you're writing code in the Windows context, you get the Windows function. If you're writing code in the Unix context, you get the Unix function. If you're writing code in an ambiguous context, the IDE should tell you that the function cannot be called out of context and you have to insert some logic to check whether the system is Windows or Unix. For Zig, it could even be possible to autocomplete the code to something like:

if isWindows
    foo(arg1, arg2, arg3)
else if isUnix
    foo(arg1, arg2)
Arya-Elfren commented 1 year ago

I think the IDE should render it based on the code context.

This should be possible as an extension of this proposal.

The compiler goes through a function and says "for this line I need to evaluate it with these config options {win, osx, x86...}". Then the IDE asks: "If I were to insert a line here, what build options would I have to satisfy simultaneously?".

This almost looks like type narrowing, build flag narrowing?

If you have an incompatible superset it would suggest a switch statement.


I don't know if this is a good idea, or feasible.

matu3ba commented 8 months ago

Here a few possible approaches:

One tradeoff with all above approaches is that the user has no (easy) way to plug own target logic.