Skip to content

Bundled static curl and BoringSSL archive grouping is ineffective in Linux source link #7556

Description

@mstoelzle

Checklist

  • Clean upstream checkout at the exact reported revision.
  • Reached the shared-library link and preserved the failing import.
  • Captured the generated link order and compared only the concrete-archive LINK_GROUP:RESCAN correction.

Environment

Ubuntu 26.04.1 LTS, x86_64
Linux 7.0.0-31-generic
Python 3.12.13
CMake 4.2.3; Ninja 1.13.2; GCC 15.2.0
Open3D 1a9eb990f9a20936c30c428568c602bdef760744
Clean checkout status before configure: empty

Exact reproduction

cmake -S . -B build-link -G Ninja \
  -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON \
  -DBUILD_GUI=ON -DBUILD_WEBRTC=OFF -DBUILD_CUDA_MODULE=OFF \
  -DUSE_SYSTEM_CURL=OFF -DUSE_SYSTEM_OPENSSL=OFF \
  -DPython3_EXECUTABLE=/path/to/python

set -o pipefail
cmake --build build-link --target pip-package --parallel 24 --verbose 2>&1 \
  | tee build-original.log
status=${PIPESTATUS[0]}
printf '\nExit status: %s\n' "$status" | tee -a build-original.log

Separately recorded prerequisites

The first generated graph was blocked by #7555's prebuilt-Filament variant (lib/*.a declared versus lib/x86_64/*.a imported and installed). I corrected the archive-directory declaration in both Filament external-project files before testing this link issue. GCC 15 also required the unrelated host workaround -DCMAKE_CXX_FLAGS=-include cstdint. Neither changes curl/BoringSSL order or semantics.

Original generated link order

The shared-library link completed, but CMake placed an empty group immediately after liblzf while the concrete bundled archives appeared later ungrouped:

... libOpen3D_3rdparty_liblzf.a -Wl,-\( -Wl,-\) ...
... boringssl/src/ext_boringssl/lib/libssl.a
    boringssl/src/ext_boringssl/lib/libcrypto.a
    curl/lib/libcurl.a ...

The full generated command is reproducible without relying on shell history:

ninja -C build-link -t commands lib/Release/libOpen3D.so.0.19.0 | tail -n 1

Because this is a shared link, GNU ld permitted unresolved references. The resulting library was:

aaa45a944532fa3128df9eec8c3dd03e11793b2024f9311ec8889acce469477f  libOpen3D.so.0.19.0

nm -D --undefined-only showed strong bundled-curl TLS references including BIO_free, EVP_PKEY_free, SSL_CTX_new, and X509_INFO_free. Importing the generated package produced the target failure:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/tmp/open3d-audit-7556-build/lib/python_package/open3d/__init__.py", line 79, in <module>
    from open3d.pybind import (
ImportError: /tmp/open3d-audit-7556-build/lib/python_package/open3d/libOpen3D.so.0.19: undefined symbol: X509_INFO_free

Exit status: 1

libcrypto.a defines X509_INFO_free; the archive was simply scanned before the later libcurl.a introduced the reference.

Isolated concrete-archive control

The control grouped the concrete archive paths on the build interface:

set(_curl_openssl_archives
    "${CURL_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${CURL_LIBRARIES}${CMAKE_STATIC_LIBRARY_SUFFIX}")
foreach(_library IN LISTS BORINGSSL_LIBRARIES)
    list(APPEND _curl_openssl_archives
        "${BORINGSSL_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${_library}${CMAKE_STATIC_LIBRARY_SUFFIX}")
endforeach()
set(_curl_iface_libs
    "$<BUILD_INTERFACE:$<LINK_GROUP:RESCAN,${_curl_openssl_archives}>>")
set_property(TARGET 3rdparty_curl PROPERTY INTERFACE_LINK_LIBRARIES
    "${_curl_iface_libs}")

The regenerated final command contains the actual archives inside one rescan group (order is curl, ssl, crypto):

... -Wl,--start-group
    curl/lib/libcurl.a
    boringssl/src/ext_boringssl/lib/libssl.a
    boringssl/src/ext_boringssl/lib/libcrypto.a
    -Wl,--end-group ...

The separate MKL archive group remains intact. pip-package completes with exit status 0. The control library and wheel are:

d75d25012b9c3592c624675eae9c0e9dc06302dfce1b6010a86bcaf217bc7e3c  libOpen3D.so.0.19.0
b79867388b29b9abc24ef1b7c5e854e4a159fd605e3ee8761965f7c8fe931d7d  open3d_cpu-0.19.0+1a9eb99-cp312-cp312-manylinux_2_43_x86_64.whl

The only remaining OPENSSL_* entries in nm -D --undefined-only are the three expected weak memory hooks. Import now succeeds:

0.19.0+1a9eb99
Exit status: 0

Result

Confirmed. Grouping INTERFACE targets produced an empty group and left the actual bundled curl/BoringSSL archives subject to one-pass ordering. Applying LINK_GROUP:RESCAN to the concrete archive paths emits a real group, removes the strong TLS undefined symbols, and makes the generated Python package importable.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions