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

Fix: Add -arch x86_64 to CXXFLAGS on macOS ARM64 to Resolve Linker Errors in Mixed C++ and D Testss #21012

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

gulugulubing
Copy link

Problem

On Apple Silicon, the default architecture for C++ compilers is ARM64,
which conflicts with DMD's x86_64 output. This causes linker errors when
building mixed C++ and D projects during make test.

Solution

This change adds -arch x86_64 to the CXXFLAGS to ensure the C++ compiler
generates x86_64 objects on macOS.

Testing

  • Verified that the build succeeds on macOS with Apple Silicon.
  • Confirmed that the generated objects are x86_64.
  • All affected tests now pass without linker errors.

This merge is necessary to bring the latest changes from the master branch into
the fix-cxxflags-arch-x86_64 branch. The issue was discovered while running
`make test` on macOS arm64. This ensures that the fix for adding `-arch x86_64` to CXXFLAGS remains
compatible with recent updates in the main branch and resolves the problem
encountered during testing.
This merge is necessary to bring the latest changes from the master branch into
the fix-cxxflags-arch-x86_64 branch. The issue was discovered while running
`make test on masOS arm64. This ensures that the fix for adding `-arch x86_64` to CXXFLAGS remains
compatible with recent updates in the main branch and resolves the problem
encountered during testing.
@dlang-bot
Copy link
Contributor

Thanks for your pull request and interest in making D better, @gulugulubing! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the coverage diff by visiting the details link of the codecov check)
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

Please see CONTRIBUTING.md for more information.


If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment.

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 + dmd#21012"

@kinke
Copy link
Contributor

kinke commented Mar 17, 2025

#17035 shows that this isn't needed, on an arm64 macOS runner. The reason AFAIU being that both DMD and the testrunner are x86_64 executables, and in that case, the invoked universal cc/c++ binary defaults to the x86_64 version.

@gulugulubing
Copy link
Author

#17035 shows that this isn't needed, on an arm64 macOS runner. The reason AFAIU being that both DMD and the testrunner are x86_64 executables, and in that case, the invoked universal cc/c++ binary defaults to the x86_64 version.

Thank you for your feedback! I understand the discussion in the referenced issue is about building and running DMD natively on ARM64 macOS, which is a different scenario from my PR.

My issue occurs during the testing phase after building, specifically when running make test. The problem is that the C++ compiler defaults to generating ARM64 code on Apple Silicon, while DMD generates x86_64 code. This causes linker errors when linking mixed C++ and D code. Here's an example of the error:

ld: warning: ignoring file '/dlang/dmd/compiler/test/test_results/runnable_cxx/d/test6716.cpp.o': found architecture 'arm64', required architecture 'x86_64'
Undefined symbols for architecture x86_64:
"_main", referenced from:

ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Error: undefined reference to _main
perhaps a library needs to be added with the -L flag or pragma(lib, ...)
Error: linker exited with status 1

@kinke
Copy link
Contributor

kinke commented Mar 17, 2025

I understand the discussion in the referenced issue is about building and running DMD natively on ARM64 macOS, which is a different scenario from my PR.

Yeah the PR is a bit messy (still in draft) - but what's key is that it adds a macOS 14 job using latest DMD (and another one using LDC). That is a job that builds an x86_64 DMD (not a native arm64 one) on a M1 runner, and then runs all tests as x86_64, no arm64 involved anywhere. And that job works today, without any changes, especially no -arch x86_64 switches - the 1st commit alone passed that job (835d2b9).

Which make are you using? For CI there, we use brew install make and then the /opt/homebrew/opt/make/libexec/gnubin/make binary. Just in case there's an arch difference across CI and your box for that executable; it's the top-most process when running make test. Oh wait, just seen that CI doesn't run make test, but runs the tests manually:

dmd/ci/run.sh

Lines 131 to 132 in a4cbc08

$build_path/dmd -g -i -Icompiler/test -release compiler/test/run.d -ofgenerated/run
generated/run -j$N --environment MODEL=$MODEL HOST_DMD=$build_path/dmd "${args[@]}"

So I guess it's plausible that make gets in the way and causes these issues on your box. Maybe there's a way to put it into x86_64 mode? (I don't have Apple stuff.)


What we definitely don't want are hardcoded -arch x86_64 flags here in these test files. E.g., LDC supports arm64 too and runs these tests, on native M1 runners.

@gulugulubing
Copy link
Author

I understand the discussion in the referenced issue is about building and running DMD natively on ARM64 macOS, which is a different scenario from my PR.

Yeah the PR is a bit messy (still in draft) - but what's key is that it adds a macOS 14 job using latest DMD (and another one using LDC). That is a job that builds an x86_64 DMD (not a native arm64 one) on a M1 runner, and then runs all tests as x86_64, no arm64 involved anywhere. And that job works today, without any changes, especially no -arch x86_64 switches - the 1st commit alone passed that job (835d2b9).

Which make are you using? For CI there, we use brew install make and then the /opt/homebrew/opt/make/libexec/gnubin/make binary. Just in case there's an arch difference across CI and your box for that executable; it's the top-most process when running make test. Oh wait, just seen that CI doesn't run make test, but runs the tests manually:

dmd/ci/run.sh

Lines 131 to 132 in a4cbc08

$build_path/dmd -g -i -Icompiler/test -release compiler/test/run.d -ofgenerated/run
generated/run -j$N --environment MODEL=$MODEL HOST_DMD=$build_path/dmd "${args[@]}"

So I guess it's plausible that make gets in the way and causes these issues on your box. Maybe there's a way to put it into x86_64 mode? (I don't have Apple stuff.)

What we definitely don't want are hardcoded -arch x86_64 flags here in these test files. E.g., LDC supports arm64 too and runs these tests, on native M1 runners.

My make version is :
GNU Make 4.4.1
Built for aarch64-apple-darwin23.4.0

As a newcomer to contributing, I'm still getting familiar with the D language build process. Modifying the complex scripts or Makefile to enforce arch -x86_64 feels a bit challenging for me at this stage. Therefore, I tried making the change directly in the test files instead. While I understand this approach may seem less elegant, it appeared to be simpler and more controllable for me as a beginner. I appreciate your understanding and guidance!

@kinke
Copy link
Contributor

kinke commented Mar 17, 2025

No worries, and thx for contributing! :)

You could add some implicit args after this line:

findTestParameter(envData, file, "CXXFLAGS", testArgs.cxxflags);

E.g.:

// DMD on macOS: force Apple clang to produce x86_64 code (on arm64 too), like DMD
version (DigitalMars) version (OSX)
    testArgs.cxxflags ~= " -arch x86_64";

Edit: Or append them after this:

if (cxxflags)
command ~= " " ~ cxxflags;

@gulugulubing
Copy link
Author

No worries, and thx for contributing! :)

You could add some implicit args after this line:

findTestParameter(envData, file, "CXXFLAGS", testArgs.cxxflags);

E.g.:

// DMD on macOS: force Apple clang to produce x86_64 code (on arm64 too), like DMD
version (DigitalMars) version (OSX)
    testArgs.cxxflags ~= " -arch x86_64";

Edit: Or append them after this:

if (cxxflags)
command ~= " " ~ cxxflags;

Thank you! I tried modifying the d_do_test.d file by adding the -arch x86_64 flag in the two suggested locations, but the test process still fails with the same error.

@thewilsonator
Copy link
Contributor

CI is green now, this good to go?

@kinke
Copy link
Contributor

kinke commented Mar 21, 2025

Have you read what I wrote? No hardcoded args in these test files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants