main: escape commands while printing them with the -x flag

This should make issues such as the one in
https://github.com/tinygo-org/tinygo/issues/1910 more obvious.
Этот коммит содержится в:
Ayke van Laethem 2021-06-02 14:39:43 +02:00 коммит произвёл Ron Evans
родитель af65c006e6
коммит 4e610a0ee7
4 изменённых файлов: 30 добавлений и 9 удалений

Просмотреть файл

@ -547,8 +547,8 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
} }
ldflags = append(ldflags, dependency.result) ldflags = append(ldflags, dependency.result)
} }
if config.Options.PrintCommands { if config.Options.PrintCommands != nil {
fmt.Printf("%s %s\n", config.Target.Linker, strings.Join(ldflags, " ")) config.Options.PrintCommands(config.Target.Linker, ldflags...)
} }
err = link(config.Target.Linker, ldflags...) err = link(config.Target.Linker, ldflags...)
if err != nil { if err != nil {

Просмотреть файл

@ -56,7 +56,7 @@ import (
// depfile but without invalidating its name. For this reason, the depfile is // depfile but without invalidating its name. For this reason, the depfile is
// written on each new compilation (even when it seems unnecessary). However, it // written on each new compilation (even when it seems unnecessary). However, it
// could in rare cases lead to a stale file fetched from the cache. // could in rare cases lead to a stale file fetched from the cache.
func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands bool) (string, error) { func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands func(string, ...string)) (string, error) {
// Hash input file. // Hash input file.
fileHash, err := hashFile(abspath) fileHash, err := hashFile(abspath)
if err != nil { if err != nil {
@ -128,8 +128,8 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands
// flags (for the assembler) is a compiler error. // flags (for the assembler) is a compiler error.
flags = append(flags, "-Qunused-arguments") flags = append(flags, "-Qunused-arguments")
} }
if printCommands { if printCommands != nil {
fmt.Printf("clang %s\n", strings.Join(flags, " ")) printCommands("clang", flags...)
} }
err = runCCompiler(flags...) err = runCCompiler(flags...)
if err != nil { if err != nil {

Просмотреть файл

@ -25,7 +25,7 @@ type Options struct {
PrintIR bool PrintIR bool
DumpSSA bool DumpSSA bool
VerifyIR bool VerifyIR bool
PrintCommands bool PrintCommands func(cmd string, args ...string)
Debug bool Debug bool
PrintSizes string PrintSizes string
PrintAllocs *regexp.Regexp // regexp string PrintAllocs *regexp.Regexp // regexp string

27
main.go
Просмотреть файл

@ -95,12 +95,31 @@ func copyFile(src, dst string) error {
// executeCommand is a simple wrapper to exec.Cmd // executeCommand is a simple wrapper to exec.Cmd
func executeCommand(options *compileopts.Options, name string, arg ...string) *exec.Cmd { func executeCommand(options *compileopts.Options, name string, arg ...string) *exec.Cmd {
if options.PrintCommands { if options.PrintCommands != nil {
fmt.Printf("%s %s\n", name, strings.Join(arg, " ")) options.PrintCommands(name, arg...)
} }
return exec.Command(name, arg...) return exec.Command(name, arg...)
} }
// printCommand prints a command to stdout while formatting it like a real
// command (escaping characters etc). The resulting command should be easy to
// run directly in a shell, although it is not guaranteed to be a safe shell
// escape. That's not a problem as the primary use case is printing the command,
// not running it.
func printCommand(cmd string, args ...string) {
command := append([]string{cmd}, args...)
for i, arg := range command {
// Source: https://www.oreilly.com/library/view/learning-the-bash/1565923472/ch01s09.html
const specialChars = "~`#$&*()\\|[]{};'\"<>?! "
if strings.ContainsAny(arg, specialChars) {
// See: https://stackoverflow.com/questions/15783701/which-characters-need-to-be-escaped-when-using-bash
arg = "'" + strings.ReplaceAll(arg, `'`, `'\''`) + "'"
command[i] = arg
}
}
fmt.Fprintln(os.Stderr, strings.Join(command, " "))
}
// Build compiles and links the given package and writes it to outpath. // Build compiles and links the given package and writes it to outpath.
func Build(pkgName, outpath string, options *compileopts.Options) error { func Build(pkgName, outpath string, options *compileopts.Options) error {
config, err := builder.NewConfig(options) config, err := builder.NewConfig(options)
@ -1008,7 +1027,6 @@ func main() {
PrintSizes: *printSize, PrintSizes: *printSize,
PrintStacks: *printStacks, PrintStacks: *printStacks,
PrintAllocs: printAllocs, PrintAllocs: printAllocs,
PrintCommands: *printCommands,
Tags: *tags, Tags: *tags,
GlobalValues: globalVarValues, GlobalValues: globalVarValues,
WasmAbi: *wasmAbi, WasmAbi: *wasmAbi,
@ -1016,6 +1034,9 @@ func main() {
OpenOCDCommands: ocdCommands, OpenOCDCommands: ocdCommands,
LLVMFeatures: *llvmFeatures, LLVMFeatures: *llvmFeatures,
} }
if *printCommands {
options.PrintCommands = printCommand
}
os.Setenv("CC", "clang -target="+*target) os.Setenv("CC", "clang -target="+*target)