]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Share the package directory across all image builds
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Fri, 12 Jul 2024 15:07:22 +0000 (17:07 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Fri, 12 Jul 2024 16:41:01 +0000 (18:41 +0200)
This allows packages built by one image to easily be installed in
another image when using mkosi.images.

mkosi/__init__.py
mkosi/context.py
mkosi/resources/mkosi.md

index 03061aa30d95660ce1950da1300c82c75c658e9a..ab76677b46ac3f0c79bf487a6eb4763829c2a0a6 100644 (file)
@@ -594,7 +594,7 @@ def run_prepare_scripts(context: Context, build: bool) -> None:
                             Mount(json, "/work/config.json", ro=True),
                             Mount(context.root, "/buildroot"),
                             Mount(context.artifacts, "/work/artifacts"),
-                            Mount(context.packages, "/work/packages"),
+                            Mount(context.package_dir, "/work/packages"),
                             *(
                                 [Mount(context.config.build_dir, "/work/build", ro=True)]
                                 if context.config.build_dir
@@ -682,7 +682,7 @@ def run_build_scripts(context: Context) -> None:
                             Mount(context.install_dir, "/work/dest"),
                             Mount(context.staging, "/work/out"),
                             Mount(context.artifacts, "/work/artifacts"),
-                            Mount(context.packages, "/work/packages"),
+                            Mount(context.package_dir, "/work/packages"),
                             *(
                                 [Mount(context.config.build_dir, "/work/build")]
                                 if context.config.build_dir
@@ -759,7 +759,7 @@ def run_postinst_scripts(context: Context) -> None:
                             Mount(context.root, "/buildroot"),
                             Mount(context.staging, "/work/out"),
                             Mount(context.artifacts, "/work/artifacts"),
-                            Mount(context.packages, "/work/packages"),
+                            Mount(context.package_dir, "/work/packages"),
                             *(
                                 [Mount(context.config.build_dir, "/work/build", ro=True)]
                                 if context.config.build_dir
@@ -834,7 +834,7 @@ def run_finalize_scripts(context: Context) -> None:
                             Mount(context.root, "/buildroot"),
                             Mount(context.staging, "/work/out"),
                             Mount(context.artifacts, "/work/artifacts"),
-                            Mount(context.packages, "/work/packages"),
+                            Mount(context.package_dir, "/work/packages"),
                             *(
                                 [Mount(context.config.build_dir, "/work/build", ro=True)]
                                 if context.config.build_dir
@@ -1770,7 +1770,6 @@ def finalize_default_initrd(
     *,
     resources: Path,
     output_dir: Optional[Path] = None,
-    package_dir: Optional[Path] = None,
 ) -> Config:
     if config.root_password:
         password, hashed = config.root_password
@@ -1808,7 +1807,6 @@ def finalize_default_initrd(
         *(f"--volatile-package={package}" for package in config.initrd_volatile_packages),
         *(f"--package-directory={d}" for d in config.package_directories),
         *(f"--volatile-package-directory={d}" for d in config.volatile_package_directories),
-        *([f"--volatile-package-directory={package_dir}"] if package_dir else []),
         "--output", "initrd",
         *(["--image-id", config.image_id] if config.image_id else []),
         *(["--image-version", config.image_version] if config.image_version else []),
@@ -1856,7 +1854,6 @@ def build_default_initrd(context: Context) -> Path:
         context.config,
         resources=context.resources,
         output_dir=context.workspace,
-        package_dir=context.packages,
     )
 
     assert config.output_dir
@@ -1878,6 +1875,7 @@ def build_default_initrd(context: Context) -> Path:
                 resources=context.resources,
                 # Re-use the repository metadata snapshot from the main image for the initrd.
                 package_cache_dir=context.package_cache_dir,
+                package_dir=context.package_dir,
             )
         )
 
@@ -3895,7 +3893,7 @@ def build_image(context: Context) -> None:
 
         with createrepo(context):
             install_package_directories(context, context.config.volatile_package_directories)
-            install_package_directories(context, [context.packages])
+            install_package_directories(context, [context.package_dir])
 
         install_volatile_packages(context)
         install_build_dest(context)
@@ -4668,7 +4666,7 @@ def run_sync(args: Args, config: Config, *, resources: Path) -> None:
         run_sync_scripts(context)
 
 
-def run_build(args: Args, config: Config, *, resources: Path) -> None:
+def run_build(args: Args, config: Config, *, resources: Path, package_dir: Optional[Path] = None) -> None:
     if (uid := os.getuid()) != 0:
         become_root()
     unshare(CLONE_NEWNS)
@@ -4719,7 +4717,7 @@ def run_build(args: Args, config: Config, *, resources: Path) -> None:
             rchown_package_manager_dirs(config),
             setup_workspace(args, config) as workspace,
         ):
-            build_image(Context(args, config, workspace=workspace, resources=resources))
+            build_image(Context(args, config, workspace=workspace, resources=resources, package_dir=package_dir))
 
 
 def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None:
@@ -4820,32 +4818,33 @@ def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None:
 
     build = False
 
-    for i, config in enumerate(images):
-        images[i] = config = dataclasses.replace(
-            config,
-            tools_tree=(
-                tools.output_dir_or_cwd() / tools.output
-                if tools and config.tools_tree == Path("default")
-                else config.tools_tree
+    with tempfile.TemporaryDirectory(dir=last.workspace_dir_or_default(), prefix="mkosi-packages-") as package_dir:
+        for i, config in enumerate(images):
+            images[i] = config = dataclasses.replace(
+                config,
+                tools_tree=(
+                    tools.output_dir_or_cwd() / tools.output
+                    if tools and config.tools_tree == Path("default")
+                    else config.tools_tree
+                )
             )
-        )
 
-        images[i] = config = run_configure_scripts(config)
+            images[i] = config = run_configure_scripts(config)
 
-        if args.verb != Verb.build and args.force == 0:
-            continue
+            if args.verb != Verb.build and args.force == 0:
+                continue
 
-        if (
-            config.output_format != OutputFormat.none and
-            (config.output_dir_or_cwd() / config.output_with_compression).exists()
-        ):
-            continue
+            if (
+                config.output_format != OutputFormat.none and
+                (config.output_dir_or_cwd() / config.output_with_compression).exists()
+            ):
+                continue
 
-        check_inputs(config)
-        fork_and_wait(run_sync, args, config, resources=resources)
-        fork_and_wait(run_build, args, config, resources=resources)
+            check_inputs(config)
+            fork_and_wait(run_sync, args, config, resources=resources)
+            fork_and_wait(run_build, args, config, resources=resources, package_dir=Path(package_dir))
 
-        build = True
+            build = True
 
     if build and args.auto_bump:
         bump_image_version()
index 761358130918b77f11976cafeba414c21b3c2c4e..920271487ba0dcff5036caf747da607ebe6f96c7 100644 (file)
@@ -23,12 +23,15 @@ class Context:
         workspace: Path,
         resources: Path,
         package_cache_dir: Optional[Path] = None,
+        package_dir: Optional[Path] = None,
     ) -> None:
         self.args = args
         self.config = config
         self.workspace = workspace
         self.resources = resources
         self.package_cache_dir = package_cache_dir or (self.root / "var")
+        self.package_dir = package_dir or (self.workspace / "packages")
+        self.package_dir.mkdir(exist_ok=True)
 
         with umask(~0o755):
             # Using a btrfs subvolume as the upperdir in an overlayfs results in EXDEV so make sure we create
@@ -45,7 +48,6 @@ class Context:
         self.staging.mkdir()
         self.pkgmngr.mkdir()
         self.repository.mkdir()
-        self.packages.mkdir()
         self.artifacts.mkdir()
         self.install_dir.mkdir()
 
@@ -65,10 +67,6 @@ class Context:
     def repository(self) -> Path:
         return self.workspace / "repository"
 
-    @property
-    def packages(self) -> Path:
-        return self.workspace / "packages"
-
     @property
     def artifacts(self) -> Path:
         return self.workspace / "artifacts"
index 15f8d13eafc7d33b302ea5ce9d6dcf3e16bd79c6..b47f60f336f6d24397260bad5645df16cd970da5 100644 (file)
@@ -770,9 +770,6 @@ boolean argument: either `1`, `yes`, or `true` to enable, or `0`, `no`,
     running scripts. If the `mkosi.packages/` directory is found in the local
     directory it is also used for this purpose.
 
-    Build scripts can add more packages to the local repository by
-    placing the built packages in `$PACKAGEDIR`.
-
 `VolatilePackageDirectories=`, `--volatile-package-directory=`
 
 :   Like `PackageDirectories=`, but the packages in these directories
@@ -780,6 +777,12 @@ boolean argument: either `1`, `yes`, or `true` to enable, or `0`, `no`,
     packages are installed. Specifically, if `Incremental=` is enabled,
     the packages from these directories will not be cached.
 
+    Additionally, build scripts can add more packages to the local
+    repository by placing the built packages in `$PACKAGEDIR`. The
+    packages placed in `$PACKAGEDIR` are shared between all image builds
+    and thus available for installation in all images using
+    `VolatilePackages=`.
+
 `WithRecommends=`, `--with-recommends=`
 :   Configures whether to install recommended or weak dependencies,
     depending on how they are named by the used package manager, or not.