diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 356f3ca..0e4da9f 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -33,9 +33,15 @@ jobs: - os: ubuntu-24.04 name: linux-x86_64 target: linux + - os: ubuntu-24.04-arm + name: linux-aarch64 + target: linux - os: macos-latest name: macos-arm64 target: macos + - os: macos-latest + name: macos-x86_64 + target: macos - os: windows-latest name: windows-x86_64 target: windows @@ -101,7 +107,26 @@ jobs: run: | if [ "${{ matrix.target }}" = "linux" ]; then export LUA_PREFIX="/usr" - export LUA_LIB="/usr/lib/x86_64-linux-gnu/liblua5.4.a" + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH) + export LUA_LIB="/usr/lib/${MULTIARCH}/liblua5.4.a" + just build + elif [ "${{ matrix.target }}" = "macos" ] && [ "${{ matrix.name }}" = "macos-x86_64" ]; then + export MACOSX_DEPLOYMENT_TARGET="11.0" + + # Build Lua 5.4 from source for x86_64 + # (Homebrew lua@5.4 on ARM64 only provides arm64 libraries) + LUA_SRC_DIR="${{ runner.temp }}/lua-5.4.7" + curl -sL https://www.lua.org/ftp/lua-5.4.7.tar.gz | tar xz -C "${{ runner.temp }}" + cd "$LUA_SRC_DIR" + make macosx CC="clang -arch x86_64" AR="ar rc" MYCFLAGS="-arch x86_64" MYLDFLAGS="-arch x86_64" + make local + cd "${{ github.workspace }}" + + export LUA_PREFIX="$LUA_SRC_DIR/install" + export LUA_LIB="$LUA_SRC_DIR/install/lib/liblua.a" + export LUA_INCLUDE="$LUA_SRC_DIR/install/include" + export CMAKE_OSX_ARCHITECTURES="x86_64" + export CC="clang -arch x86_64" just build elif [ "${{ matrix.target }}" = "macos" ]; then export LUA_PREFIX="$(brew --prefix lua@5.4)" @@ -138,24 +163,56 @@ jobs: fi fi + - name: Verify Binary Architecture + if: matrix.target == 'macos' + run: | + EXPECTED_ARCH="${{ matrix.name == 'macos-arm64' && 'arm64' || 'x86_64' }}" + ACTUAL_ARCH=$(lipo -archs roda) + echo "Expected: $EXPECTED_ARCH, Got: $ACTUAL_ARCH" + if [ "$ACTUAL_ARCH" != "$EXPECTED_ARCH" ]; then + echo "::error::Binary architecture mismatch! Expected $EXPECTED_ARCH, got $ACTUAL_ARCH" + exit 1 + fi + file roda + - name: Generate Rockspec - if: matrix.target == 'linux' + if: matrix.name == 'linux-x86_64' run: | lx generate-rockspec - name: Validate Rockspec - if: matrix.target == 'linux' + if: matrix.name == 'linux-x86_64' run: | luarocks lint *.rockspec - - name: Upload Release Artifacts + - name: Upload Release Artifacts (with rockspec) + if: matrix.name == 'linux-x86_64' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - if [ "${{ matrix.target }}" = "linux" ]; then - gh release upload ${{ needs.release-please.outputs.tag_name }} roda-${{ matrix.name }}.tar.gz roda-${{ matrix.name }}.tar.gz.sha256 *.rockspec --clobber - elif [ "${{ matrix.target }}" = "windows" ]; then - gh release upload ${{ needs.release-please.outputs.tag_name }} roda-${{ matrix.name }}.zip roda-${{ matrix.name }}.zip.sha256 --clobber - else - gh release upload ${{ needs.release-please.outputs.tag_name }} roda-${{ matrix.name }}.tar.gz roda-${{ matrix.name }}.tar.gz.sha256 --clobber - fi \ No newline at end of file + gh release upload ${{ needs.release-please.outputs.tag_name }} \ + roda-${{ matrix.name }}.tar.gz roda-${{ matrix.name }}.tar.gz.sha256 *.rockspec --clobber + + - name: Upload Release Artifacts (Linux aarch64) + if: matrix.name == 'linux-aarch64' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release upload ${{ needs.release-please.outputs.tag_name }} \ + roda-${{ matrix.name }}.tar.gz roda-${{ matrix.name }}.tar.gz.sha256 --clobber + + - name: Upload Release Artifacts (Windows) + if: matrix.target == 'windows' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release upload ${{ needs.release-please.outputs.tag_name }} \ + roda-${{ matrix.name }}.zip roda-${{ matrix.name }}.zip.sha256 --clobber + + - name: Upload Release Artifacts (macOS) + if: matrix.target == 'macos' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release upload ${{ needs.release-please.outputs.tag_name }} \ + roda-${{ matrix.name }}.tar.gz roda-${{ matrix.name }}.tar.gz.sha256 --clobber \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md index b22cbd3..3fe22a0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,7 +7,6 @@ Roda (Portuguese for "wheel") is a pure Lua terminal spinner library and CLI too - `lua/roda/` – Core Lua library modules (`init.lua`, `ansi.lua`, `spinners.lua`, etc.) - `spec/` – Busted unit tests (`*_spec.lua`) - `demo/` – Example scripts and recordings -- `docs/` – Documentation - `assets/` – Images and demo GIF - `bin/` – CLI entry point (`spin.lua`) - `.github/workflows/` – CI/CD pipelines (tests, publish, release) diff --git a/README.md b/README.md index df2003f..cbc5746 100644 --- a/README.md +++ b/README.md @@ -24,13 +24,78 @@ ## Installation -### Using Lux (recommended) +### Homebrew (macOS and Linux) + +```bash +brew install tkolleh/tap/roda +``` + +Or tap first, then install: + +```bash +brew tap tkolleh/tap +brew install roda +``` + +### Standalone Binary (no Lua required) + +Download a prebuilt binary from the [latest release](https://github.com/tkolleh/roda.lua/releases/latest). Binaries are available for **macOS ARM64**, **macOS Intel**, **Linux x86\_64**, and **Linux ARM64**. + +#### macOS (Apple Silicon) + +```bash +curl -fSLO https://github.com/tkolleh/roda.lua/releases/latest/download/roda-macos-arm64.tar.gz +curl -fSLO https://github.com/tkolleh/roda.lua/releases/latest/download/roda-macos-arm64.tar.gz.sha256 +shasum -a 256 -c roda-macos-arm64.tar.gz.sha256 +tar xzf roda-macos-arm64.tar.gz +chmod +x roda +sudo mv roda /usr/local/bin/ +``` + +#### macOS (Intel) + +```bash +curl -fSLO https://github.com/tkolleh/roda.lua/releases/latest/download/roda-macos-x86_64.tar.gz +curl -fSLO https://github.com/tkolleh/roda.lua/releases/latest/download/roda-macos-x86_64.tar.gz.sha256 +shasum -a 256 -c roda-macos-x86_64.tar.gz.sha256 +tar xzf roda-macos-x86_64.tar.gz +chmod +x roda +sudo mv roda /usr/local/bin/ +``` + +#### Linux (x86\_64) + +```bash +curl -fSLO https://github.com/tkolleh/roda.lua/releases/latest/download/roda-linux-x86_64.tar.gz +curl -fSLO https://github.com/tkolleh/roda.lua/releases/latest/download/roda-linux-x86_64.tar.gz.sha256 +shasum -a 256 -c roda-linux-x86_64.tar.gz.sha256 +tar xzf roda-linux-x86_64.tar.gz +chmod +x roda +sudo mv roda /usr/local/bin/ +``` + +#### Linux (ARM64) + +```bash +curl -fSLO https://github.com/tkolleh/roda.lua/releases/latest/download/roda-linux-aarch64.tar.gz +curl -fSLO https://github.com/tkolleh/roda.lua/releases/latest/download/roda-linux-aarch64.tar.gz.sha256 +shasum -a 256 -c roda-linux-aarch64.tar.gz.sha256 +tar xzf roda-linux-aarch64.tar.gz +chmod +x roda +sudo mv roda /usr/local/bin/ +``` + +### Lua Library + +If you want to use Roda as a Lua library in your own scripts or applications: + +#### Using Lux (recommended) ```bash lx add roda ``` -### Using LuaRocks +#### Using LuaRocks ```bash luarocks install roda diff --git a/justfile b/justfile index 8fac6c6..4d54591 100644 --- a/justfile +++ b/justfile @@ -42,6 +42,7 @@ lua_prefix := env('LUA_PREFIX', if os() == "macos" { `brew --prefix lua` } else lua_version := env('LUA_VERSION', if os() == "macos" { "5.5" } else { "5.4" }) # Add lux build dependencies to PATH so luastatic can be found automatically + export PATH := absolute_path(".lux/" + lua_version + "/build_dependencies/" + lua_version + "/bin") + ":" + env_var('PATH') # Include path for Lua development headers (override with LUA_INCLUDE env var) @@ -56,6 +57,12 @@ macos_version := if os() == "macos" { `sw_vers -productVersion | cut -d. -f1-2` build_dir := absolute_path(clean(env('BUILD_DIR', '.build'))) package_name := "roda" +# Cross-compilation support (set CMAKE_OSX_ARCHITECTURES and CC env vars for cross builds) + +cmake_osx_arch := env('CMAKE_OSX_ARCHITECTURES', '') +cmake_osx_arch_flag := if cmake_osx_arch != "" { "-DCMAKE_OSX_ARCHITECTURES=" + cmake_osx_arch } else { "" } +cc := env('CC', 'gcc') + # --- Default --- [doc("Show all available recipes grouped by category")] @@ -135,7 +142,7 @@ prep: build-luv: prep @echo "Building static luv and shared module..." {{ if path_exists(build_dir / "luv") == "true" { "" } else { "git clone --recursive https://github.com/luvit/luv.git " + (build_dir / "luv") } }} - cd {{ build_dir / 'luv' }} && cmake -DBUILD_MODULE=ON -DBUILD_STATIC_LIBS=ON -DWITH_LUA_ENGINE=Lua -DLUA_BUILD_TYPE=System -DLUA_INCLUDE_DIR={{ lua_include }} -DLUA_LIBRARIES={{ lua_lib }} . + cd {{ build_dir / 'luv' }} && cmake -DBUILD_MODULE=ON -DBUILD_STATIC_LIBS=ON -DWITH_LUA_ENGINE=Lua -DLUA_BUILD_TYPE=System -DLUA_INCLUDE_DIR={{ lua_include }} -DLUA_LIBRARIES={{ lua_lib }} {{ cmake_osx_arch_flag }} . cd {{ build_dir / 'luv' }} && make cp {{ build_dir / 'luv' / 'libluv.a' }} {{ build_dir }}/ cp {{ build_dir / 'luv' / 'deps' / 'libuv' / 'libuv.a' }} {{ build_dir }}/ @@ -147,7 +154,7 @@ build-luv: prep build-system: prep @echo "Building static luasystem..." {{ if path_exists(build_dir / "luasystem") == "true" { "" } else { "git clone https://github.com/o-lim/luasystem.git " + (build_dir / "luasystem") } }} - cd {{ build_dir / 'luasystem' }} && gcc -c src/core.c src/compat.c src/time.c -I{{ lua_include }} + cd {{ build_dir / 'luasystem' }} && {{ cc }} -c src/core.c src/compat.c src/time.c -I{{ lua_include }} cd {{ build_dir / 'luasystem' }} && ar rcs libsystem.a core.o compat.o time.o cp {{ build_dir / 'luasystem' / 'libsystem.a' }} {{ build_dir }}/