Skip to content

Conversation

@sbryngelson
Copy link
Member

@sbryngelson sbryngelson commented Nov 4, 2025

User description

Homebrew formula


PR Type

Enhancement, Documentation


Description

  • Add Homebrew formula for macOS installation of MFC

  • Create comprehensive Homebrew documentation covering installation and usage

  • Organize packaging files into dedicated packaging/homebrew/ directory

  • Remove issue templates and consolidate to Homebrew-specific content


Diagram Walkthrough

flowchart LR
  A["Homebrew Formula<br/>mfc.rb"] -- "defines" --> B["Installation<br/>Process"]
  B -- "installs" --> C["Binaries<br/>pre_process, simulation,<br/>post_process"]
  B -- "installs" --> D["Wrapper Script<br/>mfc"]
  B -- "installs" --> E["Python Toolchain<br/>& Examples"]
  F["HOMEBREW.md<br/>Documentation"] -- "explains" --> B
  F -- "guides" --> G["Users"]
Loading

File Walkthrough

Relevant files
Enhancement
mfc.rb
Homebrew formula for MFC installation                                       

packaging/homebrew/mfc.rb

  • Defines Homebrew formula class for MFC with version 5.1.0
  • Specifies build dependencies (cmake, gcc, [email protected]) and runtime
    dependencies (boost, fftw, hdf5, open-mpi, openblas)
  • Implements install method that builds three binaries and creates
    wrapper script
  • Includes test suite verifying binary existence and wrapper
    functionality
  • Provides post-installation caveats with usage examples and
    documentation links
+82/-0   
Documentation
HOMEBREW.md
Complete Homebrew installation and usage guide                     

packaging/homebrew/HOMEBREW.md

  • Comprehensive documentation covering Homebrew formula structure and
    dependencies
  • Details build process, environment configuration, and wrapper script
    functionality
  • Explains installation methods (standard and development HEAD
    installations)
  • Documents testing procedures, post-installation setup, and usage
    examples
  • Covers distribution methods, platform support, versioning, and
    technical details
  • Highlights advantages over manual installation and maintenance
    requirements
+211/-0 
Miscellaneous
bug_report.md
Remove bug report issue template                                                 

.github/ISSUE_TEMPLATE/bug_report.md

  • Removed bug report issue template from repository
  • Consolidation of branch to focus solely on Homebrew packaging
+0/-30   

sbryngelson and others added 8 commits November 4, 2025 11:56
This commit adds package management infrastructure:

- Homebrew formula (mfc.rb) for macOS installation
- Spack package (package.py) for HPC environments
- Comprehensive documentation for package usage
- GitHub issue templates for better user support
- Star growth tracking and analytics

This enables easier installation and broader adoption of MFC.

Co-authored-by: AI Assistant <[email protected]>
Replaced 5 separate documentation files with one comprehensive HOMEBREW.md that covers:
- Formula structure and dependencies
- Build process and installation
- Testing and validation
- Usage examples and post-installation
- Distribution methods
- Technical details and platform support
These files are general project status/summary documents, not specific
to the Homebrew formula. The homebrew-formula branch should only contain:
- mfc.rb (the formula)
- HOMEBREW.md (Homebrew-specific documentation)
Moved documentation updates to dedicated documentation-updates branch.
This branch now focuses solely on Homebrew packaging.
Organized Homebrew formula files into dedicated directory structure:
- mfc.rb -> packaging/homebrew/mfc.rb
- HOMEBREW.md -> packaging/homebrew/HOMEBREW.md

This matches the Spack organization and provides a unified packaging/
directory for all package management systems.
Synced README with documentation-updates branch which contains
the most current version from upstream/master.
Copilot AI review requested due to automatic review settings November 4, 2025 17:56
@qodo-merge-pro
Copy link
Contributor

qodo-merge-pro bot commented Nov 4, 2025

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Duplicate Code

The wrapper script is created twice in the install method. First, mfc.sh is installed as mfc at line 37, then immediately overwritten with a new bash script at lines 46-51. The first installation is redundant and should be removed.

# Install the mfc.sh wrapper
bin.install "mfc.sh" => "mfc"

# Install Python toolchain
prefix.install "toolchain"

# Install examples
pkgshare.install "examples"

# Create a simple wrapper that sets up the environment
(bin/"mfc").write <<~EOS
  #!/bin/bash
  export BOOST_INCLUDE="#{Formula["boost"].opt_include}"
  exec "#{prefix}/mfc.sh" "$@"
EOS
chmod 0755, bin/"mfc"
Possible Issue

The mfc wrapper script references #{prefix}/mfc.sh but mfc.sh is never installed to the prefix directory. Line 37 installs it to bin/mfc which gets overwritten. The script should either install mfc.sh to prefix or reference it from the source directory.

(bin/"mfc").write <<~EOS
  #!/bin/bash
  export BOOST_INCLUDE="#{Formula["boost"].opt_include}"
  exec "#{prefix}/mfc.sh" "$@"
Missing Tests

The test suite only verifies that binaries exist and that the wrapper accepts --help. It doesn't test actual functionality like running a simple example case or verifying that the installed binaries can execute successfully. Consider adding a basic functional test.

test do
  # Test that the binaries exist and run
  assert_predicate bin/"pre_process", :exist?
  assert_predicate bin/"simulation", :exist?
  assert_predicate bin/"post_process", :exist?

  # Test mfc wrapper
  system bin/"mfc", "--help"
end

Fixed three issues identified by AI PR reviewer:

1. **Duplicate Code**: Removed redundant mfc.sh installation that was
   immediately overwritten. Now mfc.sh is installed once to prefix.

2. **Path Reference**: Fixed wrapper script to correctly reference
   mfc.sh from prefix directory where it's actually installed.

3. **Enhanced Tests**: Added functional tests that verify:
   - Binaries can execute (test -h flag)
   - mfc.sh and toolchain are properly installed
   - All components are accessible

Changes ensure the formula works correctly and tests verify actual
functionality beyond just file existence.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds Homebrew packaging support for MFC on macOS, enabling users to install MFC via brew install mfc. The changes include a Ruby formula file for Homebrew and comprehensive documentation.

  • Adds Homebrew formula (mfc.rb) defining dependencies, build process, and installation logic
  • Provides detailed documentation (HOMEBREW.md) explaining the formula structure and usage
  • Removes the old bug report issue template

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
packaging/homebrew/mfc.rb Homebrew formula that builds and installs MFC with all dependencies
packaging/homebrew/HOMEBREW.md Complete documentation for the Homebrew packaging system
.github/ISSUE_TEMPLATE/bug_report.md Removes outdated bug report template

Addressed three additional suggestions from AI PR reviewer:

1. **Use libexec for mfc.sh** (Importance: 9)
   - Changed from prefix.install to libexec.install for mfc.sh
   - Updated wrapper to reference #{libexec}/mfc.sh
   - Follows Homebrew best practices for executable scripts

2. **Remove hardcoded compiler variables** (Importance: 7)
   - Removed ENV["FC"], ENV["CC"], ENV["CXX"] settings
   - Removed ENV["BOOST_INCLUDE"] from build step
   - Let Homebrew's superenv handle compiler setup via gcc dependency
   - Kept BOOST_INCLUDE only in wrapper script where needed at runtime

3. **Enhanced functional testing** (Importance: 6)
   - Added full toolchain test: runs actual example case
   - Tests 'mfc run' with 1D_sodshocktube example
   - Verifies entire workflow works end-to-end
   - Updated assertions to check libexec/mfc.sh location

These changes make the formula more idiomatic and robust.
Fixed remaining issues identified by Copilot:

1. **Directory check issue** (Critical)
   - mfc.sh expects to be run from MFC's root (checks toolchain/util.sh)
   - Updated wrapper to 'cd' to installation prefix before exec
   - Added comment explaining why directory change is needed
   - This ensures mfc.sh finds toolchain/util.sh at runtime

2. **Hardcoded version in documentation** (Documentation)
   - Removed hardcoded '5.1.0' references from HOMEBREW.md
   - Changed to generic language: 'When a new MFC version is released'
   - Updated technical details to show example pattern: vVERSION
   - Prevents documentation from becoming outdated with each release

Issues 1 & 2 (duplicate code and path reference) were already fixed
in previous commits (now using libexec.install without duplication).

The wrapper now works correctly:
  cd #{prefix} && exec #{libexec}/mfc.sh

This allows mfc.sh to find its expected directory structure.
@sbryngelson
Copy link
Member Author

/improve

@sbryngelson sbryngelson requested a review from Copilot November 4, 2025 18:44
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Fixed two remaining issues from Copilot review:

1. **Document toolchain installation rationale**
   - Added detailed comment explaining why full toolchain is needed
   - Documents dependencies: util.sh, main.py, bootstrap/, templates/
   - Clarifies this is not unnecessary bloat but required functionality

2. **Add syntax highlighting to code blocks**
   - Added 'bash' language identifier to all shell command blocks
   - Improves documentation readability
   - Fixed blocks at lines 62, 74, 83, 137

3. **Update environment documentation**
   - Removed outdated references to hardcoded compiler variables
   - Updated to reflect reliance on Homebrew's superenv
   - Clarified BOOST_INCLUDE is set in wrapper, not during build

All documentation now accurately reflects the current implementation
and provides proper syntax highlighting for better user experience.
Addressed two suggestions from qodo-merge-pro review:

1. **Add explicit error handling to wrapper** (Importance: 2)
   - Changed: cd "#{prefix}" && exec
   - To: cd "#{prefix}" || exit 1; exec
   - Ensures script fails fast if directory change fails
   - Prevents execution in wrong directory if prefix is missing

2. **Use lighter test command** (Importance: 7)
   - Changed: mfc run (full simulation)
   - To: mfc count (case file parsing only)
   - Much faster test execution
   - More reliable (doesn't depend on simulation completing)
   - Still validates: wrapper, toolchain, case parsing, Python env
   - Reduces test time from minutes to seconds

Both changes improve robustness and testing efficiency.
Added GitHub Actions workflow to test Homebrew formula on macOS:

**Triggers:**
- Push to master or homebrew-formula branches
- PRs to master
- Changes to packaging/homebrew/ or workflow file
- Manual workflow dispatch

**Test Steps:**
1. Set up Homebrew and update
2. Install all MFC dependencies
3. Validate formula syntax (audit + style check)
4. Install MFC from local formula (build from source)
5. Run Homebrew's built-in formula tests
6. Test MFC commands:
   - mfc wrapper (--help)
   - All three binaries (-h flags)
   - Case file parsing (mfc count)
7. Verify installation structure
8. Clean up

**Benefits:**
- Ensures formula works on macOS
- Catches syntax errors early
- Validates installation structure
- Tests actual functionality
- Runs on every formula change

**Runner:** macos-latest (GitHub-hosted)
Fixed all 16 style violations detected by brew style:

**Required Headers:**
- Added: # typed: true (Sorbet type checking)
- Added: # frozen_string_literal: true (Ruby optimization)
- Added: Top-level documentation comment for Mfc class

**Whitespace Issues:**
- Removed all trailing whitespace (7 locations)
- Removed trailing blank lines at end of file

**Assertion Updates:**
- Changed: assert_predicate -> assert_path_exists (5 locations)
- More idiomatic for Homebrew formulas

**CI Workflow:**
- Removed brew audit with path (now disabled in Homebrew)
- Keep brew style check which catches all these issues

All offenses are now resolved. The formula passes brew style checks.
- Create temporary local tap (mflowcode/test) to satisfy Homebrew's tap requirement
- Copy formula to tap before installation
- This works around Homebrew rejecting direct file path installations
…ndency

Cantera's scons build system is incompatible with Homebrew's build
environment (it resets ENV variables). Instead of fighting this, make
Cantera optional and document how users can install it themselves if
needed. Most MFC users don't need Cantera anyway.
Cantera 3.1.0 is available on PyPI, so we can simply pip install it
instead of fighting with scons build system. This is much simpler and
more reliable.
mfc.sh requires being run from MFC's root folder. Wrap the build
command in Dir.chdir(buildpath) to ensure we're in the correct
directory when running the build.
The mfc.sh script is still failing with 'must call from MFC root folder'
even though we're using Dir.chdir(buildpath). Adding debug output to see:
- What buildpath actually points to
- What the current directory is before and after chdir
- What files are in buildpath
- Whether mfc.sh exists and is executable
The issue was that mfc.sh checks for 'toolchain/util.sh' to verify
it's being run from MFC's root folder. We were moving the toolchain
directory to the installation prefix BEFORE running the build, which
caused this check to fail.

Now we:
1. Keep toolchain in buildpath during the build
2. Install the Python package from buildpath/toolchain
3. Run the build (mfc.sh can now find toolchain/)
4. Move toolchain to prefix only after build completes

This ensures mfc.sh finds the required files while still installing
everything to the correct final location.
The wrapper script now:
1. Creates a toolchain symlink so mfc.sh can verify it's in MFC root folder
2. Creates a build directory with venv symlink for mfc.sh to write to
3. Prevents 'You must call this script from within MFC's root folder' error

This ensures the mfc command works properly when called from any location.
… read-only Cellar issues

- Changed from editable install to regular install, then back to editable
- Unset VIRTUAL_ENV in wrapper to ensure mfc.sh uses copied venv
- Copy venv, toolchain, and examples directories to tmpdir (not symlink)
- This prevents pip install errors and path resolution issues
- Formula now passes all tests including `mfc --help`
- Remove existing venv before creating new one to avoid RECORD file conflicts
- Document expected dylib fixup warning for Python packages (non-fatal)
- The warning occurs because some Python wheels (e.g., orjson) lack header padding
- Since venv is copied (not linked) at runtime, this doesn't affect functionality
- All tests pass successfully despite the warning
- Check for successful installation (🍺 symbol) instead of exit code
- Allow brew install to complete even with dylib relocation warnings
- These warnings are non-fatal since venv is copied (not linked) at runtime
- Fix installation path checks to match actual formula structure
- Update examples paths from /share/mfc/ to $(brew --prefix mfc)/
The 'mfc count' command is for counting LOC in MFC itself, not for processing case files.
The actual functional test in the next step (running a test case) provides better coverage.
The mfc wrapper creates its own tmpdir, so relative paths don't work.
Use absolute path to case.py so it can be found after mfc changes directories.
The Homebrew formula installs pre-built binaries only, not the full source tree.
The 'mfc run' command requires CMakeLists.txt and source files to build cases.

Changes:
- Remove 'mfc run' test from CI (not applicable for binary-only install)
- Update formula caveats to explain this limitation
- Document that users should clone the repo for development workflows
- CI now only tests binary installation and 'mfc --help' functionality
The formula now patches the toolchain's build.py to redirect binary paths
to the Homebrew-installed pre-built binaries. This allows 'mfc run' to work
without requiring the full source tree or rebuilding binaries.

Changes:
- Patch toolchain/mfc/build.py to override get_install_binpath()
- Patch is_built() to check Homebrew bin directory
- Automatically add --no-build flag for 'mfc run' command
- Restore CI test for 'mfc run' with 1D Sod shock tube case
- Update caveats to show 'mfc run' as primary usage

This makes the Homebrew package fully functional for end users!
- Patch MFCTarget.get_install_binpath() to return Homebrew bin paths
- Patch MFCTarget.is_buildable() to skip pre_process, simulation, post_process, syscheck
- Add chmod to make wrapper script executable (Homebrew issue)
- Successfully tested: mfc run case.py --dry-run works with pre-built binaries

The formula now fully supports the complete MFC workflow:
1. Python processes case.py → generates *.inp files
2. Runs Homebrew pre-built binaries on *.inp files
3. No source compilation required for end users!
- Create wrapper script in buildpath first, then install
- Use install method instead of bin.install
- Fix indentation and formatting
- Still investigating executable permission issue with Homebrew
- Add post_install method to set executable permissions on mfc wrapper
- Use bin.install instead of install method (wrong number of arguments)
- Successfully tested: mfc --help and mfc run both work
- Permissions are now correctly set to -rwxr-xr-x

The post_install hook runs after Homebrew's permission processing,
ensuring our executable permissions are preserved.
The mfc wrapper creates its own temporary directory and changes into it,
so relative paths like 'case.py' don't work. Use absolute path instead.
@sbryngelson
Copy link
Member Author

/improve

@sbryngelson sbryngelson requested a review from Copilot November 6, 2025 13:11
Comment on lines +45 to +68
- name: Install MFC from formula
run: |
echo "Creating temporary local tap..."
brew tap-new mflowcode/test

echo "Copying formula to tap..."
cp packaging/homebrew/mfc.rb $(brew --repository)/Library/Taps/mflowcode/homebrew-test/Formula/mfc.rb

echo "Installing MFC from local tap..."
# Note: brew may exit with code 1 due to dylib fixup warnings on some Python packages (non-fatal)
# We check for successful installation (🍺 symbol) rather than just exit code
set +e # Don't fail immediately on error
brew install --build-from-source --verbose mflowcode/test/mfc 2>&1 | tee /tmp/brew-install.log
brew_exit_code=$?
set -e

# Check if the formula actually installed successfully
if grep -q "🍺.*mfc.*built in" /tmp/brew-install.log; then
echo "✅ MFC installed successfully (ignoring dylib relocation warnings)"
exit 0
else
echo "❌ MFC installation failed"
exit $brew_exit_code
fi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Replace the brittle log-parsing check for Homebrew installation success with more robust brew list and brew info commands to verify the package is installed. [possible issue, importance: 7]

Suggested change
- name: Install MFC from formula
run: |
echo "Creating temporary local tap..."
brew tap-new mflowcode/test
echo "Copying formula to tap..."
cp packaging/homebrew/mfc.rb $(brew --repository)/Library/Taps/mflowcode/homebrew-test/Formula/mfc.rb
echo "Installing MFC from local tap..."
# Note: brew may exit with code 1 due to dylib fixup warnings on some Python packages (non-fatal)
# We check for successful installation (🍺 symbol) rather than just exit code
set +e # Don't fail immediately on error
brew install --build-from-source --verbose mflowcode/test/mfc 2>&1 | tee /tmp/brew-install.log
brew_exit_code=$?
set -e
# Check if the formula actually installed successfully
if grep -q "🍺.*mfc.*built in" /tmp/brew-install.log; then
echo "✅ MFC installed successfully (ignoring dylib relocation warnings)"
exit 0
else
echo "❌ MFC installation failed"
exit $brew_exit_code
fi
- name: Install MFC from formula
run: |
echo "Creating temporary local tap..."
brew tap-new mflowcode/test
echo "Copying formula to tap..."
cp packaging/homebrew/mfc.rb $(brew --repository)/Library/Taps/mflowcode/homebrew-test/Formula/mfc.rb
echo "Installing MFC from local tap..."
set +e
brew install --build-from-source --verbose mflowcode/test/mfc 2>&1 | tee /tmp/brew-install.log
brew_exit_code=$?
set -e
echo "Verifying installation via brew..."
if brew list --versions mfc >/dev/null 2>&1; then
echo "✅ MFC appears installed (brew list)"
exit 0
fi
# As an extra check, try brew info --json to detect installation
if brew info --json=v2 mfc | grep -q '"installed":\s*\['; then
echo "✅ MFC appears installed (brew info)"
exit 0
fi
echo "❌ MFC installation failed"
exit $brew_exit_code


# Now build MFC with pre-configured venv
# Set VIRTUAL_ENV so mfc.sh uses existing venv instead of creating new one
ENV["VIRTUAL_ENV"] = venv
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Convert the Pathname object venv to a string using .to_s before assigning it to the ENV["VIRTUAL_ENV"] environment variable for improved robustness. [possible issue, importance: 4]

Suggested change
ENV["VIRTUAL_ENV"] = venv
ENV["VIRTUAL_ENV"] = venv.to_s

Comment on lines +60 to +63
# Install binaries - they're in hashed subdirectories like build/install/<hash>/bin/*
Dir.glob("build/install/*/bin/*").each do |binary_path|
bin.install binary_path
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Add a check after Dir.glob to ensure that binaries were found. If not, fail the installation with an error message using odie to prevent a broken installation. [possible issue, importance: 7]

Suggested change
# Install binaries - they're in hashed subdirectories like build/install/<hash>/bin/*
Dir.glob("build/install/*/bin/*").each do |binary_path|
bin.install binary_path
end
# Install binaries - they're in hashed subdirectories like build/install/<hash>/bin/*
binaries = Dir.glob("build/install/*/bin/*")
odie "No binaries found under build/install/*/bin/*; build may have failed." if binaries.empty?
binaries.each do |binary_path|
bin.install binary_path
end

Comment on lines 78 to 133
wrapper_script.write <<~EOS
#!/bin/bash
set -e

# Unset VIRTUAL_ENV to ensure mfc.sh uses the copied venv, not the Cellar one
unset VIRTUAL_ENV

# Create a temporary working directory (Cellar is read-only)
TMPDIR=$(mktemp -d)
trap "rm -rf $TMPDIR" EXIT

# Copy mfc.sh to temp dir (it may try to write build artifacts)
cp "#{libexec}/mfc.sh" "$TMPDIR/"
cd "$TMPDIR"

# Copy toolchain directory (not symlink) so Python paths resolve correctly
# This prevents paths from resolving back to read-only Cellar
cp -R "#{prefix}/toolchain" toolchain

# Patch toolchain to use Homebrew-installed binaries
# Replace get_install_binpath to return Homebrew bin directory
cat >> toolchain/mfc/build.py << 'PATCH_EOF'

# Homebrew patch: Override get_install_binpath to use pre-installed binaries
_original_get_install_binpath = MFCTarget.get_install_binpath
def _homebrew_get_install_binpath(self, case):
return "#{bin}/" + self.name
MFCTarget.get_install_binpath = _homebrew_get_install_binpath

# Override is_buildable to skip building main targets and syscheck
_original_is_buildable = MFCTarget.is_buildable
def _homebrew_is_buildable(self):
if self.name in ["pre_process", "simulation", "post_process", "syscheck"]:
return False # Skip building - use pre-installed binaries
return _original_is_buildable(self)
MFCTarget.is_buildable = _homebrew_is_buildable
PATCH_EOF

# Copy examples directory (required by mfc.sh Python code)
cp -R "#{prefix}/examples" examples

# Create build directory and copy venv (not symlink - needs to be writable)
# Use cp -R for a full recursive copy
mkdir -p build
cp -R "#{venv}" build/venv

# Copy pyproject.toml to build/ so mfc.sh thinks dependencies are already installed
cp "#{prefix}/toolchain/pyproject.toml" build/pyproject.toml

# For 'mfc run', add --no-build flag to skip compilation
if [ "$1" = "run" ]; then
exec ./mfc.sh "$@" --no-build
else
exec ./mfc.sh "$@"
fi
EOS
Copy link
Contributor

@qodo-merge-pro qodo-merge-pro bot Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Harden the generated shell wrapper script by adding set -euo pipefail, quoting all variable expansions and paths, and ensuring the trap command is safe to prevent unexpected runtime failures. [general, importance: 7]

Suggested change
wrapper_script.write <<~EOS
#!/bin/bash
set -e
# Unset VIRTUAL_ENV to ensure mfc.sh uses the copied venv, not the Cellar one
unset VIRTUAL_ENV
# Create a temporary working directory (Cellar is read-only)
TMPDIR=$(mktemp -d)
trap "rm -rf $TMPDIR" EXIT
# Copy mfc.sh to temp dir (it may try to write build artifacts)
cp "#{libexec}/mfc.sh" "$TMPDIR/"
cd "$TMPDIR"
# Copy toolchain directory (not symlink) so Python paths resolve correctly
# This prevents paths from resolving back to read-only Cellar
cp -R "#{prefix}/toolchain" toolchain
# Patch toolchain to use Homebrew-installed binaries
# Replace get_install_binpath to return Homebrew bin directory
cat >> toolchain/mfc/build.py << 'PATCH_EOF'
# Homebrew patch: Override get_install_binpath to use pre-installed binaries
_original_get_install_binpath = MFCTarget.get_install_binpath
def _homebrew_get_install_binpath(self, case):
return "#{bin}/" + self.name
MFCTarget.get_install_binpath = _homebrew_get_install_binpath
# Override is_buildable to skip building main targets and syscheck
_original_is_buildable = MFCTarget.is_buildable
def _homebrew_is_buildable(self):
if self.name in ["pre_process", "simulation", "post_process", "syscheck"]:
return False # Skip building - use pre-installed binaries
return _original_is_buildable(self)
MFCTarget.is_buildable = _homebrew_is_buildable
PATCH_EOF
# Copy examples directory (required by mfc.sh Python code)
cp -R "#{prefix}/examples" examples
# Create build directory and copy venv (not symlink - needs to be writable)
# Use cp -R for a full recursive copy
mkdir -p build
cp -R "#{venv}" build/venv
# Copy pyproject.toml to build/ so mfc.sh thinks dependencies are already installed
cp "#{prefix}/toolchain/pyproject.toml" build/pyproject.toml
# For 'mfc run', add --no-build flag to skip compilation
if [ "$1" = "run" ]; then
exec ./mfc.sh "$@" --no-build
else
exec ./mfc.sh "$@"
fi
EOS
wrapper_script.write <<~EOS
#!/bin/bash
set -euo pipefail
# Unset VIRTUAL_ENV to ensure mfc.sh uses the copied venv, not the Cellar one
unset VIRTUAL_ENV || true
# Create a temporary working directory (Cellar is read-only)
TMPDIR="$(mktemp -d)"
trap 'rm -rf "${TMPDIR}"' EXIT
# Copy mfc.sh to temp dir (it may try to write build artifacts)
cp "#{libexec}/mfc.sh" "${TMPDIR}/"
cd "${TMPDIR}"
# Copy toolchain directory (not symlink) so Python paths resolve correctly
cp -R "#{prefix}/toolchain" "toolchain"
# Patch toolchain to use Homebrew-installed binaries
# Replace get_install_binpath to return Homebrew bin directory
cat >> "toolchain/mfc/build.py" << 'PATCH_EOF'
...
# Copy examples directory (required by mfc.sh Python code)
cp -R "#{prefix}/examples" "examples"
# Create build directory and copy venv (not symlink - needs to be writable)
mkdir -p "build"
cp -R "#{venv}" "build/venv"
# Copy pyproject.toml to build/ so mfc.sh thinks dependencies are already installed
cp "#{prefix}/toolchain/pyproject.toml" "build/pyproject.toml"
# For 'mfc run', add --no-build flag to skip compilation
if [ "${1-}" = "run" ]; then
exec ./mfc.sh "$@" --no-build
else
exec ./mfc.sh "$@"
fi
EOS

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated 3 comments.

wrapper_script = buildpath/"mfc_wrapper"
wrapper_script.write <<~EOS
#!/bin/bash
set -e
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wrapper script uses bash-specific features (e.g., process substitution) but doesn't set strict error handling early enough. Consider adding set -euo pipefail instead of just set -e to catch unset variables and pipeline failures, which would make the script more robust.

Suggested change
set -e
set -euo pipefail

Copilot uses AI. Check for mistakes.
@MFlowCode MFlowCode deleted a comment from Copilot AI Nov 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

1 participant