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.
Этот коммит содержится в:
родитель
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
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)
|
||||||
|
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче