diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e029e52..b141e71 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,6 +7,38 @@ env: SOLANA_ZIG_DIR: solana-zig jobs: + zig-test: + name: Run tests against Zig implementations + strategy: + matrix: + program: [helloworld] + fail-fast: false + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + $SOLANA_ZIG_DIR + key: zig-${{ hashFiles('./Cargo.lock') }}-$SOLANA_ZIG_VERSION + + - name: Download solana-zig compiler + shell: bash + run: SOLANA_ZIG_VERSION=$SOLANA_ZIG_VERSION ./install-solana-zig.sh $SOLANA_ZIG_DIR + + - name: Install Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: 1.78.0 + + - name: Install build deps + run: ./install-rust-build-deps.sh + + - name: Build and test program + run: ./test-zig.sh ${{ matrix.program }} + rust-test: name: Run tests against Rust implementations strategy: diff --git a/.gitignore b/.gitignore index 16531f3..c108dc6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ target/ .zig-cache/ zig-out/ +solana-zig/ diff --git a/helloworld/zig/build.zig b/helloworld/zig/build.zig new file mode 100644 index 0000000..643b417 --- /dev/null +++ b/helloworld/zig/build.zig @@ -0,0 +1,16 @@ +const std = @import("std"); +const solana = @import("solana-program-sdk"); +const base58 = @import("base58"); + +pub fn build(b: *std.Build) !void { + const target = b.resolveTargetQuery(solana.sbf_target); + const optimize = .ReleaseSmall; + const program = b.addSharedLibrary(.{ + .name = "solana_program_rosetta_helloworld", + .root_source_file = b.path("main.zig"), + .target = target, + .optimize = optimize, + }); + _ = solana.buildProgram(b, program, target, optimize); + b.installArtifact(program); +} diff --git a/helloworld/zig/build.zig.zon b/helloworld/zig/build.zig.zon new file mode 100644 index 0000000..d869fa5 --- /dev/null +++ b/helloworld/zig/build.zig.zon @@ -0,0 +1,46 @@ +.{ + .name = "solana-program-rosetta-helloworld-zig", + // This is a [Semantic Version](https://semver.org/). + // In a future version of Zig it will be used for package deduplication. + .version = "0.13.0", + + // This field is optional. + // This is currently advisory only; Zig does not yet do anything + // with this value. + .minimum_zig_version = "0.13.0", + + // This field is optional. + // Each dependency must either provide a `url` and `hash`, or a `path`. + // `zig build --fetch` can be used to fetch all dependencies of a package, recursively. + // Once all dependencies are fetched, `zig build` no longer requires + // internet connectivity. + .dependencies = .{ + .base58 = .{ + .url = "https://github.com/joncinque/base58-zig/archive/refs/tags/v0.13.3.tar.gz", + .hash = "1220fd067bf167b9062cc29ccf715ff97643c2d3f8958beea863b6036876bb71bcb8", + }, + .clap = .{ + .url = "https://github.com/Hejsil/zig-clap/archive/refs/tags/0.9.1.tar.gz", + .hash = "122062d301a203d003547b414237229b09a7980095061697349f8bef41be9c30266b", + }, + .@"solana-program-sdk" = .{ + .url = "https://github.com/joncinque/solana-program-sdk-zig/archive/refs/tags/v0.13.1.tar.gz", + .hash = "122030336f1257e3c0aa64243f5243f554b903c6b9ef3a91d48bfbe896c0c7d9b13b", + }, + }, + + // Specifies the set of files and directories that are included in this package. + // Only files and directories listed here are included in the `hash` that + // is computed for this package. + // Paths are relative to the build root. Use the empty string (`""`) to refer to + // the build root itself. + // A directory listed here means that all files within, recursively, are included. + .paths = .{ + // For example... + "build.zig", + "build.zig.zon", + "src", + "../../LICENSE", + "../../README.md", + }, +} diff --git a/helloworld/zig/main.zig b/helloworld/zig/main.zig new file mode 100644 index 0000000..b6edb73 --- /dev/null +++ b/helloworld/zig/main.zig @@ -0,0 +1,6 @@ +const sol = @import("solana-program-sdk"); + +export fn entrypoint(_: [*]u8) u64 { + sol.log("Hello world!"); + return 0; +} diff --git a/install-solana-zig.sh b/install-solana-zig.sh new file mode 100755 index 0000000..1974a51 --- /dev/null +++ b/install-solana-zig.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +if [[ -n $SOLANA_ZIG_VERSION ]]; then + solana_zig_version="$SOLANA_ZIG_VERSION" +else + solana_zig_version="v1.43.0" +fi +solana_zig_release_url="https://github.com/joncinque/solana-zig-bootstrap/releases/download/solana-$solana_zig_version" + +output_dir="$1" +if [[ -z $output_dir ]]; then + output_dir="solana-zig" +fi +output_dir="$(mkdir -p "$output_dir"; cd "$output_dir"; pwd)" +cd $output_dir + +arch=$(uname -m) +if [[ "$arch" == "arm64" ]]; then + arch="aarch64" +fi +case $(uname -s | cut -c1-7) in +"Linux") + os="linux" + abi="musl" + ;; +"Darwin") + os="macos" + abi="none" + ;; +"Windows" | "MINGW64") + os="windows" + abi="gnu" + ;; +*) + echo "install-solana-zig.sh: Unknown OS $(uname -s)" >&2 + exit 1 + ;; +esac + +solana_zig_tar=zig-$arch-$os-$abi.tar.bz2 +url="$solana_zig_release_url/$solana_zig_tar" +echo "Downloading $url" +curl --proto '=https' --tlsv1.2 -SfOL "$url" +echo "Unpacking $solana_zig_tar" +tar -xjf $solana_zig_tar +rm $solana_zig_tar + +solana_zig_dir="zig-$arch-$os-$abi-baseline" +mv "$solana_zig_dir"/* . +rmdir $solana_zig_dir +echo "solana-zig compiler available at $output_dir" diff --git a/test-zig.sh b/test-zig.sh new file mode 100755 index 0000000..05338b6 --- /dev/null +++ b/test-zig.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +PROGRAM_NAME="$1" +ZIG="$2" +ROOT_DIR="$(cd "$(dirname "$0")"; pwd)" +if [[ -z "$ZIG" ]]; then + ZIG="$ROOT_DIR/solana-zig/zig" +fi + +set -e +PROGRAM_DIR=$ROOT_DIR/$PROGRAM_NAME +cd $PROGRAM_DIR/zig +$ZIG build --summary all -freference-trace --verbose +SBF_OUT_DIR="$PROGRAM_DIR/zig/zig-out/lib" cargo test --manifest-path "$PROGRAM_DIR/Cargo.toml"