xtool: clang.Cmd supports Env/Verbose/Stdio, add CCFLAGS support

This commit is contained in:
Li Jie
2025-04-08 09:25:49 +08:00
parent b11eb742cb
commit b17632a352

View File

@@ -17,9 +17,11 @@
package clang
import (
"fmt"
"io"
"os"
"os/exec"
"runtime"
"strings"
)
@@ -27,10 +29,12 @@ import (
// Cmd represents a clang command.
type Cmd struct {
app string
Stdout io.Writer
Stderr io.Writer
app string
Env []string
Verbose bool
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
}
// New creates a new clang command.
@@ -38,33 +42,56 @@ func New(app string) *Cmd {
if app == "" {
app = "clang"
}
return &Cmd{app, os.Stdout, os.Stderr}
return &Cmd{app, nil, false, nil, os.Stdout, os.Stderr}
}
func (p *Cmd) Compile(args ...string) error {
// Parse CFLAGS environment variable into separate arguments
cflags := strings.Fields(os.Getenv("CFLAGS"))
if len(cflags) > 0 {
// Create a new slice with capacity for all arguments
newArgs := make([]string, 0, len(cflags)+len(args))
newArgs = append(newArgs, cflags...)
newArgs = append(newArgs, args...)
args = newArgs
}
return p.Exec(args...)
return p.execWithFlags([]string{"CFLAGS", "CCFLAGS"}, args...)
}
func (p *Cmd) Link(args ...string) error {
// Parse LDFLAGS environment variable into separate arguments
ldflags := strings.Fields(os.Getenv("LDFLAGS"))
if len(ldflags) > 0 {
// Create a new slice with capacity for all arguments
newArgs := make([]string, 0, len(ldflags)+len(args))
newArgs = append(newArgs, ldflags...)
newArgs = append(newArgs, args...)
args = newArgs
return p.execWithFlags([]string{"LDFLAGS", "CCFLAGS"}, args...)
}
// execWithFlags executes a clang command with flags from environment variables.
func (p *Cmd) execWithFlags(flags []string, args ...string) error {
var allFlags []string
if p.Env != nil {
for _, env := range p.Env {
parts := strings.SplitN(env, "=", 2)
if len(parts) != 2 {
continue
}
key, value := parts[0], parts[1]
for _, flagName := range flags {
if key == flagName {
allFlags = append(allFlags, strings.Fields(value)...)
break
}
}
}
} else {
for _, flagName := range flags {
envValue := os.Getenv(flagName)
if envValue != "" {
allFlags = append(allFlags, strings.Fields(envValue)...)
}
}
}
return p.Exec(args...)
cmdArgs := make([]string, 0, len(allFlags)+len(args))
cmdArgs = append(cmdArgs, allFlags...)
cmdArgs = append(cmdArgs, args...)
cmd := exec.Command(p.app, cmdArgs...)
if p.Verbose {
fmt.Fprintf(os.Stderr, "%v\n", cmd)
}
cmd.Stdin = p.Stdin
cmd.Stdout = p.Stdout
cmd.Stderr = p.Stderr
if p.Env != nil {
cmd.Env = p.Env
}
return cmd.Run()
}
// Exec executes a clang command.
@@ -72,7 +99,23 @@ func (p *Cmd) Exec(args ...string) error {
cmd := exec.Command(p.app, args...)
cmd.Stdout = p.Stdout
cmd.Stderr = p.Stderr
if p.Env != nil {
cmd.Env = p.Env
}
return cmd.Run()
}
func (p *Cmd) CheckLinkArgs(cmdArgs []string) error {
nul := "/dev/null"
if runtime.GOOS == "windows" {
nul = "NUL"
}
args := append([]string{}, cmdArgs...)
args = append(args, []string{"-x", "c", "-o", nul, "-"}...)
src := "int main() {return 0;}"
srcIn := strings.NewReader(src)
p.Stdin = srcIn
return p.execWithFlags([]string{"LDFLAGS", "CCFLAGS"}, args...)
}
// -----------------------------------------------------------------------------