From 7f88d84b2348e6e641a619fc6119d3ddf8120efe Mon Sep 17 00:00:00 2001 From: "Ian A. Mason" Date: Mon, 10 Jul 2017 13:01:21 -0700 Subject: [PATCH] sanity checker ported too. --- .travis/test.sh | 19 ++-- Makefile | 4 +- cmd/gsanity-check/main.go | 14 +++ cmd/gsanity-check/sanity.go | 203 ++++++++++++++++++++++++++++++++++++ shared/compiler.go | 5 +- shared/logging.go | 2 + 6 files changed, 231 insertions(+), 16 deletions(-) create mode 100644 cmd/gsanity-check/main.go create mode 100644 cmd/gsanity-check/sanity.go diff --git a/.travis/test.sh b/.travis/test.sh index 3569a60..5be4cac 100755 --- a/.travis/test.sh +++ b/.travis/test.sh @@ -6,23 +6,16 @@ set -e export PATH=/usr/lib/llvm-3.8/bin:${PATH} export GLLVM_OUTPUT_LEVEL=WARNING -#currently the musllvm build fails with -# -#/usr/bin/ld: obj/src/process/posix_spawn.lo: relocation R_X86_64_PC32 against protected symbol `execve' can not be used when making a shared object -#/usr/bin/ld: final link failed: Bad value -#clang: error: linker command failed with exit code 1 (use -v to see invocation) -#2017/06/29 19:10:32 Failed to link. -#make: *** [lib/libc.so] Error 1 -# -#need to investigate inside a vagrant box. -exit 0 - git clone https://github.com/SRI-CSL/musllvm.git musllvm + cd musllvm + GLLVM_CONFIGURE_ONLY=1 CC=gclang ./configure --target=LLVM --build=LLVM + make -get-bc --bitcode ./lib/libc.a + +get-bc -b ./lib/libc.a if [ -s "./lib/libc.a.bc" ] then @@ -30,3 +23,5 @@ then else exit 1 fi + +exit 0 diff --git a/Makefile b/Makefile index 3b8d0d8..418faf9 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,12 @@ GOROOT := $(shell go env GOPATH) build: - go build ./shared ./cmd/gclang ./cmd/gclang++ ./cmd/get-bc + go build ./shared ./cmd/gclang ./cmd/gclang++ ./cmd/get-bc ./cmd/gsanity-check install: build - go install ./cmd/gclang ./cmd/gclang++ ./cmd/get-bc + go install ./cmd/gclang ./cmd/gclang++ ./cmd/get-bc ./cmd/gsanity-check clean: go clean diff --git a/cmd/gsanity-check/main.go b/cmd/gsanity-check/main.go new file mode 100644 index 0000000..9bd49d6 --- /dev/null +++ b/cmd/gsanity-check/main.go @@ -0,0 +1,14 @@ +package main + +import ( + "os" +) + +func main() { + // Parse command line + var args = os.Args + args = args[1:] + + sanityCheck() + +} diff --git a/cmd/gsanity-check/sanity.go b/cmd/gsanity-check/sanity.go new file mode 100644 index 0000000..f8a1925 --- /dev/null +++ b/cmd/gsanity-check/sanity.go @@ -0,0 +1,203 @@ +package main + +import ( + "bytes" + "github.com/SRI-CSL/gllvm/shared" + "os" + "os/exec" + "runtime" + "strings" +) + +const explain_LLVM_CC_NAME = ` + +If your clang compiler is not called clang, but something else, then +you will need to set the environment variable LLVM_CC_NAME to the +appropriate string. For example if your clang is called clang-3.5 then +LLVM_CC_NAME should be set to clang-3.5. + +` + +const explain_LLVM_CXX_NAME = ` + +If your clang++ compiler is not called clang++, but something else, +then you will need to set the environment variable LLVM_CXX_NAME to +the appropriate string. For example if your clang++ is called ++clang +then LLVM_CC_NAME should be set to ++clang. + +` + +const explain_LLVM_COMPILER_PATH = ` + +Your compiler should either be in your PATH, or else located where the +environment variable LLVM_COMPILER_PATH indicates. It can also be used +to indicate the directory that contains the other LLVM tools such as +llvm-link, and llvm-ar. + +` + +const explain_LLVM_LINK_NAME = ` + +If your llvm linker is not called llvm-link, but something else, then +you will need to set the environment variable LLVM_LINK_NAME to the +appropriate string. For example if your llvm-link is called llvm-link-3.5 then +LLVM_LINK_NAME should be set to llvm-link-3.5. + +` + +const explain_LLVM_AR_NAME = ` + +If your llvm archiver is not called llvm-ar, but something else, +then you will need to set the environment variable LLVM_AR_NAME to +the appropriate string. For example if your llvm-ar is called llvm-ar-3.5 +then LLVM_AR_NAME should be set to llvm-ar-3.5. + +` + + + +// Performs the environmental sanity check. +// +// Performs the following checks in order: +// +// 1. Check that the OS is supported. +// 2. Checks that the compiler settings make sense. +// 3. Checks that the needed LLVM utilities exists. +// 4. Check that the store, if set, exists. +// +func sanityCheck() { + + checkOS() + + if ! checkCompilers() { + os.Exit(1) + } + + if ! checkAuxiliaries() { + os.Exit(1) + } + + checkStore() + + +} + + +func checkOS(){ + + platform := runtime.GOOS + + + if platform == "darwin" || platform == "linux" || platform == "freebsd" { + return + } + + shared.LogFatal("We do not support the OS %s", platform) +} + +func checkCompilers() bool { + + cc := shared.GetCompilerExecName("clang") + ccOK, _, ccVersion := checkExecutable(cc, "-v") + if !ccOK { + shared.LogError("The C compiler %s was not found or not executable.\nBetter not try using gclang!\n", cc) + } else { + shared.LogWrite("The C compiler %s is:\n\n\t%s\n\n", cc, extractLine(ccVersion, 0)) + } + + cxx := shared.GetCompilerExecName("clang++") + cxxOK, _, cxxVersion := checkExecutable(cxx, "-v") + if !ccOK { + shared.LogError("The CXX compiler %s was not found or not executable.\nBetter not try using gclang++!\n", cxx) + } else { + shared.LogWrite("The CXX compiler %s is:\n\n\t%s\n\n", cxx, extractLine(cxxVersion, 0)) + } + + + return ccOK || cxxOK +} + +func extractLine(version string, n int) string { + if len(version) == 0 { + return version + } + lines := strings.Split(version, "\n") + var line string + lenLines := len(lines) + if n < lenLines { + line = lines[n] + } else { + line = lines[lenLines - 1] + } + + return strings.TrimSpace(line) + +} + +// Executes a command then returns true for success, false if there was an error, err is either nil or the error. +func checkExecutable(cmdExecName string, varg string) (success bool, err error, output string) { + cmd := exec.Command(cmdExecName, varg) + var out bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &out + cmd.Stdin = os.Stdin + err = cmd.Run() + success = (err == nil) + output = out.String() + return +} + + +func checkAuxiliaries() bool { + linkerName := shared.LLVMLINKName + archiverName := shared.LLVMARName + + if linkerName == "" { + linkerName = "llvm-link" + } + + if archiverName == "" { + archiverName = "llvm-ar" + } + + linkerOK, _, linkerVersion := checkExecutable(linkerName, "-version") + + + if ! linkerOK { + shared.LogError("The bitcode linker %s was not found or not executable.\nBetter not try using get-bc!\n", linkerName) + shared.LogError(explain_LLVM_LINK_NAME) + } else { + shared.LogWrite("The bitcode linker %s is:\n\n\t%s\n\n", linkerName, extractLine(linkerVersion, 1)) + } + + archiverOK, _, archiverVersion := checkExecutable(archiverName, "-version") + + + if ! archiverOK { + shared.LogError("The bitcode archiver %s was not found or not executable.\nBetter not try using get-bc!\n", archiverName) + shared.LogError(explain_LLVM_AR_NAME) + } else { + shared.LogWrite("The bitcode archiver %s is:\n\n\t%s\n\n", archiverName, extractLine(archiverVersion, 1)) + } + + return true +} + +func checkStore() { + storeDir := shared.BitcodeStorePath + + if storeDir != "" { + finfo, err := os.Stat(storeDir) + if err != nil && os.IsNotExist(err) { + shared.LogError("The bitcode archive %s does not exist!\n\n", storeDir) + return + } + if ! finfo.Mode().IsDir() { + shared.LogError("The bitcode archive %s is not a directory!\n\n", storeDir) + return + } + shared.LogWrite("Using the bitcode archive %s\n\n", storeDir) + return + } + shared.LogWrite("Not using a bitcode store.\n\n") +} diff --git a/shared/compiler.go b/shared/compiler.go index b345386..c0066b4 100644 --- a/shared/compiler.go +++ b/shared/compiler.go @@ -24,7 +24,7 @@ func Compile(args []string, compiler string) (exitCode int) { var ok = true - var compilerExecName = getCompilerExecName(compiler) + var compilerExecName = GetCompilerExecName(compiler) var configureOnly bool if ConfigureOnly != "" { configureOnly = true @@ -200,7 +200,8 @@ func execCompile(compilerExecName string, pr parserResult, wg *sync.WaitGroup, o } } -func getCompilerExecName(compiler string) string { +// GetCompilerExecName returns the full path of the executable +func GetCompilerExecName(compiler string) string { switch compiler { case "clang": if LLVMCCName != "" { diff --git a/shared/logging.go b/shared/logging.go index 8e3b6e1..2f7db36 100644 --- a/shared/logging.go +++ b/shared/logging.go @@ -66,3 +66,5 @@ func LogFatal(format string, a ...interface{}) { LogError(format, a...) os.Exit(1) } + +var LogWrite = makeLogger(-1)