- Fix remaining 187 pkg/ files referencing core/cli → core/go - Move SDK library code from internal/cmd/sdk/ → pkg/sdk/ (new package) - Create pkg/rag/helpers.go with convenience functions from internal/cmd/rag/ - Fix pkg/mcp/tools_rag.go to use pkg/rag instead of internal/cmd/rag - Fix pkg/build/buildcmd/cmd_sdk.go and pkg/release/sdk.go to use pkg/sdk - Remove all non-library content: main.go, internal/, cmd/, docker/, scripts/, tasks/, tools/, .core/, .forgejo/, .woodpecker/, Taskfile.yml - Run go mod tidy to trim unused dependencies core/go is now a pure Go package suite (library only). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Claude <developers@lethean.io> Reviewed-on: #3
129 lines
3.7 KiB
Go
129 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"
|
|
|
|
"forge.lthn.ai/core/go/pkg/build"
|
|
"forge.lthn.ai/core/go/pkg/io"
|
|
)
|
|
|
|
// 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, fmt.Errorf("builders.GoBuilder.Build: config is nil")
|
|
}
|
|
|
|
if len(targets) == 0 {
|
|
return nil, fmt.Errorf("builders.GoBuilder.Build: no targets specified")
|
|
}
|
|
|
|
// Ensure output directory exists
|
|
if err := cfg.FS.EnsureDir(cfg.OutputDir); err != nil {
|
|
return nil, fmt.Errorf("builders.GoBuilder.Build: failed to create output directory: %w", err)
|
|
}
|
|
|
|
var artifacts []build.Artifact
|
|
|
|
for _, target := range targets {
|
|
artifact, err := b.buildTarget(ctx, cfg, target)
|
|
if err != nil {
|
|
return artifacts, fmt.Errorf("builders.GoBuilder.Build: failed to build %s: %w", 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{}, fmt.Errorf("failed to create platform directory: %w", 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))
|
|
env = append(env, "CGO_ENABLED=0") // CGO disabled by default for cross-compilation
|
|
cmd.Env = env
|
|
|
|
// Capture output for error messages
|
|
output, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
return build.Artifact{}, fmt.Errorf("go build failed: %w\nOutput: %s", err, string(output))
|
|
}
|
|
|
|
return build.Artifact{
|
|
Path: outputPath,
|
|
OS: target.OS,
|
|
Arch: target.Arch,
|
|
}, nil
|
|
}
|
|
|
|
// Ensure GoBuilder implements the Builder interface.
|
|
var _ build.Builder = (*GoBuilder)(nil)
|