blob: 92cb5878afc4a809759d270f84241b93a73fddf5 [file] [log] [blame] [edit]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use anyhow::Result;
use binarypackage::BinaryPackage;
use clap::Parser;
use cliutil::cli_main;
use makechroot::BindMount;
use mountsdk::MountedSDK;
use std::{
path::{Path, PathBuf},
process::ExitCode,
};
const MAIN_SCRIPT: &str = "/mnt/host/bazel-build/build_image.sh";
#[derive(Parser, Debug)]
#[clap()]
pub struct Cli {
#[command(flatten)]
mountsdk_config: mountsdk::ConfigArgs,
/// Output file path.
#[arg(long, required = true)]
output: PathBuf,
/// Image to build.
#[arg(long, required = true)]
image_to_build: String,
/// The name of the image file generated by build_image script.
#[arg(long, required = true)]
image_file_name: String,
/// File paths to binary packages to be installed on the output image.
#[arg(long)]
target_package: Vec<PathBuf>,
/// File paths to host binary packages to be made available to the
/// build_image script.
#[arg(long)]
host_package: Vec<PathBuf>,
#[arg(long)]
override_base_package: Vec<String>,
}
fn do_main() -> Result<()> {
let args = Cli::parse();
let r = runfiles::Runfiles::create()?;
let mut cfg = mountsdk::Config::try_from(args.mountsdk_config)?;
cfg.privileged = true;
cfg.bind_mounts.push(BindMount {
source: r
.rlocation("cros/bazel/ebuild/private/cmd/build_image/container_files/edb_chromeos"),
mount_path: Path::new("/build")
.join(&cfg.board)
.join("var/cache/edb/chromeos"),
});
cfg.bind_mounts.push(BindMount {
source: r.rlocation(
"cros/bazel/ebuild/private/cmd/build_image/container_files/package.accept_keywords",
),
mount_path: Path::new("/build")
.join(&cfg.board)
.join("etc/portage/package.accept_keywords/accept_all"),
});
cfg.bind_mounts.push(BindMount {
source: r.rlocation(
"cros/bazel/ebuild/private/cmd/build_image/container_files/package.provided",
),
mount_path: Path::new("/build")
.join(&cfg.board)
.join("etc/portage/profile/package.provided"),
});
cfg.bind_mounts.push(BindMount {
source: r
.rlocation("cros/bazel/ebuild/private/cmd/build_image/container_files/build_image.sh"),
mount_path: PathBuf::from(MAIN_SCRIPT),
});
for path in args.target_package {
let package = BinaryPackage::open(&path)?;
let mount_path = Path::new("/build")
.join(&cfg.board)
.join("packages")
.join(format!("{}.tbz2", package.category_pf()));
cfg.bind_mounts.push(BindMount {
mount_path,
source: path,
});
}
for path in args.host_package {
let package = BinaryPackage::open(&path)?;
let mount_path =
Path::new("/var/lib/portage/pkgs").join(format!("{}.tbz2", package.category_pf()));
cfg.bind_mounts.push(BindMount {
mount_path,
source: path,
});
}
cfg.envs.insert("BOARD".to_owned(), cfg.board.clone());
cfg.envs.insert(
"BASE_PACKAGE".to_owned(),
args.override_base_package.join(" "),
);
let mut sdk = MountedSDK::new(cfg)?;
sdk.run_cmd(&[
MAIN_SCRIPT,
&format!("--board={}", &sdk.board),
&args.image_to_build,
// TODO: add unparsed command-line args.
])?;
let path = Path::new("mnt/host/source/src/build/images")
.join(&sdk.board)
.join("latest")
.join(args.image_file_name + ".bin");
std::fs::copy(sdk.diff_dir().join(path), args.output)?;
Ok(())
}
fn main() -> ExitCode {
cli_main(do_main)
}