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

macOS link error with static curl — missing ___isOSVersionAtLeast #279

Closed
ehuss opened this issue Jul 19, 2019 · 4 comments · Fixed by #283
Closed

macOS link error with static curl — missing ___isOSVersionAtLeast #279

ehuss opened this issue Jul 19, 2019 · 4 comments · Fixed by #283

Comments

@ehuss
Copy link
Collaborator

ehuss commented Jul 19, 2019

Linking with the static feature on macOS 10.13 fails with the following error:

Undefined symbols for architecture x86_64:
  "___isOSVersionAtLeast", referenced from:
      _sectransp_connect_step1 in libcurl_sys-72a3db42ebafc5cb.rlib(sectransp.o)
      _sectransp_connect_step2 in libcurl_sys-72a3db42ebafc5cb.rlib(sectransp.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

The problem is that rustc links with the -nodefaultlibs flag. This prevents cc from linking with /Library/Developer/CommandLineTools/usr/lib/clang/10.0.0/lib/darwin/libclang_rt.osx.a (or whatever version of xcode you have), which is where ___isOSVersionAtLeast is located.

This is caused by the use of things like __builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *). Usually clang will statically strip out this builtin, which is why it normally works on 10.14. However, if you are building on an older version, it adds the call to ___isOSVersionAtLeast at runtime. Strangely, using a minor semver version (like 10.13.4 instead of 10.13) also prevents it from being determined statically when building on 10.13 (presumably it defaults to --mmacosx-version-min=10.13 which sets the floor to 10.13.0 regardless which minor version you are on).

Here's a reduced example project that will fail on 10.14 (by testing for 10.15).
foo.zip

Hopefully that's all clear. Unfortunately I don't know how to fix this. Presumably rustc uses -nodefaultlibs for a good reason. It seems unlikely to me, but maybe there is a way to discover the correct location of libclang_rt.osx.a and include it in the link list? A more draconian solution would be to unset HAVE_BUILTIN_AVAILABLE, but I think that would disable some important features (like TLS 1.3). Perhaps Alex has some clever ideas?

@alexcrichton
Copy link
Owner

Thanks for the investigation here! This all definitely makes more sense now with respect to Travis/Azure. I suspect Travis was running on 10.14 which is why we never ran into this, but Azure must be running on 10.13 or prior.

The -nodefaultlibs is something that's super old in rustc and intentional to the point that we don't want to pull in lots of libraries by default by accident, but rather we'd prefer to be in control over what's injected in and what is available for use.

I think there's two possible routes to fix this:

  • One, which I think is the more proper version, is that this crate needs to be responsible for finding the appropriate library to link here and providing a directive to link it.
  • Another, which is easier but less of a "pure" solution, is to add this symbol to Rust's compiler-builtins

Do you know if it's difficult to fidn libclang_rt.osx.a? I don't think we should run into issues if we link it and it's in theory as easy as just printing out the right rustc-link-lib annotation.

@ehuss
Copy link
Collaborator Author

ehuss commented Jul 22, 2019

Do you know if it's difficult to fidn libclang_rt.osx.a?

I don't know much about clang, so I'm just going off what I can see.

One option is to run clang --print-search-dirs. This will give you the path to /Library/Developer/CommandLineTools/usr/lib/clang/10.0.1 and you can just tack lib/darwin to the end of that.

Another option is to compile a simple binary (int main() {}) with the -v flag. This will print the complete ld path, and it could just search that. This seems more messy, though.

Neither option sounds good. It looks like the builtin needs a plist parser, which doesn't seem too pleasant to add.

I can confirm that adding rustc-link-lib:clang_rt.osx and the appropriate link-search to curl-sys build.rs seems to work.

@alexcrichton
Copy link
Owner

Heh yeah so I think we should avoid parsing -v or plist things, but using --print-search-dirs seems reasonable. We could at least just try that and see how it goes, adding more support over time as necessary to find this library.

badboy added a commit to badboy/curl-rust that referenced this issue Aug 21, 2019
On OSX we need to link against the clang runtime, which is hidden in some non-default path.
We can get the path from `clang --print-search-dirs`.
Kudos to @ehuss for finding that workaround.

Fixes alexcrichton#279.
badboy added a commit to badboy/curl-rust that referenced this issue Aug 22, 2019
On OSX we need to link against the clang runtime, which is hidden in some non-default path.
We can get the path from `clang --print-search-dirs`.
Kudos to @ehuss for finding that workaround.

Fixes alexcrichton#279.
@wagenet
Copy link

wagenet commented Oct 9, 2019

I'm running into this issue on macOS 10.15, but only when trying to compile for grcov. For me it looks like the same problem as this issue rust-lang/rust#63047.

badboy added a commit to badboy/curl-rust that referenced this issue Jan 9, 2020
On OSX we need to link against the clang runtime, which is hidden in some non-default path.
We can get the path from `clang --print-search-dirs`.
Kudos to @ehuss for finding that workaround.

Fixes alexcrichton#279.
badboy added a commit to badboy/curl-rust that referenced this issue Jan 9, 2020
On OSX we need to link against the clang runtime, which is hidden in some non-default path.
We can get the path from `clang --print-search-dirs`.
Kudos to @ehuss for finding that workaround.

Fixes alexcrichton#279.
alexcrichton pushed a commit that referenced this issue Jan 9, 2020
* Link against clang runtime on static builds on macOS

On OSX we need to link against the clang runtime, which is hidden in some non-default path.
We can get the path from `clang --print-search-dirs`.
Kudos to @ehuss for finding that workaround.

Fixes #279.

* Fix formatting
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 a pull request may close this issue.

3 participants