Add extraPlatforms for Rosetta 2 macOS

macOS systems with ARM64 can utilize a translation layer at
/Library/Apple/usr/libexec/oah to run x86_64 binaries. This change
makes Nix recognize that and it to "extra-platforms". Note that there
are two cases here since Nix could be built for either x86_64 or
aarch64. In either case, we can switch to the other architecture.
Unfortunately there is not a good way to prevent aarch64 binaries from
being run in x86_64 contexts or vice versa - programs can always
execute programs for the other architecture.
This commit is contained in:
Matthew Bauer 2020-12-03 15:35:38 -06:00
parent 6ed09cb8c2
commit 9b1824ecbd
2 changed files with 25 additions and 1 deletions

View file

@ -131,6 +131,28 @@ StringSet Settings::getDefaultSystemFeatures()
return features; return features;
} }
StringSet Settings::getDefaultExtraPlatforms()
{
if (std::string{SYSTEM} == "x86_64-linux" && !isWSL1())
return StringSet{"i686-linux"};
#if __APPLE__
// Rosetta 2 emulation layer can run x86_64 binaries on aarch64
// machines. Note that we cant force processes from executing
// x86_64 in aarch64 environments or vice versa since they can
// always exec with their own binary preferences.
else if (pathExists("/Library/Apple/usr/libexec/oah")) {
if (std::string{SYSTEM} == "x86_64-darwin")
return StringSet{"aarch64-darwin"};
else if (std::string{SYSTEM} == "aarch64-darwin")
return StringSet{"x86_64-darwin"};
else
return StringSet{};
}
#endif
else
return StringSet{};
}
bool Settings::isExperimentalFeatureEnabled(const std::string & name) bool Settings::isExperimentalFeatureEnabled(const std::string & name)
{ {
auto & f = experimentalFeatures.get(); auto & f = experimentalFeatures.get();

View file

@ -34,6 +34,8 @@ class Settings : public Config {
StringSet getDefaultSystemFeatures(); StringSet getDefaultSystemFeatures();
StringSet getDefaultExtraPlatforms();
bool isWSL1(); bool isWSL1();
public: public:
@ -545,7 +547,7 @@ public:
Setting<StringSet> extraPlatforms{ Setting<StringSet> extraPlatforms{
this, this,
std::string{SYSTEM} == "x86_64-linux" && !isWSL1() ? StringSet{"i686-linux"} : StringSet{}, getDefaultExtraPlatforms(),
"extra-platforms", "extra-platforms",
R"( R"(
Platforms other than the native one which this machine is capable of Platforms other than the native one which this machine is capable of