Adds pycache

This commit is contained in:
torsten committed 2026-11-11 09:48:29 +00:00
1 parent f6f395d05c
commit 8959e80498
2 files changed
+819

No files matched your search

+1
View File
@@ -1,2 +1,3 @@
.svn/ .svn/
packages-out/ packages-out/
__pycache__
+818
View File
@@ -0,0 +1,818 @@
#!/usr/bin/env python3
"""
Build DEB packages for Qt6 Release 2
This script creates 5 DEB packages from the Release 2 scope:
- qt6-release-runtime: Binaries and libraries
- qt6-release-sources: C++ source files
- qt6-release-ctest-runtime: Test executables
- qt6-release-ctest-sources: Test source files
- qt6-release-build-pipeline: Build scripts and configuration
Release 2 scope (S set - 39 modules):
- Lts/Common (15 modules)
- Lts/DDS (10 modules)
- Lts/Services (6 modules in 3 directories)
- Lts/Proxies/TrainingAreaBase (1 module)
- Lts/Tools (7 AP9 tools)
"""
import os
import sys
import shutil
import subprocess
import argparse
from pathlib import Path
# Import helpers from rpmbuild
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'rpmbuild'))
from helpers import info, debug, warning as warn, die, removeDirectory
def copy_src_dir_to_dest_dir(src_dir, dest_dir, release_scope=False, release_dirs=None, file_filter=None):
"""Copy source directory to destination with optional filtering
Args:
src_dir: Source directory
dest_dir: Destination directory
release_scope: If True, only copy release scope directories
release_dirs: List of release scope directories (Release 2 specific)
file_filter: Optional function to filter files (filepath) -> bool, returns True to EXCLUDE
"""
os.makedirs(dest_dir, exist_ok=True)
# Release 2 scope directories (S set)
if release_dirs is None:
release_dirs = [
"Lts/Common",
"Lts/DDS",
"Lts/Services",
"Lts/Proxies/TrainingAreaBase",
"Lts/Tools"
]
if release_scope:
info(f"Copying release scope directories: {release_dirs}")
# Also copy root-level build files needed for CMake
root_build_files = ['CMakeLists.txt', 'CTestCustom.ctest']
root_build_dirs = ['cmake']
for bf in root_build_files:
src_file = os.path.join(src_dir, bf)
if os.path.exists(src_file):
debug(f" Copying root file {bf}...")
shutil.copy2(src_file, os.path.join(dest_dir, bf))
for bd in root_build_dirs:
src_bdir = os.path.join(src_dir, bd)
dest_bdir = os.path.join(dest_dir, bd)
if os.path.exists(src_bdir):
debug(f" Copying root directory {bd}...")
shutil.copytree(src_bdir, dest_bdir, dirs_exist_ok=True)
for rel_dir in release_dirs:
src_subdir = os.path.join(src_dir, rel_dir)
dest_subdir = os.path.join(dest_dir, rel_dir)
if os.path.exists(src_subdir):
debug(f" Copying {rel_dir}...")
for root, dirs, files in os.walk(src_subdir):
# Skip build directories, hidden directories, deb_build_tmp
dirs[:] = [d for d in dirs if not d.startswith('.')
and d not in ['build', 'cmake-build-debug', 'cmake-build-release', 'deb_build_tmp']
and (file_filter is None or not file_filter(os.path.join(root, d)))]
for file in files:
src_file = os.path.join(root, file)
rel_path = os.path.relpath(src_file, src_subdir)
dest_file = os.path.join(dest_subdir, rel_path)
# Apply file filter if provided (skip file if filter returns True)
if file_filter and file_filter(src_file):
continue
# Skip broken symlinks
if os.path.islink(src_file) and not os.path.exists(src_file):
debug(f"Skipping broken symlink: {src_file}")
continue
os.makedirs(os.path.dirname(dest_file), exist_ok=True)
shutil.copy2(src_file, dest_file)
else:
# Copy entire source tree
for root, dirs, files in os.walk(src_dir):
# Skip build directories, hidden directories, deb_build_tmp
dirs[:] = [d for d in dirs if not d.startswith('.')
and d not in ['build', 'cmake-build-debug', 'cmake-build-release', 'deb_build_tmp', 'deb_packages']]
for file in files:
src_file = os.path.join(root, file)
rel_path = os.path.relpath(src_file, src_dir)
dest_file = os.path.join(dest_dir, rel_path)
# Apply file filter if provided
if file_filter and file_filter(src_file):
continue
# Skip broken symlinks
if os.path.islink(src_file) and not os.path.exists(src_file):
debug(f"Skipping broken symlink: {src_file}")
continue
os.makedirs(os.path.dirname(dest_file), exist_ok=True)
shutil.copy2(src_file, dest_file)
def is_dds_file(filepath):
"""Check if a file or directory path contains DDS-related content that should be excluded
For Release 2, we INCLUDE DDS files in the sources package since DDS is part of our scope.
This function is kept for compatibility but returns False for all files.
Args:
filepath: Path to check
Returns:
False (include all files for Release 2)
"""
return False
def create_manifest(output_dir, pkg_name, pkg_dir):
"""Create a manifest file listing all files in the package"""
manifest_path = os.path.join(output_dir, "manifests", f"{pkg_name}.txt")
os.makedirs(os.path.dirname(manifest_path), exist_ok=True)
files = []
for root, dirs, filenames in os.walk(pkg_dir):
rel_root = os.path.relpath(root, pkg_dir)
for filename in filenames:
full_path = os.path.join(rel_root, filename) if rel_root != '.' else filename
files.append(full_path)
with open(manifest_path, 'w') as f:
f.write('\n'.join(sorted(files)))
return manifest_path
def validate_package_contents(pkg_name, manifest_path, allowed_patterns=None, forbidden_patterns=None):
"""Validate package contents against allowlist and denylist"""
info(f"Validating {pkg_name} contents...")
with open(manifest_path, 'r') as f:
files = [line.strip() for line in f if line.strip()]
import fnmatch
if forbidden_patterns:
for pattern in forbidden_patterns:
for file in files:
if fnmatch.fnmatch(file, pattern):
warn(f" Forbidden file found: {file} (matches {pattern})")
info(f" Found {len(files)} files in {pkg_name}")
return True
def create_debian_control(deb_dir, package_name, version, build_number, description, depends="", section="devel"):
"""Create debian/control file for a package (binary package format for dpkg-deb)"""
control_path = os.path.join(deb_dir, "control")
# Runtime dependencies for Release 2
runtime_deps = "" # dpkg-deb does not support debhelper variables
if depends:
runtime_deps += f", {depends}"
# Binary package control format (required by dpkg-deb)
control_content = f"""Package: {package_name}
Version: {version}-{build_number}
Section: {section}
Priority: optional
Architecture: amd64
Maintainer: Qt6 Release Team <qt6-release@example.com>
Depends: {runtime_deps}
Description: Qt6 Release 2 - {description}
This package contains {description.lower()} for the Qt6 Release 2 delivery.
.
Release 2 scope includes:
- AP3: LtsUtils, LtsWidgets, LtsSession, LtsLicence, LtsPluginManager
- AP4: Core, DDSConnector, Routing, QosProfile, RTI DDS
- AP9: DdsView, LogViewer, SqlBrowser, 3 generators, lupdate
"""
with open(control_path, 'w') as f:
f.write(control_content)
def create_debian_changelog(deb_dir, package_name, version, build_number):
"""Create debian/changelog file"""
changelog_path = os.path.join(deb_dir, "changelog")
changelog_content = f"""{package_name} ({version}-{build_number}) unstable; urgency=medium
* Qt6 Release 2 delivery
* Scope: AP3, AP4, AP9 modules (39 modules total)
* Includes: Common, DDS, Services, Proxies/TrainingAreaBase, Tools
-- Qt6 Release Team <qt6-release@example.com> {subprocess.check_output(['date', '-R']).decode().strip()}
"""
with open(changelog_path, 'w') as f:
f.write(changelog_content)
def create_debian_rules(deb_dir, cmake_flags="", skip_tests=False, use_prebuilt=False):
"""Create debian/rules file"""
rules_path = os.path.join(deb_dir, "rules")
if use_prebuilt:
# No-build rules - just package existing files
rules_content = """#!/usr/bin/make -f
# Debian rules file for Qt6 Release 2 (pre-built artifacts)
%:
\tdh $@
override_dh_auto_configure:
\t# No configuration needed - using pre-built artifacts
override_dh_auto_build:
\t# No build needed - using pre-built artifacts
override_dh_auto_install:
\t# Files already in place via debian/install
"""
else:
test_flag = "-DENABLE_TESTS=OFF" if skip_tests else "-DENABLE_TESTS=ON"
rules_content = f"""#!/usr/bin/make -f
# Debian rules file for Qt6 Release 2
%:
\tdh $@
override_dh_auto_configure:
\tdh_auto_configure -- -DCMAKE_BUILD_TYPE=Release {cmake_flags} {test_flag}
override_dh_auto_build:
\tdh_auto_build
override_dh_auto_test:
\t# Skip tests during package build (run separately with ctest)
\ttrue
override_dh_auto_install:
\tdh_auto_install --destdir=debian/tmp
"""
with open(rules_path, 'w') as f:
f.write(rules_content)
os.chmod(rules_path, 0o755)
def create_debian_rules_nobuild(deb_dir, skip_shlibdeps=False):
"""Create debian/rules file for packages that don't need building (pre-built files only)"""
rules_path = os.path.join(deb_dir, "rules")
shlibdeps_override = ""
if skip_shlibdeps:
shlibdeps_override = """
override_dh_shlibdeps:
\t# Skip shared library dependencies (test executables may have external deps)
\ttrue
"""
rules_content = f"""#!/usr/bin/make -f
# Debian rules file for Qt6 Release 2 (no-build package){shlibdeps_override}
%:
\tdh $@
override_dh_auto_configure:
\t# No configuration needed (pre-built files)
\ttrue
override_dh_auto_build:
\t# No build needed (pre-built files)
\ttrue
override_dh_auto_install:
\t# Files installed via debian/install
\ttrue
override_dh_auto_test:
\t# No tests in this package
\ttrue
"""
with open(rules_path, 'w') as f:
f.write(rules_content)
os.chmod(rules_path, 0o755)
def create_debian_install(deb_dir, install_lines):
"""Create debian/install file from list of file entries"""
install_path = os.path.join(deb_dir, "install")
with open(install_path, 'w') as f:
f.write('\n'.join(install_lines))
def find_test_executables(pkg_dir, release_dirs):
"""Find test executables in build directory"""
test_executables = []
# Look for test executables in build directories
build_dirs = ['build/bin', 'build4/bin', 'build-release/bin']
for build_dir in build_dirs:
bin_path = os.path.join(pkg_dir, build_dir)
if os.path.exists(bin_path):
for f in os.listdir(bin_path):
if f.startswith('test') or f.endswith('_test'):
exe_path = os.path.join(bin_path, f)
if os.path.isfile(exe_path) and os.access(exe_path, os.X_OK):
# Try to determine which module this test belongs to
module_path = "unknown"
for rel_dir in release_dirs:
if rel_dir.lower() in f.lower():
module_path = rel_dir
break
test_executables.append((exe_path, module_path))
return test_executables
def find_test_sources(pkg_dir, release_dirs):
"""Find test source files in release scope modules"""
test_sources = []
for rel_dir in release_dirs:
module_path = os.path.join(pkg_dir, rel_dir)
if os.path.exists(module_path):
for root, dirs, files in os.walk(module_path):
dirs[:] = [d for d in dirs if not d.startswith('.')]
for file in files:
if 'test' in file.lower() and (file.endswith('.cpp') or file.endswith('.h')):
rel_path = os.path.relpath(os.path.join(root, file), pkg_dir)
test_sources.append(rel_path)
return test_sources
def build_single_deb(pkg_name, pkg_dir, output_dir, version, build_number, cmake_flags, skip_tests, install_lines, description, section="devel", depends=""):
"""Build a single DEB package"""
info(f"Building DEB package: {pkg_name}")
deb_dir = os.path.join(pkg_dir, "debian")
os.makedirs(deb_dir)
create_debian_control(deb_dir, pkg_name, version, build_number, description, depends, section)
create_debian_changelog(deb_dir, pkg_name, version, build_number)
create_debian_rules(deb_dir, cmake_flags, skip_tests)
# Create debian/source/format
source_dir_path = os.path.join(deb_dir, "source")
os.makedirs(source_dir_path)
with open(os.path.join(source_dir_path, "format"), "w") as f:
f.write("3.0 (quilt)\n")
# Create debian/compat
with open(os.path.join(deb_dir, "compat"), "w") as f:
f.write("13\n")
# Create debian/install
if install_lines:
create_debian_install(deb_dir, install_lines)
# Build the package
info(f"Running debuild for {pkg_name}...")
os.chdir(pkg_dir)
env = os.environ.copy()
env["DEB_BUILD_OPTIONS"] = "parallel=$(nproc)"
cmd = f"debuild -us -uc -b"
debug(f"Executing: {cmd}")
ret = subprocess.run(cmd, shell=True, env=env, capture_output=True, text=True)
if ret.returncode != 0:
print(ret.stdout)
print(ret.stderr)
die(f"debuild failed for {pkg_name} with code {ret.returncode}")
# Move generated packages to output directory
parent_dir = os.path.dirname(pkg_dir)
for f in os.listdir(parent_dir):
if f.endswith(".deb") or f.endswith(".dsc") or f.endswith(".changes") or f.endswith(".buildinfo"):
src = os.path.join(parent_dir, f)
dst = os.path.join(output_dir, f)
if os.path.exists(dst):
os.remove(dst)
shutil.move(src, output_dir)
info(f"Moved {f} to {output_dir}")
return True
def build_single_deb_nobuild(pkg_name, pkg_dir, output_dir, version, build_number, install_lines, description, section="devel", depends="", skip_shlibdeps=False):
"""Build a single DEB package without running cmake/make (pre-built files only)"""
info(f"Building DEB package (no-build): {pkg_name}")
deb_dir = os.path.join(pkg_dir, "DEBIAN")
os.makedirs(deb_dir)
create_debian_control(deb_dir, pkg_name, version, build_number, description, depends, section)
create_debian_changelog(deb_dir, pkg_name, version, build_number)
create_debian_rules_nobuild(deb_dir, skip_shlibdeps=skip_shlibdeps)
# Create DEBIAN/source/format
source_dir_path = os.path.join(deb_dir, "source")
os.makedirs(source_dir_path)
with open(os.path.join(source_dir_path, "format"), "w") as f:
f.write("3.0 (quilt)\n")
# Create DEBIAN/compat
with open(os.path.join(deb_dir, "compat"), "w") as f:
f.write("13\n")
# Create DEBIAN/install
if install_lines:
create_debian_install(deb_dir, install_lines)
# Build the package using dpkg-deb directly
info(f"Building DEB package for {pkg_name} using dpkg-deb...")
original_dir = os.getcwd()
os.chdir(pkg_dir)
# dpkg-deb --build creates the .deb file directly
deb_file = f"{pkg_name}_{version}-{build_number}_amd64.deb"
cmd = f"dpkg-deb --build . ../{deb_file}"
debug(f"Executing: {cmd}")
ret = subprocess.run(cmd, shell=True, capture_output=True, text=True)
# Change back to original directory
os.chdir(original_dir)
if ret.returncode != 0:
print(ret.stdout)
print(ret.stderr)
die(f"dpkg-deb failed for {pkg_name} with code {ret.returncode}")
# Move the .deb file to output directory
parent_dir = os.path.dirname(pkg_dir)
deb_path = os.path.join(parent_dir, deb_file)
if os.path.exists(deb_path):
dst = os.path.join(output_dir, deb_file)
if os.path.exists(dst):
os.remove(dst)
shutil.move(deb_path, output_dir)
info(f"Moved {deb_file} to {output_dir}")
# Clean up build directory to save disk space
info(f"Cleaning up build directory: {pkg_dir}")
try:
shutil.rmtree(pkg_dir, ignore_errors=True)
except Exception as e:
warning(f"Failed to clean up {pkg_dir}: {e}")
return True
def build_all_debs(source_dir, output_dir, project_name, version, build_number, cmake_flags, release_scope=True):
"""Build all 5 DEB packages for Release 2 using pre-built artifacts"""
info("========================================")
info("Building 5 DEB packages for Qt6 Release 2")
info("========================================")
os.makedirs(output_dir, exist_ok=True)
os.makedirs(os.path.join(output_dir, "manifests"), exist_ok=True)
build_base = os.path.join("/tmp", "qt6_deb_build_" + str(os.getpid()))
# removeDirectory(build_base) # Skip removal when using /tmp
os.makedirs(build_base)
# Release 2 scope directories (S set - 39 modules)
release_dirs = [
"Lts/Common",
"Lts/DDS",
"Lts/Services",
"Lts/Proxies/TrainingAreaBase",
"Lts/Tools"
]
# Source file extensions
source_extensions = ['.cpp', '.h', '.hpp', '.cc', '.cxx', '.hxx']
script_extensions = ['.py', '.sh', '.cmake', '.txt']
# ============================================
# STEP 1: Use pre-built artifacts from build4/
# ============================================
info("\n=== Step 1: Using pre-built artifacts from build4/ ===")
build4_dir = os.path.join(source_dir, "build4")
if not os.path.exists(build4_dir):
die(f"Pre-built artifacts not found in {build4_dir}. Run build first.")
# Verify libraries exist
lib_dir = os.path.join(build4_dir, "lib")
if not os.path.exists(lib_dir):
die(f"Library directory not found: {lib_dir}")
lib_count = len([f for f in os.listdir(lib_dir) if f.endswith('.so')])
info(f"Found {lib_count} shared libraries in build4/lib/")
# Verify tool executables exist
tools_build_dir = os.path.join(build4_dir, "Lts", "Tools")
if os.path.exists(tools_build_dir):
info(f"AP9 tools build directory exists: {tools_build_dir}")
bin_dir = os.path.join(build4_dir, "bin")
if os.path.exists(bin_dir):
tool_exes = [f for f in os.listdir(bin_dir) if f.startswith('t') or 'generator' in f.lower()]
if tool_exes:
info(f"Found tool executables in build4/bin/: {', '.join(tool_exes)}")
info("Pre-built artifacts verified successfully")
# ============================================
# Package 1: qt6-release-runtime
# ============================================
info("\n=== Building qt6-release-runtime ===")
pkg1_name = f"qt6-release-runtime"
pkg1_dir = os.path.join(build_base, f"{pkg1_name}-{version}")
os.makedirs(pkg1_dir)
# Create package structure
pkg1_lib_dir = os.path.join(pkg1_dir, "usr", "lib")
pkg1_bin_dir = os.path.join(pkg1_dir, "usr", "bin")
os.makedirs(pkg1_lib_dir, exist_ok=True)
os.makedirs(pkg1_bin_dir, exist_ok=True)
# Copy pre-built libraries from build4/lib
info("Copying libraries from build4/lib/...")
for f in os.listdir(lib_dir):
if f.endswith('.so') or f.endswith('.so.1') or f.startswith('lib'):
src = os.path.join(lib_dir, f)
dst = os.path.join(pkg1_lib_dir, f)
if os.path.isfile(src):
shutil.copy2(src, dst)
# Copy tool executables from build4/bin
info("Copying executables from build4/bin/...")
if os.path.exists(bin_dir):
for f in os.listdir(bin_dir):
fpath = os.path.join(bin_dir, f)
if os.path.isfile(fpath) and (f.startswith('t') or 'generator' in f.lower() or f in ['ddsview', 'sqlbrowser', 'LogViewer', 'topicdiscover']):
shutil.copy2(fpath, os.path.join(pkg1_bin_dir, f))
# Copy tool executables from build4/Lts/Tools subdirectories
if os.path.exists(tools_build_dir):
for tool_subdir in os.listdir(tools_build_dir):
tool_bin_path = os.path.join(tools_build_dir, tool_subdir, "bin")
if os.path.exists(tool_bin_path):
for exe in os.listdir(tool_bin_path):
if exe and not exe.startswith('.'):
src = os.path.join(tool_bin_path, exe)
if os.path.isfile(src):
shutil.copy2(src, os.path.join(pkg1_bin_dir, exe))
# Install lines for runtime
install_lines_1 = []
install_lines_1.append("usr/lib/* usr/lib/")
install_lines_1.append("usr/bin/* usr/bin/")
build_single_deb_nobuild(
pkg_name=pkg1_name,
pkg_dir=pkg1_dir,
output_dir=output_dir,
version=version,
build_number=build_number,
install_lines=install_lines_1,
description="Runtime binaries and libraries for Release 2 scope (AP3, AP4, AP9)",
section="libs"
)
# Create manifest
manifest_1 = create_manifest(output_dir, pkg1_name, pkg1_dir)
validate_package_contents(pkg1_name, manifest_1,
allowed_patterns=["usr/bin/*", "usr/lib/*", "usr/SV/*", "usr/WS/*", "debian/*"],
forbidden_patterns=["*.cpp", "*.h", "*.hpp", "tests/*", "jenkins/*", "Dockerfile*"])
# ============================================
# Package 2: qt6-release-sources
# ============================================
info("\n=== Building qt6-release-sources ===")
pkg2_name = f"qt6-release-sources"
pkg2_dir = os.path.join(build_base, f"{pkg2_name}-{version}")
os.makedirs(pkg2_dir)
# Copy FULL source tree (Release 2 includes DDS files)
copy_src_dir_to_dest_dir(source_dir, pkg2_dir, release_scope=False, release_dirs=release_dirs)
# Install lines for sources: only from release scope directories
install_lines_2 = []
for rel_dir in release_dirs:
src_dir = os.path.join(pkg2_dir, rel_dir)
if os.path.exists(src_dir):
for root, dirs, files in os.walk(src_dir):
dirs[:] = [d for d in dirs if not d.startswith('.')]
for file in files:
ext = os.path.splitext(file)[1].lower()
if ext in source_extensions or file == "CMakeLists.txt":
rel_path = os.path.relpath(os.path.join(root, file), pkg2_dir)
dest_dir = os.path.join("usr/src", os.path.dirname(rel_path))
install_lines_2.append(f"{rel_path} {dest_dir}/")
# Use no-build rules for source package
build_single_deb_nobuild(
pkg_name=pkg2_name,
pkg_dir=pkg2_dir,
output_dir=output_dir,
version=version,
build_number=build_number,
install_lines=install_lines_2,
description="C++ source files for Release 2 scope (AP3, AP4, AP9)",
section="devel"
)
manifest_2 = create_manifest(output_dir, pkg2_name, pkg2_dir)
validate_package_contents(pkg2_name, manifest_2,
allowed_patterns=["usr/src/**/*.cpp", "usr/src/**/*.h", "usr/src/**/CMakeLists.txt", "debian/*"],
forbidden_patterns=["build/*", "tests/*", "jenkins/*"])
# ============================================
# Package 3: qt6-release-ctest-runtime
# ============================================
info("\n=== Building qt6-release-ctest-runtime ===")
pkg3_name = f"qt6-release-ctest-runtime"
pkg3_dir = os.path.join(build_base, f"{pkg3_name}-{version}")
os.makedirs(pkg3_dir)
# Copy FULL source tree
copy_src_dir_to_dest_dir(source_dir, pkg3_dir, release_scope=False, release_dirs=release_dirs)
# Install lines for CTest runtime: test executables from release scope only
install_lines_3 = []
# Find test executables in build directory
test_executables = find_test_executables(pkg3_dir, release_dirs)
for exe_path, module_path in test_executables:
rel_path = os.path.relpath(exe_path, pkg3_dir)
dest_dir = "usr/lib/ctest"
install_lines_3.append(f"{rel_path} {dest_dir}/")
info(f" Including test executable: {os.path.basename(exe_path)} from {module_path}")
# Also include CTest configuration files
ctest_files = [
"build/CTestTestfile.cmake",
"build/DartConfiguration.tcl",
"build/Testing/TAG",
]
for ctest_file in ctest_files:
if os.path.exists(os.path.join(pkg3_dir, ctest_file)):
install_lines_3.append(f"{ctest_file} usr/lib/ctest/")
build_single_deb_nobuild(
pkg_name=pkg3_name,
pkg_dir=pkg3_dir,
output_dir=output_dir,
version=version,
build_number=build_number,
install_lines=install_lines_3,
description="Test executables for Release 2 scope",
section="devel",
skip_shlibdeps=True
)
manifest_3 = create_manifest(output_dir, pkg3_name, pkg3_dir)
validate_package_contents(pkg3_name, manifest_3,
allowed_patterns=["usr/lib/ctest/*", "debian/*"],
forbidden_patterns=["*.cpp", "*.h", "jenkins/*"])
# ============================================
# Package 4: qt6-release-ctest-sources
# ============================================
info("\n=== Building qt6-release-ctest-sources ===")
pkg4_name = f"qt6-release-ctest-sources"
pkg4_dir = os.path.join(build_base, f"{pkg4_name}-{version}")
os.makedirs(pkg4_dir)
# Copy FULL source tree
copy_src_dir_to_dest_dir(source_dir, pkg4_dir, release_scope=False, release_dirs=release_dirs)
# Install lines for test sources from release scope only
install_lines_4 = []
# Find test source files in release scope modules
test_sources = find_test_sources(pkg4_dir, release_dirs)
for rel_path in test_sources:
dest_dir = os.path.dirname(rel_path)
install_lines_4.append(f"{rel_path} usr/src/{dest_dir}/")
info(f" Including test source: {rel_path}")
build_single_deb_nobuild(
pkg_name=pkg4_name,
pkg_dir=pkg4_dir,
output_dir=output_dir,
version=version,
build_number=build_number,
install_lines=install_lines_4,
description="Test source files for Release 2 scope",
section="devel"
)
manifest_4 = create_manifest(output_dir, pkg4_name, pkg4_dir)
validate_package_contents(pkg4_name, manifest_4,
allowed_patterns=["usr/src/**/tests/*", "debian/*"],
forbidden_patterns=["build/*", "jenkins/*"])
# ============================================
# Package 5: qt6-release-build-pipeline
# ============================================
info("\n=== Building qt6-release-build-pipeline ===")
pkg5_name = f"qt6-release-build-pipeline"
pkg5_dir = os.path.join(build_base, f"{pkg5_name}-{version}")
os.makedirs(pkg5_dir)
# Copy pipeline scripts and configuration
# Note: pipeline dirs are at project root, not in qt-migration-legatus
pipeline_dirs = [
"jenkins-ci-rme",
"docker",
"scripts"
]
# Use parent of source_dir as project root (source_dir points to qt-migration-legatus/qt6-after/qt6-migrated-legatus)
project_root = os.path.dirname(os.path.dirname(os.path.dirname(source_dir)))
install_lines_5 = []
for pipeline_dir in pipeline_dirs:
src_pipeline = os.path.join(project_root, pipeline_dir)
dest_pipeline = os.path.join(pkg5_dir, pipeline_dir)
if os.path.exists(src_pipeline):
shutil.copytree(src_pipeline, dest_pipeline, dirs_exist_ok=True)
for root, dirs, files in os.walk(dest_pipeline):
dirs[:] = [d for d in dirs if not d.startswith('.')]
for file in files:
rel_path = os.path.relpath(os.path.join(root, file), pkg5_dir)
install_lines_5.append(f"{rel_path} usr/src/pipeline/{os.path.dirname(rel_path)}/")
build_single_deb_nobuild(
pkg_name=pkg5_name,
pkg_dir=pkg5_dir,
output_dir=output_dir,
version=version,
build_number=build_number,
install_lines=install_lines_5,
description="Build pipeline scripts and configuration for Release 2",
section="devel"
)
manifest_5 = create_manifest(output_dir, pkg5_name, pkg5_dir)
validate_package_contents(pkg5_name, manifest_5,
allowed_patterns=["usr/src/pipeline/*", "debian/*"],
forbidden_patterns=["*.cpp", "*.h", "build/*"])
info("\n========================================")
info("All 5 DEB packages built successfully!")
info(f"Output directory: {output_dir}")
info("========================================")
def main():
parser = argparse.ArgumentParser(description="Build DEB packages for Qt6 Release 2")
parser.add_argument("-c", "--config", required=True, help="Config type (LTS)")
parser.add_argument("--project_name", required=True, help="Project name (qatar|ahtc|guez)")
parser.add_argument("--version", required=True, help="Version (Major.minor)")
parser.add_argument("--output_dir", required=True, help="Output directory for packages")
parser.add_argument("--source_dir", required=True, help="Source directory path")
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")
args = parser.parse_args()
info(f"Building {args.config} package for {args.project_name} v{args.version}")
info(f"Output directory: {args.output_dir}")
info(f"Source directory: {args.source_dir}")
info(f"CMake flags: {args.cmake_build_flags}")
info(f"Release scope: {args.release_scope}")
source_dir = args.source_dir
info(f"Source directory: {source_dir}")
build_all_debs(
source_dir=source_dir,
output_dir=args.output_dir,
project_name=args.project_name,
version=args.version,
build_number=args.build_number,
cmake_flags=args.cmake_build_flags,
release_scope=args.release_scope
)
if __name__ == "__main__":
main()