bldr/util/gocompiler/gocompiler.go
Rama master · réplica de lectura del repositorio original.
package gocompiler
import (
"bytes"
"context"
"os"
"os/exec"
"path/filepath"
"strings"
uexec "github.com/aperturerobotics/util/exec"
"github.com/pkg/errors"
bldr_manifest "github.com/s4wave/spacewave/bldr/manifest"
"github.com/sirupsen/logrus"
)
// BldrTinyGoJSImportBuildTag selects Bldr's direct TinyGo JavaScript import ABI.
const BldrTinyGoJSImportBuildTag = "bldr_tinygo_js_imports"
// GoScriptBuildTag selects source meant for GoScript compilation.
const GoScriptBuildTag = "goscript"
// CloudflareBuildTag selects source meant for Cloudflare Workers builds.
const CloudflareBuildTag = "bldr_cloudflare"
// SQLLiteBuildTag selects the reduced SQL surface for every build that sets
// PureGoBuildTag: source gated on sql_lite drops the go-mysql-server driver,
// stdlib database/sql integration, collation tables, and other native-only
// SQL paths from the artifact.
const SQLLiteBuildTag = "sql_lite"
// PureGoBuildTag selects portable Go over assembly in the standard library and
// dependencies. Only targets that cannot run Go assembly set it: TinyGo,
// GoScript, and WebAssembly output. Native builds keep hardware hashing.
const PureGoBuildTag = "purego"
// GoScriptCompilerCacheRootEnv overrides the root of the GoScript compiler
// package artifact cache. The value off disables the cache.
const GoScriptCompilerCacheRootEnv = "BLDR_GOSCRIPT_COMPILER_CACHE_ROOT"
// GetDefaultArgs returns compiler flags that preserve the module manifest.
func GetDefaultArgs() []string {
return []string{
"-v",
"-buildvcs=false",
"-mod=readonly",
}
}
// GetDefaultTinygoLlvmFeatures returns the WebAssembly features enabled for TinyGo.
func GetDefaultTinygoLlvmFeatures() []string {
// https://github.com/llvm/llvm-project/blob/91423d71938d7a1dba27188e6d854148a750a3dd/clang/lib/Basic/Targets/WebAssembly.cpp#L150
// https://github.com/llvm/llvm-project/blob/91423d71938d7a1dba27188e6d854148a750a3dd/clang/lib/Basic/Targets/WebAssembly.cpp#L180
return []string{
// https://caniuse.com/?search=WebAssembly
// Baseline 2023: https://caniuse.com/wasm-simd
"+simd128",
// All browsers support: https://caniuse.com/wasm-signext
"+sign-ext",
// All browsers support: https://caniuse.com/wasm-threads
"+atomics",
// All browsers support: https://caniuse.com/wasm-bulk-memory
"+bulk-memory",
// All browsers support: https://caniuse.com/wasm-multi-value
"+multivalue",
// All browsers support: https://caniuse.com/wasm-mutable-globals
"+mutable-globals",
// All browsers support: https://caniuse.com/wasm-reference-types
"+reference-types",
// All browsers support: https://caniuse.com/wasm-nontrapping-fptoint
"+nontrapping-fptoint",
}
}
// GetDefaultEnv selects module mode without changing the configured module proxy.
func GetDefaultEnv() []string {
return []string{
"GO111MODULE=on",
// Vendored builds require module isolation from workspace configuration.
"GOWORK=off",
}
}
// NewGoCompilerCmd builds a compiler command with module defaults and the caller's environment.
func NewGoCompilerCmd(ctx context.Context, cmd string, args ...string) *exec.Cmd {
ecmd := uexec.NewCmd(ctx, cmd, args...)
ecmd.Env = os.Environ()
ecmd.Env = append(ecmd.Env, GetDefaultEnv()...)
return ecmd
}
// ExecGoCompiler runs the Go compiler and collects the log output.
func ExecGoCompiler(le *logrus.Entry, cmd *exec.Cmd) error {
return uexec.ExecCmd(le, cmd)
}
// NewBuildTags constructs build tags for a build type.
//
// NOTE: ExecBuildEntrypoint calls this automatically.
func NewBuildTags(buildType bldr_manifest.BuildType) []string {
return []string{"build_type_" + buildType.String()}
}
// GetWasmExecPath gets the path to wasm_exec.js and ensures it exists.
func GetWasmExecPath(ctx context.Context, le *logrus.Entry, useTinygo bool) (string, error) {
// Query the selected compiler's installation root.
var goc *exec.Cmd
if useTinygo {
goc = NewGoCompilerCmd(ctx, "tinygo", "env", "TINYGOROOT")
} else {
goc = NewGoCompilerCmd(ctx, "go", "env", "GOROOT")
}
var gocBuf bytes.Buffer
goc.Stdout = &gocBuf
if err := uexec.ExecCmd(le, goc); err != nil {
return "", errors.Wrap(err, "cannot determine GOROOT")
}
goRootDir, _, _ := strings.Cut(gocBuf.String(), "\n")
// Resolve the runtime adapter and require it to exist in that installation.
var wasmExecFile string
if useTinygo {
wasmExecFile = filepath.Join(goRootDir, "targets/wasm_exec.js")
} else {
wasmExecFile = filepath.Join(goRootDir, "lib/wasm/wasm_exec.js")
}
if _, err := os.Stat(wasmExecFile); err != nil {
return wasmExecFile, errors.Wrapf(err, "cannot find wasm_exec.js in goroot: %s", wasmExecFile)
}
return wasmExecFile, nil
}