@@ -72,7 +72,7 @@ vcpkg_consumer() { |
72 | 72 |
|
73 | 73 | if is_windows; then |
74 | 74 | # The pack collects it from the runtime search directory. |
75 | | - ls target/vcpkg_installed/x64-windows/bin/fmt.dll > /dev/null || fail "x64-windows built no fmt.dll" |
| 75 | + ls target/vcpkg_installed/x64-windows/x64-windows/bin/fmt.dll > /dev/null || fail "x64-windows built no fmt.dll" |
76 | 76 | run_directly vcpkg-consumer | tee target/ci/direct.log |
77 | 77 | grep -qE '^vcpkg-consumer: fmt [0-9]+ says 42$' target/ci/direct.log || |
78 | 78 | fail "started from the build directory, the program did not find fmt.dll" |
@@ -83,6 +83,51 @@ vcpkg_consumer() { |
83 | 83 | fi |
84 | 84 | } |
85 | 85 |
|
| 86 | +# LINUX UNDER A libc++ TOOLCHAIN. The host compiler vcpkg and CMake find uses |
| 87 | +# libstdc++, whose `std::` symbols a libc++ program cannot link. The default |
| 88 | +# triplet is then the generated `x64-linux-libcxx`, whose ports build with |
| 89 | +# mcpp's clang; fmt's interface returns `std::string`, so the link itself is the |
| 90 | +# criterion. The prefix is then shown to survive the default toolchain's own |
| 91 | +# installation, which vcpkg would remove if the two triplets shared one. |
| 92 | +vcpkg_libcxx() { |
| 93 | + local llvm="${MCPP_LLVM:-llvm@22.1.8}" gen=x64-linux-libcxx |
| 94 | + [ "$(uname -m)" = aarch64 ] && gen=arm64-linux-libcxx |
| 95 | + cd "$ROOT/tests/vcpkg-consumer" |
| 96 | + rm -rf target vcpkg_installed |
| 97 | + mkdir -p target/ci |
| 98 | + "$MCPP" build --toolchain "$llvm" 2>&1 | tee target/ci/libcxx-build.log |
| 99 | + "$MCPP" run --toolchain "$llvm" | tee target/ci/libcxx-run.log |
| 100 | + grep -qE '^vcpkg-consumer: fmt [0-9]+ says 42$' target/ci/libcxx-run.log || fail "the libc++ program did not print through fmt" |
| 101 | + local lib; lib=$(find target/vcpkg_installed -path "*/$gen/$gen/lib/libfmt.a" | head -1) |
| 102 | + [ -n "$lib" ] || fail "no $gen prefix with libfmt.a" |
| 103 | + grep -q 'std::__1::' <(nm -C "$lib") || fail "$lib is not built against libc++" |
| 104 | + echo "ok: under $llvm the ports build with mcpp's clang and the program links them" |
| 105 | + |
| 106 | + "$MCPP" build 2>&1 | tee target/ci/default-build.log |
| 107 | + "$MCPP" run | tee target/ci/default-run.log |
| 108 | + grep -qE '^vcpkg-consumer: fmt [0-9]+ says 42$' target/ci/default-run.log || fail "the default toolchain's program did not print through fmt" |
| 109 | + [ -f "$lib" ] || fail "the default toolchain's installation removed the $gen prefix" |
| 110 | + local stamp; stamp=$(find target -path '*deps-vcpkg*' -name "$gen.stamp" | head -1) |
| 111 | + [ -n "$stamp" ] || fail "no $gen installation stamp" |
| 112 | + touch -r "$stamp" target/ci/before-switch-back |
| 113 | + sleep 1 |
| 114 | + "$MCPP" build --toolchain "$llvm" --profile dev > target/ci/switch-back.log 2>&1 || |
| 115 | + { cat target/ci/switch-back.log; fail "the build switched back to $llvm failed"; } |
| 116 | + [ -z "$(find "$stamp" -newer target/ci/before-switch-back)" ] || |
| 117 | + fail "switching back to $llvm re-ran its installation" |
| 118 | + echo "ok: the two toolchains' prefixes coexist, and switching back installs nothing" |
| 119 | + |
| 120 | + # deps-cmake takes the same compilers. |
| 121 | + cd "$ROOT/tests/cmake-consumer" |
| 122 | + rm -rf target |
| 123 | + mkdir -p target/ci |
| 124 | + "$MCPP" build --toolchain "$llvm" 2>&1 | tee target/ci/libcxx-build.log |
| 125 | + "$MCPP" run --toolchain "$llvm" | grep -q '^cmake-consumer: greet says 42$' || fail "the libc++ cmake-consumer did not run" |
| 126 | + grep -rqs 'CMAKE_CXX_COMPILER:[A-Z]*=.*xim-x-llvm.*/clang++' target --include=CMakeCache.txt || |
| 127 | + fail "deps-cmake configured the subproject without mcpp's clang" |
| 128 | + echo "ok: deps-cmake configures the subproject with mcpp's clang under $llvm" |
| 129 | +} |
| 130 | + |
86 | 131 | vcpkg_workspace() { |
87 | 132 | cd "$ROOT/tests/vcpkg-workspace" |
88 | 133 | rm -rf target app-a/target app-b/target vcpkg_installed |
@@ -106,10 +151,7 @@ cmake_consumer() { |
106 | 151 | "$MCPP" run | tee target/ci/run.log |
107 | 152 | grep -q '^cmake-consumer: greet says 42$' target/ci/run.log || fail "the program did not call the subproject's library" |
108 | 153 | assert_not_rerun "$(stamp_of deps-cmake)" |
109 | | - # The builds after an edit are planned as well. The subproject lies inside |
110 | | - # this repository, the tree mcpp stamps for the plugins' host tool |
111 | | - # (mcpp#705), so an edit also rebuilds `mcpp-deps`; the build that is |
112 | | - # expected to re-run the installation absorbs that rebuild. |
| 154 | + # The builds after an edit are planned as well. |
113 | 155 | touch greet/greet.c |
114 | 156 | "$MCPP" build --profile dev > target/ci/third-build.log 2>&1 || { cat target/ci/third-build.log; fail "the rebuild failed"; } |
115 | 157 | # The installed library is the product of the rebuild, whatever the engine |
@@ -234,15 +276,60 @@ qt_widgets_consumer() { |
234 | 276 | find target/dist -ipath '*platforms/qoffscreen.dll' | grep -q . || |
235 | 277 | fail "the packed tree carries no platforms/qoffscreen.dll" |
236 | 278 | echo "ok: the packed tree carries the Qt modules and the platform plugins" |
| 279 | + # The VC++ runtime Qt's DLLs import travels with them, so the program |
| 280 | + # does not depend on the target machine's VC++ Redistributable. |
| 281 | + for dll in msvcp140.dll vcruntime140.dll vcruntime140_1.dll; do |
| 282 | + find target -path '*/bin/*' -iname "$dll" | grep -q . || fail "$dll was not placed beside the program" |
| 283 | + find target/dist -iname "$dll" | grep -q . || fail "the packed tree carries no $dll" |
| 284 | + done |
| 285 | + echo "ok: the VC++ runtime is beside the program and in the packed tree" |
| 286 | + fi |
| 287 | + if ! is_windows && ! is_macos; then |
| 288 | + # QtGui's runtime closure comes from the payload: the program runs |
| 289 | + # under the ecosystem's loader, which reads no host library directory. |
| 290 | + "$MCPP" pack --format dir | tee target/ci/pack.log |
| 291 | + for so in libQt6Widgets.so.6 libdbus-1.so.3 libxkbcommon.so.0 libfontconfig.so.1; do |
| 292 | + find target/dist -name "$so*" | grep -q . || fail "the packed tree carries no $so" |
| 293 | + done |
| 294 | + echo "ok: the packed tree carries Qt and QtGui's runtime closure" |
237 | 295 | fi |
238 | 296 | } |
239 | 297 |
|
| 298 | +# The SDK at each level `rules-qt` consults, read back from the fact the rule |
| 299 | +# records (`rules-qt.sdk=<level>: <root>`, in the build program's cache). |
| 300 | +qt_sdk_consumer() { |
| 301 | + cd "$ROOT/tests/qt-sdk-consumer" |
| 302 | + rm -rf target |
| 303 | + mkdir -p target/ci |
| 304 | + sdk_fact() { grep -h -o 'rules-qt\.sdk=[^"]*' target/.build-mcpp/build.mcpp.cache | tail -1; } |
| 305 | + "$MCPP" build 2>&1 | tee target/ci/build.log |
| 306 | + "$MCPP" run | tee target/ci/run.log |
| 307 | + grep -qE '^qt-sdk-consumer: Qt 6\.' target/ci/run.log || fail "the program did not load QtCore" |
| 308 | + local fact root; fact=$(sdk_fact) |
| 309 | + case "$fact" in "rules-qt.sdk=xlings: "*) ;; *) fail "the project's payload was not the SDK: $fact" ;; esac |
| 310 | + root=${fact#rules-qt.sdk=xlings: } |
| 311 | + echo "ok: the SDK is the payload the project declares ($root)" |
| 312 | + |
| 313 | + # The payload's root, named for one machine, then by the build program. |
| 314 | + QT_ROOT_DIR="$root" "$MCPP" build > target/ci/env-build.log 2>&1 || { cat target/ci/env-build.log; fail "the build under QT_ROOT_DIR failed"; } |
| 315 | + fact=$(sdk_fact) |
| 316 | + [ "$fact" = "rules-qt.sdk=QT_ROOT_DIR: $root" ] || fail "QT_ROOT_DIR was not the SDK: $fact" |
| 317 | + echo "ok: QT_ROOT_DIR names the SDK, and a change re-plans the build" |
| 318 | + QT_SDK_CONSUMER_ROOT="$root" QT_ROOT_DIR=/nonexistent "$MCPP" build > target/ci/options-build.log 2>&1 || |
| 319 | + { cat target/ci/options-build.log; fail "the build under options::root failed"; } |
| 320 | + fact=$(sdk_fact) |
| 321 | + [ "$fact" = "rules-qt.sdk=options: $root" ] || fail "options::root was not the SDK: $fact" |
| 322 | + echo "ok: options::root names the SDK ahead of QT_ROOT_DIR" |
| 323 | +} |
| 324 | + |
240 | 325 | case "${1:-}" in |
241 | 326 | vcpkg-consumer) vcpkg_consumer ;; |
| 327 | + vcpkg-libcxx) vcpkg_libcxx ;; |
242 | 328 | archive-consumer) archive_consumer ;; |
243 | 329 | vcpkg-workspace) vcpkg_workspace ;; |
244 | 330 | cmake-consumer) cmake_consumer ;; |
245 | 331 | qt-consumer) qt_consumer ;; |
246 | 332 | qt-widgets-consumer) qt_widgets_consumer ;; |
247 | | - *) echo "usage: $0 vcpkg-consumer|archive-consumer|vcpkg-workspace|cmake-consumer|qt-consumer|qt-widgets-consumer"; exit 2 ;; |
| 333 | + qt-sdk-consumer) qt_sdk_consumer ;; |
| 334 | + *) echo "usage: $0 vcpkg-consumer|vcpkg-libcxx|archive-consumer|vcpkg-workspace|cmake-consumer|qt-consumer|qt-widgets-consumer|qt-sdk-consumer"; exit 2 ;; |
248 | 335 | esac |