Skip to content

Commit

Permalink
Merge pull request #821 from nevalang/cli-build-cmd-help
Browse files Browse the repository at this point in the history
Cli build cmd help
  • Loading branch information
emil14 authored Jan 5, 2025
2 parents 696e68d + 579938e commit 961d90a
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 35 deletions.
12 changes: 4 additions & 8 deletions cmd/neva/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
)

func main() {
wd, err := os.Getwd()
workdir, err := os.Getwd()
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -53,9 +53,7 @@ func main() {
&desugarer,
analyzer,
irgen,
native.NewBackend(
golangBackend,
),
native.NewBackend(golangBackend),
)

wasmCompiler := compiler.New(
Expand All @@ -64,9 +62,7 @@ func main() {
&desugarer,
analyzer,
irgen,
wasm.NewBackend(
golangBackend,
),
wasm.NewBackend(golangBackend),
)

jsonCompiler := compiler.New(
Expand All @@ -89,7 +85,7 @@ func main() {

// command-line app that can compile and interpret neva code
app := cli.NewApp(
wd,
workdir,
bldr,
goCompiler,
nativeCompiler,
Expand Down
2 changes: 2 additions & 0 deletions docs/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ This will produce an `output` file in the directory where neva-cli was executed,

Once again you should see `Hello, World!`.

> Execute `neva build --help` to learn more - how to compile to Go, WASM or how to do cross-compilation e.g. compile linux binaries in windows.
## Core Concepts

### Components
Expand Down
106 changes: 79 additions & 27 deletions internal/cli/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cli

import (
"fmt"
"os"

"github.com/nevalang/neva/internal/compiler"

Expand All @@ -10,15 +11,15 @@ import (

func newBuildCmd(
workdir string,
goc compiler.Compiler,
nativec compiler.Compiler,
wasmc compiler.Compiler,
jsonc compiler.Compiler,
dotc compiler.Compiler,
compilerToGo compiler.Compiler,
compilerToNative compiler.Compiler,
compilerToWASM compiler.Compiler,
compilerToJSON compiler.Compiler,
compilerToDOT compiler.Compiler,
) *cli.Command {
return &cli.Command{
Name: "build",
Usage: "Build neva program from source code",
Usage: "Generate target platform code from neva program",
Args: true,
Flags: []cli.Flag{
&cli.StringFlag{
Expand All @@ -31,7 +32,7 @@ func newBuildCmd(
},
&cli.StringFlag{
Name: "target",
Usage: "Target platform for build",
Usage: "Target platform for build (options: go, wasm, native, json, dot). For 'native' target, 'target-os' and 'target-arch' flags can be used, but if used, they must be used together.",
Action: func(ctx *cli.Context, s string) error {
switch s {
case "go", "wasm", "native", "json", "dot":
Expand All @@ -40,50 +41,101 @@ func newBuildCmd(
return fmt.Errorf("Unknown target %s", s)
},
},
&cli.StringFlag{
Name: "target-os",
Usage: "Target operating system for native build. See 'neva osarch' for supported combinations. Only supported for native target. Not needed if building for the current platform. Must be combined properly with 'target-arch'.",
},
&cli.StringFlag{
Name: "target-arch",
Usage: "Target architecture for native build. See 'neva osarch' for supported combinations. Only supported for native target. Not needed if building for the current platform. Must be combined properly with 'target-os'.",
},
},
ArgsUsage: "Provide path to main package",
Action: func(cliCtx *cli.Context) error {
var target string
if cliCtx.IsSet("target") {
target = cliCtx.String("target")
} else {
target = "native"
}

switch target {
case "go", "wasm", "json", "dot", "native":
default:
return fmt.Errorf("Unknown target %s", target)
}

var targetOS, targetArch string
if cliCtx.IsSet("target-os") {
targetOS = cliCtx.String("target-os")
}
if cliCtx.IsSet("target-arch") {
targetArch = cliCtx.String("target-arch")
}
if (targetOS != "" && targetArch == "") || (targetOS == "" && targetArch != "") {
return fmt.Errorf("target-os and target-arch must be set together")
}
if target != "native" && targetOS != "" {
return fmt.Errorf("target-os and target-arch are only supported when target is native")
}

mainPkg, err := mainPkgPathFromArgs(cliCtx)
if err != nil {
return err
}

output := workdir
outputDirPath := workdir
if cliCtx.IsSet("output") {
output = cliCtx.String("output")
}

var target string
if cliCtx.IsSet("target") {
target = cliCtx.String("target")
outputDirPath = cliCtx.String("output")
}

var trace bool
var isTraceEnabled bool
if cliCtx.IsSet("trace") {
trace = true
isTraceEnabled = true
}

input := compiler.CompilerInput{
compilerInput := compiler.CompilerInput{
Main: mainPkg,
Output: output,
Trace: trace,
Output: outputDirPath,
Trace: isTraceEnabled,
}

var c compiler.Compiler
var compilerToUse compiler.Compiler
switch target {
case "go":
c = goc
compilerToUse = compilerToGo
case "wasm":
c = wasmc
compilerToUse = compilerToWASM
case "json":
c = jsonc
compilerToUse = compilerToJSON
case "dot":
c = dotc
default:
c = nativec
compilerToUse = compilerToDOT
case "native":
compilerToUse = compilerToNative
}

if targetOS != "" {
prevGOOS := os.Getenv("GOOS")
prevGOARCH := os.Getenv("GOARCH")

if err := os.Setenv("GOOS", targetOS); err != nil {
return fmt.Errorf("set GOOS: %w", err)
}
if err := os.Setenv("GOARCH", targetArch); err != nil {
return fmt.Errorf("set GOARCH: %w", err)
}

defer func() {
if err := os.Setenv("GOOS", prevGOOS); err != nil {
panic(err)
}
if err := os.Setenv("GOARCH", prevGOARCH); err != nil {
panic(err)
}
}()
}

return c.Compile(cliCtx.Context, input)
return compilerToUse.Compile(cliCtx.Context, compilerInput)
},
}
}
1 change: 1 addition & 0 deletions internal/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func NewApp(
newGetCmd(workdir, bldr),
newRunCmd(workdir, nativec),
newBuildCmd(workdir, goc, nativec, wasmc, jsonc, dotc),
newOSArchCmd(),
},
}
}
Expand Down
34 changes: 34 additions & 0 deletions internal/cli/osarch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package cli

import (
"fmt"
"os/exec"
"strings"

cli "github.com/urfave/cli/v2"
)

func newOSArchCmd() *cli.Command {
return &cli.Command{
Name: "osarch",
Usage: "List supported OS/architecture combinations for native target",
Action: func(cliCtx *cli.Context) error {
cmd := exec.Command("go", "tool", "dist", "list")
output, err := cmd.Output()
if err != nil {
return fmt.Errorf("failed to execute go tool dist list: %w", err)
}

fmt.Println("Supported OS/architecture combinations for native target:")
fmt.Println("(use these values for --target-os and --target-arch flags when cross-compiling)")
fmt.Println()

platforms := strings.Split(strings.TrimSpace(string(output)), "\n")
for _, platform := range platforms {
fmt.Println(platform)
}

return nil
},
}
}

0 comments on commit 961d90a

Please sign in to comment.