From 646b1fc8baeaae0027dd5fcc531b881d8d29d8a2 Mon Sep 17 00:00:00 2001 From: berrux_dev Date: Fri, 13 Nov 2026 18:27:40 +0100 Subject: [PATCH] DEB: build the Release 2 scope instead of the impossible full tree A full-tree build (ninja all) is not possible on the Release 2 tree: out-of-scope modules reference modules excluded from the scope (e.g. TopicEditorBase -> LtsScriptTimeline; 100+ CMakeLists references), and cmake --install hard-fails on targets that were never built. Align the DEB pipeline with its own description (binaries and libraries from release scope S): - make_rpm_ubuntu26_release2.py: new --build_targets option (space-separated CMake/Ninja targets; empty = legacy full tree). Step 1 builds only those targets; the runtime DEB is staged from the scoped build artifacts (bin/ + lib/) and packaged with build_deb nobuild, replacing the full-tree debuild/cmake-buildsystem path. - new_docker_build_release2.sh: pass the Release 2 group targets via --build_targets; exclude the driver build4* dirs from the staging tar (the DEB step builds its own tree; nothing consumes the driver build output). Fix two comments inside the single-quoted docker bash -c string that contained apostrophes, which broke word construction and failed bash -n. Co-Authored-By: Claude Code --- .../new_docker_build_release2.sh | 12 +++- .../rpmbuild/make_rpm_ubuntu26_release2.py | 65 ++++++++++++++----- 2 files changed, 58 insertions(+), 19 deletions(-) diff --git a/qt6-after/qt6-migrated-legatus/new_docker_build_release2.sh b/qt6-after/qt6-migrated-legatus/new_docker_build_release2.sh index 5680c1eed..68fdc7867 100755 --- a/qt6-after/qt6-migrated-legatus/new_docker_build_release2.sh +++ b/qt6-after/qt6-migrated-legatus/new_docker_build_release2.sh @@ -586,9 +586,16 @@ if [[ "${RUN_JENKINS_BUILDER}" == "ON" ]]; then log_info "Staging workspace to ${STAGE_DIR}" rm -rf "${STAGE_DIR}" mkdir -p "${STAGE_DIR}" + # Exclude build4* (the driver build dirs, e.g. build4_): the DEB + # pipeline builds its own tree in /build; nothing in the DEB step + # consumes the driver build output (the ctest DEB looks for a plain build4 + # dir, which the driver never creates; it uses build4_ instead). + # NOTE: no apostrophes allowed in comments here - this block lives inside + # the single-quoted docker bash -c string (see lines 477/653). tar --exclude='./rpms' --exclude='./.git' --exclude='./build' \ --exclude='./deb_build_tmp' --exclude='./deb_stage' --exclude='./packages-out' \ --exclude='./legatus-qt6_1.0.tar.gz' \ + --exclude=./build4\* \ -cf - -C "${WORKSPACE_DIR}" . | tar -xf - -C "${STAGE_DIR}" if [[ ! -f "${STAGED_SOURCE_DIR}/CMakeLists.txt" || ! -f "${STAGED_SOURCE_DIR}/rpmbuild/make_rpm_ubuntu26_release2.py" ]]; then @@ -607,8 +614,8 @@ if [[ "${RUN_JENKINS_BUILDER}" == "ON" ]]; then # DEB cmake flags: -DBUILD_RTI=ON is required - the full-tree DEB build # compiles RTI codegen consumers (e.g. svcPdmCommon -> pdm_enums.hpp) # whose BUILD_RTI=OFF stubs were removed as "forbidden OFF variants". - # (A '#' line inside a backslash-continued command breaks the continuation - # and drops the remaining arguments - keep comments outside it.) + # (A lone hash line inside a backslash-continued command breaks the + # continuation and drops the remaining arguments - keep comments outside it.) cd "${STAGED_SOURCE_DIR}/rpmbuild" if python3 make_rpm_ubuntu26_release2.py -c LTS \ --project_name "${PROJECT}" \ @@ -616,6 +623,7 @@ if [[ "${RUN_JENKINS_BUILDER}" == "ON" ]]; then --output_dir "${DOCKER_MOUNT_ROOT}/rpms/${PROJECT}/${OS_VERSION}/" \ --source_dir "${STAGED_SOURCE_DIR}" \ --cmake_build_flags "-DUSE_IPO=ON -DUSE_UNITY_BUILD=ON -DGUEZ_MODE=${GUEZ_MODE} -DBUILD_WLS=ON -DPostgreSQL_TYPE_INCLUDE_DIR=/usr/include/postgresql/ -DBUILD_RTI=ON -DRELEASE_BUILD=ON" \ + --build_targets "${GROUP1_TARGETS[*]} ${GROUP3_TARGETS[*]} ${GROUP5_TARGETS[*]} ${GROUP6_TARGETS[*]}" \ --build_number "${BUILD_NUMBER}" \ --release_scope; then log_info "Package build completed successfully" diff --git a/qt6-after/qt6-migrated-legatus/rpmbuild/make_rpm_ubuntu26_release2.py b/qt6-after/qt6-migrated-legatus/rpmbuild/make_rpm_ubuntu26_release2.py index 1b00ccb1a..3e7154186 100644 --- a/qt6-after/qt6-migrated-legatus/rpmbuild/make_rpm_ubuntu26_release2.py +++ b/qt6-after/qt6-migrated-legatus/rpmbuild/make_rpm_ubuntu26_release2.py @@ -408,8 +408,14 @@ def build_nobuild_package(name, source_dir, build_base, output_dir, version, bui validate_package_contents(name, manifest, allowed_patterns, forbidden_patterns) -def build_all_debs(source_dir, output_dir, version, build_number, cmake_flags): - """Build the 5 DEB packages: build once from the source tree, then package.""" +def build_all_debs(source_dir, output_dir, version, build_number, cmake_flags, + build_targets=""): + """Build the 5 DEB packages: build once from the source tree, then package. + + build_targets: space-separated CMake/Ninja target list (the Release 2 + scope). When non-empty, only these targets are built; when empty, the + legacy full-tree build is used. + """ info("========================================") info("Building 5 DEB packages for Qt6 Release") info("========================================") @@ -420,8 +426,16 @@ def build_all_debs(source_dir, output_dir, version, build_number, cmake_flags): os.makedirs(build_base) release_dirs = ["TetraIF", "Z/src", "Lts/Common"] - # Step 1: build once from the full source tree - info("\n=== Step 1: Building from full source tree ===") + # Step 1: build the release scope from the source tree. + # A full-tree build (ninja all) is NOT possible on the Release 2 tree: + # out-of-scope modules reference modules excluded from the scope + # (e.g. TopicEditorBase -> LtsScriptTimeline, 100+ CMakeLists files), so + # their link rules fail. The release scope is built instead. + info("\n=== Step 1: Building release scope ===") + if build_targets: + info(f"Targets: {build_targets}") + else: + warning("No target list given - building the full tree (legacy behavior)") build_dir = os.path.join(source_dir, "build") os.makedirs(build_dir, exist_ok=True) os.chdir(build_dir) @@ -432,27 +446,40 @@ def build_all_debs(source_dir, output_dir, version, build_number, cmake_flags): # breaks every Qt target. Ninja handles automoc correctly. run(f"cmake -G Ninja -DCMAKE_BUILD_TYPE=Release {cmake_flags} ..", "CMake configuration failed") info("Running build...") - run(f"ninja -j$(nproc)", "Build failed") + run(f"ninja -j$(nproc) {build_targets}".rstrip(), "Build failed") info("Build completed successfully") - # Package 1: qt6-release-runtime (binaries and libraries, built via debuild) + # Package 1: qt6-release-runtime (binaries and libraries from release scope S) + # + # The artifacts are taken from the step-1 scoped build above. A debuild + # with the cmake buildsystem is not an option here: dh_auto_install runs + # 'cmake --install', which fails hard on every target that has an install + # rule but was not built (file INSTALL cannot find), and a full build is + # not possible on the Release 2 tree (see step 1). info("\n=== Building qt6-release-runtime ===") pkg1_dir = os.path.join(build_base, f"qt6-release-runtime-{version}") os.makedirs(pkg1_dir) - # FULL source tree (needed for debian/rules cmake reference) - copy_src_dir_to_dest_dir(source_dir, pkg1_dir) - # Install from all component install paths: ALL -> bin/, lib/ ; SV/ ; WS/ + staged = 0 + for src_root, dst_root in ((os.path.join(build_dir, "bin"), "usr/bin"), + (os.path.join(build_dir, "lib"), "usr/lib")): + if not os.path.isdir(src_root): + continue + for entry in sorted(os.listdir(src_root)): + src_path = os.path.join(src_root, entry) + if not os.path.isfile(src_path): + continue + dst_dir = os.path.join(pkg1_dir, dst_root) + os.makedirs(dst_dir, exist_ok=True) + shutil.copy2(src_path, os.path.join(dst_dir, entry)) + staged += 1 + info(f"Staged {staged} artifacts from {build_dir}") install_lines_1 = [ "usr/bin/* usr/bin/", - "usr/lib/*.so* usr/lib/", - "usr/SV/bin/* usr/bin/", - "usr/SV/lib/*.so* usr/lib/", - "usr/WS/bin/* usr/bin/", - "usr/WS/lib/*.so* usr/lib/", + "usr/lib/* usr/lib/", ] build_deb(pkg_name="qt6-release-runtime", pkg_dir=pkg1_dir, output_dir=output_dir, - version=version, build_number=build_number, cmake_flags=cmake_flags, - skip_tests=True, install_lines=install_lines_1, + version=version, build_number=build_number, nobuild=True, + skip_shlibdeps=True, install_lines=install_lines_1, description="Qt6 Release Runtime - binaries and libraries from release scope S", section="libs") manifest_1 = create_manifest(output_dir, "qt6-release-runtime", pkg1_dir) @@ -517,6 +544,9 @@ def main(): parser.add_argument("--cmake_build_flags", default="", help="CMake build flags") parser.add_argument("--build_number", default="1", help="Build number") parser.add_argument("--release_scope", action="store_true", help="Only include release scope files") + parser.add_argument("--build_targets", default="", + help="Space-separated CMake/Ninja targets to build " + "(release scope); empty = full tree (legacy)") args = parser.parse_args() info(f"Building {args.config} package for {args.project_name} v{args.version}") @@ -526,7 +556,8 @@ def main(): info(f"Release scope: {args.release_scope}") build_all_debs(source_dir=args.source_dir, output_dir=args.output_dir, version=args.version, build_number=args.build_number, - cmake_flags=args.cmake_build_flags) + cmake_flags=args.cmake_build_flags, + build_targets=args.build_targets) if __name__ == "__main__":