refactor build/install/run pipeline
This commit is contained in:
158
internal/build/run.go
Normal file
158
internal/build/run.go
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package build
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/goplus/llgo/internal/mockable"
|
||||
)
|
||||
|
||||
func runNative(ctx *context, app, pkgDir, pkgName string, conf *Config, mode Mode) error {
|
||||
switch mode {
|
||||
case ModeRun:
|
||||
args := make([]string, 0, len(conf.RunArgs)+1)
|
||||
if isWasmTarget(conf.Goos) {
|
||||
wasmer := os.ExpandEnv(WasmRuntime())
|
||||
wasmerArgs := strings.Split(wasmer, " ")
|
||||
wasmerCmd := wasmerArgs[0]
|
||||
wasmerArgs = wasmerArgs[1:]
|
||||
switch wasmer {
|
||||
case "wasmtime":
|
||||
args = append(args, "--wasm", "multi-memory=true", app)
|
||||
args = append(args, conf.RunArgs...)
|
||||
case "iwasm":
|
||||
args = append(args, "--stack-size=819200000", "--heap-size=800000000", app)
|
||||
args = append(args, conf.RunArgs...)
|
||||
default:
|
||||
args = append(args, wasmerArgs...)
|
||||
args = append(args, app)
|
||||
args = append(args, conf.RunArgs...)
|
||||
}
|
||||
app = wasmerCmd
|
||||
} else {
|
||||
args = conf.RunArgs
|
||||
}
|
||||
cmd := exec.Command(app, args...)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if s := cmd.ProcessState; s != nil {
|
||||
mockable.Exit(s.ExitCode())
|
||||
}
|
||||
case ModeTest:
|
||||
cmd := exec.Command(app, conf.RunArgs...)
|
||||
cmd.Dir = pkgDir
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||
fmt.Fprintf(os.Stderr, "%s: exit code %d\n", app, exitErr.ExitCode())
|
||||
if !ctx.testFail {
|
||||
ctx.testFail = true
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "failed to run test %s: %v\n", app, err)
|
||||
if !ctx.testFail {
|
||||
ctx.testFail = true
|
||||
}
|
||||
}
|
||||
}
|
||||
case ModeCmpTest:
|
||||
cmpTest(pkgDir, pkgName, app, conf.GenExpect, conf.RunArgs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runInEmulator(emulator, app, pkgDir, pkgName string, conf *Config, mode Mode, verbose bool) error {
|
||||
if emulator == "" {
|
||||
return fmt.Errorf("target %s does not have emulator configured", conf.Target)
|
||||
}
|
||||
if verbose {
|
||||
fmt.Fprintf(os.Stderr, "Using emulator: %s\n", emulator)
|
||||
}
|
||||
|
||||
switch mode {
|
||||
case ModeRun:
|
||||
return runEmuCmd(app, emulator, conf.RunArgs, verbose)
|
||||
case ModeTest:
|
||||
return runEmuCmd(app, emulator, conf.RunArgs, verbose)
|
||||
case ModeCmpTest:
|
||||
cmpTest(pkgDir, pkgName, app, conf.GenExpect, conf.RunArgs)
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// runEmuCmd runs the application in emulator by formatting the emulator command template
|
||||
func runEmuCmd(appPath, emulatorTemplate string, runArgs []string, verbose bool) error {
|
||||
// Build environment map for template variable expansion
|
||||
envs := map[string]string{
|
||||
"": appPath, // {} expands to app path
|
||||
"bin": appPath,
|
||||
"hex": appPath,
|
||||
"zip": appPath,
|
||||
"img": appPath,
|
||||
"uf2": appPath,
|
||||
}
|
||||
|
||||
// Expand the emulator command template
|
||||
emulatorCmd := emulatorTemplate
|
||||
for placeholder, path := range envs {
|
||||
var target string
|
||||
if placeholder == "" {
|
||||
target = "{}"
|
||||
} else {
|
||||
target = "{" + placeholder + "}"
|
||||
}
|
||||
emulatorCmd = strings.ReplaceAll(emulatorCmd, target, path)
|
||||
}
|
||||
|
||||
if verbose {
|
||||
fmt.Fprintf(os.Stderr, "Running in emulator: %s\n", emulatorCmd)
|
||||
}
|
||||
|
||||
// Parse command and arguments
|
||||
cmdParts := strings.Fields(emulatorCmd)
|
||||
if len(cmdParts) == 0 {
|
||||
panic(fmt.Errorf("empty emulator command"))
|
||||
}
|
||||
|
||||
// Add run arguments to the end
|
||||
cmdParts = append(cmdParts, runArgs...)
|
||||
|
||||
// Execute the emulator command
|
||||
cmd := exec.Command(cmdParts[0], cmdParts[1:]...)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if s := cmd.ProcessState; s != nil {
|
||||
mockable.Exit(s.ExitCode())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user