Skip to content
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

aarch64-darwin: Improve error message when trying to do a x86_64-darwin build and Rosetta is not installed #12323

Open
2 tasks
edolstra opened this issue Jan 21, 2025 · 6 comments
Labels
error-messages Confusing messages and better diagnostics feature Feature request or proposal good first issue Quick win for first-time contributors macos Nix on macOS, aka OS X, aka darwin

Comments

@edolstra
Copy link
Member

Is your feature request related to a problem?

Currently you just get

% nix build nix#hydraJobs.build.nix-functional-tests.x86_64-darwin
error: a 'x86_64-darwin' with features {} is required to build '/nix/store/07c6yy8wamq9707ja3bvdr60kjhaxli3-nix-2.26.0pre20250121_b8c296f.drv', but I am a 'aarch64-darwin' with features {apple-virt, benchmark, big-parallel, nixos-test}

Proposed solution

Ideally it would tell you to run /usr/sbin/softwareupdate --install-rosetta --agree-to-license to enable x86_64-darwin support.

Alternative solutions

Additional context

Checklist


Add 👍 to issues you find important.

@edolstra edolstra added error-messages Confusing messages and better diagnostics feature Feature request or proposal macos Nix on macOS, aka OS X, aka darwin labels Jan 21, 2025
@aidenfoxivey
Copy link

aidenfoxivey commented Jan 21, 2025

I presume this is coming from src/libstore/unix/build/local-derivation-goal.cc

Would something like

    /* Right platform? */
    if (!parsedDrv->canBuildLocally(worker.store)) {
        // since aarch64-darwin has Rosetta 2, this user can actually run x86_64-darwin on their hardware - we should tell them to run the command to install Darwin 2
        if (drv->platform == "x86_64-darwin" && setttings.thisSystem == "aarch64-darwin") {
            throw Error("run `/usr/sbin/softwareupdate --install-rosetta --agree-to-license` to enable your %s to run programs for %s", settings.thisSystem, drv->platform);
        } else {
            throw Error("a '%s' with features {%s} is required to build '%s', but I am a '%s' with features {%s}",
                drv->platform,
                concatStringsSep(", ", parsedDrv->getRequiredSystemFeatures()),
                worker.store.printStorePath(drvPath),
                settings.thisSystem,
                concatStringsSep<StringSet>(", ", worker.store.systemFeatures));
        }
}

be what you're looking for?

@tomberek tomberek added the good first issue Quick win for first-time contributors label Jan 22, 2025
@tomberek
Copy link
Contributor

It's on the right track. There might be a function to check if Rosetta is enabled in settings::getDefaultExtraPlatforms.

@aidenfoxivey
Copy link

Sounds good! I'll poke around and modify my solution.

@aidenfoxivey
Copy link

Hmm, so checking whether Rosetta is enabled should be done within canBuildLocally I feel. If it returns true, then it shouldn't even have an error.

That way, if it returns false (and we have the condition I wrote earlier as being on a compatible platform) we can instead prompt the user to run the appropriate command. Does that seem reasonable?

@aidenfoxivey
Copy link

Oh okay, I see that's already a thing - awesome

@aidenfoxivey
Copy link

Yeah it seems like Settings::getDefaultExtraPlatforms() should already be called by the time that we get to canBuildLocally which then calls

    if (std::string{SYSTEM} == "aarch64-darwin" &&
        runProgram(RunOptions {.program = "arch", .args = {"-arch", "x86_64", "/usr/bin/true"}, .mergeStderrToStdout = true}).first == 0)
        extraPlatforms.insert("x86_64-darwin");

This is then called in

Setting<StringSet> extraPlatforms{
        this,
        getDefaultExtraPlatforms(),

When canBuildLocally is called,

bool ParsedDerivation::canBuildLocally(Store & localStore) const
{
    if (drv.platform != settings.thisSystem.get()
        && !settings.extraPlatforms.get().count(drv.platform)
        && !drv.isBuiltin())
        return false;

    if (settings.maxBuildJobs.get() == 0
        && !drv.isBuiltin())
        return false;

    for (auto & feature : getRequiredSystemFeatures())
        if (!localStore.systemFeatures.get().count(feature)) return false;

    return true;
}

my suspicion is that extraPlatforms should contain the right information.

Thus, I think it's enough to assume Rosetta 2 isn't enabled by the time that we get into the if statement. I feel like from there we can just compare the drv->platform and settings.thisSystem as I did above.

That's just my thoughts though - is there something I'm missing here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
error-messages Confusing messages and better diagnostics feature Feature request or proposal good first issue Quick win for first-time contributors macos Nix on macOS, aka OS X, aka darwin
Projects
None yet
Development

No branches or pull requests

3 participants