Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
/ druntime Public archive

darwin: Add __xxx_OS_VERSION_MIN constants for Darwin platforms#3299

Closed
ibuclaw wants to merge 1 commit intodlang:masterfrom
ibuclaw:osxavailability
Closed

darwin: Add __xxx_OS_VERSION_MIN constants for Darwin platforms#3299
ibuclaw wants to merge 1 commit intodlang:masterfrom
ibuclaw:osxavailability

Conversation

@ibuclaw
Copy link
Member

@ibuclaw ibuclaw commented Dec 1, 2020

The idea here is similar to FreeBSD's __FreeBSD_version constant. What differs however, is that rather than it being a fixed to a release version of OS X, the versions correspond to a configurable minimum required version number (set by the user passing -mmacosx-version-min=) to control what OS functionality is available at compile-time. So, the compiler predefining OSX_10_9 means that we are targeting all releases starting from macOS 10.9 (Mavericks). In C, this is equivalent to the __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ macros.

Example usage:

module core.sys.posix.stdio;

version (Darwin)
{
    import core.sys.darwin.config;

    static if (__MAC_OS_X_VERSION_MIN >= __MAC_10_7)
    {
        ssize_t getdelim(char**, size_t*, int, FILE*);
        ssize_t getline(char**, size_t*, FILE*);
    }
}

A CTFE-only function could be added to core.sys.darwin.config instead to cover all different platforms in one.

bool __osx_available_starting(int osx = __MAC_OS_X_VERSION_MIN,
                              int iphone = __IPHONE_OS_VERSION_MIN,
                              int tvos = __TV_OS_VERSION_MIN,
                              int watchos = __WATCH_OS_VERSION_MIN)
{
    version (OSX)
        return osx >= __MAC_OS_X_VERSION_MIN;
    else version (iOS)
        return iphone >= __IPHONE_OS_VERSION_MIN;
    else version (TVOS)
        return tvos >= __TV_OS_VERSION_MIN;
    else version (WatchOS)
        return watchos >= __WATCH_OS_VERSION_MIN;
    else
        static assert(0, "Unsupported");
}

static if (__osx_available_starting(__MAC_10_7))
{
    // ...
}

Ping @jacob-carlborg, @kinke:

  1. Does this seem reasonable? Or should the version condition be a bit more clear that they are lower bound version controls.
  2. What are reasonable baselines to set for the iPhone, TVOS, and WatchOS targets?
  3. Are the current version numbers defined enough, or should they all be listed?

@dlang-bot
Copy link
Contributor

Thanks for your pull request, @ibuclaw!

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "master + druntime#3299"

@kinke
Copy link
Contributor

kinke commented Dec 1, 2020

Do you have a concrete use case? The get{delim,line} is IMO absolutely uninteresting - IIRC, 10.7 came with native TLS and as such is a prerequisite for LDC anyway.

@kinke
Copy link
Contributor

kinke commented Dec 1, 2020

@ibuclaw
Copy link
Member Author

ibuclaw commented Dec 1, 2020

Do you have a concrete use case? The get{delim,line} is IMO absolutely uninteresting - IIRC, 10.7 came with native TLS and as such is a prerequisite for LDC anyway.

GCC still has emulated TLS. I am conversing with someone who is testing on various versions current and old, i386, x86_64, and PPC (he might be getting ARM hardware soon). I've only got a late 2009 mac-mini myself (10.6), pretty much everything passes except for missing symbols added in later releases.

@ibuclaw
Copy link
Member Author

ibuclaw commented Dec 1, 2020

Some parts of the bindings have comments like this

The following functions are present as of Mac OSX 10.15:

Would perhaps be more useful to put that in code.

@kinke
Copy link
Contributor

kinke commented Dec 1, 2020

Would perhaps be more useful to put that in code.

My understanding is that the env variable (MACOSX_DEPLOYMENT_TARGET) controls the SDK used for linking (with Apple-clang at least), so setting the var suffices to produce linker errors or fix them. versioning requires the D compiler to predefine the correct one, either explicitly specified by the user (-mtriple=x86_64-apple-macos10.7) and/or taking the env var into account as well.

@jacob-carlborg
Copy link
Contributor

I think this approach is a bad idea, just as I thought __FreeBSD_version was a bad idea. I think a better approach would be to add a new keys to __traits. One for the minimum version and one for the current version (perhaps max version as well? I didn't even know that existed until now). Otherwise someone needs to update this file every time a new version is released of a platform. Who is going to do that? The file is already out of date and it's not even merged yet. The latest version of macOS is 10.16/11.0.

I'm not sure what __osx_available_starting is supposed to do. Is it supposed to match the availability attribute [1]? The availability attribute is a bit more complicated and involves possible weak linage.

What are reasonable baselines to set for the iPhone, TVOS, and WatchOS targets?

According to the headers, if nothing is specified:

  • macOS x86 and x86-64: 10.4
  • macOS ARM and ARM64: 10.5
  • macOS other: 10.1

For the other platforms I cannot find the same values but these are the lowest available versions:

  • iPhone 2.0
  • tvOS 9.0
  • watchOS 1.0

Are the current version numbers defined enough

No, you're missing a couple of newer versions. The latest versions are:

  • macOS 10.16/11.0
  • iPhone 14.0
  • tvOS 14.0
  • watchOS 7.0

An alternative is to more closely match the availability attribute [1]:

void foo() @available(macOS, 10.13);

[1] https://clang.llvm.org/docs/AttributeReference.html#availability
[2] https://clang.llvm.org/docs/LanguageExtensions.html#objective-c-available

@ibuclaw
Copy link
Member Author

ibuclaw commented Dec 1, 2020

I'm not sure what __osx_available_starting is supposed to do. Is it supposed to match the availability attribute [1]? The availability attribute is a bit more complicated and involves possible weak linage.

Just a gate for whether or not to declare a symbol. Don't want to declare if using it results in missing symbol error at runtime.

What are reasonable baselines to set for the iPhone, TVOS, and WatchOS targets?

According to the headers, if nothing is specified:

  • macOS x86 and x86-64: 10.4
  • macOS ARM and ARM64: 10.5
  • macOS other: 10.1

And 10.4 for PPC64, though I went with 10.5 as it is the last version that supports all hardware apple has released on.

No, you're missing a couple of newer versions. The latest versions are:

OK, the sources on apple/xnu are probably out of date.

@jacob-carlborg
Copy link
Contributor

jacob-carlborg commented Dec 1, 2020

My understanding is that the env variable (MACOSX_DEPLOYMENT_TARGET) controls the SDK used for linking (with Apple-clang at least), so setting the var suffices to produce linker errors or fix them. versioning requires the D compiler to predefine the correct one, either explicitly specified by the user (-mtriple=x86_64-apple-macos10.7) and/or taking the env var into account as well.

No, MACOSX_DEPLOYMENT_TARGET specifies earliest version of macOS the executable it will run on. It's the same as specifying the -mmacosx-version-min flag (yes, the compiler need to take MACOSX_DEPLOYMENT_TARGET into consideration). It's also the same as specifying the version as part of the target triple. I think back in the GCC days, there was no option to specify a target triple. Back then, either the MACOSX_DEPLOYMENT_TARGET environment variable or the -mmacosx-version-min flag was used. GCC also had the -arch (only on Apple's custom GCC) flag to specify x64, x86-64, PPC or PPC64. But it was not possible to have the same fine grained control as the target triple in Clang now days.

The only differences I've noticed between MACOSX_DEPLOYMENT_TARGET and -mmacosx-version-min is that the environment variable covers all tools, while the flag is only for the compiler. For example, if you specify 10.6 with the flag, it will fail because the linker won't use the correct object file containing the start symbol. But if the environment variable is used, the linker will use the correct object file.

Have a look at: https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html

@jacob-carlborg
Copy link
Contributor

Just a gate for whether or not to declare a symbol. Don't want to declare if using it results in missing symbol error at runtime.

That's not how the SDK works. If a function is specified to be available on macOS 10.13 and later. If the minimum version specified is 10.12, you can still use the 10.13 symbol if you guard it with a runtime check. The symbol will have weak linkage. This means the same executable can run on both 10.12 and 10.13 and on 10.13 it can take advantage of some feature only available in that version. If the minimum version specified is 10.13, then you don't have to do a runtime check of the symbol and the symbol will have normal linkage.

OK, the sources on apple/xnu are probably out of date.

That's why this approach is not a good idea.

@ibuclaw
Copy link
Member Author

ibuclaw commented Dec 1, 2020

I think this approach is a bad idea, just as I thought __FreeBSD_version was a bad idea. I think a better approach would be to add a new keys to __traits. One for the minimum version and one for the current version (perhaps max version as well? I didn't even know that existed until now). Otherwise someone needs to update this file every time a new version is released of a platform. Who is going to do that? The file is already out of date and it's not even merged yet. The latest version of macOS is 10.16/11.0.

__traits is a bad approach on the surface as it's potentially asking the front-end implementation to be aware of things it has no right to know about. A good approach of dealing with them agnostically should be sorted out.

@jacob-carlborg
Copy link
Contributor

__traits is a bad approach on the surface as it's potentially asking the front-end implementation to be aware of things it has no right to know about. A good approach of dealing with them agnostically should be sorted out.

Version identifiers are already set by the frontend (at least in DMD). What about the already existing __traits(getTargetInfo) [1]?

[1] https://dlang.org/spec/traits.html#getTargetInfo

@jacob-carlborg
Copy link
Contributor

BTW, this is slightly related: dlang/dmd#10476.

@ibuclaw
Copy link
Member Author

ibuclaw commented Dec 2, 2020

@kinke, on an unrelated note: ModuleInfo, should it go in __DATA,__minfodata or __DATA,.minfo?

@kinke
Copy link
Contributor

kinke commented Dec 2, 2020

I have no idea (I guess it doesn't matter) - the Mac stuff was done by other people, most likely @dnadlinger. Our druntime sections stuff for Mac vastly differs from upstream, see #2322, incl. support for shared druntime/Phobos.

@ibuclaw
Copy link
Member Author

ibuclaw commented Dec 2, 2020

__traits is a bad approach on the surface as it's potentially asking the front-end implementation to be aware of things it has no right to know about. A good approach of dealing with them agnostically should be sorted out.

Version identifiers are already set by the frontend (at least in DMD). What about the already existing __traits(getTargetInfo) [1]?

The current targetInfo identifiers are vague enough to not be tied to any platform. Whereas asking for a specific version of a given OS isn't. I'd have to sit down and sketch out if getTargetInfo can be done in a way that just involves one hook that may call any provider in the back-end. Possibly having a shared array may be enough.

I have no idea (I guess it doesn't matter) - the Mac stuff was done by other people, most likely @dnadlinger. Our druntime sections stuff for Mac vastly differs from upstream, see #2322, incl. support for shared druntime/Phobos.

I have successfully implemented shared support using _d_dso_registry, but the internals are different. I'll make a note to see if there's any improvements that can be done on my side. :-)

@jacob-carlborg
Copy link
Contributor

on an unrelated note: ModuleInfo, should it go in __DATA,__minfodata or __DATA,.minfo

As kinke mentioned, it doesn't matter. All I know is that segments and sections in Mach-O images should start with __ (not a requirement).

If there's an interest in trying to unify all compilers and use the same druntime we should pick one name and stick to it. I think that name should start with __ to follow the platform conventions. By that logic we should pick __minfodata which will lead to fewer places to change.

@jacob-carlborg
Copy link
Contributor

The current targetInfo identifiers are vague enough to not be tied to any platform. Whereas asking for a specific version of a given OS isn't. I'd have to sit down and sketch out if getTargetInfo can be done in a way that just involves one hook that may call any provider in the back-end. Possibly having a shared array may be enough.

__traits(getTargetInfo, "operatingSystemVersion"). And specify that to return an implementation defined value. That could have been used for FreeBSD as well.

I would prefer we try focus on the language side first instead of just picking the easiest way to implement something in the compiler. D has already been affected by this philosophy quite a bit.

@ibuclaw
Copy link
Member Author

ibuclaw commented Dec 2, 2020

__traits(getTargetInfo, "operatingSystemVersion"). And specify that to return an implementation defined value. That could have been used for FreeBSD as well.

It only takes one person to implement that in DMD for Linux (possibly in response to a bugzilla issue), another to start depending on it in druntime, and then I'm having to raise revert PRs for refusing to support such bile.

@Geod24
Copy link
Member

Geod24 commented Jul 9, 2022

Druntime have been merged into DMD. Please re-submit your PR to dlang/dmd repository.

@Geod24 Geod24 closed this Jul 9, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants