all: add support for Windows
Этот коммит содержится в:
родитель
8906192690
коммит
7369a0e7f2
11 изменённых файлов: 157 добавлений и 28 удалений
50
Makefile
50
Makefile
|
@ -1,7 +1,6 @@
|
||||||
|
|
||||||
# aliases
|
# aliases
|
||||||
all: tinygo
|
all: tinygo
|
||||||
tinygo: build/tinygo
|
|
||||||
|
|
||||||
# Default build and source directories, as created by `make llvm-build`.
|
# Default build and source directories, as created by `make llvm-build`.
|
||||||
LLVM_BUILDDIR ?= llvm-build
|
LLVM_BUILDDIR ?= llvm-build
|
||||||
|
@ -33,28 +32,55 @@ else
|
||||||
LLVM_OPTION += '-DLLVM_ENABLE_ASSERTIONS=OFF'
|
LLVM_OPTION += '-DLLVM_ENABLE_ASSERTIONS=OFF'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: all tinygo build/tinygo test $(LLVM_BUILDDIR) llvm-source clean fmt gen-device gen-device-nrf gen-device-avr
|
.PHONY: all tinygo test $(LLVM_BUILDDIR) llvm-source clean fmt gen-device gen-device-nrf gen-device-avr
|
||||||
|
|
||||||
LLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen core coroutines debuginfodwarf executionengine instrumentation interpreter ipo irreader linker lto mc mcjit objcarcopts option profiledata scalaropts support target
|
LLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen core coroutines debuginfodwarf executionengine instrumentation interpreter ipo irreader linker lto mc mcjit objcarcopts option profiledata scalaropts support target
|
||||||
|
|
||||||
UNAME_S := $(shell uname -s)
|
ifeq ($(OS),Windows_NT)
|
||||||
ifeq ($(UNAME_S),Linux)
|
EXE = .exe
|
||||||
START_GROUP = -Wl,--start-group
|
START_GROUP = -Wl,--start-group
|
||||||
END_GROUP = -Wl,--end-group
|
END_GROUP = -Wl,--end-group
|
||||||
else ifeq ($(UNAME_S),Darwin)
|
|
||||||
|
# LLVM compiled using MinGW on Windows appears to have problems with threads.
|
||||||
|
# Without this flag, linking results in errors like these:
|
||||||
|
# libLLVMSupport.a(Threading.cpp.obj):Threading.cpp:(.text+0x55): undefined reference to `std::thread::hardware_concurrency()'
|
||||||
|
LLVM_OPTION += -DLLVM_ENABLE_THREADS=OFF
|
||||||
|
|
||||||
|
CGO_LDFLAGS += -static -static-libgcc -static-libstdc++
|
||||||
|
CGO_LDFLAGS_EXTRA += -lversion
|
||||||
|
|
||||||
|
# Build libclang manually because the CMake-based build system on Windows
|
||||||
|
# doesn't allow building libclang as a static library.
|
||||||
|
LIBCLANG_PATH = $(abspath build/libclang-custom.a)
|
||||||
|
LIBCLANG_FILES = $(abspath $(wildcard $(LLVM_BUILDDIR)/tools/clang/tools/libclang/CMakeFiles/libclang.dir/*.cpp.obj))
|
||||||
|
|
||||||
|
# Add the libclang dependency to the tinygo binary target.
|
||||||
|
tinygo: $(LIBCLANG_PATH)
|
||||||
|
test: $(LIBCLANG_PATH)
|
||||||
|
# Build libclang.
|
||||||
|
$(LIBCLANG_PATH): $(LIBCLANG_FILES)
|
||||||
|
@mkdir -p build
|
||||||
|
ar rcs $(LIBCLANG_PATH) $^
|
||||||
|
|
||||||
|
else ifeq ($(shell uname -s),Darwin)
|
||||||
MD5SUM = md5
|
MD5SUM = md5
|
||||||
|
LIBCLANG_PATH = $(abspath $(LLVM_BUILDDIR))/lib/libclang.a
|
||||||
|
else
|
||||||
|
LIBCLANG_PATH = $(abspath $(LLVM_BUILDDIR))/lib/libclang.a
|
||||||
|
START_GROUP = -Wl,--start-group
|
||||||
|
END_GROUP = -Wl,--end-group
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CLANG_LIBS = $(START_GROUP) $(abspath $(LLVM_BUILDDIR))/lib/libclang.a -lclangAnalysis -lclangARCMigrate -lclangAST -lclangASTMatchers -lclangBasic -lclangCodeGen -lclangCrossTU -lclangDriver -lclangDynamicASTMatchers -lclangEdit -lclangFormat -lclangFrontend -lclangFrontendTool -lclangHandleCXX -lclangHandleLLVM -lclangIndex -lclangLex -lclangParse -lclangRewrite -lclangRewriteFrontend -lclangSema -lclangSerialization -lclangStaticAnalyzerCheckers -lclangStaticAnalyzerCore -lclangStaticAnalyzerFrontend -lclangTooling -lclangToolingASTDiff -lclangToolingCore -lclangToolingInclusions $(END_GROUP) -lstdc++
|
CLANG_LIBS = $(START_GROUP) -lclangAnalysis -lclangARCMigrate -lclangAST -lclangASTMatchers -lclangBasic -lclangCodeGen -lclangCrossTU -lclangDriver -lclangDynamicASTMatchers -lclangEdit -lclangFormat -lclangFrontend -lclangFrontendTool -lclangHandleCXX -lclangHandleLLVM -lclangIndex -lclangLex -lclangParse -lclangRewrite -lclangRewriteFrontend -lclangSema -lclangSerialization -lclangStaticAnalyzerCheckers -lclangStaticAnalyzerCore -lclangStaticAnalyzerFrontend -lclangTooling -lclangToolingASTDiff -lclangToolingCore -lclangToolingInclusions $(END_GROUP) -lstdc++
|
||||||
|
|
||||||
LLD_LIBS = $(START_GROUP) -llldCOFF -llldCommon -llldCore -llldDriver -llldELF -llldMachO -llldMinGW -llldReaderWriter -llldWasm -llldYAML $(END_GROUP)
|
LLD_LIBS = $(START_GROUP) -llldCOFF -llldCommon -llldCore -llldDriver -llldELF -llldMachO -llldMinGW -llldReaderWriter -llldWasm -llldYAML $(END_GROUP)
|
||||||
|
|
||||||
|
|
||||||
# For static linking.
|
# For static linking.
|
||||||
ifneq ("$(wildcard $(LLVM_BUILDDIR)/bin/llvm-config)","")
|
ifneq ("$(wildcard $(LLVM_BUILDDIR)/bin/llvm-config*)","")
|
||||||
CGO_CPPFLAGS=$(shell $(LLVM_BUILDDIR)/bin/llvm-config --cppflags) -I$(abspath $(CLANG_SRC))/include -I$(abspath $(LLD_SRC))/include
|
CGO_CPPFLAGS=$(shell $(LLVM_BUILDDIR)/bin/llvm-config --cppflags) -I$(abspath $(CLANG_SRC))/include -I$(abspath $(LLD_SRC))/include
|
||||||
CGO_CXXFLAGS=-std=c++11
|
CGO_CXXFLAGS=-std=c++11
|
||||||
CGO_LDFLAGS=-L$(LLVM_BUILDDIR)/lib $(CLANG_LIBS) $(LLD_LIBS) $(shell $(LLVM_BUILDDIR)/bin/llvm-config --ldflags --libs --system-libs $(LLVM_COMPONENTS))
|
CGO_LDFLAGS+=$(LIBCLANG_PATH) -std=c++11 -L$(abspath $(LLVM_BUILDDIR)/lib) $(CLANG_LIBS) $(LLD_LIBS) $(shell $(LLVM_BUILDDIR)/bin/llvm-config --ldflags --libs --system-libs $(LLVM_COMPONENTS)) -lstdc++ $(CGO_LDFLAGS_EXTRA)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,9 +134,9 @@ $(LLVM_BUILDDIR): $(LLVM_BUILDDIR)/build.ninja
|
||||||
|
|
||||||
|
|
||||||
# Build the Go compiler.
|
# Build the Go compiler.
|
||||||
build/tinygo:
|
tinygo:
|
||||||
@if [ ! -f "$(LLVM_BUILDDIR)/bin/llvm-config" ]; then echo "Fetch and build LLVM first by running:"; echo " make llvm-source"; echo " make $(LLVM_BUILDDIR)"; exit 1; fi
|
@if [ ! -f "$(LLVM_BUILDDIR)/bin/llvm-config" ]; then echo "Fetch and build LLVM first by running:"; echo " make llvm-source"; echo " make $(LLVM_BUILDDIR)"; exit 1; fi
|
||||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) build -o build/tinygo -tags byollvm .
|
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) build -o build/tinygo$(EXE) -tags byollvm .
|
||||||
|
|
||||||
test:
|
test:
|
||||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test -v -tags byollvm ./interp ./transform .
|
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test -v -tags byollvm ./interp ./transform .
|
||||||
|
@ -198,7 +224,7 @@ endif
|
||||||
$(TINYGO) build -o wasm.wasm -target=wasm examples/wasm/export
|
$(TINYGO) build -o wasm.wasm -target=wasm examples/wasm/export
|
||||||
$(TINYGO) build -o wasm.wasm -target=wasm examples/wasm/main
|
$(TINYGO) build -o wasm.wasm -target=wasm examples/wasm/main
|
||||||
|
|
||||||
release: build/tinygo gen-device
|
release: tinygo gen-device
|
||||||
@mkdir -p build/release/tinygo/bin
|
@mkdir -p build/release/tinygo/bin
|
||||||
@mkdir -p build/release/tinygo/lib/clang/include
|
@mkdir -p build/release/tinygo/lib/clang/include
|
||||||
@mkdir -p build/release/tinygo/lib/CMSIS/CMSIS
|
@mkdir -p build/release/tinygo/lib/CMSIS/CMSIS
|
||||||
|
@ -208,7 +234,7 @@ release: build/tinygo gen-device
|
||||||
@mkdir -p build/release/tinygo/pkg/armv7m-none-eabi
|
@mkdir -p build/release/tinygo/pkg/armv7m-none-eabi
|
||||||
@mkdir -p build/release/tinygo/pkg/armv7em-none-eabi
|
@mkdir -p build/release/tinygo/pkg/armv7em-none-eabi
|
||||||
@echo copying source files
|
@echo copying source files
|
||||||
@cp -p build/tinygo build/release/tinygo/bin
|
@cp -p build/tinygo$(EXE) build/release/tinygo/bin
|
||||||
@cp -p $(abspath $(CLANG_SRC))/lib/Headers/*.h build/release/tinygo/lib/clang/include
|
@cp -p $(abspath $(CLANG_SRC))/lib/Headers/*.h build/release/tinygo/lib/clang/include
|
||||||
@cp -rp lib/CMSIS/CMSIS/Include build/release/tinygo/lib/CMSIS/CMSIS
|
@cp -rp lib/CMSIS/CMSIS/Include build/release/tinygo/lib/CMSIS/CMSIS
|
||||||
@cp -rp lib/CMSIS/README.md build/release/tinygo/lib/CMSIS
|
@cp -rp lib/CMSIS/README.md build/release/tinygo/lib/CMSIS
|
||||||
|
|
61
azure-pipelines.yml
Обычный файл
61
azure-pipelines.yml
Обычный файл
|
@ -0,0 +1,61 @@
|
||||||
|
jobs:
|
||||||
|
- job: Build
|
||||||
|
timeoutInMinutes: 180
|
||||||
|
pool:
|
||||||
|
vmImage: 'VS2017-Win2016'
|
||||||
|
steps:
|
||||||
|
- checkout: self
|
||||||
|
- task: CacheBeta@0
|
||||||
|
displayName: Cache LLVM source
|
||||||
|
inputs:
|
||||||
|
key: llvm-source-8-windows-v0
|
||||||
|
path: llvm-project
|
||||||
|
- task: Bash@3
|
||||||
|
displayName: Download LLVM source
|
||||||
|
inputs:
|
||||||
|
targetType: inline
|
||||||
|
script: make llvm-source
|
||||||
|
- task: CacheBeta@0
|
||||||
|
displayName: Cache LLVM build
|
||||||
|
inputs:
|
||||||
|
key: llvm-build-8-windows-v1
|
||||||
|
path: llvm-build
|
||||||
|
- task: Bash@3
|
||||||
|
displayName: Build LLVM
|
||||||
|
inputs:
|
||||||
|
targetType: inline
|
||||||
|
script: |
|
||||||
|
if [ ! -f llvm-build/lib/liblldELF.a ]
|
||||||
|
then
|
||||||
|
choco install ninja
|
||||||
|
make llvm-build
|
||||||
|
fi
|
||||||
|
- task: Bash@3
|
||||||
|
displayName: Install QEMU
|
||||||
|
inputs:
|
||||||
|
targetType: inline
|
||||||
|
script: choco install qemu
|
||||||
|
- task: Bash@3
|
||||||
|
displayName: Test TinyGo
|
||||||
|
inputs:
|
||||||
|
targetType: inline
|
||||||
|
script: |
|
||||||
|
export PATH="$PATH:./llvm-build/bin:/c/Program Files/qemu"
|
||||||
|
make test
|
||||||
|
- task: Bash@3
|
||||||
|
displayName: Build TinyGo release tarball
|
||||||
|
inputs:
|
||||||
|
targetType: inline
|
||||||
|
script: |
|
||||||
|
export PATH="$PATH:./llvm-build/bin:/c/Program Files/qemu"
|
||||||
|
make release -j4
|
||||||
|
- publish: $(System.DefaultWorkingDirectory)/build/release.tar.gz
|
||||||
|
displayName: Publish tarball as artifact
|
||||||
|
artifact: tinygo.windows-amd64.tar.gz
|
||||||
|
- task: Bash@3
|
||||||
|
displayName: Smoke tests
|
||||||
|
inputs:
|
||||||
|
targetType: inline
|
||||||
|
script: |
|
||||||
|
export PATH="$PATH:./llvm-build/bin:/c/Program Files/qemu"
|
||||||
|
make smoketest TINYGO=build/tinygo AVR=0 RISCV=0
|
|
@ -109,10 +109,10 @@ func moveFile(src, dst string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = os.Rename(dst+".tmp", dst)
|
err = outf.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return outf.Close()
|
return os.Rename(dst+".tmp", dst)
|
||||||
}
|
}
|
||||||
|
|
10
commands.go
10
commands.go
|
@ -24,6 +24,14 @@ func init() {
|
||||||
commands["ld.lld"] = append(commands["ld.lld"], "/usr/local/opt/llvm/bin/ld.lld")
|
commands["ld.lld"] = append(commands["ld.lld"], "/usr/local/opt/llvm/bin/ld.lld")
|
||||||
commands["wasm-ld"] = append(commands["wasm-ld"], "/usr/local/opt/llvm/bin/wasm-ld")
|
commands["wasm-ld"] = append(commands["wasm-ld"], "/usr/local/opt/llvm/bin/wasm-ld")
|
||||||
}
|
}
|
||||||
|
// Add the path for when LLVM was installed with the installer from
|
||||||
|
// llvm.org, which by default doesn't add LLVM to the $PATH environment
|
||||||
|
// variable.
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
commands["clang"] = append(commands["clang"], "clang", "C:\\Program Files\\LLVM\\bin\\clang.exe")
|
||||||
|
commands["ld.lld"] = append(commands["ld.lld"], "lld", "C:\\Program Files\\LLVM\\bin\\lld.exe")
|
||||||
|
commands["wasm-ld"] = append(commands["wasm-ld"], "C:\\Program Files\\LLVM\\bin\\wasm-ld.exe")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func execCommand(cmdNames []string, args ...string) error {
|
func execCommand(cmdNames []string, args ...string) error {
|
||||||
|
@ -33,7 +41,7 @@ func execCommand(cmdNames []string, args ...string) error {
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err, ok := err.(*exec.Error); ok && err.Err == exec.ErrNotFound {
|
if err, ok := err.(*exec.Error); ok && (err.Err == exec.ErrNotFound || err.Err.Error() == "file does not exist") {
|
||||||
// this command was not found, try the next
|
// this command was not found, try the next
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,7 @@ func fuzzyEqualIR(s1, s2 string) bool {
|
||||||
func filterIrrelevantIRLines(lines []string) []string {
|
func filterIrrelevantIRLines(lines []string) []string {
|
||||||
var out []string
|
var out []string
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
|
line = strings.TrimSpace(line) // drop '\r' on Windows
|
||||||
if line == "" || line[0] == ';' {
|
if line == "" || line[0] == ';' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -317,9 +317,9 @@ func (p *Program) parseFile(path string, mode parser.Mode) (*ast.File, error) {
|
||||||
defer rd.Close()
|
defer rd.Close()
|
||||||
relpath := path
|
relpath := path
|
||||||
if filepath.IsAbs(path) {
|
if filepath.IsAbs(path) {
|
||||||
relpath, err = filepath.Rel(p.Dir, path)
|
rp, err := filepath.Rel(p.Dir, path)
|
||||||
if err != nil {
|
if err == nil {
|
||||||
return nil, err
|
relpath = rp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return parser.ParseFile(p.fset, relpath, rd, mode)
|
return parser.ParseFile(p.fset, relpath, rd, mode)
|
||||||
|
|
6
main.go
6
main.go
|
@ -552,11 +552,7 @@ func FlashGDB(pkgName, target, port string, ocdOutput bool, config *BuildConfig)
|
||||||
}
|
}
|
||||||
// Make sure the daemon doesn't receive Ctrl-C that is intended for
|
// Make sure the daemon doesn't receive Ctrl-C that is intended for
|
||||||
// GDB (to break the currently executing program).
|
// GDB (to break the currently executing program).
|
||||||
// https://stackoverflow.com/a/35435038/559350
|
setCommandAsDaemon(daemon)
|
||||||
daemon.SysProcAttr = &syscall.SysProcAttr{
|
|
||||||
Setpgid: true,
|
|
||||||
Pgid: 0,
|
|
||||||
}
|
|
||||||
// Start now, and kill it on exit.
|
// Start now, and kill it on exit.
|
||||||
daemon.Start()
|
daemon.Start()
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|
13
main_test.go
13
main_test.go
|
@ -45,11 +45,13 @@ func TestCompiler(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(tmpdir)
|
defer os.RemoveAll(tmpdir)
|
||||||
|
|
||||||
t.Log("running tests on host...")
|
if runtime.GOOS != "windows" {
|
||||||
for _, path := range matches {
|
t.Log("running tests on host...")
|
||||||
t.Run(path, func(t *testing.T) {
|
for _, path := range matches {
|
||||||
runTest(path, tmpdir, "", t)
|
t.Run(path, func(t *testing.T) {
|
||||||
})
|
runTest(path, tmpdir, "", t)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
|
@ -162,6 +164,7 @@ func runTest(path, tmpdir string, target string, t *testing.T) {
|
||||||
|
|
||||||
// putchar() prints CRLF, convert it to LF.
|
// putchar() prints CRLF, convert it to LF.
|
||||||
actual := bytes.Replace(stdout.Bytes(), []byte{'\r', '\n'}, []byte{'\n'}, -1)
|
actual := bytes.Replace(stdout.Bytes(), []byte{'\r', '\n'}, []byte{'\n'}, -1)
|
||||||
|
expected = bytes.Replace(expected, []byte{'\r', '\n'}, []byte{'\n'}, -1) // for Windows
|
||||||
|
|
||||||
// Check whether the command ran successfully.
|
// Check whether the command ran successfully.
|
||||||
fail := false
|
fail := false
|
||||||
|
|
|
@ -70,6 +70,7 @@ func fuzzyEqualIR(s1, s2 string) bool {
|
||||||
func filterIrrelevantIRLines(lines []string) []string {
|
func filterIrrelevantIRLines(lines []string) []string {
|
||||||
var out []string
|
var out []string
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
|
line = strings.TrimSpace(line) // drop '\r' on Windows
|
||||||
if line == "" || line[0] == ';' {
|
if line == "" || line[0] == ';' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
20
util_unix.go
Обычный файл
20
util_unix.go
Обычный файл
|
@ -0,0 +1,20 @@
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
// This file contains utility functions for Unix-like systems (e.g. Linux).
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// setCommandAsDaemon makes sure this command does not receive signals sent to
|
||||||
|
// the parent.
|
||||||
|
func setCommandAsDaemon(daemon *exec.Cmd) {
|
||||||
|
// https://stackoverflow.com/a/35435038/559350
|
||||||
|
daemon.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
Setpgid: true,
|
||||||
|
Pgid: 0,
|
||||||
|
}
|
||||||
|
}
|
13
util_windows.go
Обычный файл
13
util_windows.go
Обычный файл
|
@ -0,0 +1,13 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
// This file contains utility functions for Windows.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
// setCommandAsDaemon makes sure this command does not receive signals sent to
|
||||||
|
// the parent. It is unimplemented on Windows.
|
||||||
|
func setCommandAsDaemon(daemon *exec.Cmd) {
|
||||||
|
// Not implemented.
|
||||||
|
}
|
Загрузка…
Создание таблицы
Сослаться в новой задаче