]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
cmake: lib order fixes for picky linkers (e.g. binutils `ld`)
authorViktor Szakats <commit@vsz.me>
Wed, 5 Feb 2025 12:17:52 +0000 (13:17 +0100)
committerViktor Szakats <commit@vsz.me>
Thu, 6 Feb 2025 22:35:04 +0000 (23:35 +0100)
This issue was not addressed with CMake builds so far. curl-for-win
worked thanks to its `-Wl,--start-group` workaround. It affects
binutils `ld` linking statically. Shared linking and llvm's `lld`
doesn't need strict lib order, and are not affected.

The solution is to pass libs in dependency order, with least dependent
(e.g. system) libs last. In case of cyclic dependency, may pass libs
twice.

Fix most issues by moving Windows system libs `ws2_32` and `bcrypt`
last, and move SSH libs first due to their dependence on crypto
backends and zlib compression.

Also:
- modify an existing Linux curl-for-win job to use gcc.
- add a specific Windows gcc job to test this. Make it use different
  options than the default to extend build coverage too: `libssh`,
  `zlib-ng`, 32-bit.
- prefer CMake imported targets for OpenSSL and ZLIB.

Examples of issues fixed:

Windows LibreSSL, libpsl vs. ws2_32:
```
x86_64-w64-mingw32-ld: curl/libressl/lib/libcrypto.a(bss_sock.c.obj):bss_sock.c:(.text$sock_ctrl[sock_ctrl]+0x59): undefined reference to `__imp_shutdown'
x86_64-w64-mingw32-ld: curl/libressl/lib/libcrypto.a(gcm128.c.obj):gcm128.c:(.text$CRYPTO_gcm128_init[CRYPTO_gcm128_init]+0x65): undefined reference to `__imp_ntohl'
x86_64-w64-mingw32-ld: curl/libpsl/_x64-win-ucrt/usr/lib/libpsl.a(psl.o):(.text$psl_is_cookie_domain_acceptable+0xef): undefined reference to `__imp_WSAStringToAddressW'
```
Ref: https://github.com/curl/curl/actions/runs/13157579253/job/36718144881?pr=16182#step:3:5354

Linux libssh2 vs. zlib:
```
/usr/lib/gcc-cross/aarch64-linux-gnu/12/../../../../aarch64-linux-gnu/bin/ld: curl/libssh2/_a64-linux-gnu-libressl/usr/lib/libssh2.a(unity_0_c.c.o): in function `comp_method_zlib_dtor':
(.text.comp_method_zlib_dtor+0x8c): undefined reference to `deflateEnd'
/usr/lib/gcc-cross/aarch64-linux-gnu/12/../../../../aarch64-linux-gnu/bin/ld: curl/libssh2/_a64-linux-gnu-libressl/usr/lib/libssh2.a(unity_0_c.c.o): in function `comp_method_zlib_comp':
(.text.comp_method_zlib_comp+0x50): undefined reference to `deflate'
/usr/lib/gcc-cross/aarch64-linux-gnu/12/../../../../aarch64-linux-gnu/bin/ld: curl/libssh2/_a64-linux-gnu-libressl/usr/lib/libssh2.a(unity_0_c.c.o): in function `comp_method_zlib_init':
(.text.comp_method_zlib_init+0x8c): undefined reference to `deflateInit_'
```
Ref: https://github.com/curl/curl/actions/runs/13157270420/job/36717189086?pr=16182#step:3:5285

Windows libssh vs. ws2_32 and LibreSSL:
```
/usr/bin/i686-w64-mingw32-ld: curl/libssh/_x86-win-ucrt-libressl/usr/lib/libssh.a(connect.c.obj):(.text$ssh_connect_host_nonblocking+0x92): undefined reference to `WspiapiGetAddrInfo@16'
/usr/bin/i686-w64-mingw32-ld: curl/libssh/_x86-win-ucrt-libressl/usr/lib/libssh.a(connect.c.obj):(.text$ssh_connect_host_nonblocking+0x3d9): undefined reference to `gai_strerrorA'
/usr/bin/i686-w64-mingw32-ld: curl/libssh/_x86-win-ucrt-libressl/usr/lib/libssh.a(kex.c.obj):(.text$ssh_client_select_hostkeys+0xd2): undefined reference to `FIPS_mode'
/usr/bin/i686-w64-mingw32-ld: curl/libssh/_x86-win-ucrt-libressl/usr/lib/libssh.a(options.c.obj):(.text$ssh_options_set+0x942): undefined reference to `FIPS_mode'
```
Ref: https://github.com/curl/curl/actions/runs/13163986294/job/36739557888?pr=16182#step:3:5127
Ref: https://github.com/curl/curl/actions/runs/13163986294/job/36739557888?pr=16182#step:3:5121

Closes #16182

.github/workflows/curl-for-win.yml
CMakeLists.txt

index ab4515fc9996f90b7bc188bd8c2e30b2311a696c..07207e24669bce40febdfaffd42ed85938be43af 100644 (file)
@@ -42,7 +42,7 @@ env:
   CW_NOPKG: '1'
 
 jobs:
-  linux-glibc-llvm:
+  linux-glibc-gcc:
     runs-on: ubuntu-latest
     timeout-minutes: 30
     steps:
@@ -55,7 +55,7 @@ jobs:
         run: |
           git clone --depth 1 https://github.com/curl/curl-for-win
           mv curl-for-win/* .
-          export CW_CONFIG='-main-werror-linux-a64-x64'
+          export CW_CONFIG='-main-werror-linux-a64-x64-gcc-nolibgroup'
           export CW_REVISION='${{ github.sha }}'
           DOCKER_IMAGE='debian:bookworm-slim'
           export DOCKER_CONTENT_TRUST=1
@@ -137,3 +137,27 @@ jobs:
               '^(CW_|GITHUB_)') \
             "${DOCKER_IMAGE}" \
             sh -c ./_ci-linux-debian.sh
+
+  win-gcc-libssh-zlibng-x86:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+        with:
+          persist-credentials: false
+          path: 'curl'
+          fetch-depth: 8
+      - name: 'build'
+        run: |
+          git clone --depth 1 https://github.com/curl/curl-for-win
+          mv curl-for-win/* .
+          export CW_CONFIG='-main-werror-win-x86-gcc-nolibgroup-libssh1-zlibng'
+          export CW_REVISION='${{ github.sha }}'
+          . ./_versions.sh
+          docker trust inspect --pretty "${DOCKER_IMAGE}"
+          time docker pull "${DOCKER_IMAGE}"
+          docker images --digests
+          time docker run --volume "$(pwd):$(pwd)" --workdir "$(pwd)" \
+            --env-file <(env | grep -a -E \
+              '^(CW_|GITHUB_)') \
+            "${DOCKER_IMAGE}" \
+            sh -c ./_ci-linux-debian.sh
index ce1318c6dde6ecc327b396c374d4dcbeaf7ee1d4..3bf2d4381c1b083b9541b436ac36406989cf9787 100644 (file)
@@ -623,10 +623,6 @@ elseif(NOT WIN32 AND NOT APPLE)
   endif()
 endif()
 
-if(WIN32)
-  list(APPEND CURL_LIBS "ws2_32" "bcrypt")
-endif()
-
 # Check SSL libraries
 option(CURL_ENABLE_SSL "Enable SSL support" ON)
 
@@ -1308,9 +1304,9 @@ set(USE_LIBSSH2 OFF)
 if(CURL_USE_LIBSSH2)
   find_package(Libssh2)
   if(LIBSSH2_FOUND)
-    list(APPEND CURL_LIBS ${LIBSSH2_LIBRARIES})
+    set(CURL_LIBS ${LIBSSH2_LIBRARIES} ${CURL_LIBS})  # keep it before TLS-crypto, compression
     list(APPEND CURL_LIBDIRS ${LIBSSH2_LIBRARY_DIRS})
-    list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${LIBSSH2_PC_REQUIRES})
+    set(LIBCURL_PC_REQUIRES_PRIVATE ${LIBSSH2_PC_REQUIRES} ${LIBCURL_PC_REQUIRES_PRIVATE})
     include_directories(SYSTEM ${LIBSSH2_INCLUDE_DIRS})
     link_directories(${LIBSSH2_LIBRARY_DIRS})
     if(LIBSSH2_CFLAGS)
@@ -1325,9 +1321,9 @@ option(CURL_USE_LIBSSH "Use libssh" OFF)
 mark_as_advanced(CURL_USE_LIBSSH)
 if(NOT USE_LIBSSH2 AND CURL_USE_LIBSSH)
   find_package(Libssh REQUIRED)
-  list(APPEND CURL_LIBS ${LIBSSH_LIBRARIES})
+  set(CURL_LIBS ${LIBSSH_LIBRARIES} ${CURL_LIBS})  # keep it before TLS-crypto, compression
   list(APPEND CURL_LIBDIRS ${LIBSSH_LIBRARY_DIRS})
-  list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${LIBSSH_PC_REQUIRES})
+  set(LIBCURL_PC_REQUIRES_PRIVATE ${LIBSSH_PC_REQUIRES} ${LIBCURL_PC_REQUIRES_PRIVATE})
   include_directories(SYSTEM ${LIBSSH_INCLUDE_DIRS})
   link_directories(${LIBSSH_LIBRARY_DIRS})
   if(LIBSSH_CFLAGS)
@@ -1344,7 +1340,7 @@ if(NOT USE_LIBSSH2 AND NOT USE_LIBSSH AND CURL_USE_WOLFSSH)
   if(USE_WOLFSSL)
     find_package(WolfSSH)
     if(WOLFSSH_FOUND)
-      list(APPEND CURL_LIBS ${WOLFSSH_LIBRARIES})
+      set(CURL_LIBS ${WOLFSSH_LIBRARIES} ${CURL_LIBS})  # keep it before TLS-crypto, compression
       include_directories(SYSTEM ${WOLFSSH_INCLUDE_DIRS})
       set(USE_WOLFSSH ON)
     endif()
@@ -1930,6 +1926,8 @@ include(CMake/OtherTests.cmake)
 add_definitions("-DHAVE_CONFIG_H")
 
 if(WIN32)
+  list(APPEND CURL_LIBS "ws2_32" "bcrypt")
+
   # _fseeki64() requires VS2005
   if(NOT MSVC OR (MSVC_VERSION GREATER_EQUAL 1400))
     set(USE_WIN32_LARGE_FILES ON)