gnustep / libobjc2

Objective-C runtime library intended for use with Clang.
http://www.gnustep.org/
MIT License
426 stars 116 forks source link

v2.1 existence of "libsupc++.a" breaks test suite build #197

Closed Un1Gfn closed 6 months ago

Un1Gfn commented 3 years ago
$ uname -a
Linux 820g3 5.11.2-arch1-1 #1 SMP PREEMPT Fri, 26 Feb 2021 18:26:41 +0000 x86_64 GNU/Linux
$ cat /etc/lsb-release
LSB_VERSION=1.4
DISTRIB_ID=Arch
DISTRIB_RELEASE=rolling
DISTRIB_DESCRIPTION="Arch Linux"
$ clang --version
clang version 11.1.0
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

Build v2.1 tarball

$ cmake -B Build -S . \
    -DCMAKE_BUILD_TYPE=None \
    -DCMAKE_CXX_COMPILER=clang++ \
    -DCMAKE_C_COMPILER=clang \
    -DCMAKE_INSTALL_PREFIX=/usr \
    -DGNUSTEP_INSTALL_TYPE=NONE \
    -DOLDABI_COMPAT=OFF \
    \
    -DCMAKE_VERBOSE_MAKEFILE=ON
cmake -LA 2>&1 ``` BOEHM_GC:BOOL=FALSE BUILD_STATIC_LIBOBJC:BOOL=false CMAKE_ADDR2LINE:FILEPATH=/usr/bin/addr2line CMAKE_AR:FILEPATH=/usr/bin/ar CMAKE_ASM_COMPILER:FILEPATH=/usr/bin/clang CMAKE_ASM_COMPILER_AR:FILEPATH=/usr/bin/llvm-ar CMAKE_ASM_COMPILER_RANLIB:FILEPATH=/usr/bin/llvm-ranlib CMAKE_ASM_FLAGS:STRING= CMAKE_ASM_FLAGS_DEBUG:STRING=-g CMAKE_ASM_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG CMAKE_ASM_FLAGS_NONE:STRING= CMAKE_ASM_FLAGS_RELEASE:STRING=-O3 -DNDEBUG CMAKE_ASM_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG CMAKE_BUILD_TYPE:STRING=None CMAKE_COLOR_MAKEFILE:BOOL=ON CMAKE_CXX_COMPILER:STRING=/usr/bin/clang++ CMAKE_CXX_COMPILER_AR:FILEPATH=/usr/bin/llvm-ar CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/usr/bin/llvm-ranlib CMAKE_CXX_FLAGS:STRING=-D_FORTIFY_SOURCE=2 -march=x86-64 -mtune=generic -O2 -pipe -fno-plt CMAKE_CXX_FLAGS_DEBUG:STRING=-g CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG CMAKE_CXX_FLAGS_NONE:STRING= CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG CMAKE_C_COMPILER:STRING=/usr/bin/clang CMAKE_C_COMPILER_AR:FILEPATH=/usr/bin/llvm-ar CMAKE_C_COMPILER_RANLIB:FILEPATH=/usr/bin/llvm-ranlib CMAKE_C_FLAGS:STRING=-D_FORTIFY_SOURCE=2 -march=x86-64 -mtune=generic -O2 -pipe -fno-plt CMAKE_C_FLAGS_DEBUG:STRING=-g CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG CMAKE_C_FLAGS_NONE:STRING= CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG CMAKE_DLLTOOL:FILEPATH=/usr/bin/llvm-dlltool CMAKE_EXE_LINKER_FLAGS:STRING=-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= CMAKE_EXE_LINKER_FLAGS_NONE:STRING= CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= CMAKE_EXPORT_COMPILE_COMMANDS:BOOL= CMAKE_INSTALL_PREFIX:PATH=/usr CMAKE_LINKER:FILEPATH=/usr/bin/ld CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make CMAKE_MODULE_LINKER_FLAGS:STRING=-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= CMAKE_MODULE_LINKER_FLAGS_NONE:STRING= CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= CMAKE_NM:FILEPATH=/usr/bin/nm CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib CMAKE_READELF:FILEPATH=/usr/bin/readelf CMAKE_SHARED_LINKER_FLAGS:STRING=-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= CMAKE_SHARED_LINKER_FLAGS_NONE:STRING= CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= CMAKE_SKIP_INSTALL_RPATH:BOOL=NO CMAKE_SKIP_RPATH:BOOL=NO CMAKE_STATIC_LINKER_FLAGS:STRING= CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= CMAKE_STATIC_LINKER_FLAGS_NONE:STRING= CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= CMAKE_STRIP:FILEPATH=/usr/bin/strip CMAKE_VERBOSE_MAKEFILE:BOOL=ON CPACK_GENERATOR:STRING=TGZ CPACK_SOURCE_RPM:BOOL=OFF CPACK_SOURCE_TBZ2:BOOL=ON CPACK_SOURCE_TGZ:BOOL=ON CPACK_SOURCE_TXZ:BOOL=ON CPACK_SOURCE_TZ:BOOL=ON CPACK_SOURCE_ZIP:BOOL=OFF CPACK_STRIP_FILES:BOOL=true CXX_RUNTIME_LIB:FILEPATH=/usr/lib/libsupc++.a DEBUG_ARC_COMPAT:BOOL=FALSE ENABLE_OBJCXX:BOOL=true ENABLE_TRACING:BOOL=FALSE GNUSTEP_CONFIG:FILEPATH=/usr/bin/gnustep-config GNUSTEP_INSTALL_TYPE:STRING=NONE INCLUDE_DIRECTORY:STRING=objc LEGACY_COMPAT:BOOL=FALSE LIBOBJC_NAME:STRING=objc LIB_INSTALL_PATH:STRING=lib OLDABI_COMPAT:BOOL=OFF TESTS:BOOL=TRUE TYPE_DEPENDENT_DISPATCH:BOOL=TRUE ```
$ make -j1 -C Build
[ 14%] Linking C executable ObjCXXEHInterop
cd /home/darren/.cache/yay/libobjc2/src/libobjc2-2.1/Build/Test && /usr/bin/cmake -E cmake_link_script CMakeFiles/ObjCXXEHInterop.dir/link.txt --verbose=1
/usr/bin/clang -D_FORTIFY_SOURCE=2 -march=x86-64 -mtune=generic -O2 -pipe -fno-plt -Xclang -fexceptions -Xclang -fobjc-exceptions -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -rdynamic CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.mm.o CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.m.o CMakeFiles/test_runtime.dir/Test.m.o -o ObjCXXEHInterop  -Wl,-rpath,/home/darren/.cache/yay/libobjc2/src/libobjc2-2.1/Build ../libobjc.so.4.6 -Wl,-Bstatic -lsupc++ -Wl,-Bdynamic
/usr/bin/ld: ../libobjc.so.4.6: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
/usr/bin/ld: ../libobjc.so.4.6: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: ../libobjc.so.4.6: undefined reference to `std::ios_base::Init::~Init()'
/usr/bin/ld: ../libobjc.so.4.6: undefined reference to `std::cerr'
/usr/bin/ld: ../libobjc.so.4.6: undefined reference to `ceilf'
/usr/bin/ld: ../libobjc.so.4.6: undefined reference to `std::ios_base::Init::Init()'
clang-11: error: linker command failed with exit code 1 (use -v to see invocation)
Un1Gfn commented 3 years ago

Build succeeds with -DTESTS=OFF but how may I build the test suite then?

davidchisnall commented 3 years ago

Interesting. It looks as if the runtime is picking up some C++ standard library symbol dependencies. I think this may be a thing that happens with libstdc++ if you include iostream, whether you actually use it or not. I don't know which compilation units are pulling that in - we don't include it directly, so must be transitively including it somehow. Can you look at the preprocessed versions of the [Objective-]C++ files and see where it comes from?

I suspect on Ubuntu (which we test in CI) there's no libsupc++, so this is masked by the build system deciding to unconditionally link libstdc++. On Arch, it seems to find a libsupc++.a. We shouldn't be using a static libsupc++, so the correct fix is probably to tweak the libsupc++ lookup to find only the SHARED version. Can you try tweaking the CMakeLists.txt to do that and see if it works for you?

Un1Gfn commented 3 years ago

Ubuntu 20.10 Groovy Gorilla provides /usr/lib/gcc/x86_64-linux-gnu/10/libsupc++.a in package libstdc++-10-dev

Arch Linux:

$ pacman --query --owns /usr/lib/lib{sup,std}*
/usr/lib/libsupc++.a is owned by gcc 10.2.0-6
/usr/lib/libstdc++.a is owned by gcc 10.2.0-6
/usr/lib/libstdc++fs.a is owned by gcc 10.2.0-6
/usr/lib/libstdc++.so is owned by gcc-libs 10.2.0-6
/usr/lib/libstdc++.so.6 is owned by gcc-libs 10.2.0-6
/usr/lib/libstdc++.so.6.0.28 is owned by gcc-libs 10.2.0-6

I will not remove /usr/lib/libsupc++.a by uninstalling gcc :/

tweak the libsupc++ lookup to find only the SHARED version

$ pacman --files --regex 'libsupc.*so.*'
$ 

Simply patch it out, as a complete NOOB to CMake, no shared version anyway :)

$ patch --verbose CMakeLists.txt <<"EOP"
--- CMakeLists.txt
+++ CMakeLists.txt
@@ -289,7 +289,7 @@
    # If it doesn't, then look for GNU libsupc++.so instead (either works,
    # they're ABI compatible).
    if (NOT CXX_RUNTIME)
-     test_cxx(supc++ false)
+     #
    endif (NOT CXX_RUNTIME)
    # libc++abi does not currently work, don't try it.
    if (NOT CXX_RUNTIME)
EOP
$ cmake -B Build -S . \
    -DCMAKE_BUILD_TYPE=None \
    -DCMAKE_CXX_COMPILER=clang++ \
    -DCMAKE_C_COMPILER=clang \
    -DCMAKE_INSTALL_PREFIX=/usr \
    -DGNUSTEP_INSTALL_TYPE=NONE \
    -DLIBOBJC_NAME=objc2 \
    -DOLDABI_COMPAT=OFF \
    -DTESTS=ON \
    \
    -DCMAKE_VERBOSE_MAKEFILE=OFF

Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed

$ make -C Build
$ make -C test

Success

davidchisnall commented 3 years ago

I think we still have a bug. The existence of libsupc++.a should not break the build.

Un1Gfn commented 3 years ago

FYI

before (collapsed in cmake -LA 2>&1):

CXX_RUNTIME_LIB:FILEPATH=/usr/lib/libsupc++.a

after:

$ cmake -S .. -B . -LA |& grep CXX_RUNT
CXX_RUNTIME_LIB:FILEPATH=CXX_RUNTIME_LIB-NOTFOUND
davidchisnall commented 1 year ago

The CMake has now been reworked and doesn't try to link directly against a C++ runtime. Can you try again?