]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Call 'mkosi.finalize' script 281/head
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 4 Nov 2018 13:17:55 +0000 (14:17 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 6 Nov 2018 15:54:37 +0000 (16:54 +0100)
This is similar to 'mkosi.postinst', but is called in the host. This
makes it much easier to copy-in files. It is also much quicker when
creating images for a foreign architecture.

v2:
- s/postinst2/finalize/g
- call the script first with "build" too
- pass the root directory as $BUILDROOT (like rpmbuild) and not as
  a positional argument. (This is easier to consume for scripts and
  also easier to extend with additional variables in the future.)
- update to use args_find_path()

README.md
mkosi

index dfbb36d432d18da46818871866dffd6cc5801390..e364106abdbe203c8b3a211ae0ae956f5637981c 100644 (file)
--- a/README.md
+++ b/README.md
@@ -184,7 +184,7 @@ they exist in the local directory:
   `systemd-nspawn`), with `$SRCDIR` pointing to the *source*
   tree. `$DESTDIR` points to a directory where the script should place
   any files generated it would like to end up in the *final*
-  image. Note that `make`/`automake` based build systems generally
+  image. Note that `make`/`automake`/`meson` based build systems generally
   honour `$DESTDIR`, thus making it very natural to build *source*
   trees from the build script. After the *development* image was built
   and the build script ran inside of it, it is removed again. After
@@ -205,16 +205,34 @@ they exist in the local directory:
   artifacts.
 
 * `mkosi.postinst` may be an executable script. If it exists it is
-  invoked as last step of preparing an image, from within the image
-  context. It is once called for the *development* image (if this is
-  enabled, see above) with the "build" command line parameter, right
-  before invoking the build script. It is called a second time for the
-  *final* image with the "final" command line parameter, right before
-  the image is considered complete. This script may be used to alter
-  the images without any restrictions, after all software packages and
-  built sources have been installed. Note that this script is executed
-  directly in the image context with the final root directory in
-  place, without any `$SRCDIR`/`$DESTDIR` setup.
+  invoked as the penultimate step of preparing an image, from within
+  the image context. It is once called for the *development* image (if
+  this is enabled, see above) with the "build" command line parameter,
+  right before invoking the build script. It is called a second time
+  for the *final* image with the "final" command line parameter, right
+  before the image is considered complete. This script may be used to
+  alter the images without any restrictions, after all software
+  packages and built sources have been installed. Note that this
+  script is executed directly in the image context with the final root
+  directory in place, without any `$SRCDIR`/`$DESTDIR` setup.
+
+* `mkosi.finalize` may be an executable script. If it exists it is
+  invoked as last step of preparing an image, from the host system.
+  It is once called for the *development* image (if this is enabled,
+  see above) with the "build" command line parameter, as the last step
+  before invoking the build script, after the `mkosi.postinst` script
+  is invoked.  It is called the second time with the "final" command
+  line parameter as the last step before the image is considered
+  complete. The environment variable `$BUILDROOT` points to the root
+  directory of the installation image. Additional verbs may be added
+  in the future, the script should be prepared for that. This script
+  may be used to alter the images without any restrictions, after all
+  software packages and built sources have been installed. This script
+  is more flexible than `mkosi.postinst` in two regards: it has access
+  to the host file system so it's easier to copy in additional files
+  or to modify the image based on external configuration, and the
+  script is run in the host, so it can be used even without emulation
+  even if the image has a foreign architecture.
 
 * `mkosi.mksquashfs-tool` may be an executable script. If it exists is
   is called instead of `mksquashfs`.
diff --git a/mkosi b/mkosi
index f68c9f1f75727991d1294a07403b8bfb71c7c98e..7a08bf5ffacd1217b7422eef5a18f224e0f68967 100755 (executable)
--- a/mkosi
+++ b/mkosi
@@ -1789,6 +1789,8 @@ def run_postinst_script(args, workspace, run_build_script, for_cache):
     if for_cache:
         return
 
+    verb = "build" if run_build_script else "final"
+
     with complete_step('Running postinstall script'):
 
         # We copy the postinst script into the build tree. We'd prefer
@@ -1799,9 +1801,18 @@ def run_postinst_script(args, workspace, run_build_script, for_cache):
         shutil.copy2(args.postinst_script,
                      os.path.join(workspace, "root", "root/postinst"))
 
-        run_workspace_command(args, workspace, "/root/postinst", "build" if run_build_script else "final", network=args.with_network)
+        run_workspace_command(args, workspace, "/root/postinst", verb, network=args.with_network)
         os.unlink(os.path.join(workspace, "root", "root/postinst"))
 
+def run_finalize_script(args: CommandLineArguments, workspace: str, *, verb: str):
+    if args.finalize_script is None:
+        return
+
+    with complete_step('Running finalize script'):
+        buildroot = workspace + '/root'
+        env = collections.ChainMap({'BUILDROOT':buildroot}, os.environ)
+        run([args.finalize_script, verb], env=env, check=True)
+
 def find_kernel_file(workspace_root, pattern):
     # Look for the vmlinuz file in the workspace
     workspace_pattern = os.path.join(workspace_root, pattern.lstrip('/'))
@@ -2578,6 +2589,7 @@ def parse_args() -> CommandLineArguments:
     group.add_argument("--build-dir", help='Path to use as persistent build directory', metavar='PATH')
     group.add_argument("--build-package", action=CommaDelimitedListAction, dest='build_packages', default=[], help='Additional packages needed for build script', metavar='PACKAGE')
     group.add_argument("--postinst-script", help='Postinstall script to run inside image', metavar='PATH')
+    group.add_argument("--finalize-script", help='Postinstall script to run outside image', metavar='PATH')
     group.add_argument('--use-git-files', type=parse_boolean,
                        help='Ignore any files that git itself ignores (default: guess)')
     group.add_argument('--git-files', choices=('cached', 'others'),
@@ -2901,6 +2913,9 @@ def process_setting(args: CommandLineArguments, section: str, key: str, value: A
         elif key in {"PostinstallScript", "PostInstallationScript"}:
             if args.postinst_script is None:
                 args.postinst_script = value
+        elif key == "FinalizeScript":
+            if args.finalize_script is None:
+                args.finalize_script = value
         elif key == "WithNetwork":
             if args.with_network is None:
                 args.with_network = parse_boolean(value)
@@ -3139,6 +3154,7 @@ def load_args() -> CommandLineArguments:
     args_find_path(args, 'build_sources',   ".")
     args_find_path(args, 'build_dir',       "mkosi.builddir/")
     args_find_path(args, 'postinst_script', "mkosi.postinst");
+    args_find_path(args, 'finalize_script', "mkosi.finalize");
     args_find_path(args, 'output_dir',      "mkosi.output/");
     args_find_path(args, 'mksquashfs_tool', "mkosi.mksquashfs-tool", type=lambda x: [x])
 
@@ -3291,6 +3307,9 @@ def load_args() -> CommandLineArguments:
     if args.postinst_script is not None:
         args.postinst_script = os.path.abspath(args.postinst_script)
 
+    if args.finalize_script is not None:
+        args.finalize_script = os.path.abspath(args.finalize_script)
+
     if args.cache_path is not None:
         args.cache_path = os.path.abspath(args.cache_path)
 
@@ -3460,6 +3479,7 @@ def print_summary(args: CommandLineArguments) -> None:
     sys.stderr.write("       Build Directory: " + none_to_none(args.build_dir) + "\n")
     sys.stderr.write("        Build Packages: " + line_join_list(args.build_packages) + "\n")
     sys.stderr.write("    Postinstall Script: " + none_to_none(args.postinst_script) + "\n")
+    sys.stderr.write("       Finalize Script: " + none_to_none(args.finalize_script) + "\n")
     sys.stderr.write("  Scripts with network: " + yes_no(args.with_network) + "\n")
     sys.stderr.write("       nspawn Settings: " + none_to_none(args.nspawn_settings) + "\n")
 
@@ -3701,6 +3721,8 @@ def build_stuff(args: CommandLineArguments) -> None:
                        args.cache_pre_inst)
             remove_artifacts(args, workspace.name, raw, tar, run_build_script=False)
 
+    run_finalize_script(args, workspace.name, verb='build')
+
     if args.build_script:
         # Run the image builder for the first (develpoment) stage in preparation for the build script
         raw, tar, root_hash = build_image(args, workspace, run_build_script=True)
@@ -3708,6 +3730,8 @@ def build_stuff(args: CommandLineArguments) -> None:
         run_build_script(args, workspace.name, raw)
         remove_artifacts(args, workspace.name, raw, tar, run_build_script=True)
 
+    run_finalize_script(args, workspace.name, verb='final')
+
     # Run the image builder for the second (final) stage
     raw, tar, root_hash = build_image(args, workspace, run_build_script=False, cleanup=True)