diff --git a/.github/workflows/test-macos-bootstrap.yml b/.github/workflows/test-macos-bootstrap.yml new file mode 100644 index 000000000..7535da777 --- /dev/null +++ b/.github/workflows/test-macos-bootstrap.yml @@ -0,0 +1,78 @@ +# SPDX-FileCopyrightText: 2026 Contributors to the p4lang/behavioral-model project +# +# SPDX-License-Identifier: Apache-2.0 + +name: Test macOS bootstrap script + +on: + pull_request: + branches: + - main + paths: + - 'tools/macos/bootstrap_mac.sh' + push: + branches: + - main + paths: + - 'tools/macos/bootstrap_mac.sh' + +# Cancel any preceding run on the pull request. +concurrency: + group: test-macos-bootstrap-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + check-changes: + name: Check whether tests need to be run based on diff + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: antrea-io/has-changes@v2 + id: check_diff + with: + paths-ignore: docs/* *.md + outputs: + has_changes: ${{ steps.check_diff.outputs.has_changes }} + + test-macos-bootstrap: + needs: check-changes + if: ${{ needs.check-changes.outputs.has_changes == 'yes' }} + runs-on: ${{ matrix.os }} + name: test-macos-bootstrap (${{ matrix.os }}) + strategy: + fail-fast: false + matrix: + os: + - macos-15 # arm64 (Apple Silicon, latest) + steps: + - uses: actions/checkout@v6 + with: + submodules: 'recursive' + + - name: Run macOS bootstrap script + run: | + bash tools/macos/bootstrap_mac.sh + + - name: Verify key dependencies were installed + run: | + brew list automake + brew list autoconf + brew list cmake + brew list boost + brew list gmp + brew list openssl + brew list pkg-config + python3 --version + pip3 --version + + - name: Build BMv2 + run: | + export PATH="$(brew --prefix bison)/bin:$PATH" + export PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig:$(brew --prefix jsoncpp)/lib/pkgconfig:$PKG_CONFIG_PATH" + export LDFLAGS="-L$(brew --prefix openssl)/lib -L$(brew --prefix thrift)/lib -L$(brew --prefix nanomsg)/lib -L$(brew --prefix gmp)/lib -L$(brew --prefix xxhash)/lib -L$(brew --prefix jsoncpp)/lib -L$(brew --prefix boost)/lib" + export CPPFLAGS="-I$(brew --prefix openssl)/include -I$(brew --prefix thrift)/include -I$(brew --prefix nanomsg)/include -I$(brew --prefix gmp)/include -I$(brew --prefix xxhash)/include -I$(brew --prefix jsoncpp)/include -I$(brew --prefix boost)/include" + ./autogen.sh + mkdir -p build && cd build + ../configure + make -j$(sysctl -n hw.logicalcpu) + diff --git a/tools/macos/bootstrap_mac.sh b/tools/macos/bootstrap_mac.sh index 0ee232b33..2e13ffb58 100755 --- a/tools/macos/bootstrap_mac.sh +++ b/tools/macos/bootstrap_mac.sh @@ -1,5 +1,4 @@ #! /bin/bash - # SPDX-FileCopyrightText: 2016 Barefoot Networks, Inc. # # SPDX-License-Identifier: Apache-2.0 @@ -7,58 +6,58 @@ set -e set -x -tools_dir=`dirname $0` - -# check for brew, -if [[ -z `which brew` ]]; then - # install homebrew - /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" - # python pip installs in /usr/local/tests - sudo mkdir -p /usr/local/tests - sudo chown ${USER}:admin /usr/local/tests -fi - -# check for pip -if [[ -z `which pip` ]]; then - (>&2 echo 'Please install pip by "curl -O https://bootstrap.pypa.io/get-pip.py | sudo python3 get-pip.py"') - exit 1 +# Installation helper: skip already-installed packages. +brew_install() { + if brew list "$1" &>/dev/null; then + echo "$1 is already installed, skipping" + else + brew install "$1" + fi +} + +# Check if Homebrew is already installed. +if ! command -v brew &>/dev/null; then + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" fi -# check for clang version -cxx_full_version=`clang++ --version | grep version` -cxx_version=`echo $cxx_full_version | cut -f 4 -d " "` -if [[ $cxx_version < "8.0.0" ]]; then - echo "Please install Xcode 8 or command line tools v8 or higher." - echo "It is a requirement for thread_local support" - echo "" - echo "You have: $cxx_full_version" - exit 1 +# Add Homebrew to PATH for both arm64 (Apple Silicon) and x86_64. +if [[ $(uname -m) == 'arm64' ]]; then + eval "$(/opt/homebrew/bin/brew shellenv)" +else + eval "$(/usr/local/bin/brew shellenv)" fi +# Fetch the latest formulae. brew update -# install basic tools -brew install automake autoconf bison boost clang-format cmake coreutils \ - doxygen gcc@5 gmp libevent openssl pkg-config wget -# bison needs a bit more nudging -brew link --overwrite --force bison - -# we need realpath from coreutils -brews_dir=`realpath $tools_dir`/brews - -# thrift -brew install --HEAD ${brews_dir}/thrift.rb --with-python --with-libevent - -brew install python -/usr/local/bin/pip install pcapy - -# nanomsg -brew install nanomsg - -# # scapy -pip install scapy - -# pynng -/usr/local/bin/pip install pynng==0.9.0 - -/usr/local/bin/pip install PyYAML +# Required packages for bmv2. +REQUIRED_PACKAGES=( + autoconf + automake + cmake + libtool + boost + bison + pkg-config + libevent + openssl + coreutils + gmp + nanomsg + thrift + xxhash + jsoncpp + python3 +) + +for package in "${REQUIRED_PACKAGES[@]}"; do + brew_install "${package}" +done + +# bison installed via Homebrew must appear before system bison on PATH. +export PATH="$(brew --prefix bison)/bin:$PATH" + +# Install Python dependencies. +# --break-system-packages is required on modern macOS (PEP 668) to allow +# pip to install into the system Python environment. +pip3 install --user --break-system-packages scapy pynng==0.9.0 PyYAML