diff --git a/.gitignore b/.gitignore index 6976dfdaaf..4d23afa60f 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ stories*.bin err.log numpy.txt result.txt +expect.txt.new _go/ _runtime/ diff --git a/cmd/internal/base/pass.go b/cmd/internal/base/pass.go index 9e035d8675..3b5c7d7d01 100644 --- a/cmd/internal/base/pass.go +++ b/cmd/internal/base/pass.go @@ -71,7 +71,7 @@ func NewPassArgs(flag *flag.FlagSet) *PassArgs { func PassBuildFlags(cmd *Command) *PassArgs { p := NewPassArgs(&cmd.Flag) - p.Bool("n", "x") + p.Bool("n") // Note: "a" flag removed - now handled by flags.AddBuildFlags() p.Bool("linkshared", "race", "msan", "asan", "trimpath", "work") diff --git a/cmd/internal/flags/flags.go b/cmd/internal/flags/flags.go index fc132b4b2d..1001aaca85 100644 --- a/cmd/internal/flags/flags.go +++ b/cmd/internal/flags/flags.go @@ -41,6 +41,7 @@ var SizeReport bool var SizeFormat string var SizeLevel string var ForceRebuild bool +var PrintCommands bool const DefaultTestTimeout = "10m" // Matches Go's default test timeout @@ -50,6 +51,7 @@ func AddCommonFlags(fs *flag.FlagSet) { func AddBuildFlags(fs *flag.FlagSet) { fs.BoolVar(&ForceRebuild, "a", false, "Force rebuilding of packages that are already up-to-date") + fs.BoolVar(&PrintCommands, "x", false, "Print the commands") fs.StringVar(&Tags, "tags", "", "Build tags") fs.StringVar(&BuildEnv, "buildenv", "", "Build environment") if buildenv.Dev { @@ -174,6 +176,7 @@ func UpdateConfig(conf *build.Config) error { conf.CompilerHash = compilerhash.Value() conf.Tags = Tags conf.Verbose = Verbose + conf.PrintCommands = PrintCommands conf.Target = Target conf.Port = Port conf.BaudRate = BaudRate diff --git a/internal/build/build.go b/internal/build/build.go index e6836a7881..f10c5523ce 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -129,6 +129,7 @@ type Config struct { AbiMode AbiMode GenExpect bool // only valid for ModeCmpTest Verbose bool + PrintCommands bool GenLL bool // generate pkg .ll files CheckLLFiles bool // check .ll files valid CheckLinkArgs bool // check linkargs valid @@ -544,7 +545,7 @@ func (c *context) compiler() *clang.Cmd { c.crossCompile.Linker, ) cmd := clang.NewCompiler(config) - cmd.Verbose = c.buildConf.Verbose + cmd.Verbose = c.shouldPrintCommands(false) return cmd } @@ -557,10 +558,15 @@ func (c *context) linker() *clang.Cmd { c.crossCompile.Linker, ) cmd := clang.NewLinker(config) - cmd.Verbose = c.buildConf.Verbose + cmd.Verbose = c.shouldPrintCommands(false) return cmd } +// shouldPrintCommands reports whether command tracing should be enabled. +func (c *context) shouldPrintCommands(verbose bool) bool { + return c.buildConf.PrintCommands || c.buildConf.Verbose || verbose +} + // normalizeToArchive creates an archive from object files and sets ArchiveFile. // This ensures the link step always consumes .a archives regardless of cache state. func normalizeToArchive(ctx *context, aPkg *aPackage, verbose bool) error { @@ -802,6 +808,7 @@ func compileExtraFiles(ctx *context, verbose bool) ([]string, error) { return nil, nil } + printCmds := ctx.shouldPrintCommands(verbose) var objFiles []string llgoRoot := env.LLGoROOT() @@ -839,7 +846,7 @@ func compileExtraFiles(ctx *context, verbose bool) ([]string, error) { if ctx.buildConf.GenLL { llFile := baseName + ".ll" llArgs := append(slices.Clone(baseArgs), "-emit-llvm", "-S", "-o", llFile, "-c", srcFile) - if verbose { + if printCmds { fmt.Fprintf(os.Stderr, "Compiling extra file (ll): clang %s\n", strings.Join(llArgs, " ")) } cmd := ctx.compiler() @@ -851,7 +858,7 @@ func compileExtraFiles(ctx *context, verbose bool) ([]string, error) { // Always compile to .o for linking objFile := baseName + ".o" objArgs := append(baseArgs, "-o", objFile, "-c", srcFile) - if verbose { + if printCmds { fmt.Fprintf(os.Stderr, "Compiling extra file: clang %s\n", strings.Join(objArgs, " ")) } cmd := ctx.compiler() @@ -925,8 +932,9 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, outputPa // Generate main module file (needed for global variables even in library modes) // This is compiled directly to .o and added to linkInputs (not cached) + // Use a stable synthetic name to avoid confusing it with the real main package in traces/logs. entryPkg := genMainModule(ctx, llssa.PkgRuntime, pkg, needRuntime, needPyInit, needAbiInit) - entryObjFile, err := exportObject(ctx, entryPkg.PkgPath, entryPkg.ExportFile, []byte(entryPkg.LPkg.String())) + entryObjFile, err := exportObject(ctx, "entry_main", entryPkg.ExportFile, []byte(entryPkg.LPkg.String())) if err != nil { return err } @@ -971,9 +979,10 @@ func isRuntimePkg(pkgPath string) bool { } func linkObjFiles(ctx *context, app string, objFiles, linkArgs []string, verbose bool) error { + printCmds := ctx.shouldPrintCommands(verbose) // Handle c-archive mode differently - use ar tool instead of linker if ctx.buildConf.BuildMode == BuildModeCArchive { - return ctx.createArchiveFile(app, objFiles, verbose) + return ctx.createArchiveFile(app, objFiles, printCmds) } buildArgs := []string{"-o", app} @@ -998,7 +1007,7 @@ func linkObjFiles(ctx *context, app string, objFiles, linkArgs []string, verbose if strings.HasSuffix(objFile, ".ll") { oFile := strings.TrimSuffix(objFile, ".ll") + ".o" args := []string{"-o", oFile, "-c", objFile, "-Wno-override-module"} - if verbose { + if printCmds { fmt.Fprintln(os.Stderr, "clang", args) } if err := ctx.compiler().Compile(args...); err != nil { @@ -1015,7 +1024,7 @@ func linkObjFiles(ctx *context, app string, objFiles, linkArgs []string, verbose buildArgs = append(buildArgs, objFiles...) cmd := ctx.linker() - cmd.Verbose = verbose + cmd.Verbose = printCmds return cmd.Link(buildArgs...) } @@ -1069,7 +1078,8 @@ func (c *context) createArchiveFile(archivePath string, objFiles []string, verbo args := append([]string{"rcs", tmpName}, objFiles...) arCmd := c.archiver() cmd := exec.Command(arCmd, args...) - if len(verbose) > 0 && verbose[0] { + printCmds := c.shouldPrintCommands(len(verbose) > 0 && verbose[0]) + if printCmds { fmt.Fprintf(os.Stderr, "%s %s\n", filepath.Base(arCmd), strings.Join(args, " ")) } if output, err := cmd.CombinedOutput(); err != nil { @@ -1141,20 +1151,21 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) error { ctx.cTransformer.TransformModule(ret.Path(), ret.Module()) - cgoLLFiles, cgoLdflags, err := buildCgo(ctx, aPkg, aPkg.Package.Syntax, externs, verbose) + printCmds := ctx.shouldPrintCommands(verbose) + cgoLLFiles, cgoLdflags, err := buildCgo(ctx, aPkg, aPkg.Package.Syntax, externs, printCmds) if err != nil { return fmt.Errorf("build cgo of %v failed: %v", pkgPath, err) } aPkg.ObjFiles = append(aPkg.ObjFiles, cgoLLFiles...) - aPkg.ObjFiles = append(aPkg.ObjFiles, concatPkgLinkFiles(ctx, pkg, verbose)...) + aPkg.ObjFiles = append(aPkg.ObjFiles, concatPkgLinkFiles(ctx, pkg, printCmds)...) aPkg.LinkArgs = append(aPkg.LinkArgs, cgoLdflags...) if aPkg.AltPkg != nil { - altLLFiles, altLdflags, e := buildCgo(ctx, aPkg, aPkg.AltPkg.Syntax, externs, verbose) + altLLFiles, altLdflags, e := buildCgo(ctx, aPkg, aPkg.AltPkg.Syntax, externs, printCmds) if e != nil { return fmt.Errorf("build cgo of %v failed: %v", pkgPath, e) } aPkg.ObjFiles = append(aPkg.ObjFiles, altLLFiles...) - aPkg.ObjFiles = append(aPkg.ObjFiles, concatPkgLinkFiles(ctx, aPkg.AltPkg.Package, verbose)...) + aPkg.ObjFiles = append(aPkg.ObjFiles, concatPkgLinkFiles(ctx, aPkg.AltPkg.Package, printCmds)...) aPkg.LinkArgs = append(aPkg.LinkArgs, altLdflags...) } if pkg.ExportFile != "" { @@ -1207,7 +1218,8 @@ func exportObject(ctx *context, pkgPath string, exportFile string, data []byte) } objFile.Close() args := []string{"-o", objFile.Name(), "-c", f.Name(), "-Wno-override-module"} - if ctx.buildConf.Verbose { + if ctx.shouldPrintCommands(false) { + fmt.Fprintf(os.Stderr, "# compiling %s for pkg: %s\n", f.Name(), pkgPath) fmt.Fprintln(os.Stderr, "clang", args) } cmd := ctx.compiler() @@ -1564,11 +1576,11 @@ func clFiles(ctx *context, files string, pkg *packages.Package, procFile func(li } for _, file := range strings.Split(files, ";") { cFile := filepath.Join(dir, strings.TrimSpace(file)) - clFile(ctx, args, cFile, expFile, procFile, verbose) + clFile(ctx, args, cFile, expFile, pkg.PkgPath, procFile, verbose) } } -func clFile(ctx *context, args []string, cFile, expFile string, procFile func(linkFile string), verbose bool) { +func clFile(ctx *context, args []string, cFile, expFile, pkgPath string, procFile func(linkFile string), verbose bool) { baseName := expFile + filepath.Base(cFile) ext := filepath.Ext(cFile) @@ -1578,10 +1590,12 @@ func clFile(ctx *context, args []string, cFile, expFile string, procFile func(li } // If GenLL is enabled, first emit .ll for debugging, then compile to .o + printCmds := ctx.shouldPrintCommands(verbose) if ctx.buildConf.GenLL { llFile := baseName + ".ll" llArgs := append(slices.Clone(args), "-emit-llvm", "-S", "-o", llFile, "-c", cFile) - if verbose { + if printCmds { + fmt.Fprintf(os.Stderr, "# compiling %s for pkg: %s\n", llFile, pkgPath) fmt.Fprintln(os.Stderr, "clang", llArgs) } cmd := ctx.compiler() @@ -1592,7 +1606,8 @@ func clFile(ctx *context, args []string, cFile, expFile string, procFile func(li // Always compile to .o for linking objFile := baseName + ".o" objArgs := append(args, "-o", objFile, "-c", cFile) - if verbose { + if printCmds { + fmt.Fprintf(os.Stderr, "# compiling %s for pkg: %s\n", objFile, pkgPath) fmt.Fprintln(os.Stderr, "clang", objArgs) } cmd := ctx.compiler() diff --git a/internal/build/cgo.go b/internal/build/cgo.go index 67cfda1365..f00aa198bd 100644 --- a/internal/build/cgo.go +++ b/internal/build/cgo.go @@ -86,7 +86,7 @@ func buildCgo(ctx *context, pkg *aPackage, files []*ast.File, externs []string, } } for _, cfile := range cfiles { - clFile(ctx, cflags, cfile, pkg.ExportFile, func(linkFile string) { + clFile(ctx, cflags, cfile, pkg.ExportFile, pkg.PkgPath, func(linkFile string) { llfiles = append(llfiles, linkFile) }, verbose) } @@ -122,14 +122,14 @@ func buildCgo(ctx *context, pkg *aPackage, files []*ast.File, externs []string, tmpName := tmpFile.Name() defer os.Remove(tmpName) code := cgoHeader + "\n\n" + preamble.src - externDecls, err := genExternDeclsByClang(pkg, code, cflags, cgoSymbols) + externDecls, err := genExternDeclsByClang(pkg, code, cflags, cgoSymbols, verbose) if err != nil { return nil, nil, fmt.Errorf("failed to generate extern decls: %v", err) } if err = os.WriteFile(tmpName, []byte(code+"\n\n"+externDecls), 0644); err != nil { return nil, nil, fmt.Errorf("failed to write temp file: %v", err) } - clFile(ctx, cflags, tmpName, pkg.ExportFile, func(linkFile string) { + clFile(ctx, cflags, tmpName, pkg.ExportFile, pkg.PkgPath, func(linkFile string) { llfiles = append(llfiles, linkFile) }, verbose) } @@ -146,7 +146,7 @@ type clangASTNode struct { Inner []clangASTNode `json:"inner,omitempty"` } -func genExternDeclsByClang(pkg *aPackage, src string, cflags []string, cgoSymbols map[string]string) (string, error) { +func genExternDeclsByClang(pkg *aPackage, src string, cflags []string, cgoSymbols map[string]string, verbose bool) (string, error) { tmpSrc, err := os.CreateTemp("", "cgo-src-*.c") if err != nil { return "", fmt.Errorf("failed to create temp file: %v", err) @@ -156,11 +156,11 @@ func genExternDeclsByClang(pkg *aPackage, src string, cflags []string, cgoSymbol return "", fmt.Errorf("failed to write temp file: %v", err) } symbolNames := make(map[string]bool) - if err := getFuncNames(tmpSrc.Name(), cflags, symbolNames); err != nil { + if err := getFuncNames(tmpSrc.Name(), cflags, symbolNames, verbose); err != nil { return "", fmt.Errorf("failed to get func names: %v", err) } macroNames := make(map[string]bool) - if err := getMacroNames(tmpSrc.Name(), cflags, macroNames); err != nil { + if err := getMacroNames(tmpSrc.Name(), cflags, macroNames, verbose); err != nil { return "", fmt.Errorf("failed to get macro names: %v", err) } @@ -213,10 +213,10 @@ static void _init_%s() { return b.String(), nil } -func getMacroNames(file string, cflags []string, macroNames map[string]bool) error { +func getMacroNames(file string, cflags []string, macroNames map[string]bool, verbose bool) error { args := append([]string{"-dM", "-E"}, cflags...) args = append(args, file) - cmd := exec.Command("clang", args...) + cmd := execCommandVerbose(verbose, "clang", args...) output, err := cmd.Output() if err != nil { return err @@ -233,10 +233,10 @@ func getMacroNames(file string, cflags []string, macroNames map[string]bool) err return nil } -func getFuncNames(file string, cflags []string, symbolNames map[string]bool) error { +func getFuncNames(file string, cflags []string, symbolNames map[string]bool, verbose bool) error { args := append([]string{"-Xclang", "-ast-dump=json", "-fsyntax-only"}, cflags...) args = append(args, file) - cmd := exec.Command("clang", args...) + cmd := execCommandVerbose(verbose, "clang", args...) cmd.Stderr = os.Stderr output, err := cmd.Output() if err != nil { @@ -263,6 +263,13 @@ func getFuncNames(file string, cflags []string, symbolNames map[string]bool) err return nil } +func execCommandVerbose(verbose bool, name string, arg ...string) *exec.Cmd { + if verbose { + fmt.Fprintf(os.Stderr, "%s %s\n", name, strings.Join(arg, " ")) + } + return exec.Command(name, arg...) +} + func extractFuncNames(node *clangASTNode, funcNames map[string]bool) { for _, inner := range node.Inner { if inner.Kind == "FunctionDecl" && inner.Name != "" { diff --git a/internal/build/run.go b/internal/build/run.go index 5d335cc9b9..e9fe46a9fa 100644 --- a/internal/build/run.go +++ b/internal/build/run.go @@ -56,6 +56,9 @@ func runNative(ctx *context, app, pkgDir, pkgName string, conf *Config, mode Mod } else { args = conf.RunArgs } + if conf.PrintCommands { + fmt.Fprintf(os.Stderr, "%s %s\n", app, strings.Join(args, " ")) + } cmd := exec.Command(app, args...) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout @@ -68,6 +71,9 @@ func runNative(ctx *context, app, pkgDir, pkgName string, conf *Config, mode Mod mockable.Exit(s.ExitCode()) } case ModeTest: + if conf.PrintCommands { + fmt.Fprintf(os.Stderr, "%s %s\n", app, strings.Join(conf.RunArgs, " ")) + } cmd := exec.Command(app, conf.RunArgs...) cmd.Dir = pkgDir cmd.Stdout = os.Stdout @@ -106,9 +112,9 @@ func runInEmulator(emulator string, envMap map[string]string, pkgDir, pkgName st switch mode { case ModeRun: - return runEmuCmd(envMap, emulator, conf.RunArgs, verbose) + return runEmuCmd(envMap, emulator, conf.RunArgs, verbose, conf.PrintCommands) case ModeTest: - return runEmuCmd(envMap, emulator, conf.RunArgs, verbose) + return runEmuCmd(envMap, emulator, conf.RunArgs, verbose, conf.PrintCommands) case ModeCmpTest: cmpTest(pkgDir, pkgName, envMap["out"], conf.GenExpect, conf.RunArgs) return nil @@ -117,7 +123,7 @@ func runInEmulator(emulator string, envMap map[string]string, pkgDir, pkgName st } // runEmuCmd runs the application in emulator by formatting the emulator command template -func runEmuCmd(envMap map[string]string, emulatorTemplate string, runArgs []string, verbose bool) error { +func runEmuCmd(envMap map[string]string, emulatorTemplate string, runArgs []string, verbose bool, printCmds bool) error { // Expand the emulator command template emulatorCmd := emulatorTemplate for placeholder, path := range envMap { @@ -145,6 +151,9 @@ func runEmuCmd(envMap map[string]string, emulatorTemplate string, runArgs []stri // Add run arguments to the end cmdParts = append(cmdParts, runArgs...) + if printCmds { + fmt.Fprintf(os.Stderr, "%s %s\n", cmdParts[0], strings.Join(cmdParts[1:], " ")) + } // Execute the emulator command cmd := exec.Command(cmdParts[0], cmdParts[1:]...)