go-build/pkg/build/builders/go.go
Snider bb64608120 refactor(module): migrate module path to dappco.re/go/core/build
Update go.mod module declaration, all require lines, and .go import
paths from forge.lthn.ai to dappco.re. Dependencies updated: core
v0.5.0, log v0.1.0, io v0.2.0. Replace directives added for local
module resolution. forge.lthn.ai/core/cli and go-inference retained
at old paths (not yet migrated).

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 01:53:16 +00:00

134 lines
3.7 KiB
Go

// Package builders provides build implementations for different project types.
package builders
import (
"context"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"dappco.re/go/core/build/pkg/build"
"dappco.re/go/core/io"
coreerr "dappco.re/go/core/log"
)
// GoBuilder implements the Builder interface for Go projects.
type GoBuilder struct{}
// NewGoBuilder creates a new GoBuilder instance.
func NewGoBuilder() *GoBuilder {
return &GoBuilder{}
}
// Name returns the builder's identifier.
func (b *GoBuilder) Name() string {
return "go"
}
// Detect checks if this builder can handle the project in the given directory.
// Uses IsGoProject from the build package which checks for go.mod or wails.json.
func (b *GoBuilder) Detect(fs io.Medium, dir string) (bool, error) {
return build.IsGoProject(fs, dir), nil
}
// Build compiles the Go project for the specified targets.
// It sets GOOS, GOARCH, and CGO_ENABLED environment variables,
// applies ldflags and trimpath, and runs go build.
func (b *GoBuilder) Build(ctx context.Context, cfg *build.Config, targets []build.Target) ([]build.Artifact, error) {
if cfg == nil {
return nil, coreerr.E("GoBuilder.Build", "config is nil", nil)
}
if len(targets) == 0 {
return nil, coreerr.E("GoBuilder.Build", "no targets specified", nil)
}
// Ensure output directory exists
if err := cfg.FS.EnsureDir(cfg.OutputDir); err != nil {
return nil, coreerr.E("GoBuilder.Build", "failed to create output directory", err)
}
var artifacts []build.Artifact
for _, target := range targets {
artifact, err := b.buildTarget(ctx, cfg, target)
if err != nil {
return artifacts, coreerr.E("GoBuilder.Build", "failed to build "+target.String(), err)
}
artifacts = append(artifacts, artifact)
}
return artifacts, nil
}
// buildTarget compiles for a single target platform.
func (b *GoBuilder) buildTarget(ctx context.Context, cfg *build.Config, target build.Target) (build.Artifact, error) {
// Determine output binary name
binaryName := cfg.Name
if binaryName == "" {
binaryName = filepath.Base(cfg.ProjectDir)
}
// Add .exe extension for Windows
if target.OS == "windows" && !strings.HasSuffix(binaryName, ".exe") {
binaryName += ".exe"
}
// Create platform-specific output path: output/os_arch/binary
platformDir := filepath.Join(cfg.OutputDir, fmt.Sprintf("%s_%s", target.OS, target.Arch))
if err := cfg.FS.EnsureDir(platformDir); err != nil {
return build.Artifact{}, coreerr.E("GoBuilder.buildTarget", "failed to create platform directory", err)
}
outputPath := filepath.Join(platformDir, binaryName)
// Build the go build arguments
args := []string{"build"}
// Add trimpath flag
args = append(args, "-trimpath")
// Add ldflags if specified
if len(cfg.LDFlags) > 0 {
ldflags := strings.Join(cfg.LDFlags, " ")
args = append(args, "-ldflags", ldflags)
}
// Add output path
args = append(args, "-o", outputPath)
// Add the project directory as the build target (current directory)
args = append(args, ".")
// Create the command
cmd := exec.CommandContext(ctx, "go", args...)
cmd.Dir = cfg.ProjectDir
// Set up environment
env := os.Environ()
env = append(env, fmt.Sprintf("GOOS=%s", target.OS))
env = append(env, fmt.Sprintf("GOARCH=%s", target.Arch))
if cfg.CGO {
env = append(env, "CGO_ENABLED=1")
} else {
env = append(env, "CGO_ENABLED=0")
}
cmd.Env = env
// Capture output for error messages
output, err := cmd.CombinedOutput()
if err != nil {
return build.Artifact{}, coreerr.E("GoBuilder.buildTarget", "go build failed: "+string(output), err)
}
return build.Artifact{
Path: outputPath,
OS: target.OS,
Arch: target.Arch,
}, nil
}
// Ensure GoBuilder implements the Builder interface.
var _ build.Builder = (*GoBuilder)(nil)