Broken compiler produced if linker produced an error message at build time
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Clang's build system runs `ld -v` and parses the output to determine the linker version, saving it in `HOST_LINK_VERSION`. If the linker instead produces an error, Clang's build system can misinterpret the error message as a version number. It then bakes that erroneous linker version number into the compiler, and the compiler uses it if the user doesn't request a different linker version. In our case, this resulted in a compiler that produced the error message:
```
clang: error: invalid version number in '-mlinker-version=2.2.'
```
We build Clang using `-DCMAKE_LINKER=/opt/local/bin/ld` in order to use a copy of Apple's ld64 built by MacPorts, rather than the one included with Xcode.
I surmise that this problem happened because MacPorts recently updated to a new version of libxml2 which changed its major version. Before, MacPorts had libxml2.2.dylib; now it has libxml2.16.dylib. All software linking with the library must therefore be rebuilt. I suspect that one of the dependencies of ld64 hadn't been rebuilt, causing ld64 to emit an error like this:
```
dyld: Library not loaded: /opt/local/lib/libxml2.2.dylib
```
The Clang build system interpreted that as indicating linker version `2.2.`.
For more on the problem we experienced, read the description at https://trac.macports.org/ticket/73601, then you can skip ahead to my analysis at https://trac.macports.org/ticket/73601#comment:16.
We had a similar report five years ago in https://trac.macports.org/ticket/61280 which we could not explain at the time but which I am now convinced was caused by the same problem.
In our case, we experienced the problem with Clang 9.0.1 and 3.4. I know these are old but it looks like your current code still determines the linker version this way:
https://github.com/llvm/llvm-project/blob/3f65a03e8abb3e6fb3372cf4c254d6c9f090e2e0/cmake/Modules/GetDarwinLinkerVersion.cmake#L5-L17
I observe that you appear to intend to catch linker errors (`HAD_ERROR`), but it's not working, perhaps because shells typically only report the error code of the last command in a pipeline (in this case `head -1`) and that last command is succeeding. Bash's `set -o pipefail` would counteract that, for example.
You have received some other complaints about the consequences of trying to detect the linker version at build time rather than runtime, because it breaks if the linker is downgraded after build time. See #30813 and #45878.
Contributor guide
Research direction
Start with cmake/Modules/GetDarwinLinkerVersion.cmake at the referenced lines and inspect how the ld -v pipeline and HAD_ERROR result are handled. Reproduce the case with linker output containing an error, then verify that an error is not saved as HOST_LINK_VERSION and that the resulting compiler no longer emits the invalid linker-version diagnostic.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cmake
- Domain
- build-system, compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100