From 62d74d83290032480da316a9e7f4069678ee6f13 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Thu, 22 Nov 2018 13:24:13 +0100 Subject: [PATCH] all: compile and link using clang, where possible --- builtins.go | 2 +- docs/installation.rst | 9 ++++---- main.go | 25 +++++++++++++++++---- target.go | 50 +++++++++++++++++++++++------------------- targets/arduino.json | 13 ++++++----- targets/arm.ld | 3 +++ targets/avr.json | 7 +++++- targets/bluepill.json | 18 +++++++-------- targets/cortex-m.json | 13 ++++++++++- targets/cortex-m.s | 2 +- targets/digispark.json | 13 ++++++----- targets/nrf51.json | 20 ++++++++--------- targets/nrf52.json | 20 ++++++++--------- targets/nrf52840.json | 20 ++++++++--------- targets/qemu.json | 18 +++++++-------- 15 files changed, 133 insertions(+), 100 deletions(-) diff --git a/builtins.go b/builtins.go index 2d43a8ed..8d665457 100644 --- a/builtins.go +++ b/builtins.go @@ -195,7 +195,7 @@ func loadBuiltins(target string) (path string, err error) { objpath := filepath.Join(dir, objname+".o") objs = append(objs, objpath) srcpath := filepath.Join(builtinsDir, name) - cmd := exec.Command(commands["clang"], "-c", "-Oz", "-g", "-Werror", "-Wall", "-std=c11", "-fshort-enums", "-nostdlibinc", "--target="+target, "-o", objpath, srcpath) + cmd := exec.Command(commands["clang"], "-c", "-Oz", "-g", "-Werror", "-Wall", "-std=c11", "-fshort-enums", "-nostdlibinc", "-ffunction-sections", "-fdata-sections", "--target="+target, "-o", objpath, srcpath) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Dir = dir diff --git a/docs/installation.rst b/docs/installation.rst index f1719a94..af50ceca 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -24,11 +24,10 @@ ARM LLVM backend (which is even used in the propietary C compiler from ARM). Compiling to object code should be supported out of the box, but compiling the final binary and flashing it needs some extra tools. - * binutils (``arm-none-eabi-objcopy``) for producing .hex files for - flashing. - * GCC (``arm-none-eabi-gcc``) for linking object files. - * Clang 7 (``clang-7``) for building the `compiler runtime library - `_. + * binutils (``arm-none-eabi-ld``, ``arm-none-eabi-objcopy``) for linking and + for producing .hex files for flashing. + * Clang 7 (``clang-7``) for building assembly files and the `compiler + runtime library `_ . * The flashing tool for the particular chip, like ``openocd`` or ``nrfjprog``. diff --git a/main.go b/main.go index e87636d6..d371e466 100644 --- a/main.go +++ b/main.go @@ -10,6 +10,7 @@ import ( "os/exec" "os/signal" "path/filepath" + "strconv" "strings" "syscall" @@ -161,14 +162,30 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act cachePath, _ = filepath.Split(librt) } - // Link the object file with the system compiler. + // Prepare link command. executable := filepath.Join(dir, "main") tmppath := executable // final file - args := append(spec.PreLinkArgs, "-o", executable, objfile) + ldflags := append(spec.LDFlags, "-o", executable, objfile) if spec.RTLib == "compiler-rt" { - args = append(args, "-L", cachePath, "-lrt-"+spec.Triple) + ldflags = append(ldflags, "-L", cachePath, "-lrt-"+spec.Triple) } - cmd := exec.Command(spec.Linker, args...) + + // Compile extra files. + for i, path := range spec.ExtraFiles { + outpath := filepath.Join(dir, "extra-"+strconv.Itoa(i)+"-"+filepath.Base(path)+".o") + cmd := exec.Command(spec.Compiler, append(spec.CFlags, "-c", "-o", outpath, path)...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Dir = sourceDir() + err := cmd.Run() + if err != nil { + return err + } + ldflags = append(ldflags, outpath) + } + + // Link the object files together. + cmd := exec.Command(spec.Linker, ldflags...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Dir = sourceDir() diff --git a/target.go b/target.go index 8d425595..b8f73ddf 100644 --- a/target.go +++ b/target.go @@ -18,18 +18,21 @@ import ( // https://doc.rust-lang.org/nightly/nightly-rustc/rustc_target/spec/struct.TargetOptions.html // https://github.com/shepmaster/rust-arduino-blink-led-no-core-with-cargo/blob/master/blink/arduino.json type TargetSpec struct { - Inherits []string `json:"inherits"` - Triple string `json:"llvm-target"` - BuildTags []string `json:"build-tags"` - Linker string `json:"linker"` - RTLib string `json:"rtlib"` // compiler runtime library (libgcc, compiler-rt) - PreLinkArgs []string `json:"pre-link-args"` - Objcopy string `json:"objcopy"` - Emulator []string `json:"emulator"` - Flasher string `json:"flash"` - OCDDaemon []string `json:"ocd-daemon"` - GDB string `json:"gdb"` - GDBCmds []string `json:"gdb-initial-cmds"` + Inherits []string `json:"inherits"` + Triple string `json:"llvm-target"` + BuildTags []string `json:"build-tags"` + Compiler string `json:"compiler"` + Linker string `json:"linker"` + RTLib string `json:"rtlib"` // compiler runtime library (libgcc, compiler-rt) + CFlags []string `json:"cflags"` + LDFlags []string `json:"ldflags"` + ExtraFiles []string `json:"extra-files"` + Objcopy string `json:"objcopy"` + Emulator []string `json:"emulator"` + Flasher string `json:"flash"` + OCDDaemon []string `json:"ocd-daemon"` + GDB string `json:"gdb"` + GDBCmds []string `json:"gdb-initial-cmds"` } // copyProperties copies all properties that are set in spec2 into itself. @@ -41,15 +44,18 @@ func (spec *TargetSpec) copyProperties(spec2 *TargetSpec) { spec.Triple = spec2.Triple } spec.BuildTags = append(spec.BuildTags, spec2.BuildTags...) + if spec2.Compiler != "" { + spec.Compiler = spec2.Compiler + } if spec2.Linker != "" { spec.Linker = spec2.Linker } if spec2.RTLib != "" { spec.RTLib = spec2.RTLib } - if len(spec2.PreLinkArgs) != 0 { - spec.PreLinkArgs = spec2.PreLinkArgs - } + spec.CFlags = append(spec.CFlags, spec2.CFlags...) + spec.LDFlags = append(spec.LDFlags, spec2.LDFlags...) + spec.ExtraFiles = append(spec.ExtraFiles, spec2.ExtraFiles...) if spec2.Objcopy != "" { spec.Objcopy = spec2.Objcopy } @@ -143,13 +149,13 @@ func LoadTarget(target string) (*TargetSpec, error) { // No target spec available. Use the default one, useful on most systems // with a regular OS. *spec = TargetSpec{ - Triple: target, - BuildTags: []string{runtime.GOOS, runtime.GOARCH}, - Linker: "cc", - PreLinkArgs: []string{"-no-pie"}, // WARNING: clang < 5.0 requires -nopie - Objcopy: "objcopy", - GDB: "gdb", - GDBCmds: []string{"run"}, + Triple: target, + BuildTags: []string{runtime.GOOS, runtime.GOARCH}, + Linker: "cc", + LDFlags: []string{"-no-pie"}, // WARNING: clang < 5.0 requires -nopie + Objcopy: "objcopy", + GDB: "gdb", + GDBCmds: []string{"run"}, } return spec, nil } diff --git a/targets/arduino.json b/targets/arduino.json index 795a9956..20e592be 100644 --- a/targets/arduino.json +++ b/targets/arduino.json @@ -2,14 +2,15 @@ "inherits": ["avr"], "llvm-target": "avr-atmel-none", "build-tags": ["arduino", "atmega328p", "atmega", "avr5"], - "pre-link-args": [ - "-nostartfiles", - "-mmcu=avr5", + "cflags": [ + "-mmcu=atmega328p" + ], + "ldflags": [ "-Wl,--defsym=_bootloader_size=512", "-Wl,--defsym=_stack_size=512", - "-T", "src/device/avr/atmega328p.ld", - "-T", "targets/avr.ld", - "-Wl,--gc-sections", + "-T", "src/device/avr/atmega328p.ld" + ], + "extra-files": [ "targets/avr.S", "src/device/avr/atmega328p.s" ], diff --git a/targets/arm.ld b/targets/arm.ld index 2788fddd..c964331d 100644 --- a/targets/arm.ld +++ b/targets/arm.ld @@ -1,4 +1,7 @@ +/* Unused, but here to silence a linker warning. */ +ENTRY(Reset_Handler) + /* define output sections */ SECTIONS { diff --git a/targets/avr.json b/targets/avr.json index debb5478..abe486ec 100644 --- a/targets/avr.json +++ b/targets/avr.json @@ -1,5 +1,10 @@ { "build-tags": ["avr", "js", "wasm"], + "compiler": "avr-gcc", "linker": "avr-gcc", - "objcopy": "avr-objcopy" + "objcopy": "avr-objcopy", + "ldflags": [ + "-T", "targets/avr.ld", + "-Wl,--gc-sections" + ] } diff --git a/targets/bluepill.json b/targets/bluepill.json index 3c086ec6..ef2c915a 100644 --- a/targets/bluepill.json +++ b/targets/bluepill.json @@ -2,16 +2,14 @@ "inherits": ["cortex-m"], "llvm-target": "armv7m-none-eabi", "build-tags": ["bluepill", "stm32f103xx", "stm32"], - "pre-link-args": [ - "-nostdlib", - "-nostartfiles", - "-mcpu=cortex-m3", - "-mthumb", - "-T", "targets/stm32.ld", - "-Wl,--gc-sections", - "-fno-exceptions", "-fno-unwind-tables", - "-ffunction-sections", "-fdata-sections", - "-Os", + "cflags": [ + "--target=armv7m-none-eabi", + "-Qunused-arguments" + ], + "ldflags": [ + "-T", "targets/stm32.ld" + ], + "extra-files": [ "src/device/stm32/stm32f103xx.s" ], "flash": "openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c 'program {hex} reset exit'" diff --git a/targets/cortex-m.json b/targets/cortex-m.json index 71d354f4..b373ef9b 100644 --- a/targets/cortex-m.json +++ b/targets/cortex-m.json @@ -1,7 +1,18 @@ { "build-tags": ["tinygo.arm", "js", "wasm"], - "linker": "arm-none-eabi-gcc", + "compiler": "clang-7", + "linker": "arm-none-eabi-ld", "rtlib": "compiler-rt", + "cflags": [ + "-Oz", + "-mthumb", + "-fshort-enums", + "-fno-exceptions", "-fno-unwind-tables", + "-ffunction-sections", "-fdata-sections" + ], + "ldflags": [ + "--gc-sections" + ], "objcopy": "arm-none-eabi-objcopy", "gdb": "arm-none-eabi-gdb" } diff --git a/targets/cortex-m.s b/targets/cortex-m.s index 62ed28ef..595ff56f 100644 --- a/targets/cortex-m.s +++ b/targets/cortex-m.s @@ -26,7 +26,7 @@ Default_Handler: .set \handler, Default_Handler .endm -.section .isr_vector +.section .isr_vector, "a", %progbits .global __isr_vector // Interrupt vector as defined by Cortex-M, starting with the stack top. // On reset, SP is initialized with *0x0 and PC is loaded with *0x4, loading diff --git a/targets/digispark.json b/targets/digispark.json index 02d9b87e..6c198f4f 100644 --- a/targets/digispark.json +++ b/targets/digispark.json @@ -2,14 +2,15 @@ "inherits": ["avr"], "llvm-target": "avr-atmel-none", "build-tags": ["digispark", "attiny85", "attiny", "avr2", "avr25"], - "pre-link-args": [ - "-nostartfiles", - "-mmcu=attiny85", + "cflags": [ + "-mmcu=attiny85" + ], + "ldflags": [ "-Wl,--defsym=_bootloader_size=2180", "-Wl,--defsym=_stack_size=128", - "-T", "src/device/avr/attiny85.ld", - "-T", "targets/avr.ld", - "-Wl,--gc-sections", + "-T", "src/device/avr/attiny85.ld" + ], + "extra-files": [ "targets/avr.S", "src/device/avr/attiny85.s" ], diff --git a/targets/nrf51.json b/targets/nrf51.json index 68c6b14f..f37db3e9 100644 --- a/targets/nrf51.json +++ b/targets/nrf51.json @@ -2,18 +2,16 @@ "inherits": ["cortex-m"], "llvm-target": "armv6m-none-eabi", "build-tags": ["nrf51822", "nrf51", "nrf"], - "pre-link-args": [ - "-nostdlib", - "-nostartfiles", - "-mcpu=cortex-m0", - "-mthumb", - "-T", "targets/nrf51.ld", - "-Wl,--gc-sections", - "-fno-exceptions", "-fno-unwind-tables", - "-ffunction-sections", "-fdata-sections", - "-Os", + "cflags": [ + "--target=armv6m-none-eabi", + "-Qunused-arguments", "-DNRF51", - "-Ilib/CMSIS/CMSIS/Include", + "-Ilib/CMSIS/CMSIS/Include" + ], + "ldflags": [ + "-T", "targets/nrf51.ld" + ], + "extra-files": [ "lib/nrfx/mdk/system_nrf51.c", "src/device/nrf/nrf51.s" ] diff --git a/targets/nrf52.json b/targets/nrf52.json index 53ff2a47..6eeaf651 100644 --- a/targets/nrf52.json +++ b/targets/nrf52.json @@ -2,18 +2,16 @@ "inherits": ["cortex-m"], "llvm-target": "armv7em-none-eabi", "build-tags": ["nrf52", "nrf"], - "pre-link-args": [ - "-nostdlib", - "-nostartfiles", - "-mcpu=cortex-m4", - "-mthumb", - "-T", "targets/nrf52.ld", - "-Wl,--gc-sections", - "-fno-exceptions", "-fno-unwind-tables", - "-ffunction-sections", "-fdata-sections", - "-Os", + "cflags": [ + "--target=armv7em-none-eabi", + "-Qunused-arguments", "-DNRF52832_XXAA", - "-Ilib/CMSIS/CMSIS/Include", + "-Ilib/CMSIS/CMSIS/Include" + ], + "ldflags": [ + "-T", "targets/nrf52.ld" + ], + "extra-files": [ "lib/nrfx/mdk/system_nrf52.c", "src/device/nrf/nrf52.s" ] diff --git a/targets/nrf52840.json b/targets/nrf52840.json index 8346735c..d49a1f0a 100644 --- a/targets/nrf52840.json +++ b/targets/nrf52840.json @@ -2,18 +2,16 @@ "inherits": ["cortex-m"], "llvm-target": "armv7em-none-eabi", "build-tags": ["nrf52840", "nrf"], - "pre-link-args": [ - "-nostdlib", - "-nostartfiles", - "-mcpu=cortex-m4", - "-mthumb", - "-T", "targets/nrf52840.ld", - "-Wl,--gc-sections", - "-fno-exceptions", "-fno-unwind-tables", - "-ffunction-sections", "-fdata-sections", - "-Os", + "cflags": [ + "--target=armv7em-none-eabi", + "-Qunused-arguments", "-DNRF52840_XXAA", - "-Ilib/CMSIS/CMSIS/Include", + "-Ilib/CMSIS/CMSIS/Include" + ], + "ldflags": [ + "-T", "targets/nrf52840.ld" + ], + "extra-files": [ "lib/nrfx/mdk/system_nrf52840.c", "src/device/nrf/nrf52840.s" ] diff --git a/targets/qemu.json b/targets/qemu.json index 7cc23da8..929fb1e8 100644 --- a/targets/qemu.json +++ b/targets/qemu.json @@ -2,16 +2,14 @@ "inherits": ["cortex-m"], "llvm-target": "armv7m-none-eabi", "build-tags": ["qemu", "lm3s6965"], - "pre-link-args": [ - "-nostdlib", - "-nostartfiles", - "-mcpu=cortex-m0", - "-mthumb", - "-T", "targets/lm3s6965.ld", - "-Wl,--gc-sections", - "-fno-exceptions", "-fno-unwind-tables", - "-ffunction-sections", "-fdata-sections", - "-Os", + "cflags": [ + "--target=armv7m-none-eabi", + "-Qunused-arguments" + ], + "ldflags": [ + "-T", "targets/lm3s6965.ld" + ], + "extra-files": [ "targets/cortex-m.s" ], "emulator": ["qemu-system-arm", "-machine", "lm3s6965evb", "-semihosting", "-nographic", "-kernel"]