mirror of
https://gitlab.redox-os.org/redox-os/redox.git
synced 2026-06-20 20:04:19 +08:00
Merge branch 'logs-n-verbosity' into 'master'
Allow logging for non TUI and verbose tuning See merge request redox-os/cookbook!682
This commit is contained in:
commit
6c080eb8f1
@ -63,6 +63,7 @@ const REPO_HELP_STR: &str = r#"
|
||||
|
||||
cook env and their defaults:
|
||||
CI= set to any value to disable TUI
|
||||
COOKBOOK_LOGS= whether to capture build logs (default is !CI)
|
||||
COOKBOOK_OFFLINE=false prevent internet access if possible
|
||||
COOKBOOK_NONSTOP=false pkeep running even a recipe build failed
|
||||
COOKBOOK_VERBOSE=true print success/error on each recipe
|
||||
@ -144,7 +145,7 @@ impl CliConfig {
|
||||
cookbook_dir: current_dir.join("recipes"),
|
||||
repo_dir: current_dir.join("repo"),
|
||||
// build dir here is hardcoded in repo_builder as well
|
||||
logs_dir: if get_config().cook.tui_logs {
|
||||
logs_dir: if get_config().cook.logs {
|
||||
Some(current_dir.join("build/logs"))
|
||||
} else {
|
||||
None
|
||||
@ -212,17 +213,15 @@ fn main_inner() -> anyhow::Result<()> {
|
||||
for recipe in &recipe_names {
|
||||
match repo_inner(&config, &command, recipe) {
|
||||
Ok(_) => {
|
||||
if verbose {
|
||||
eprintln!(
|
||||
"{}{}{} {} - successful{}{}",
|
||||
style::Bold,
|
||||
color::Fg(color::AnsiValue(46)),
|
||||
command.to_string(),
|
||||
recipe.name.as_str(),
|
||||
color::Fg(color::Reset),
|
||||
style::Reset,
|
||||
);
|
||||
}
|
||||
eprintln!(
|
||||
"{}{}{} {} - successful{}{}",
|
||||
style::Bold,
|
||||
color::Fg(color::AnsiValue(46)),
|
||||
command.to_string(),
|
||||
recipe.name.as_str(),
|
||||
color::Fg(color::Reset),
|
||||
style::Reset,
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
if config.cook.nonstop && verbose {
|
||||
@ -264,12 +263,48 @@ fn repo_inner(
|
||||
recipe: &CookRecipe,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
Ok(match *command {
|
||||
CliCommand::Fetch => {
|
||||
handle_fetch(recipe, config, &None)?;
|
||||
}
|
||||
CliCommand::Cook => {
|
||||
let source_dir = handle_fetch(recipe, config, &None)?;
|
||||
handle_cook(recipe, config, source_dir, recipe.is_deps, &None)?
|
||||
CliCommand::Fetch | CliCommand::Cook => {
|
||||
let repo_inner_fn = move |logger: &PtyOut| -> Result<(), anyhow::Error> {
|
||||
let source_dir = handle_fetch(recipe, config, logger)?;
|
||||
if *command == CliCommand::Cook {
|
||||
handle_cook(recipe, config, source_dir, recipe.is_deps, logger)?;
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
let Some(log_path) = &config.logs_dir else {
|
||||
return repo_inner_fn(&None);
|
||||
};
|
||||
|
||||
let (status_tx, status_rx) = mpsc::channel::<StatusUpdate>();
|
||||
let (mut stdout_writer, mut stderr_writer) = setup_logger(&status_tx, &recipe.name);
|
||||
let mut app = TuiApp::new(vec![recipe.clone()]);
|
||||
app.dump_logs_anyway = true;
|
||||
let th = thread::spawn(move || {
|
||||
while let Ok(update) = status_rx.recv() {
|
||||
let mut should_break = false;
|
||||
if let StatusUpdate::FlushLog(_p, _q) = &update {
|
||||
should_break = true;
|
||||
}
|
||||
app.update_status(update);
|
||||
if should_break {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
let mut logger = Some((&mut stdout_writer, &mut stderr_writer));
|
||||
let result = repo_inner_fn(&logger);
|
||||
if let Err(err_ctx) = &result {
|
||||
log_to_pty!(&logger, "\n{:?}", err_ctx)
|
||||
}
|
||||
// successful fetch is not that useful to log
|
||||
if *command == CliCommand::Cook || result.is_err() {
|
||||
flush_pty(&mut logger);
|
||||
let log_path = log_path.join(format!("{}.log", recipe.name.as_str()));
|
||||
status_tx
|
||||
.send(StatusUpdate::FlushLog(recipe.name.clone(), log_path))
|
||||
.unwrap_or_default();
|
||||
}
|
||||
let _ = th.join();
|
||||
}
|
||||
CliCommand::Unfetch => handle_clean(recipe, config, true, true)?,
|
||||
CliCommand::Clean => handle_clean(recipe, config, false, true)?,
|
||||
@ -598,7 +633,7 @@ enum RecipeStatus {
|
||||
Failed(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
enum StatusUpdate {
|
||||
StartFetch(PackageName),
|
||||
Fetched(CookRecipe),
|
||||
@ -650,6 +685,7 @@ struct TuiApp {
|
||||
cook_panel_rect: Option<Rect>,
|
||||
log_panel_rect: Option<Rect>,
|
||||
prompt: Option<FailurePrompt>,
|
||||
dump_logs_anyway: bool,
|
||||
dump_logs_on_exit: Option<(PackageName, String)>,
|
||||
}
|
||||
|
||||
@ -681,6 +717,7 @@ impl TuiApp {
|
||||
cook_panel_rect: None,
|
||||
log_panel_rect: None,
|
||||
prompt: None,
|
||||
dump_logs_anyway: false,
|
||||
dump_logs_on_exit: None,
|
||||
}
|
||||
}
|
||||
@ -759,6 +796,9 @@ impl TuiApp {
|
||||
StatusUpdate::PushLog(name, chunk) => {
|
||||
let buffer = self.log_byte_buffer.entry(name.clone()).or_default();
|
||||
buffer.extend_from_slice(&chunk);
|
||||
if self.dump_logs_anyway {
|
||||
let _ = std::io::stdout().write_all(&chunk);
|
||||
}
|
||||
let log_list = self.logs.entry(name.clone()).or_default();
|
||||
while let Some(newline_pos) = buffer.iter().position(|&b| b == b'\n') {
|
||||
let line_bytes = buffer.drain(..=newline_pos).collect::<Vec<u8>>();
|
||||
@ -842,12 +882,12 @@ fn run_tui_cook(
|
||||
'done: for (recipe, source_dir) in work_rx {
|
||||
let name = recipe.name.clone();
|
||||
let is_deps = recipe.is_deps;
|
||||
cooker_status_tx
|
||||
.send(StatusUpdate::StartCook(name.clone()))
|
||||
.unwrap();
|
||||
let (mut stdout_writer, mut stderr_writer) = setup_logger(&cooker_status_tx, &name);
|
||||
let mut logger = Some((&mut stdout_writer, &mut stderr_writer));
|
||||
'again: loop {
|
||||
cooker_status_tx
|
||||
.send(StatusUpdate::StartCook(name.clone()))
|
||||
.unwrap();
|
||||
let handler = handle_cook(
|
||||
&recipe,
|
||||
&cooker_config,
|
||||
@ -937,14 +977,12 @@ fn run_tui_cook(
|
||||
let fetcher_handle = thread::spawn(move || {
|
||||
'done: for recipe in fetcher_recipes {
|
||||
let name = recipe.name.clone();
|
||||
fetcher_status_tx
|
||||
.send(StatusUpdate::StartFetch(name.clone()))
|
||||
.unwrap();
|
||||
|
||||
let (mut stdout_writer, mut stderr_writer) = setup_logger(&fetcher_status_tx, &name);
|
||||
let mut logger = Some((&mut stdout_writer, &mut stderr_writer));
|
||||
|
||||
'again: loop {
|
||||
fetcher_status_tx
|
||||
.send(StatusUpdate::StartFetch(name.clone()))
|
||||
.unwrap();
|
||||
let handler = handle_fetch(&recipe, &fetcher_config, &logger);
|
||||
if let Some(log_path) = fetcher_config.logs_dir.as_ref()
|
||||
// successful fetch log usually not that helpful
|
||||
|
||||
@ -12,12 +12,11 @@ pub struct CookConfigOpt {
|
||||
/// whether to use TUI to allow parallel build
|
||||
/// default value is yes if "CI" env unset and STDIN is open.
|
||||
pub tui: Option<bool>,
|
||||
/// whether to write logs to build/logs dir
|
||||
/// only usable when tui is used
|
||||
pub tui_logs: Option<bool>,
|
||||
/// whether to write logs to build/logs dir, default true on TUI
|
||||
pub logs: Option<bool>,
|
||||
/// whether to ignore build errors
|
||||
pub nonstop: Option<bool>,
|
||||
/// whether to print success recipes info and warnings
|
||||
/// whether to print verbose logs to certain commands
|
||||
/// build failure still be printed anyway
|
||||
pub verbose: Option<bool>,
|
||||
}
|
||||
@ -27,7 +26,7 @@ pub struct CookConfig {
|
||||
pub offline: bool,
|
||||
pub jobs: usize,
|
||||
pub tui: bool,
|
||||
pub tui_logs: bool,
|
||||
pub logs: bool,
|
||||
pub nonstop: bool,
|
||||
pub verbose: bool,
|
||||
}
|
||||
@ -38,7 +37,7 @@ impl From<CookConfigOpt> for CookConfig {
|
||||
offline: value.offline.unwrap(),
|
||||
jobs: value.jobs.unwrap(),
|
||||
tui: value.tui.unwrap(),
|
||||
tui_logs: value.tui_logs.unwrap(),
|
||||
logs: value.logs.unwrap(),
|
||||
nonstop: value.nonstop.unwrap(),
|
||||
verbose: value.verbose.unwrap(),
|
||||
}
|
||||
@ -80,8 +79,8 @@ pub fn init_config() {
|
||||
.unwrap_or(1),
|
||||
));
|
||||
}
|
||||
if config.cook_opt.tui_logs.is_none() {
|
||||
config.cook_opt.tui_logs = config.cook_opt.tui;
|
||||
if config.cook_opt.logs.is_none() {
|
||||
config.cook_opt.logs = Some(extract_env("COOKBOOK_LOGS", config.cook_opt.tui.unwrap()));
|
||||
}
|
||||
if config.cook_opt.offline.is_none() {
|
||||
config.cook_opt.offline = Some(extract_env("COOKBOOK_OFFLINE", false));
|
||||
|
||||
@ -29,6 +29,7 @@ fn auto_deps_from_dynamic_linking(
|
||||
) -> BTreeSet<PackageName> {
|
||||
let mut paths = BTreeSet::new();
|
||||
let mut visited = BTreeSet::new();
|
||||
let verbose = crate::config::get_config().cook.verbose;
|
||||
// Base directories may need to be updated for packages that place binaries in odd locations.
|
||||
let mut walk = VecDeque::from([
|
||||
stage_dir.join("libexec"),
|
||||
@ -95,7 +96,9 @@ fn auto_deps_from_dynamic_linking(
|
||||
continue;
|
||||
};
|
||||
if let Ok(relative_path) = path.strip_prefix(stage_dir) {
|
||||
log_to_pty!(logger, "DEBUG: {} needs {}", relative_path.display(), name);
|
||||
if verbose {
|
||||
log_to_pty!(logger, "DEBUG: {} needs {}", relative_path.display(), name);
|
||||
}
|
||||
}
|
||||
needed.insert(name.to_string());
|
||||
}
|
||||
@ -129,7 +132,9 @@ fn auto_deps_from_dynamic_linking(
|
||||
continue;
|
||||
};
|
||||
if needed.contains(child_name) {
|
||||
log_to_pty!(logger, "DEBUG: {} provides {}", dep, child_name);
|
||||
if verbose {
|
||||
log_to_pty!(logger, "DEBUG: {} provides {}", dep, child_name);
|
||||
}
|
||||
deps.insert(dep.clone());
|
||||
missing.remove(child_name);
|
||||
}
|
||||
@ -138,8 +143,10 @@ fn auto_deps_from_dynamic_linking(
|
||||
}
|
||||
}
|
||||
|
||||
for name in missing {
|
||||
log_to_pty!(logger, "WARN: {} missing", name);
|
||||
if verbose {
|
||||
for name in missing {
|
||||
log_to_pty!(logger, "INFO: {} missing", name);
|
||||
}
|
||||
}
|
||||
|
||||
deps
|
||||
@ -171,6 +178,8 @@ pub fn build(
|
||||
) -> Result<(PathBuf, BTreeSet<PackageName>), String> {
|
||||
let sysroot_dir = target_dir.join("sysroot");
|
||||
let stage_dir = target_dir.join("stage");
|
||||
let cli_verbose = crate::config::get_config().cook.verbose;
|
||||
let cli_jobs = crate::config::get_config().cook.jobs;
|
||||
if recipe.build.kind == BuildKind::None {
|
||||
// metapackages don't need to do anything here
|
||||
return Ok((stage_dir, BTreeSet::new()));
|
||||
@ -207,12 +216,7 @@ pub fn build(
|
||||
if sysroot_dir.is_dir() {
|
||||
let sysroot_modified = modified_dir(&sysroot_dir)?;
|
||||
if sysroot_modified < source_modified || sysroot_modified < deps_modified {
|
||||
log_to_pty!(
|
||||
logger,
|
||||
"DEBUG: '{}' newer than '{}'",
|
||||
source_dir.display(),
|
||||
sysroot_dir.display()
|
||||
);
|
||||
log_to_pty!(logger, "DEBUG: updating '{}'", sysroot_dir.display());
|
||||
remove_all(&sysroot_dir)?;
|
||||
}
|
||||
}
|
||||
@ -257,12 +261,7 @@ pub fn build(
|
||||
if stage_dir.is_dir() {
|
||||
let stage_modified = modified_dir(&stage_dir)?;
|
||||
if stage_modified < source_modified || stage_modified < deps_modified {
|
||||
log_to_pty!(
|
||||
logger,
|
||||
"DEBUG: '{}' newer than '{}'",
|
||||
source_dir.display(),
|
||||
stage_dir.display()
|
||||
);
|
||||
log_to_pty!(logger, "DEBUG: updating '{}'", stage_dir.display());
|
||||
remove_all(&stage_dir)?;
|
||||
}
|
||||
}
|
||||
@ -328,10 +327,10 @@ pub fn build(
|
||||
let cookbook_stage = stage_dir_tmp.canonicalize().unwrap();
|
||||
let cookbook_source = source_dir.canonicalize().unwrap();
|
||||
let cookbook_sysroot = sysroot_dir.canonicalize().unwrap();
|
||||
|
||||
let bash_args = if cli_verbose { "-ex" } else { "-e" };
|
||||
let mut command = if is_redox() {
|
||||
let mut command = Command::new("bash");
|
||||
command.arg("-ex");
|
||||
command.arg(bash_args);
|
||||
command.env("COOKBOOK_REDOXER", "cargo");
|
||||
command
|
||||
} else {
|
||||
@ -339,7 +338,7 @@ pub fn build(
|
||||
.canonicalize()
|
||||
.unwrap_or(PathBuf::from("/bin/false"));
|
||||
let mut command = Command::new(&cookbook_redoxer);
|
||||
command.arg("env").arg("bash").arg("-ex");
|
||||
command.arg("env").arg("bash").arg(bash_args);
|
||||
command.env("COOKBOOK_REDOXER", &cookbook_redoxer);
|
||||
command
|
||||
};
|
||||
@ -351,6 +350,10 @@ pub fn build(
|
||||
command.env("COOKBOOK_STAGE", &cookbook_stage);
|
||||
command.env("COOKBOOK_SOURCE", &cookbook_source);
|
||||
command.env("COOKBOOK_SYSROOT", &cookbook_sysroot);
|
||||
command.env("COOKBOOK_MAKE_JOBS", cli_jobs.to_string());
|
||||
if cli_verbose {
|
||||
command.env("COOKBOOK_VERBOSE", "1");
|
||||
}
|
||||
if offline_mode {
|
||||
command.env("COOKBOOK_OFFLINE", "1");
|
||||
}
|
||||
|
||||
@ -364,11 +364,14 @@ pub(crate) fn fetch_extract_tar(
|
||||
logger: &PtyOut,
|
||||
) -> Result<(), String> {
|
||||
let mut command = Command::new("tar");
|
||||
let verbose = crate::config::get_config().cook.verbose;
|
||||
if is_redox() {
|
||||
command.arg("xvf");
|
||||
command.arg(if verbose { "xvf" } else { "xf" });
|
||||
} else {
|
||||
command.arg("--extract");
|
||||
command.arg("--verbose");
|
||||
if verbose {
|
||||
command.arg("--verbose");
|
||||
}
|
||||
command.arg("--file");
|
||||
}
|
||||
command.arg(&source_tar);
|
||||
|
||||
@ -44,12 +44,7 @@ pub fn package(
|
||||
if package_file.is_file() {
|
||||
let stage_modified = modified_dir(stage_dir)?;
|
||||
if modified(&package_file)? < stage_modified {
|
||||
log_to_pty!(
|
||||
logger,
|
||||
"DEBUG: '{}' newer than '{}'",
|
||||
stage_dir.display(),
|
||||
package_file.display()
|
||||
);
|
||||
log_to_pty!(logger, "DEBUG: updating '{}'", package_file.display());
|
||||
remove_all(&package_file)?;
|
||||
remove_all(&package_meta)?;
|
||||
}
|
||||
|
||||
@ -11,11 +11,11 @@ function DYNAMIC_INIT {
|
||||
|
||||
if [ "${TARGET}" != "x86_64-unknown-redox" ]
|
||||
then
|
||||
echo "WARN: ${TARGET} does not support dynamic linking." >&2
|
||||
[ -z "${COOKBOOK_VERBOSE}" ] || echo "WARN: ${TARGET} does not support dynamic linking." >&2
|
||||
return
|
||||
fi
|
||||
|
||||
echo "DEBUG: Program is being compiled dynamically."
|
||||
[ -z "${COOKBOOK_VERBOSE}" ] || echo "DEBUG: Program is being compiled dynamically."
|
||||
|
||||
COOKBOOK_CONFIGURE_FLAGS=(
|
||||
--host="${GNU_TARGET}"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user