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
asciiquarium using 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's libexec directory.
- Copy the main
asciiquarium script directly into the formula's bin directory.
- Make the main script executable.
- Create necessary environment wrappers (e.g., setting
PERL5LIB) for any executables installed by the resources into libexec/bin, placing these wrappers in the formula's bin directory.
- 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) to PREFIX/bin.
- Set appropriate executable permissions (
chmod 0755).
- Check for any executables installed by resources into
libexec/bin and create wrappers for them in PREFIX/bin that set up the necessary environment (e.g., PERL5LIB pointing to libexec/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 ...
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 becausesapphire'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 tolibexec, setting up environment wrappers) rather than a conventional build process.Steps to Reproduce
asciiquariumusing the build from source flag, preferably with verbose logging:Expected Behavior
sapphireshould recognize thatasciiquariumdoesn't have a standard build system and apply the appropriate installation logic for script-based formulas, similar to how Homebrew handles it:Curses,Term::Animation) into the formula'slibexecdirectory.asciiquariumscript directly into the formula'sbindirectory.PERL5LIB) for any executables installed by the resources intolibexec/bin, placing these wrappers in the formula'sbindirectory.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
(Full verbose logs can be provided if needed)
Environment
15.3.2(Apple Silicon /arm64/aarch64)v1.88.0-nightlyAnalysis / Suggested Solution
The core issue is that the current build logic in
sapphire-core/src/build/formula/source/mod.rs(specifically withindetect_and_build_in_cwdor similar) assumes a standard build system exists. For "no-build" script formulas likeasciiquarium, 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):
libexec, potentially handled by the existing resource loop).asciiquarium) toPREFIX/bin.chmod 0755).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: