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

Linker warnings in Mac OS Ventura #13846

Closed
PascalLeMerrer opened this issue Sep 27, 2023 · 24 comments · Fixed by #14466
Closed

Linker warnings in Mac OS Ventura #13846

PascalLeMerrer opened this issue Sep 27, 2023 · 24 comments · Fixed by #14466
Labels
kind:bug A bug in the code. Does not apply to documentation, specs, etc. platform:darwin

Comments

@PascalLeMerrer
Copy link

PascalLeMerrer commented Sep 27, 2023

Bug Report

I installed Crystal on MacOS Ventura, using Homebrew.
It worked, however compiling a simple hello world generates 280 warnings like:

ld: warning: no platform load command found in '/Users/pascal/.cache/crystal/Users-pascal-Documents-tutorials-crystal-hello_world.cr/F-loat32.o', assuming: macOS
ld: warning: no platform load command found in '/Users/pascal/.cache/crystal/Users-pascal-Documents-tutorials-crystal-hello_world.cr/C-rystal.o', assuming: macOS

Crystal version: 1.9.2
OS Version: Ventura, then Sonoma (I upgraded it, but it did not change anything)
Brew doctor does not signal anything wrong.

The steps I followed:

brew update
brew install crystal

echo 'puts "Hello, World!"' > hello.cr

crystal hello.cr
@PascalLeMerrer PascalLeMerrer added the kind:bug A bug in the code. Does not apply to documentation, specs, etc. label Sep 27, 2023
@beta-ziliani beta-ziliani changed the title Crystal Linker warnings in Ventura Sep 27, 2023
@HertzDevil
Copy link
Contributor

HertzDevil commented Sep 27, 2023

This seems to be related to a "new linker" in Xcode 15, see https://projects.blender.org/blender/blender/pulls/110243 for example. I couldn't reproduce this warning but it looks like you could try passing --link-flags=-Wl,-ld_classic to use the old linker

@PascalLeMerrer
Copy link
Author

crystal hello.cr --link-flags=-Wl,-ld_classic has no visible effect on this issue

1 similar comment
@PascalLeMerrer
Copy link
Author

crystal hello.cr --link-flags=-Wl,-ld_classic has no visible effect on this issue

@beta-ziliani
Copy link
Member

beta-ziliani commented Sep 27, 2023

@PascalLeMerrer in order to pass parameters to the run command you need to provide explicitly the command:

crystal run --link-flags=-Wl,-ld_classic hello.cr

@PascalLeMerrer
Copy link
Author

It works much better indeed! Thanks @beta-ziliani

@PascalLeMerrer PascalLeMerrer changed the title Linker warnings in Ventura Linker warnings in Mac OS Ventura Sep 28, 2023
@fnordfish
Copy link
Contributor

Just an observation:
crystal eval has the same issue, and it doesn't take --link-flags.
export LDFLAGS="-Wl,-ld_classic" doesn't seem to get picked up.

@HertzDevil
Copy link
Contributor

HertzDevil commented Sep 28, 2023

You should be able to do CRYSTAL_OPTS="--link-flags=-Wl,-ld_classic"

@mloughran
Copy link

Just to note that macOS Sonoma (14) is also affected (as one might expect) by the same issue, and that setting the --link-flags as above avoids the warnings.

Out of interest: I happened to notice that binaries created with the "new linker" are about 10% smaller than when using these flags.

@Mark24Code
Copy link

Same problem

maxfierke added a commit to maxfierke/mstrap that referenced this issue Oct 15, 2023
See crystal-lang/crystal#13846

Unclear right now on if this is Crystal issue, LLVM issue, or something else
@crimson-knight
Copy link

crimson-knight commented Oct 16, 2023

FYI, I upgraded to Sonoma today and was getting linker warnings like this:

object file (H-ash5858E-ntry40S-tring4432S-tring41.o) was built for newer macOS version (14.0) than being linked (13.3)

There is also an update for xcode-tools that once installed resolved the linker warnings.

@chikega
Copy link

chikega commented Oct 18, 2023

@PascalLeMerrer in order to pass parameters to the run command you need to provide explicitly the command:

crystal run --link-flags=-Wl,-ld_classic hello.cr

This works for me. I'm running macOS Sonoma 14 and XCode 15.0 (15A240d).

@Narven
Copy link

Narven commented Oct 24, 2023

CRYSTAL_OPTS="--link-flags=-Wl,-ld_classic" crystal run hello.cr

works for me . I'm on:
macOS 14.0 23A344 x86_64 Sonoma

sdt added a commit to sdt/.dotfiles that referenced this issue Nov 5, 2023
@w-A-L-L-e
Copy link

Yes even better is to just put this export in your bashrc or .zshrc

export CRYSTAL_OPTS="--link-flags=-Wl,-ld_classic"

then crystal build, crystal run etc all work without the ld warnings.

@hovsater
Copy link
Contributor

hovsater commented Apr 5, 2024

I've been investigating this and it's related to the default target triple produced by Crystal during compilation. It seems like in order to fix a bug back in 2015, we stripped the minimum deployment target from the target triple in this commit. Since then, further work has been put into place to normalize target triples from different architectures.

crystal/src/llvm.cr

Lines 91 to 109 in 1675145

def self.default_target_triple : String
chars = LibLLVM.get_default_target_triple
case triple = string_and_dispose(chars)
when .starts_with?("x86_64-apple-macosx"), .starts_with?("x86_64-apple-darwin")
# normalize on `macosx` and remove minimum deployment target version
"x86_64-apple-macosx"
when .starts_with?("aarch64-apple-macosx"), .starts_with?("aarch64-apple-darwin")
# normalize on `macosx` and remove minimum deployment target version
"aarch64-apple-macosx"
when .starts_with?("aarch64-unknown-linux-android")
# remove API version
"aarch64-unknown-linux-android"
when .starts_with?("x86_64-pc-solaris")
# remove API version
"x86_64-pc-solaris"
else
triple
end
end
.

With the release of Xcode 15, a new linker was introduced and with it came these warning messages. It appears that the new linker is stricter in which target triples it considers valid. Specifically, it looks like the minimum deployment target is required. E.g., aarch64-apple-darwin23.3.0 is valid, while aarch64-apple-darwin is not.

Before I go ahead and submit the pull request, I'd love to discuss what the correct path forward is. We could change the behaviour of LLVM#default_target_triple to only strip the minimum deployment target for macOS versions below a certain threshold or we could drop the stripping behaviour entirely (not sure that's a good idea). An alternative would be to hard-code the minimum deployment target to something like 10.14.6. Judging by the last two available SDKs that sounds reasonable at first sight.

$ cd /Library/Developer/CommandLineTools/SDKs
$ find . -maxdepth 1 ! -type l ! -path . -exec bash -c 'echo {} && gojq ".SupportedTargets.macosx | { MinimumDeploymentTarget, MaximumDeploymentTarget, RecommendedDeploymentTarget }" {}/SDKSettings.json' \;
./MacOSX13.3.sdk
{
  "MaximumDeploymentTarget": "13.3.99",
  "MinimumDeploymentTarget": "10.13",
  "RecommendedDeploymentTarget": "10.14.6"
}
./MacOSX14.4.sdk
{
  "MaximumDeploymentTarget": "14.4.99",
  "MinimumDeploymentTarget": "10.13",
  "RecommendedDeploymentTarget": "10.14.6"
}

10.14.6 would support versions down to Xcode 10, which was publicly released on September 17, 2018.

@HertzDevil
Copy link
Contributor

Does this also explain why I couldn't reproduce this on my M2 since the normalization fails due to #14052?

@hovsater
Copy link
Contributor

hovsater commented Apr 5, 2024

It does, yes. I'm seeing the same behaviour on my machine since the default triple returned by LLVM is arm64-apple-darwin23.3.0 and thus it doesn't get normalised by LLVM#default_target_triple. The architecture still gets normalized by Crystal::Codegen::Target:

# Perform additional normalization and parsing
case @architecture
when "i486", "i586", "i686"
@architecture = "i386"
when "amd64"
@architecture = "x86_64"
when "arm64"
@architecture = "aarch64"
when .starts_with?("arm")
@architecture = "arm"
else
# no need to tweak the architecture
end

but the new linker seem to accept that anyway.

@hovsater
Copy link
Contributor

hovsater commented Apr 5, 2024

It turns out we hard-code the target in the distribution-scripts. This is definitely also an issue.

I'm also not entirely sure that comment is correct (at least not any more). Running /usr/bin/clang --print-targets produces:

  Registered Targets:
    aarch64    - AArch64 (little endian)
    aarch64_32 - AArch64 (little endian ILP32)
    aarch64_be - AArch64 (big endian)
    arm        - ARM
    arm64      - ARM64 (little endian)
    arm64_32   - ARM64 (little endian ILP32)
    armeb      - ARM (big endian)
    thumb      - Thumb
    thumbeb    - Thumb (big endian)
    x86        - 32-bit X86: Pentium-Pro and above
    x86-64     - 64-bit X86: EM64T and AMD64

I've also confirmed that the following all compile without any warnings:

$ clang -Xclang '-triple=arm64-apple-macosx14.0.0' hello.c -o hello
$ clang -Xclang '-triple=aarch64-apple-macosx14.0.0' heloc.c -o hello
$ clang -Xclang '-triple=arm64-apple-darwin23.2.0' hello.c -o hello
$ clang -Xclang '-triple=aarch64-apple-darwin23.2.0' hello.c -o hello

while the following does not:

$ clang -Xclang '-triple=arm64-apple-darwin' hello.c -o hello
$ clang -Xclang '-triple=aarch64-apple-darwin' hello.c -o hello
$ clang -Xclang '-triple=arm64-apple-macosx' hello.c -o hello
$ clang -Xclang '-triple=aarch64-apple-macosx' hello.c -o hello

they all produce a warning like the following:

ld: warning: no platform load command found in '/private/var/folders/lp/053qjqyj1cg5gx_23kr9fphc0000gn/T/hello-b3b8c6.o', assuming: macOS

hovsater added a commit to hovsater/distribution-scripts that referenced this issue Apr 6, 2024
With the release of Xcode 15, a new linker was introduced and with it
came warnings from the linker on macOS specifically. It appears that the
new linker is stricter in which target triples it considers valid.
Specifically, it looks like the minimum deployment target is required.
E.g., `aarch64-apple-darwin23.3.0` is valid, while
`aarch64-apple-darwin` is not.

See also:

* https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes#Linking
* crystal-lang/crystal#13846
hovsater added a commit to hovsater/distribution-scripts that referenced this issue Apr 6, 2024
With the release of Xcode 15, a new linker was introduced and with it
came warnings from the linker. It appears that the new linker is
stricter in which target triples it considers valid. Specifically, it
looks like the minimum deployment target is required. E.g.,
`aarch64-apple-darwin23.3.0` is valid, while `aarch64-apple-darwin` is
not.

See also:

* https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes#Linking
* crystal-lang/crystal#13846
@straight-shoota
Copy link
Member

straight-shoota commented Apr 6, 2024

This is great work, thanks Kevin for digging into this 🚀

I guess there's a reason why LLVM doesn't normalize target triples. Our normalization is quite significant in some places.

Before we make changes that bring back version numbers, we need to check where these triples are used and whether some use cases may depend on normalized values. We may have to offer both, the full raw triple as well as a normalized version.

hovsater added a commit to hovsater/distribution-scripts that referenced this issue Apr 6, 2024
With the release of Xcode 15, a new linker was introduced and with it
came warnings from the linker. It appears that the new linker is
stricter in which target triples it considers valid. Specifically, it
looks like the minimum deployment target is required. E.g.,
`aarch64-apple-darwin23.3.0` is valid, while `aarch64-apple-darwin` is
not.

See also:

* https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes#Linking
* crystal-lang/crystal#13846
@oprypin
Copy link
Member

oprypin commented Apr 27, 2024

I am running into this issue when I use Intel macs on GitHub Actions since this week.
Moreover, presumably due to the same root cause, I am unable to link against any C libraries that I built myself in CI, whereas just a week ago I was able to. This is an error in addition to the warnings that others already reported.
This is probably because GitHub Actions updated their Xcode.

ld: warning: REFERENCED_DYNAMICALLY flag on symbol '_catch_exception_raise' is deprecated
...
ld: warning: no platform load command found in '/Users/runner/.cache/crystal/Users-runner-work-crystal-chipmunk-crystal-chipmunk-spec/T-uple40U-I-nt6441.o0.o', assuming: macOS
dyld[15199]: Symbol not found: _cpArbiterGetContactPointSet

https://github.com/oprypin/crystal-chipmunk/actions/runs/8859208139/job/24329593971
https://github.com/oprypin/crsfml/actions/runs/8859272671/job/24328862277

@oprypin
Copy link
Member

oprypin commented Apr 27, 2024

The warnings are now always reproducible on GitHub Actions with runs-on: macos-13.
https://github.com/crystal-lang/install-crystal/actions/runs/8859670657/job/24329698775

@oprypin
Copy link
Member

oprypin commented Apr 27, 2024

Back to the C library troubles-
Even if I apply CRYSTAL_OPTS="--link-flags=-Wl,-ld_classic" I am still building my C libraries with the new linker. (Presumably would need to apply such flags to the step that builds the C library as well).
As such, I get this error instead:

ld: warning: dylib (/usr/local/lib/libchipmunk.dylib) was built for newer macOS version (13.6) than being linked (13.0)
dyld[15192]: Symbol not found: _cpArbiterGetContactPointSet

https://github.com/oprypin/crystal-chipmunk/actions/runs/8859789088/job/24329985809

@yanecc
Copy link

yanecc commented May 1, 2024

I met the same warnings on GitHub Actions, with the full warning message here.

https://github.com/yanecc/MockGPT/actions/runs/8913041997/job/24477764716#step:4:24

@hovsater
Copy link
Contributor

hovsater commented May 1, 2024

Those warnings should be gone whenever #14466 gets merged.

@GrantBirki
Copy link

GrantBirki commented May 6, 2024

I am also getting errors in GitHub Actions when using MacOS based runners. Builds on Linux work fine:

[14/13] Codegen (linking)                 
cc _main.o3.o -o /Users/runner/work/runway/runway/bin/runway  -rdynamic -L/Users/runner/work/_temp/crystal-latest-true-undefined/embedded/lib -lssh2 -lxml2 -lz `command -v pkg-config > /dev/null && pkg-config --libs --silence-errors libssl || printf %s '-lssl -lcrypto'` `command -v pkg-config > /dev/null && pkg-config --libs --silence-errors libcrypto || printf %s '-lcrypto'` -L/opt/homebrew/Cellar/libyaml/0.2.5/lib -lyaml -lpcre2-8 -lgc -L/opt/homebrew/Cellar/libevent/2.1.12_1/lib -levent_pthreads -levent -L/opt/homebrew/Cellar/libevent/2.1.12_1/lib -levent -liconv
E: Error target runway failed to compile:
ld: warning: ignoring duplicate libraries: '-levent'
ld: library 'ssh2' not found
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Error: execution of command failed with exit status 1: cc "${@}" -o /Users/runner/work/runway/runway/bin/runway  -rdynamic -L/Users/runner/work/_temp/crystal-latest-true-undefined/embedded/lib -lssh2 -lxml2 -lz `command -v pkg-config > /dev/null && pkg-config --libs --silence-errors libssl || printf %s '-lssl -lcrypto'` `command -v pkg-config > /dev/null && pkg-config --libs --silence-errors libcrypto || printf %s '-lcrypto'` -L/opt/homebrew/Cellar/libyaml/0.2.5/lib -lyaml -lpcre2-8 -lgc -L/opt/homebrew/Cellar/libevent/2.1.12_1/lib -levent_pthreads -levent -L/opt/homebrew/Cellar/libevent/2.1.12_1/lib -levent -liconv

source logs


Update

I swapped from macos-latest to macos-13 and now my CI is working. Not ideal, but points to a greater issue in later MacOS versions:

Image

straight-shoota pushed a commit that referenced this issue Jun 15, 2024
Starting with Xcode 15, the minimum deployment target is required in the target triple.

With the release of Xcode 15, a [new linker was introduced](https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes#Linking) and with it came warning messages like this:

    ld: warning: no platform load command found in '/Users/pascal/.cache/crystal/Users-pascal-Documents-tutorials-crystal-hello_world.cr/F-loat32.o', assuming: macOS

It appears that the new linker is stricter in which target triples it considers valid. Specifically, it looks like the minimum deployment target is required. E.g., `aarch64-apple-darwin23.3.0` is valid, while `aarch64-apple-darwin` is not. See #13846 (comment) for details.

This patch removes code which strips the minimum deployment target in `LLVM.default_target_triple` as an effort for standardization.

See also: crystal-lang/distribution-scripts#296
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:bug A bug in the code. Does not apply to documentation, specs, etc. platform:darwin
Projects
None yet
Development

Successfully merging a pull request may close this issue.