|
| 1 | +# mcpp — modern C++23 build & package management tool. |
| 2 | +# |
| 3 | +# This formula ships the SAME prebuilt release artifacts that upstream's |
| 4 | +# `install.sh` one-liner downloads (mcpp-community/mcpp → release.yml). |
| 5 | +# |
| 6 | +# Why `mcpp-m` and not `mcpp`: homebrew-core already owns the name `mcpp` |
| 7 | +# (Matsui's C preprocessor). Same collision as Arch, where upstream ships |
| 8 | +# `mcpp-bin` / `mcpp-m`. `Aliases/` maps both of those spellings here, so |
| 9 | +# `brew install mcpp-community/mcpp/mcpp` works too once the tap is present. |
| 10 | +# |
| 11 | +# version / url / sha256 are rewritten by scripts/update-formula.sh — the |
| 12 | +# bump workflow owns those three lines, so don't hand-edit them. |
| 13 | +class McppM < Formula |
| 14 | + desc "Modern C++23 build and package management tool (module-first)" |
| 15 | + homepage "https://github.com/mcpp-community/mcpp" |
| 16 | + version "2026.7.30.3" |
| 17 | + license "Apache-2.0" |
| 18 | + |
| 19 | + # mcpp keeps its package index in sync over git. |
| 20 | + depends_on "git" |
| 21 | + |
| 22 | + on_macos do |
| 23 | + # Upstream publishes an arm64-only macOS artifact, built with minos 14.0 |
| 24 | + # (release.yml asserts it). Intel Macs have no asset — build from source |
| 25 | + # via `xlings install mcpp` or the install.sh one-liner instead. |
| 26 | + depends_on arch: :arm64 |
| 27 | + depends_on macos: :sonoma |
| 28 | + |
| 29 | + url "https://github.com/mcpp-community/mcpp/releases/download/v2026.7.30.3/mcpp-2026.7.30.3-macosx-arm64.tar.gz" |
| 30 | + sha256 "1659be17b3f54c495c224179a570dd220fcfead25bbcda0c6279b20afa6a4e18" |
| 31 | + end |
| 32 | + |
| 33 | + on_linux do |
| 34 | + on_intel do |
| 35 | + url "https://github.com/mcpp-community/mcpp/releases/download/v2026.7.30.3/mcpp-2026.7.30.3-linux-x86_64.tar.gz" |
| 36 | + sha256 "115cc537b17bfcaf5b5d13e0c7fcf9a591864cb6f18d10244e3828cfc1f8e1c4" |
| 37 | + end |
| 38 | + on_arm do |
| 39 | + url "https://github.com/mcpp-community/mcpp/releases/download/v2026.7.30.3/mcpp-2026.7.30.3-linux-aarch64.tar.gz" |
| 40 | + sha256 "aff78e9e04d0dfc09ef828b9a5aad3e1e4afff19de47b493a88bbbf803a00d14" |
| 41 | + end |
| 42 | + end |
| 43 | + |
| 44 | + livecheck do |
| 45 | + url :homepage |
| 46 | + strategy :github_latest |
| 47 | + end |
| 48 | + |
| 49 | + def install |
| 50 | + # The release tarball is a self-contained tree. Keep it whole under |
| 51 | + # libexec and put a launcher on PATH — see the wrapper comment below for |
| 52 | + # why a plain `bin.install` would break every write mcpp makes. |
| 53 | + libexec.install "bin" |
| 54 | + libexec.install "registry" if File.directory?("registry") |
| 55 | + |
| 56 | + # mcpp WRITES at runtime: registry sandbox, BMI/metadata caches, logs and |
| 57 | + # every toolchain it downloads (hundreds of MB). It resolves MCPP_HOME |
| 58 | + # from the running binary's *real* path (canonical, symlinks resolved), so |
| 59 | + # a bare symlink into the Cellar would make MCPP_HOME the Cellar version |
| 60 | + # dir — `brew upgrade` would then silently drop every installed toolchain. |
| 61 | + # Pin the two env knobs the binary honors, deferring to values the user |
| 62 | + # already exported. Mirrors the Arch launcher (upstream scripts/aur). |
| 63 | + (bin/"mcpp").write <<~SH |
| 64 | + #!/bin/sh |
| 65 | + export MCPP_HOME="${MCPP_HOME:-$HOME/.mcpp}" |
| 66 | + export MCPP_VENDORED_XLINGS="${MCPP_VENDORED_XLINGS:-#{libexec}/registry/bin/xlings}" |
| 67 | + exec "#{libexec}/bin/mcpp" "$@" |
| 68 | + SH |
| 69 | + chmod 0755, bin/"mcpp" |
| 70 | + |
| 71 | + prefix.install "LICENSE" if File.exist?("LICENSE") |
| 72 | + doc.install "README.md" if File.exist?("README.md") |
| 73 | + end |
| 74 | + |
| 75 | + def caveats |
| 76 | + <<~EOS |
| 77 | + mcpp keeps per-user state in ~/.mcpp (registry, caches, toolchains). |
| 78 | + Override with MCPP_HOME=<dir>; remove ~/.mcpp to reset. |
| 79 | +
|
| 80 | + The first `mcpp build` downloads a toolchain (LLVM on macOS) and may |
| 81 | + take a while. It is cached in ~/.mcpp and survives `brew upgrade`. |
| 82 | + EOS |
| 83 | + end |
| 84 | + |
| 85 | + test do |
| 86 | + assert_match version.to_s, shell_output("#{bin}/mcpp --version") |
| 87 | + assert_match "Usage:", shell_output("#{bin}/mcpp --help") |
| 88 | + |
| 89 | + # The launcher must pin MCPP_HOME outside the Cellar, or `brew upgrade` |
| 90 | + # would take the user's toolchains with it. Asserted statically: the |
| 91 | + # commands that would print the resolved home (`mcpp self env`) bootstrap |
| 92 | + # the sandbox over the network, which has no place in a formula test. |
| 93 | + launcher = (bin/"mcpp").read |
| 94 | + assert_match(/MCPP_HOME="\$\{MCPP_HOME:-\$HOME\/\.mcpp\}"/, launcher) |
| 95 | + assert_predicate libexec/"bin/mcpp", :executable? |
| 96 | + end |
| 97 | +end |
0 commit comments