From: Viktor Szakats Date: Wed, 6 Aug 2025 20:17:50 +0000 (+0200) Subject: cmake: optimize building examples in CI X-Git-Tag: curl-8_16_0~207 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fe5225b5eaf3a1a0ce149023d38a9922a114798b;p=thirdparty%2Fcurl.git cmake: optimize building examples in CI In CI we want to ensure that examples build cleanly, but we don't want to actually run them there. Meaning it's enough to just compile, but not link them in CI. Saving time up to 2-4x (MSVC), and disk space up to 1.2GB (or 8-70x). Add a new cmake target that compiles all examples without linking them into runnable binaries. Keep a full build for a single example to test if it links correctly. Also: - CI: switch over all `curl-examples` targets to `curl-examples-build` - GHA/linux-old: build examples in one of the cmake builds. Result highlights: Job | Bef. | Bef. | Aft. | Aft. | :------------------ | ---: | ----: | ---: |----: | cygwin | 15s | 9MB | 10s | 1MB | msys | 13s | 8MB | 7s | 1MB | dl-mingw 15 | 39s | 113M | 34s | 2MB | dl-mingw 9.5.0 | 49s | 115MB | 42s | 2MB | dl-mingw 7.3.0 | 19s | 113MB | 14s | 2MB | dl-mingw 6.4.0 | 9s | 12MB | 7s | 4MB | Linux cross | 19s | 28MB | 19s | 2MB | MSVC UWP | 65s | 374MB | 9s | 17MB | MSVC x64 | 22s | 846MB | 9s | 17MB | VS2010 | 48s | 105MB | 15s | 9MB | VS2022 clang-cl | 195s | 1.2GB | 51s | 20MB | iOS Xcode | 8s | | 5s | | macOS LibreSSL | 16s | | 11s | | Linux aws-lc | 3s | | 1s | | Follow-up to dda251ef1020da07dc4640a225e01051cb977535 #18232 Closes #18209 --- diff --git a/.github/workflows/http3-linux.yml b/.github/workflows/http3-linux.yml index 3dab2b56cf..3fec315199 100644 --- a/.github/workflows/http3-linux.yml +++ b/.github/workflows/http3-linux.yml @@ -546,7 +546,7 @@ jobs: - name: 'build examples' run: | if [ "${MATRIX_BUILD}" = 'cmake' ]; then - cmake --build bld --verbose --target curl-examples + cmake --build bld --verbose --target curl-examples-build else make -C bld V=1 examples fi diff --git a/.github/workflows/linux-old.yml b/.github/workflows/linux-old.yml index 5b8f92f03b..736a3cc100 100644 --- a/.github/workflows/linux-old.yml +++ b/.github/workflows/linux-old.yml @@ -123,6 +123,9 @@ jobs: - name: 'cmake run tests' run: make -C bld-cares test-ci + - name: 'cmake build examples' + run: make -C bld-cares curl-examples-build + - name: 'autoreconf' run: autoreconf -if diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index b293a140f7..7c64a23558 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -698,7 +698,7 @@ jobs: if: ${{ matrix.build.make-custom-target != 'tidy' }} run: | if [ "${MATRIX_BUILD}" = 'cmake' ]; then - ${MATRIX_MAKE_PREFIX} cmake --build bld --verbose --target curl-examples + ${MATRIX_MAKE_PREFIX} cmake --build bld --verbose --target curl-examples-build else ${MATRIX_MAKE_PREFIX} make -C bld V=1 examples fi diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 04c30a75c0..90d04fab17 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -199,7 +199,7 @@ jobs: - name: 'build examples' run: | if [ "${MATRIX_BUILD}" = 'cmake' ]; then - cmake --build bld ${MATRIX_OPTIONS} --parallel 4 --target curl-examples --verbose + cmake --build bld ${MATRIX_OPTIONS} --parallel 4 --target curl-examples-build --verbose else make -C bld examples V=1 fi @@ -520,7 +520,7 @@ jobs: if: ${{ contains(matrix.build.name, '+examples') }} run: | if [ "${MATRIX_BUILD}" = 'cmake' ]; then - cmake --build bld --verbose --target curl-examples + cmake --build bld --verbose --target curl-examples-build else make -C bld examples V=1 fi diff --git a/.github/workflows/non-native.yml b/.github/workflows/non-native.yml index 9a92804219..e8a105e39c 100644 --- a/.github/workflows/non-native.yml +++ b/.github/workflows/non-native.yml @@ -83,7 +83,7 @@ jobs: time cmake --build bld --target test-ci fi echo '::group::build examples' - time cmake --build bld --target curl-examples + time cmake --build bld --target curl-examples-build echo '::endgroup::' openbsd: @@ -128,7 +128,7 @@ jobs: time cmake --build bld --target test-ci fi echo '::group::build examples' - time cmake --build bld --target curl-examples + time cmake --build bld --target curl-examples-build echo '::endgroup::' freebsd: @@ -232,7 +232,7 @@ jobs: if [ "${MATRIX_DESC#*!examples*}" = "${MATRIX_DESC}" ]; then echo '::group::build examples' if [ "${MATRIX_BUILD}" = 'cmake' ]; then - time cmake --build bld --target curl-examples + time cmake --build bld --target curl-examples-build else time make -C bld examples fi @@ -361,7 +361,7 @@ jobs: - name: 'build examples' run: | if [ "${MATRIX_BUILD}" = 'cmake' ]; then - cmake --build bld --target curl-examples + cmake --build bld --target curl-examples-build else make -C bld examples fi @@ -473,7 +473,7 @@ jobs: if: ${{ matrix.build == 'cmake' }} # skip for autotools to save time run: | if [ "${MATRIX_BUILD}" = 'cmake' ]; then - cmake --build bld --target curl-examples + cmake --build bld --target curl-examples-build else make -C bld examples fi diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index d0e1157f7b..5d9aac713b 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -177,7 +177,7 @@ jobs: run: | PATH=/usr/bin if [ "${MATRIX_BUILD}" = 'cmake' ]; then - cmake --build bld --verbose --target curl-examples + cmake --build bld --verbose --target curl-examples-build else make -C bld V=1 examples fi @@ -404,7 +404,7 @@ jobs: timeout-minutes: 5 run: | if [ "${MATRIX_BUILD}" = 'cmake' ]; then - cmake --build bld --verbose --target curl-examples + cmake --build bld --verbose --target curl-examples-build else make -C bld V=1 examples fi @@ -589,7 +589,7 @@ jobs: timeout-minutes: 5 run: | PATH="/d/my-cache/${MATRIX_DIR}/bin:$PATH" - cmake --build bld --target curl-examples + cmake --build bld --target curl-examples-build - name: 'disk space used' run: du -sh .; echo; du -sh -t 250KB ./*; echo; du -h -t 250KB bld @@ -687,7 +687,7 @@ jobs: if: ${{ matrix.compiler != 'clang-tidy' }} # Save time by skipping this for clang-tidy run: | if [ "${MATRIX_BUILD}" = 'cmake' ]; then - cmake --build bld --target curl-examples + cmake --build bld --target curl-examples-build else make -C bld examples fi @@ -935,7 +935,7 @@ jobs: - name: 'build examples' timeout-minutes: 5 if: ${{ contains(matrix.name, '+examples') }} - run: cmake --build bld --config "${MATRIX_TYPE}" --parallel 5 --target curl-examples + run: cmake --build bld --config "${MATRIX_TYPE}" --parallel 5 --target curl-examples-build - name: 'disk space used' run: du -sh .; echo; du -sh -t 250KB ./*; echo; du -h -t 250KB bld diff --git a/appveyor.sh b/appveyor.sh index 225d577f8c..e9871415e0 100644 --- a/appveyor.sh +++ b/appveyor.sh @@ -163,7 +163,7 @@ fi if [ "${EXAMPLES}" = 'ON' ] && \ [ "${BUILD_SYSTEM}" = 'CMake' ]; then - time cmake --build _bld --config "${PRJ_CFG}" --parallel 2 --target curl-examples + time cmake --build _bld --config "${PRJ_CFG}" --parallel 2 --target curl-examples-build fi # disk space used diff --git a/docs/examples/CMakeLists.txt b/docs/examples/CMakeLists.txt index f69445fbfe..cb1d983890 100644 --- a/docs/examples/CMakeLists.txt +++ b/docs/examples/CMakeLists.txt @@ -28,10 +28,40 @@ add_custom_target(curl-examples) curl_transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake") include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake") -foreach(_target IN LISTS check_PROGRAMS) +set(_all_canary "") +set(_all "all") +foreach(_target IN LISTS check_PROGRAMS _all) # keep '_all' last set(_target_name "curl-example-${_target}") - add_executable(${_target_name} EXCLUDE_FROM_ALL "${_target}.c") - add_dependencies(curl-examples ${_target_name}) + if(_target STREQUAL "all") + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12) + set(_examples_c "${check_PROGRAMS}") + list(TRANSFORM _examples_c APPEND ".c") + add_library(${_target_name} OBJECT EXCLUDE_FROM_ALL ${_examples_c}) + if(MSVC AND NOT CMAKE_C_COMPILER_ID STREQUAL "Clang") + # CMake generates a static library for the OBJECT target. Silence these 'lib.exe' warnings: + # warning LNK4006: main already defined in ....obj; second definition ignored + # warning LNK4221: This object file does not define any previously undefined public symbols, + # so it will not be used by any link operation that consumes this library + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.13) + set_target_properties(${_target_name} PROPERTIES STATIC_LIBRARY_OPTIONS "-ignore:4006;-ignore:4221") + else() + set_target_properties(${_target_name} PROPERTIES STATIC_LIBRARY_FLAGS "-ignore:4006 -ignore:4221") + endif() + endif() + else() + set(_examples_c "") + foreach(_src IN LISTS check_PROGRAMS) + list(APPEND _examples_c "${_src}.c") + endforeach() + add_library(${_target_name} STATIC EXCLUDE_FROM_ALL ${_examples_c}) + endif() + add_custom_target(curl-examples-build) # Special target to compile all tests quickly and build a single test to probe linkage + add_dependencies(curl-examples-build ${_target_name} ${_all_canary}) # Include a full build of a single test + else() + set(_all_canary ${_target_name}) # Save the last test for the curl-examples-build target + add_executable(${_target_name} EXCLUDE_FROM_ALL "${_target}.c") + add_dependencies(curl-examples ${_target_name}) + endif() target_link_libraries(${_target_name} ${LIB_SELECTED} ${CURL_NETWORK_AND_TIME_LIBS}) target_compile_definitions(${_target_name} PRIVATE "CURL_NO_OLDIES" "$<$:WIN32_LEAN_AND_MEAN>" "$<$:_CRT_SECURE_NO_DEPRECATE>")