[MacPorts] #62426: libc++: using a newer libc++ to build software on older macos systems
MacPorts
noreply at macports.org
Tue Sep 27 12:52:33 UTC 2022
#62426: libc++: using a newer libc++ to build software on older macos systems
-------------------------------------+--------------------
Reporter: kencu | Owner: kencu
Type: enhancement | Status: closed
Priority: Normal | Milestone:
Component: ports | Version:
Resolution: fixed | Keywords:
Port: libcxx macports-libcxx |
-------------------------------------+--------------------
Comment (by RJVB):
Replying to [comment:67 kencu]:
> It's not a clean mapping. At last count, Apple was carrying something
like 12,000 patches for xcode on top of the LLVM tree, or some similar
number. So their versions are not quite llvm's versions.
This could explain things, if they introduce change that cause ABI
compatibility problems. But if they do that it's a miracle that we never
ran into issues using the libc++ headers from clang++-mp-XY with
/usr/lib/libc++.dylib! I suppose you can see why?!
Even if the mapping isn't clean we can still make it based on the LLVM
version Apple apply their patches to. For instance, suppose OS Foo
includes libc++ 1200.0.1 which is a patched version of LLVM 12.0.1 that
mapping could say 1200.0.1 corresponds to stock 12.0.2 (which AFAIK would
never exist). Then `port:libcxx_macports` could set the current_version of
libc++ 13.0.x to `1200.13.x`, or something comparable that sits between 2
Apple libc++ version numbers.
----
I've been tinkering with your example.
libcxx-test.cpp:
{{{
#include "llvm/Support/Errc.h"
#include "clang/Basic/FileManager.h"
#include <iostream>
int main(int argc, const char *argv[])
{
clang::FileManager fileMgr((clang::FileSystemOptions()));
for (int i = 0 ; i < argc ; ++i) {
#if LLVM_VERSION_MAJOR > 9
auto file = fileMgr.getFileRef(argv[i], /*OpenFile=*/true);
std::error_code EC = llvm::errorToErrorCode(file.takeError());
#else
auto file = fileMgr.getFile(argv[i], /*OpenFile=*/true);
std::error_code EC = file ?
llvm::errorToErrorCode(llvm::Error::success()) :
llvm::errorToErrorCode(llvm::createStringError(llvm::errc::no_such_file_or_directory,
"%s"));
#endif
std::cout << argv[i] << " : EC.message is " << EC.message() << "\n";
bool not_no_such = (EC != llvm::errc::no_such_file_or_directory);
bool is_no_such = !not_no_such;
std::cout << "EC == no_such_file_or_directory is " << is_no_such <<
"\n";
}
return 0;
}
}}}
build-libcxx-test.sh:
{{{
#!/bin/sh
CC="$1"
shift
# -I/opt/local/libexec/llvm-14/include
-Wl,-rpath,/opt/local/libexec/llvm-14/lib -L/opt/local/libexec/llvm-14/lib
${CC} -c libcxx-test.cpp -std=c++17 -stdlib=libc++
-D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS \
-D__STDC_LIMIT_MACROS "$@"
${CC} libcxx-test.o -o libcxx-test -Wl,-search_paths_first
-Wl,-headerpad_max_install_names -lclangFrontend \
-lclangSerialization -lclangDriver -lclangCodeGen -lclangParse
-lclangSema -lclangAnalysis -lclangEdit \
-lclangASTMatchers -lclangAST -lclangLex -lclangBasic -lLLVM "$@"
}}}
With port:clang-12 I can reproduce your symptom, and if I link explictly
to /usr/lib/libc++.dylib I get correct behaviour
{{{
> build-libcxx-test.sh clang++-mp-12 -I/opt/local/libexec/llvm-12/include/
-Wl,-rpath,/opt/local/libexec/llvm-12/lib -L/opt/local/libexec/llvm-12/lib
-Wl,-rpath,/opt/local/lib -L/opt/local/lib /usr/lib/libc++.dylib &&
libcxx-test ./nonexistant.h libcxx-test.cpp
clang: warning: -Wl,-rpath,/opt/local/libexec/llvm-12/lib: 'linker' input
unused [-Wunused-command-line-argument]
clang: warning: -Wl,-rpath,/opt/local/lib: 'linker' input unused
[-Wunused-command-line-argument]
clang: warning: /usr/lib/libc++.dylib: 'linker' input unused [-Wunused-
command-line-argument]
clang: warning: argument unused during compilation:
'-L/opt/local/libexec/llvm-12/lib' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-L/opt/local/lib'
[-Wunused-command-line-argument]
libcxx-test : EC.message is Undefined error: 0
EC == no_such_file_or_directory is 0
./nonexistant.h : EC.message is No such file or directory
EC == no_such_file_or_directory is 1
libcxx-test.cpp : EC.message is Undefined error: 0
EC == no_such_file_or_directory is 0
}}}
This also applies to using `/opt/local/lib/libc++.dylib` from my own
`macstrop:libcxx` port
{{{
> build-libcxx-test.sh clang++-mp-12 -I/opt/local/libexec/llvm-12/include/
-Wl,-rpath,/opt/local/libexec/llvm-12/lib -L/opt/local/libexec/llvm-12/lib
-Wl,-rpath,/opt/local/lib -L/opt/local/lib /opt/local/lib/libc++.dylib &&
libcxx-test ./nonexistant.h libcxx-test.cpp && ldd libcxx-test
clang: warning: -Wl,-rpath,/opt/local/libexec/llvm-12/lib: 'linker' input
unused [-Wunused-command-line-argument]
clang: warning: -Wl,-rpath,/opt/local/lib: 'linker' input unused
[-Wunused-command-line-argument]
clang: warning: /opt/local/lib/libc++.dylib: 'linker' input unused
[-Wunused-command-line-argument]
clang: warning: argument unused during compilation:
'-L/opt/local/libexec/llvm-12/lib' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-L/opt/local/lib'
[-Wunused-command-line-argument]
libcxx-test : EC.message is Undefined error: 0
EC == no_such_file_or_directory is 0
./nonexistant.h : EC.message is No such file or directory
EC == no_such_file_or_directory is 0
libcxx-test.cpp : EC.message is Undefined error: 0
EC == no_such_file_or_directory is 0
libcxx-test:
/opt/local/libexec/llvm-12/lib/libLLVM.dylib (compatibility
version 1.0.0, current version 12.0.1)
/opt/local/lib/libc++.1.dylib (compatibility version 1.0.0,
current version 9.0.1)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current
version 1197.1.1)
}}}
I would have to build my `macstrop:libcxx at 12.0.1` to verify if something
changed between libc++ 9 and libc++ 12 . That is not impossible of course,
but then again *AFAIK* libc++ 9 is new enough to provide support for
current C++ standards, on systems that ship an earlier version.
Now, the weird thing I see is when I remove
`/opt/local/libexec/llvm-12/lib/libc++.dylib` so the linker/editor doesn't
find that libc++ any more.
In that case, `ld` refuses to acknowledge both libc++.dylib versions that
are in its path. I can add either explicitly (= with the absolute path) as
in the commands shown above but without that I get missing symbol errors
for everything provided by libc++ .
Can you confirm this? I have no explanation for it, but it would be
interesting to rebuild clang-12 WITHOUT libc++ .
I can do that, but it takes hours on my system so if that is not the case
for you I'd appreciate if you could check first if that makes a
difference.
--
Ticket URL: <https://trac.macports.org/ticket/62426#comment:68>
MacPorts <https://www.macports.org/>
Ports system for macOS
More information about the macports-tickets
mailing list