Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/mecha: add ability to compile Zig modules using mecha build command #29

Merged
merged 2 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 39 additions & 6 deletions cmd/mecha/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,33 +50,47 @@ GLOBAL OPTIONS:
--version, -v print the version
```

## New project
### New project

```bash
mecha new project example.com/myproject
```

## New project based on template
### New project based on template

```bash
mecha new project -t=blink example.com/myproject
```

## New module
### New module

```bash
mecha new module mymodule

```

## New module based on template
### New TinyGo WASM module based on template

```bash
mecha new module -t=blink mymodule

```

## Build modules in current project
### New Rust WASM module based on template

```bash
mecha new module -t=pingrs -type=rust pingrs

```

## New Zig WASM module based on template

```bash
mecha new module -t=pingzig -type=zig pingzig

```

### Build modules in current project

```bash
mecha build
Expand All @@ -88,8 +102,27 @@ or
mecha build modules
```

## Build application for current project
### Build application for current project

```bash
mecha build project
```

## Using `mecha` with Rust

If you want to use the `mecha` command with Rust, you will need to install Rust as follows.

- First install Rust by using the instructions here: https://www.rust-lang.org/tools/install

- Then, install the Rust `wasm32-unknown-unknown` target.

```bash
rustup target add wasm32-unknown-unknown
```
Any Rust modules in your project's `modules` directory should be automatically built when you run the `mecha build` command.

## Using `mecha` with Zig

If you want to use the `mecha` command with Zig, you will need to install Zig 0.11.0 by using the instructions here: https://ziglang.org/learn/getting-started/#installing-zig

Any Zig modules in your project's `modules` directory should be automatically built when you run the `mecha build` command.
40 changes: 40 additions & 0 deletions cmd/mecha/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,15 @@ func buildModules(cCtx *cli.Context) error {
continue
}

// check if there is a build.zig file in the directory
_, err = os.Stat(filepath.Join(wd, "modules", f.Name(), "build.zig"))
if err == nil {
if err := buildZigModule(filepath.Join(wd, "modules"), f.Name()); err != nil {
return err
}
continue
}

// no go.mod or Cargo.toml file found
fmt.Println("No module files found in", f.Name(), "skipping...")
}
Expand Down Expand Up @@ -176,6 +185,37 @@ func buildRustModule(modulesPath, name string) error {
return nil
}

func buildZigModule(modulesPath, name string) error {
s := spinner.New(spinner.CharSets[5], 100*time.Millisecond, spinner.WithWriter(os.Stdout))
s.Suffix = " Building Zig module " + name
s.FinalMSG = "Done.\n"
s.Start()
defer s.Stop()

fmt.Println("Building Zig module", name)
modulePath := filepath.Join(modulesPath, name)
os.Chdir(modulePath)
defer os.Chdir("../..")

cmd := exec.Command("zig", "build")

var stdoutBuf, stderrBuf bytes.Buffer
cmd.Stdout = io.MultiWriter(&spinWriter{s, os.Stdout, false}, &stdoutBuf)
cmd.Stderr = io.MultiWriter(&spinWriter{s, os.Stderr, false}, &stderrBuf)

if err := cmd.Run(); err != nil {
fmt.Printf("zig build error %s: %v\n", modulePath, err)
os.Exit(1)
}

if err := copyFile(filepath.Join(modulePath, "zig-out", "lib", name+".wasm"), filepath.Join(modulesPath, name+".wasm")); err != nil {
fmt.Printf("copy file error %s: %v\n", modulePath, err)
os.Exit(1)
}

return nil
}

// copyFile copies the given file or directory from src to dst. It can copy over
// a possibly already existing file (but not directory) at the destination.
func copyFile(src, dst string) error {
Expand Down
59 changes: 38 additions & 21 deletions cmd/mecha/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package main

import (
"bytes"
"context"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"

getter "github.com/hashicorp/go-getter"
"github.com/urfave/cli/v2"
)

Expand Down Expand Up @@ -61,6 +63,17 @@ func createModule(cCtx *cli.Context) error {
os.Chdir("modules")
defer os.Chdir("..")

tmpltype := cCtx.String("type")
switch {
case tmpltype == "rust":
return downloadFromTemplate(templateName, name)
case tmpltype == "zig":
return downloadFromTemplate(templateName, name)
case tmpltype == "tinygo":
default:
return fmt.Errorf("unknown template type %s", tmpltype)
}

if err := createFromTemplate(templateName, name); err != nil {
return err
}
Expand All @@ -85,27 +98,6 @@ func createFromTemplate(templ, proj string) error {
os.Exit(1)
}

// patch the go.mod file to use forked wazero
basename := filepath.Base(proj)
if err := os.Chdir(basename); err != nil {
fmt.Println(err)
os.Exit(1)
}
defer os.Chdir("..")

return nil // TODO: completely remove replaceWazeroWithFork()
}

func replaceWazeroWithFork() error {
var stdout, stderr bytes.Buffer
cmd := exec.Command("go", "mod", "edit", "-replace", "github.com/tetratelabs/wazero=github.com/hybridgroup/[email protected]")
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
fmt.Printf("%s: %v\n%s%s", cmd.String(), err, stderr.Bytes(), stdout.Bytes())
os.Exit(1)
}

return nil
}

Expand All @@ -122,3 +114,28 @@ func getModuleName() (string, error) {

return strings.TrimSuffix(stdout.String(), "\n"), nil
}

func downloadFromTemplate(templateName, name string) error {
pwd, err := os.Getwd()
if err != nil {
fmt.Printf("Error getting pwd: %s", err)
return err
}

opts := []getter.ClientOption{}
client := &getter.Client{
Ctx: context.Background(),
Src: templateName,
Dst: filepath.Base(name),
Pwd: pwd,
Mode: getter.ClientModeDir,
Options: opts,
}

if err := client.Get(); err != nil {
fmt.Printf("Error downloading template: %s", err)
return err
}

return nil
}
33 changes: 32 additions & 1 deletion cmd/mecha/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,47 @@ go 1.22.0

require (
github.com/briandowns/spinner v1.23.0
github.com/hashicorp/go-getter v1.7.3
github.com/urfave/cli/v2 v2.27.1
)

require (
cloud.google.com/go v0.104.0 // indirect
cloud.google.com/go/compute v1.10.0 // indirect
cloud.google.com/go/iam v0.5.0 // indirect
cloud.google.com/go/storage v1.27.0 // indirect
github.com/aws/aws-sdk-go v1.44.122 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/fatih/color v1.7.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
github.com/googleapis/gax-go/v2 v2.6.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-safetemp v1.0.0 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/klauspost/compress v1.15.11 // indirect
github.com/mattn/go-colorable v0.1.2 // indirect
github.com/mattn/go-isatty v0.0.8 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/ulikunitz/xz v0.5.10 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
go.opencensus.io v0.23.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.100.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71 // indirect
google.golang.org/grpc v1.50.1 // indirect
google.golang.org/protobuf v1.28.1 // indirect
)
Loading