@@ -576,12 +576,36 @@ impl Iterator for Env {
576576 }
577577}
578578
579- #[ cfg( target_os = "macos" ) ]
579+ // Use `_NSGetEnviron` on Apple platforms.
580+ //
581+ // `_NSGetEnviron` is the documented alternative (see `man environ`), and has
582+ // been available since the first versions of both macOS and iOS.
583+ //
584+ // Nowadays, specifically since macOS 10.8, `environ` has been exposed through
585+ // `libdyld.dylib`, which is linked via. `libSystem.dylib`:
586+ // <https://github.com/apple-oss-distributions/dyld/blob/dyld-1160.6/libdyld/libdyldGlue.cpp#L913>
587+ //
588+ // So in the end, it likely doesn't really matter which option we use, but the
589+ // performance cost of using `_NSGetEnviron` is extremely miniscule, and it
590+ // might be ever so slightly more supported, so let's just use that.
591+ //
592+ // NOTE: The header where this is defined (`crt_externs.h`) was added to the
593+ // iOS 13.0 SDK, which has been the source of a great deal of confusion in the
594+ // past about the availability of this API.
595+ //
596+ // NOTE(madsmtm): Neither this nor using `environ` has been verified to not
597+ // cause App Store rejections; if this is found to be the case, an alternative
598+ // implementation of this is possible using `[NSProcessInfo environment]`
599+ // - which internally uses `_NSGetEnviron` and a system-wide lock on the
600+ // environment variables to protect against `setenv`, so using that might be
601+ // desirable anyhow? Though it also means that we have to link to Foundation.
602+ #[ cfg( target_vendor = "apple" ) ]
580603pub unsafe fn environ ( ) -> * mut * const * const c_char {
581604 libc:: _NSGetEnviron ( ) as * mut * const * const c_char
582605}
583606
584- #[ cfg( not( target_os = "macos" ) ) ]
607+ // Use the `environ` static which is part of POSIX.
608+ #[ cfg( not( target_vendor = "apple" ) ) ]
585609pub unsafe fn environ ( ) -> * mut * const * const c_char {
586610 extern "C" {
587611 static mut environ: * const * const c_char ;
0 commit comments