rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.17k stars 12.56k forks source link

a static library is not linked properly to a required system library #110143

Open conanoc opened 1 year ago

conanoc commented 1 year ago

Problem

I created a crate as a static library named libaries_askar.a. When I create an Xcode project that uses this library, build fails with the following error:

Undefined symbols for architecture x86_64:
  "_SCDynamicStoreCopyComputerName", referenced from:
      whoami::platform::devicename_os::hfd1ed897939614da in libaries_askar.a(whoami-3e3bd00337b8ac7e.whoami.50980d84-cgu.12.rcgu.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I could resolve this link error by importing SystemConfiguration framework in a swift file of my app.

#if os(macOS)
import SystemConfiguration
#endif

Steps

  1. Create a crate that depends on the "whoami" crate.
  2. Build the crate as a static library.
  3. Create an xcframework of the library.
  4. Create a Swift package and add the xcframework as a binary target dependency.
  5. Build the package.

Possible Solution(s)

No response

Notes

Version

cargo 1.67.1 (8ecd4f20a 2023-01-10)
release: 1.67.1
commit-hash: 8ecd4f20a9efb626975ac18a016d480dc7183d9b
commit-date: 2023-01-10
host: x86_64-apple-darwin
libgit2: 1.5.0 (sys:0.16.0 vendored)
libcurl: 7.86.0 (sys:0.4.59+curl-7.86.0 system ssl:(SecureTransport) LibreSSL/3.3.6)
os: Mac OS 13.2.1 [64-bit]
ehuss commented 1 year ago

Transferred to rust-lang/rust, as cargo is not involved in linking.

Jules-Bertholet commented 1 year ago

@rustbot label +A-linkage

bjorn3 commented 11 months ago

The whoami crate correctly added a dependency on the SystemConfiguration framework: https://github.com/ardaku/whoami/blob/1c076a5ac667c0258f9649efd346b238ab9c7b87/src/unix.rs#L82

The issue is that if you are building a staticlib, there is no way for the staticlib itself to define all dynamic libraries it depends on. As such you need to pass --print native-static-libs to rustc when compiling the staticlib and then use all the linker arguments it prints when linking against the staticlib. For example it could show:

note: Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms.

note: native-static-libs: -lgcc_s -lutil -lrt -lpthread -lm -ldl -lc

in which case you have to pass -lgcc_s -lutil -lrt -lpthread -lm -ldl -lc to the linker when linking against the staticlib.