-
Notifications
You must be signed in to change notification settings - Fork 20
Build from source fails for script-based formulas (e.g., asciiquarium) due to missing build system detection #10
Description
Description
When attempting to install certain formulas using --build-from-source, specifically those that consist primarily of scripts and don't use a standard build system (like Make, CMake, Autotools, etc.), the installation fails. This happens because sapphire's build logic attempts to detect a build system within the source directory and fails to find one, halting the installation.
A good example is asciiquarium, which is a Perl script. It requires specific installation steps (copying the main script, installing CPAN dependencies to libexec, setting up environment wrappers) rather than a conventional build process.
Steps to Reproduce
- Attempt to install
asciiquariumusing the build from source flag, preferably with verbose logging:sapphire install asciiquarium --build-from-source -vv
Expected Behavior
sapphire should recognize that asciiquarium doesn't have a standard build system and apply the appropriate installation logic for script-based formulas, similar to how Homebrew handles it:
- Install CPAN resources (like
Curses,Term::Animation) into the formula'slibexecdirectory. - Copy the main
asciiquariumscript directly into the formula'sbindirectory. - Make the main script executable.
- Create necessary environment wrappers (e.g., setting
PERL5LIB) for any executables installed by the resources intolibexec/bin, placing these wrappers in the formula'sbindirectory. - The installation should complete successfully.
Actual Behavior
The installation fails during the build phase after extracting the source code. The build system detection logic does not find a known system (Makefile, CMakeLists.txt, etc.) and errors out.
Relevant Log Output
# ... (Dependency resolution, download, extraction) ...
INFO sapphire_core::build::formula::source: ==> Building asciiquarium from source in /Users/alxknt/Library/Caches/brew-rs-client/build-temp/asciiquarium-yYHRq4
INFO sapphire_core::build::formula::source: ==> Setting up build environment
# ... (Build environment setup) ...
INFO sapphire_core::build::formula::source: Changing working directory to build dir: /Users/alxknt/Library/Caches/brew-rs-client/build-temp/asciiquarium-yYHRq4
INFO sapphire_core::build::formula::source: ==> Detecting build system and building main formula: asciiquarium
INFO sapphire_core::build::formula::source: Attempting to detect build system in current directory (CWD)
INFO sapphire_core::build::formula::source: No subdirectories found to check.
ERROR sapphire_core::build::formula::source: Could not determine build system in CWD or its immediate subdirectory.
DEBUG sapphire_core::build::formula::source: Restored working directory to: /Users/alxknt/Github/sapphire
ERROR sapphire::cli::install: install of asciiquarium failed: Generic Error: Could not determine build system in source directory.
ERROR sapphire::cli::install: Installation failed for:
ERROR sapphire::cli::install: ✖ asciiquarium: Generic Error: Could not determine build system in source directory.
Error: Installation Error: 1 bottle(s) failed to install.
(Full verbose logs can be provided if needed)
Environment
- OS: macOS
15.3.2(Apple Silicon /arm64/aarch64) - Rust Toolchain:
v1.88.0-nightly - Build Tools: Xcode Command Line Tools, Perl
Analysis / Suggested Solution
The core issue is that the current build logic in sapphire-core/src/build/formula/source/mod.rs (specifically within detect_and_build_in_cwd or similar) assumes a standard build system exists. For "no-build" script formulas like asciiquarium, this detection fails.
A potential solution, inspired by Homebrew's handling and the analysis provided [here/by user], involves adding a check before the standard build system detections (Autotools, CMake, etc.). This check could specifically look for script files matching the formula name in the extracted source directory.
If such a script is found (and perhaps other conditions are met, e.g., presence of Perl dependencies):
- Assume it's a script-based installation.
- Ensure CPAN/other resources are installed first (likely into
libexec, potentially handled by the existing resource loop). - Manually copy the main script (e.g.,
asciiquarium) toPREFIX/bin. - Set appropriate executable permissions (
chmod 0755). - Check for any executables installed by resources into
libexec/binand create wrappers for them inPREFIX/binthat set up the necessary environment (e.g.,PERL5LIBpointing tolibexec/lib/perl5).
A concrete implementation suggestion involves adding logic similar to this within detect_and_build_in_cwd:
// --- Add check for Script-only formulas (like Perl/Asciiquarium) ---
let script_name = formula.name();
let script_path = Path::new(".").join(&script_name); // Check in current (build) dir
if script_path.is_file() {
info!("Detected potential single-file script: {}", script_name);
// TODO: Add more checks? (e.g., formula language == Perl?)
// 1. Install script to bin
let bin_dir = install_dir.join("bin");
create_dir_all_with_context(&bin_dir, "bin directory")?;
let dest_script = bin_dir.join(&script_name);
fs::copy(&script_path, &dest_script).map_err(|e| /* ... error handling ... */ )?;
// Set executable permissions (e.g., 0o755 on Unix)
// ... platform-specific chmod ...
// 2. Wrap executables from libexec/bin (if any)
let libexec_bin = install_dir.join("libexec/bin");
if libexec_bin.is_dir() {
// ... logic to iterate files in libexec_bin ...
// ... create wrapper script in bin_dir for each exe ...
// ... wrapper sets env vars (e.g., PERL5LIB=install_dir/libexec/lib/perl5) ...
// ... wrapper execs the original exe from libexec_bin ...
// ... set executable permissions on the wrapper ...
}
// 3. Return Ok to bypass standard build system checks
return Ok(());
}
// ... existing Autotools / CMake / Meson / etc. checks ...