diff --git a/.github/workflows/build-native.yml b/.github/workflows/build-native.yml index 262fa431..2120f4ae 100644 --- a/.github/workflows/build-native.yml +++ b/.github/workflows/build-native.yml @@ -75,6 +75,32 @@ jobs: exit 1 fi + # Everything recorded as needed has to be on a machine for the library to load at all, so + # the list is held to what any machine that runs .NET and has a display already has. It grew + # once without anybody choosing it: the container's linker records every library it is + # handed, used or not, and raylib hands on libSM and libICE, which a stock Ubuntu lacks. + # The viewer could not start there, and nothing noticed until somebody ran it on one. + - name: Check needed libraries + if: runner.os == 'Linux' + env: + ALLOWED: >- + libc.so.6 libm.so.6 libdl.so.2 libpthread.so.0 librt.so.1 libstdc++.so.6 libgcc_s.so.1 + libX11.so.6 libGL.so.1 ld-linux-x86-64.so.2 ld-linux-aarch64.so.1 + run: | + needed=$(objdump -p build/libdiffengine_viewer.so | awk '$1 == "NEEDED" { print $2 }') + echo "Needed:" $needed + failed=0 + for library in $needed; do + case " $ALLOWED " in + *" $library "*) ;; + *) + echo "::error::libdiffengine_viewer.so needs $library, which is not in the list of libraries it may need" + failed=1 + ;; + esac + done + exit $failed + # macOS draws with AppKit and Core Text rather than raylib and ImGui, so it is a Swift # package rather than a CMake project. Both --arch flags in one invocation produce a # universal binary, so there is no separate lipo step. diff --git a/claude.md b/claude.md index b1d84005..450ba208 100644 --- a/claude.md +++ b/claude.md @@ -622,6 +622,13 @@ the comment there about not caching "nothing staged" asks for. - Built binaries are **committed** to `src/DiffEngineViewer.{Linux,Mac}/runtimes/{rid}/native/`, so a plain `dotnet build` produces a shippable package and contributors never need CMake. Regenerate them with the `build-native` GitHub workflow, which opens a PR. +- The Linux library is linked with `--as-needed`, and `build-native` fails a build whose `NEEDED` + entries are outside a short list. A library recorded there has to be installed for the viewer + to load at all, and the manylinux container's linker records every one it is handed: raylib + passes on all of FindX11's, so the binaries built there needed `libSM` and `libICE`, which a + stock Ubuntu lacks, where the ones built on the Ubuntu runner (whose compiler passes the flag + itself) had not. GLFW opens the X11 extension libraries and `libGL` itself at run time, so only + `libX11` is left of them. **DiffEngineTray (`src/DiffEngineTray/`):** - Windows Forms tray application that handles pending file diffs diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index 5800fd12..67b1c3a6 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -109,6 +109,17 @@ target_compile_definitions(diffengine_viewer PRIVATE IMGUI_USE_WCHAR32) find_package(Threads REQUIRED) target_link_libraries(diffengine_viewer PRIVATE raylib Threads::Threads ${CMAKE_DL_LIBS}) +# Only the libraries something is actually called in are recorded as needed. raylib hands on +# everything CMake's FindX11 found, which includes libSM and libICE wherever their headers are +# installed, and nothing here or in raylib calls either. A library recorded as needed has to be +# on the machine for this one to load at all, and a stock Ubuntu has neither of those two: the +# viewer could not start, and every inline snapshot sent to it was staged instead of shown. +# Ubuntu's own compiler passes this by default, which is why the binaries built on the runner +# never had the problem and the ones built in the manylinux container did. +if(UNIX AND NOT APPLE) + target_link_options(diffengine_viewer PRIVATE LINKER:--as-needed) +endif() + # The managed side probes for a bare name; keep it identical on every platform apart from the # platform's own prefix and extension. set_target_properties(diffengine_viewer PROPERTIES diff --git a/src/DiffEngineViewer.Linux/runtimes/linux-arm64/native/libdiffengine_viewer.so b/src/DiffEngineViewer.Linux/runtimes/linux-arm64/native/libdiffengine_viewer.so index ed2b5718..1d57eb20 100644 Binary files a/src/DiffEngineViewer.Linux/runtimes/linux-arm64/native/libdiffengine_viewer.so and b/src/DiffEngineViewer.Linux/runtimes/linux-arm64/native/libdiffengine_viewer.so differ diff --git a/src/DiffEngineViewer.Linux/runtimes/linux-x64/native/libdiffengine_viewer.so b/src/DiffEngineViewer.Linux/runtimes/linux-x64/native/libdiffengine_viewer.so index bc05f05e..e7c794f4 100644 Binary files a/src/DiffEngineViewer.Linux/runtimes/linux-x64/native/libdiffengine_viewer.so and b/src/DiffEngineViewer.Linux/runtimes/linux-x64/native/libdiffengine_viewer.so differ