-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
introduce operating system version ranges as part of the target #1907
Comments
I believe the story with windows is a bit more complicated than just using the "marketing" version: https://docs.microsoft.com/en-us/windows/desktop/SysInfo/operating-system-version It all started by genius marketing to call API version 6.1 "Windows 7" and went downhill from there. I guess after some negative press they just decided to re-version their 6.4 API to 10 [1]. What does that mean in terms of target version? Not sure but I have the feeling that the API version is more useful then the marketing version. Is Windows XP really more like a distro label, while 5.1/5.2 is what matters as platform/API? [1] https://www.digitaltrends.com/computing/windows-10-kernel-to-leapfrog-from-6-4-directly-to-10-0/ |
Usually |
We use to call it "Vista 7". |
For macOS, there's an important linker flag |
Regarding the Windows stuff, people in this thread who have a better understanding than me, can you help me come up with the enum that represents Windows API versions? Here's what I would do on first guess: const WindowsVersion = enum {
Legacy, /// Represents a version that is unsupported due to being too old.
v7,
v8,
v10,
v10_2015LTSB,
v10_2016LTSB,
v10_2019LTSC,
Unreleased, /// Represents a version of windows not yet released.
}; The compiler will also need a way to detect the version of the native target. |
Linux has a special ELF section for this (and Example: qt/qtbase@bb8a618#diff-e4c3c13b1c7ed0faa458312ad4d5c1da [1] a.out: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=64dbf5608aa84b8eff7ced72abd13868652890e5, for GNU/Linux 5.3.28, not stripped |
From window's sdkddkver.h: (see also https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=vs-2019 )
I think that should translate to the following zig definition: const WindowsVersion = enum(u16) {
WindowsNT4 = 0x0400,
Windows2000 = 0x0500,
WindowsXP = 0x0501,
WindowsServer2003 = 0x0502,
WindowsVista = 0x0600,
WindowsServer2008 = 0x0600, // are duplicate enums allowed?
Windows7 = 0x0601,
Windows8 = 0x0602,
Windows8_1 = 0x0603,
Windows10 = 0x0A00,
} |
@daurnimator see #2115 |
#2847 did a proof of concept of adding more things to the target, and I think it is a good idea. This is part of zig's "optimality" claim mixed with "communicate intent precisely". When the programmer specifies the minimum target OS version, zig code can take advantage of that specification to generate better code. See also fc9e28e which solved #397. |
If anyone wants to contribute to this issue, most of the work can be in Zig code, with the following sub-task: Detect the native operating system version, for all the OSes in the support table. |
How is this meant to work for cross-compiling? e.g. is there going to be a specific option to target the Windows Seven API, or Linux 5.x, etc? |
Updated syntax for
Here's what it will look like to populate a @@ -167,7 +167,7 @@ const test_targets = blk: {
.target = Target{
.Cross = CrossTarget{
.cpu = Target.Cpu.baseline(.mipsel),
- .os = .linux,
+ .os = Target.Os.defaultVersionRange(.linux),
.abi = .musl,
},
},
@@ -178,7 +178,7 @@ const test_targets = blk: {
.target = Target{
.Cross = CrossTarget{
.cpu = Target.Cpu.baseline(.x86_64),
- .os = .macosx,
+ .os = Target.Os.defaultVersionRange(.macosx),
.abi = .gnu,
},
},
@@ -190,7 +190,7 @@ const test_targets = blk: {
.target = Target{
.Cross = CrossTarget{
.cpu = Target.Cpu.baseline(.i386),
- .os = .windows,
+ .os = Target.Os.defaultVersionRange(.windows),
.abi = .msvc,
},
}, Code that used |
How does this interact with libc version ranges? |
The only libc which has version options is glibc and it is a specific version to target, not a range. |
@andrewrk may you give more details on this?
A real life example or something? |
Here are some examples: Lines 155 to 156 in 907c558
This code is to be updated to call Another example, more consequential, is using io_uring rather than epoll in lib/std/event/loop.zig. Same principles as the previous paragraph. io_uring is quite new, so when compiling for the native OS target (which sets both min and max versions to the host OS) io_uring code would be compiled out and take up no space. This helps Zig with its "optimal" claim, because it means we can code for all the different abstractions that have been available over time, and Zig code at compile-time can determine what particular set to target. Finally, another use case for this is http://libsound.io/. Sound APIs on Windows have changed with nearly every major release of Windows, and a Zig package that wants to emit sound on Windows has a lot to gain from knowing the version range. If you happen to know that your target platform is stuck on an older Windows, then you can note that in the target version and there will be no API calls to newer features. Some people target old versions of operating systems as a hobby, such as Windows XP, and this also caters to this use case. |
I don't think it should work like this. If there are two code paths and we prefer one over another during entire lifetime of the application, then I'd expect the check result to be cached. Your method really "avoids 1 pointless syscall at runtime for this codepath." but that should be one call per entire application lifetime, not per call. So, there are three cases:
What I would really like to see for supporting multiple APIs is
|
* re-introduce `std.build.Target` which is distinct from `std.Target`. `std.build.Target` wraps `std.Target` so that it can be annotated as "the native target" or an explicitly specified target. * `std.Target.Os` is moved to `std.Target.Os.Tag`. The former is now a struct which has the tag as well as version range information. * `std.elf` gains some more ELF header constants. * `std.Target.parse` gains the ability to parse operating system version ranges as well as glibc version. * Added `std.Target.isGnuLibC()`. * self-hosted dynamic linker detection and glibc version detection. This also adds the improved logic using `/usr/bin/env` rather than invoking the system C compiler to find the dynamic linker when zig is statically linked. Related: #2084 Note: this `/usr/bin/env` code is work-in-progress. * `-target-glibc` CLI option is removed in favor of the new `-target` syntax. Example: `-target x86_64-linux-gnu.2.27` closes #1907
* re-introduce `std.build.Target` which is distinct from `std.Target`. `std.build.Target` wraps `std.Target` so that it can be annotated as "the native target" or an explicitly specified target. * `std.Target.Os` is moved to `std.Target.Os.Tag`. The former is now a struct which has the tag as well as version range information. * `std.elf` gains some more ELF header constants. * `std.Target.parse` gains the ability to parse operating system version ranges as well as glibc version. * Added `std.Target.isGnuLibC()`. * self-hosted dynamic linker detection and glibc version detection. This also adds the improved logic using `/usr/bin/env` rather than invoking the system C compiler to find the dynamic linker when zig is statically linked. Related: #2084 Note: this `/usr/bin/env` code is work-in-progress. * `-target-glibc` CLI option is removed in favor of the new `-target` syntax. Example: `-target x86_64-linux-gnu.2.27` closes #1907
* re-introduce `std.build.Target` which is distinct from `std.Target`. `std.build.Target` wraps `std.Target` so that it can be annotated as "the native target" or an explicitly specified target. * `std.Target.Os` is moved to `std.Target.Os.Tag`. The former is now a struct which has the tag as well as version range information. * `std.elf` gains some more ELF header constants. * `std.Target.parse` gains the ability to parse operating system version ranges as well as glibc version. * Added `std.Target.isGnuLibC()`. * self-hosted dynamic linker detection and glibc version detection. This also adds the improved logic using `/usr/bin/env` rather than invoking the system C compiler to find the dynamic linker when zig is statically linked. Related: #2084 Note: this `/usr/bin/env` code is work-in-progress. * `-target-glibc` CLI option is removed in favor of the new `-target` syntax. Example: `-target x86_64-linux-gnu.2.27` closes #1907
* re-introduce `std.build.Target` which is distinct from `std.Target`. `std.build.Target` wraps `std.Target` so that it can be annotated as "the native target" or an explicitly specified target. * `std.Target.Os` is moved to `std.Target.Os.Tag`. The former is now a struct which has the tag as well as version range information. * `std.elf` gains some more ELF header constants. * `std.Target.parse` gains the ability to parse operating system version ranges as well as glibc version. * Added `std.Target.isGnuLibC()`. * self-hosted dynamic linker detection and glibc version detection. This also adds the improved logic using `/usr/bin/env` rather than invoking the system C compiler to find the dynamic linker when zig is statically linked. Related: #2084 Note: this `/usr/bin/env` code is work-in-progress. * `-target-glibc` CLI option is removed in favor of the new `-target` syntax. Example: `-target x86_64-linux-gnu.2.27` closes #1907
On Linux we have kernel versions:
3.14
,4.14
,4.18
, etc.On Windows we have versions, e.g.
FreeBSD has the concept of versions: most recent e.g. 12.0
MacOS / iOS has the concept of versions too - e.g. 10.14.3
I propose for OS minimum version and maximum version to be part of the target. When you specify an OS minimum version as part of the target, it is telling userland code what ABI it can rely on. Each OS will have a default minimum version. Some standard library functions (or functions from third party packages) may give a
@compileError("this API supported only on OS version xyz and later")
. The OS minimum version will be available for userland code to observe in@import("builtin")
.Maximum version is also useful, because it can avoid code bloat, when it is compile-time known that the code will not be able to take advantage of newer OS features.
When compiling for the native target, the minimum and maximum OS versions will be the same.
The text was updated successfully, but these errors were encountered: