TamaGo compilation support (#206)

This commit is contained in:
Marcin Bugaj
2025-11-06 13:15:45 +01:00
committed by GitHub
parent 6547820fc8
commit 8d68a60de0
13 changed files with 243 additions and 4 deletions

View File

@@ -48,6 +48,12 @@ pub enum CommonError {
#[error("Root package not found in {manifest_dir}")]
CargoRootPackageNotFound { manifest_dir: PathBuf },
#[error("Attempt to get {var} env variable results in {var_error}")]
Env {
var: String,
var_error: std::env::VarError,
},
}
impl CommonError {
@@ -117,4 +123,8 @@ impl CommonError {
pub fn cargo_root_package_not_found(manifest_dir: PathBuf) -> Self {
Self::CargoRootPackageNotFound { manifest_dir }
}
pub fn env_var_error(var: String, var_error: std::env::VarError) -> Self {
Self::Env { var, var_error }
}
}

View File

@@ -753,7 +753,7 @@ mod test {
}
mod zisk {
test_compile!(Zisk, "basic");
test_compile!(Zisk, "basic_rust");
test_execute!(
Zisk,
BasicProgramInput::valid().into_output_sha256(),

View File

@@ -1,5 +1,7 @@
mod error;
mod go_customized;
mod rust_rv64ima_customized;
pub use error::Error;
pub use go_customized::GoCustomized;
pub use rust_rv64ima_customized::RustRv64imaCustomized;

View File

@@ -0,0 +1,72 @@
use std::{env, fs, path::Path, process::Command};
use ere_compile_utils::CommonError;
use ere_zkvm_interface::Compiler;
use tracing::info;
use crate::{compiler::Error, program::ZiskProgram};
pub struct GoCustomized;
impl Compiler for GoCustomized {
type Error = Error;
type Program = ZiskProgram;
fn compile(&self, guest_directory: &Path) -> Result<Self::Program, Self::Error> {
info!(
"Compiling TamaGo ZisK program at {}",
guest_directory.display()
);
let home_dir = env::var("HOME")
.map(std::path::PathBuf::from)
.map_err(|var_error| CommonError::env_var_error("HOME".to_string(), var_error))?;
let ldflags = ["-ldflags", "-T 0x80001000 -D 0xa0020000"];
let tags = [
"-tags",
"tamago,linkcpuinit,linkramstart,linkramsize,linkprintk,tinygo.wasm,tinygo,riscv64",
];
let executable = guest_directory.join("program.elf");
let mut cmd = Command::new(home_dir.join(".tamago").join("bin").join("go"));
let status = cmd
.current_dir(guest_directory)
.env("CGO_ENABLED", "0")
.env("GOROOT", home_dir.join(".tamago").as_os_str())
.env("GOOS", "tamago")
.env("GOARCH", "riscv64")
.arg("build")
.arg("-buildvcs=false")
.args(ldflags)
.args(tags)
.args(["-o", executable.to_str().unwrap()])
.arg(".")
.status()
.map_err(|err| CommonError::command(&cmd, err))?;
if !status.success() {
return Err(CommonError::command_exit_non_zero(&cmd, status, None))?;
}
let elf =
fs::read(&executable).map_err(|err| CommonError::read_file("elf", executable, err))?;
Ok(ZiskProgram { elf })
}
}
#[cfg(test)]
mod tests {
use crate::compiler::GoCustomized;
use ere_test_utils::host::testing_guest_directory;
use ere_zkvm_interface::compiler::Compiler;
#[test]
fn test_compile() {
let guest_directory = testing_guest_directory("zisk", "basic_go");
println!("Guest directory is: {guest_directory:?}");
let program = GoCustomized.compile(&guest_directory).unwrap();
assert!(!program.elf().is_empty(), "ELF bytes should not be empty.");
}
}

View File

@@ -17,7 +17,10 @@ impl Compiler for RustRv64imaCustomized {
type Program = ZiskProgram;
fn compile(&self, guest_directory: &Path) -> Result<Self::Program, Self::Error> {
info!("Compiling ZisK program at {}", guest_directory.display());
info!(
"Compiling Rust ZisK program at {}",
guest_directory.display()
);
let metadata = cargo_metadata(guest_directory)?;
let package = metadata.root_package().unwrap();
@@ -58,7 +61,7 @@ mod tests {
#[test]
fn test_compile() {
let guest_directory = testing_guest_directory("zisk", "basic");
let guest_directory = testing_guest_directory("zisk", "basic_rust");
let program = RustRv64imaCustomized.compile(&guest_directory).unwrap();
assert!(!program.elf().is_empty(), "ELF bytes should not be empty.");
}

View File

@@ -153,7 +153,7 @@ mod tests {
PROGRAM
.get_or_init(|| {
RustRv64imaCustomized
.compile(&testing_guest_directory("zisk", "basic"))
.compile(&testing_guest_directory("zisk", "basic_rust"))
.unwrap()
})
.clone()

View File

@@ -44,6 +44,13 @@ ENV RUSTUP_HOME=/usr/local/rustup \
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain ${RUST_VERSION} --no-modify-path
# Copy the TamaGo installer script from the workspace context
COPY --chmod=755 scripts/install_tamago.sh /tmp/install_tamago.sh
# Run the TamaGo installation script.
RUN /tmp/install_tamago.sh && \
rm /tmp/install_tamago.sh
# Add a non-root user for subsequent stages or use in derived images
# This is generally best practice.
ARG USERNAME=ere_user

119
scripts/install_tamago.sh Executable file
View File

@@ -0,0 +1,119 @@
#!/bin/bash
set -e # Exit on error
GO_BRANCH="tamago1.25.2-zkvm-dev"
# Configuration
INSTALL_DIR="$HOME/.tamago" # that can't be empty nor "/"!
TEMP_DIR=$(mktemp -d)
GO_BRANCH="${GO_BRANCH:-master}" # Default to master, can override with env var
# Stock Go configuration
STOCK_GO_VERSION="go1.25.3"
STOCK_GO_DIR="$TEMP_DIR/stock-go"
STOCK_GO_INSTALL=false
echo "Building Go compiler..."
echo "Installation directory: $INSTALL_DIR"
echo "Version/branch: $GO_BRANCH"
echo ""
# Clean up temp directory on exit
trap "rm -rf $TEMP_DIR" EXIT
# Check if Go 1.25.3 is installed
echo "Checking for Go compiler..."
if command -v go &> /dev/null; then
CURRENT_GO_VERSION=$(go version | awk '{print $3}')
if [ "$CURRENT_GO_VERSION" = "$STOCK_GO_VERSION" ]; then
echo "Found Go $STOCK_GO_VERSION already installed"
else
echo "Found Go $CURRENT_GO_VERSION, but need $STOCK_GO_VERSION"
STOCK_GO_INSTALL=true
fi
else
echo "Go compiler not found, will install $STOCK_GO_VERSION"
STOCK_GO_INSTALL=true
fi
# Install stock Go if needed
if [ "$STOCK_GO_INSTALL" = true ]; then
echo "Installing stock Go $STOCK_GO_VERSION..."
# Detect OS and architecture
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
case "$ARCH" in
x86_64)
ARCH="amd64"
;;
aarch64|arm64)
ARCH="arm64"
;;
*)
echo "Error: Unsupported architecture: $ARCH"
exit 1
;;
esac
GO_ARCHIVE="${STOCK_GO_VERSION}.${OS}-${ARCH}.tar.gz"
GO_URL="https://go.dev/dl/${GO_ARCHIVE}"
echo "Downloading from $GO_URL..."
cd "$TEMP_DIR"
curl -L -O "$GO_URL"
echo "Extracting Go archive..."
tar -xzf "$GO_ARCHIVE"
mv go "$STOCK_GO_DIR"
# Add stock Go to PATH
export PATH="$STOCK_GO_DIR/bin:$PATH"
export GOROOT="$STOCK_GO_DIR"
echo "Stock Go installed temporarily at $STOCK_GO_DIR"
go version
fi
# Check if git is installed
if ! command -v git &> /dev/null; then
echo "Error: git is not installed. Please install git first."
exit 1
fi
# Clone Go repository
echo "Cloning Go repository..."
cd "$TEMP_DIR"
git clone --depth 1 --branch $GO_BRANCH https://github.com/eth-act/tamago-go.git go
cd go
# Remove .git directory to save space
echo "Removing .git directory..."
rm -rf .git
# Build Go
echo "Building Go compiler..."
cd src
GOROOT_FINAL="$INSTALL_DIR" ./make.bash
# Move built Go to installation directory
echo "Installing to $INSTALL_DIR..."
cd ../..
rm -rf "$INSTALL_DIR"
mv go "$INSTALL_DIR"
echo ""
echo "Go compiler successfully built and installed to: $INSTALL_DIR"
echo ""
echo "To use this Go installation, add the following to your shell profile:"
echo ""
echo " export GOROOT=$INSTALL_DIR"
echo " export PATH=\$GOROOT/bin:\$PATH"
echo ""
echo "Then run: source ~/.bashrc (or ~/.zshrc, depending on your shell)"
echo ""
echo "Verify installation with: go version"

View File

@@ -0,0 +1,8 @@
module basic_go
go 1.24.4
require (
github.com/eth-act/skunkworks-tama v0.0.0-20251105112532-eff8e3af014b // indirect
github.com/usbarmory/tamago v0.0.0-20250710154000-3dd21eabac74 // indirect
)

View File

@@ -0,0 +1,4 @@
github.com/eth-act/skunkworks-tama v0.0.0-20251105112532-eff8e3af014b h1:Nm1FYhFjCWnKkaRZzSjGmeWdqevsunbpOnYOayWpuoM=
github.com/eth-act/skunkworks-tama v0.0.0-20251105112532-eff8e3af014b/go.mod h1:M9fXNuyicUdFmj5nBlXRTNcUbJIDLMMs4eY1QoZHM3g=
github.com/usbarmory/tamago v0.0.0-20250710154000-3dd21eabac74 h1:zH22Y68S2cpwW278H+9v4r2SWpdP+JwUk/AwVc9LOlw=
github.com/usbarmory/tamago v0.0.0-20250710154000-3dd21eabac74/go.mod h1:0Bc0GnC88LvCAoCRUcd3DBFl7cribfVbCsiMJUbXyAE=

View File

@@ -0,0 +1,14 @@
//go:build tamago && riscv64
package main
import (
"fmt"
_ "github.com/eth-act/skunkworks-tama/tamaboards/zkvm"
)
func main() {
x := 10
y := 11
fmt.Println("Hello World", x + y)
}