Wonderful (not) adventures in multi-binary go projects.

This commit is contained in:
Ian A. Mason 2017-07-05 08:14:11 -07:00
parent e2631c2c4a
commit 16cddf6fc9
12 changed files with 110 additions and 79 deletions

View File

@ -1,16 +1,16 @@
GOROOT := $(shell go env GOPATH) GOROOT := $(shell go env GOPATH)
build: build:
go build go build ./shared ./cmd/gclang ./cmd/gclang++ ./cmd/get-bc
install: build install: build
go install go install ./cmd/gclang ./cmd/gclang++ ./cmd/get-bc
ln -f -s $(GOROOT)/bin/gllvm $(GOROOT)/bin/gclang
ln -f -s $(GOROOT)/bin/gllvm $(GOROOT)/bin/gclang++
ln -f -s $(GOROOT)/bin/gllvm $(GOROOT)/bin/get-bc
clean: clean:
go clean go clean
rm -f gclang gclang++ get-bc
uninstall: uninstall:
rm -f $(GOROOT)/bin/gclang rm -f $(GOROOT)/bin/gclang

22
cmd/gclang++/main.go Normal file
View File

@ -0,0 +1,22 @@
package main
import (
"os"
"github.com/SRI-CSL/gllvm/shared"
)
func main() {
// Parse command line
var args = os.Args
args = args[1:]
exitCode := shared.Compile(args, "clang++")
shared.LogInfo("Calling %v returned %v\n", os.Args, exitCode)
//important to pretend to look like the actual wrapped command
os.Exit(exitCode)
}

21
cmd/gclang/main.go Normal file
View File

@ -0,0 +1,21 @@
package main
import (
"os"
"github.com/SRI-CSL/gllvm/shared"
)
func main() {
// Parse command line
var args = os.Args
args = args[1:]
exitCode := shared.Compile(args, "clang")
shared.LogInfo("Calling %v returned %v\n", os.Args, exitCode)
//important to pretend to look like the actual wrapped command
os.Exit(exitCode)
}

19
cmd/get-bc/main.go Normal file
View File

@ -0,0 +1,19 @@
package main
import (
"os"
"github.com/SRI-CSL/gllvm/shared"
)
func main() {
// Parse command line
var args = os.Args
shared.Extract(args)
shared.LogInfo("Calling %v DID NOT TELL US WHAT HAPPENED\n", os.Args)
// could be more honest about our success here
os.Exit(0)
}

View File

@ -1,32 +0,0 @@
package main
import (
"os"
"path"
)
func main() {
// Parse command line
var args = os.Args
_, callerName := path.Split(args[0])
args = args[1:]
var exitCode int
switch callerName {
case "gclang":
exitCode = compile(args, "clang")
case "gclang++":
exitCode = compile(args, "clang++")
case "get-bc":
extract(args)
default:
logError("You should call %s with a valid name.", callerName)
}
logInfo("Calling %v returned %v\n", os.Args, exitCode)
//important to pretend to look like the actual wrapped command
os.Exit(exitCode)
}

View File

@ -1,4 +1,5 @@
package main package shared
import ( import (
"io" "io"
@ -16,7 +17,7 @@ type bitcodeToObjectLink struct {
objPath string objPath string
} }
func compile(args []string, compilerName string) (exitCode int) { func Compile(args []string, compilerName string) (exitCode int) {
exitCode = 0 exitCode = 0
//in the configureOnly case we have to know the exit code of the compile //in the configureOnly case we have to know the exit code of the compile
//because that is how configure figures out what it can and cannot do. //because that is how configure figures out what it can and cannot do.
@ -117,14 +118,14 @@ func attachBitcodePathToObject(bcFile, objFile string) {
tmpContent := []byte(absBcPath + "\n") tmpContent := []byte(absBcPath + "\n")
tmpFile, err := ioutil.TempFile("", "gllvm") tmpFile, err := ioutil.TempFile("", "gllvm")
if err != nil { if err != nil {
logFatal("attachBitcodePathToObject: %v\n", err) LogFatal("attachBitcodePathToObject: %v\n", err)
} }
defer os.Remove(tmpFile.Name()) defer os.Remove(tmpFile.Name())
if _, err := tmpFile.Write(tmpContent); err != nil { if _, err := tmpFile.Write(tmpContent); err != nil {
logFatal("attachBitcodePathToObject: %v\n", err) LogFatal("attachBitcodePathToObject: %v\n", err)
} }
if err := tmpFile.Close(); err != nil { if err := tmpFile.Close(); err != nil {
logFatal("attachBitcodePathToObject: %v\n", err) LogFatal("attachBitcodePathToObject: %v\n", err)
} }
// Let's write the bitcode section // Let's write the bitcode section
@ -164,7 +165,7 @@ func compileTimeLinkFiles(compilerExecName string, pr parserResult, objFiles []s
args = append(args, "-o", outputFile) args = append(args, "-o", outputFile)
success, err := execCmd(compilerExecName, args, "") success, err := execCmd(compilerExecName, args, "")
if !success { if !success {
logFatal("Failed to link: %v.", err) LogFatal("Failed to link: %v.", err)
} }
} }
@ -174,7 +175,7 @@ func buildObjectFile(compilerExecName string, pr parserResult, srcFile string, o
args = append(args, srcFile, "-c", "-o", objFile) args = append(args, srcFile, "-c", "-o", objFile)
success, err := execCmd(compilerExecName, args, "") success, err := execCmd(compilerExecName, args, "")
if !success { if !success {
logFatal("Failed to build object file for %s because: %v\n", srcFile, err) LogFatal("Failed to build object file for %s because: %v\n", srcFile, err)
} }
} }
@ -184,7 +185,7 @@ func buildBitcodeFile(compilerExecName string, pr parserResult, srcFile string,
args = append(args, "-emit-llvm", "-c", srcFile, "-o", bcFile) args = append(args, "-emit-llvm", "-c", srcFile, "-o", bcFile)
success, err := execCmd(compilerExecName, args, "") success, err := execCmd(compilerExecName, args, "")
if !success { if !success {
logFatal("Failed to build bitcode file for %s because: %v\n", srcFile, err) LogFatal("Failed to build bitcode file for %s because: %v\n", srcFile, err)
} }
} }
@ -193,7 +194,7 @@ func execCompile(compilerExecName string, pr parserResult, wg *sync.WaitGroup, o
defer (*wg).Done() defer (*wg).Done()
success, err := execCmd(compilerExecName, pr.InputList, "") success, err := execCmd(compilerExecName, pr.InputList, "")
if !success { if !success {
logError("Failed to compile using given arguments: %v\n", err) LogError("Failed to compile using given arguments: %v\n", err)
*ok = false *ok = false
} }
} }
@ -211,7 +212,7 @@ func getCompilerExecName(compilerName string) string {
} }
return filepath.Join(LLVMToolChainBinDir, compilerName) return filepath.Join(LLVMToolChainBinDir, compilerName)
default: default:
logFatal("The compiler %s is not supported by this tool.", compilerName) LogFatal("The compiler %s is not supported by this tool.", compilerName)
return "" return ""
} }
} }

View File

@ -1,4 +1,4 @@
package main package shared
import ( import (
"os" "os"

View File

@ -1,4 +1,4 @@
package main package shared
import ( import (
"debug/elf" "debug/elf"
@ -25,7 +25,7 @@ type extractionArgs struct {
IsBuildBitcodeArchive bool IsBuildBitcodeArchive bool
} }
func extract(args []string) { func Extract(args []string) {
ea := parseExtractionArgs(args) ea := parseExtractionArgs(args)
switch ea.InputType { switch ea.InputType {
@ -39,7 +39,7 @@ func extract(args []string) {
case fileTypeARCHIVE: case fileTypeARCHIVE:
handleArchive(ea) handleArchive(ea)
default: default:
logFatal("Incorrect input file type %v.", ea.InputType) LogFatal("Incorrect input file type %v.", ea.InputType)
} }
} }
@ -84,7 +84,7 @@ func parseExtractionArgs(args []string) extractionArgs {
args = args[1:] args = args[1:]
case "-o": case "-o":
if len(args) < 2 { if len(args) < 2 {
logFatal("There was an error parsing the arguments: %v.", origArgs) LogFatal("There was an error parsing the arguments: %v.", origArgs)
} }
ea.OutputFile = args[1] ea.OutputFile = args[1]
args = args[2:] args = args[2:]
@ -96,14 +96,14 @@ func parseExtractionArgs(args []string) extractionArgs {
// Sanity-check the parsed arguments // Sanity-check the parsed arguments
if len(ea.InputFile) == 0 { if len(ea.InputFile) == 0 {
logFatal("No input file was given.") LogFatal("No input file was given.")
} }
if _, err := os.Stat(ea.InputFile); os.IsNotExist(err) { if _, err := os.Stat(ea.InputFile); os.IsNotExist(err) {
logFatal("The input file %s does not exist.", ea.InputFile) LogFatal("The input file %s does not exist.", ea.InputFile)
} }
realPath, err := filepath.EvalSymlinks(ea.InputFile) realPath, err := filepath.EvalSymlinks(ea.InputFile)
if err != nil { if err != nil {
logFatal("There was an error getting the real path of %s.", ea.InputFile) LogFatal("There was an error getting the real path of %s.", ea.InputFile)
} }
ea.InputFile = realPath ea.InputFile = realPath
ea.InputType = getFileType(realPath) ea.InputType = getFileType(realPath)
@ -126,7 +126,7 @@ func parseExtractionArgs(args []string) extractionArgs {
} }
ea.ObjectTypeInArchive = fileTypeMACHOBJECT ea.ObjectTypeInArchive = fileTypeMACHOBJECT
default: default:
logFatal("Unsupported platform: %s.", platform) LogFatal("Unsupported platform: %s.", platform)
} }
// Create output filename if not given // Create output filename if not given
@ -169,7 +169,7 @@ func handleArchive(ea extractionArgs) {
// Create tmp dir // Create tmp dir
tmpDirName, err := ioutil.TempDir("", "gllvm") tmpDirName, err := ioutil.TempDir("", "gllvm")
if err != nil { if err != nil {
logFatal("The temporary directory in which to extract object files could not be created.") LogFatal("The temporary directory in which to extract object files could not be created.")
} }
defer os.RemoveAll(tmpDirName) defer os.RemoveAll(tmpDirName)
@ -179,7 +179,7 @@ func handleArchive(ea extractionArgs) {
arArgs = append(arArgs, inputAbsPath) arArgs = append(arArgs, inputAbsPath)
success, err := execCmd("ar", arArgs, tmpDirName) success, err := execCmd("ar", arArgs, tmpDirName)
if !success { if !success {
logFatal("Failed to extract object files from %s to %s because: %v.\n", ea.InputFile, tmpDirName, err) LogFatal("Failed to extract object files from %s to %s because: %v.\n", ea.InputFile, tmpDirName, err)
} }
// Define object file handling closure // Define object file handling closure
@ -232,10 +232,10 @@ func archiveBcFiles(ea extractionArgs, bcFiles []string) {
args = append(args, bcFilesInDir...) args = append(args, bcFilesInDir...)
success, err := execCmd(ea.ArchiverName, args, dir) success, err := execCmd(ea.ArchiverName, args, dir)
if !success { if !success {
logFatal("There was an error creating the bitcode archive: %v.\n", err) LogFatal("There was an error creating the bitcode archive: %v.\n", err)
} }
} }
logInfo("Built bitcode archive: %s.", ea.OutputFile) LogInfo("Built bitcode archive: %s.", ea.OutputFile)
} }
func extractTimeLinkFiles(ea extractionArgs, filesToLink []string) { func extractTimeLinkFiles(ea extractionArgs, filesToLink []string) {
@ -247,20 +247,20 @@ func extractTimeLinkFiles(ea extractionArgs, filesToLink []string) {
linkArgs = append(linkArgs, filesToLink...) linkArgs = append(linkArgs, filesToLink...)
success, err := execCmd(ea.LinkerName, linkArgs, "") success, err := execCmd(ea.LinkerName, linkArgs, "")
if !success { if !success {
logFatal("There was an error linking input files into %s because %v.\n", ea.OutputFile, err) LogFatal("There was an error linking input files into %s because %v.\n", ea.OutputFile, err)
} }
logInfo("Bitcode file extracted to: %s.", ea.OutputFile) LogInfo("Bitcode file extracted to: %s.", ea.OutputFile)
} }
func extractSectionDarwin(inputFile string) (contents []string) { func extractSectionDarwin(inputFile string) (contents []string) {
machoFile, err := macho.Open(inputFile) machoFile, err := macho.Open(inputFile)
if err != nil { if err != nil {
logFatal("Mach-O file %s could not be read.", inputFile) LogFatal("Mach-O file %s could not be read.", inputFile)
} }
section := machoFile.Section(DarwinSectionName) section := machoFile.Section(DarwinSectionName)
sectionContents, errContents := section.Data() sectionContents, errContents := section.Data()
if errContents != nil { if errContents != nil {
logFatal("Error reading the %s section of Mach-O file %s.", DarwinSectionName, inputFile) LogFatal("Error reading the %s section of Mach-O file %s.", DarwinSectionName, inputFile)
} }
contents = strings.Split(strings.TrimSuffix(string(sectionContents), "\n"), "\n") contents = strings.Split(strings.TrimSuffix(string(sectionContents), "\n"), "\n")
return return
@ -269,12 +269,12 @@ func extractSectionDarwin(inputFile string) (contents []string) {
func extractSectionUnix(inputFile string) (contents []string) { func extractSectionUnix(inputFile string) (contents []string) {
elfFile, err := elf.Open(inputFile) elfFile, err := elf.Open(inputFile)
if err != nil { if err != nil {
logFatal("ELF file %s could not be read.", inputFile) LogFatal("ELF file %s could not be read.", inputFile)
} }
section := elfFile.Section(ELFSectionName) section := elfFile.Section(ELFSectionName)
sectionContents, errContents := section.Data() sectionContents, errContents := section.Data()
if errContents != nil { if errContents != nil {
logFatal("Error reading the %s section of ELF file %s.", ELFSectionName, inputFile) LogFatal("Error reading the %s section of ELF file %s.", ELFSectionName, inputFile)
} }
contents = strings.Split(strings.TrimSuffix(string(sectionContents), "\n"), "\n") contents = strings.Split(strings.TrimSuffix(string(sectionContents), "\n"), "\n")
return return
@ -304,7 +304,7 @@ func writeManifest(ea extractionArgs, bcFiles []string, artifactFiles []string)
contents := []byte(section1 + section2) contents := []byte(section1 + section2)
manifestFilename := ea.OutputFile + ".llvm.manifest" manifestFilename := ea.OutputFile + ".llvm.manifest"
if err := ioutil.WriteFile(manifestFilename, contents, 0644); err != nil { if err := ioutil.WriteFile(manifestFilename, contents, 0644); err != nil {
logFatal("There was an error while writing the manifest file: ", err) LogFatal("There was an error while writing the manifest file: ", err)
} }
logInfo("Manifest file written to %s.", manifestFilename) LogInfo("Manifest file written to %s.", manifestFilename)
} }

View File

@ -1,4 +1,4 @@
package main package shared
import ( import (
"os" "os"
@ -35,7 +35,7 @@ func getFileType(realPath string) (fileType int) {
cmd := exec.Command("file", realPath) cmd := exec.Command("file", realPath)
out, err := cmd.Output() out, err := cmd.Output()
if err != nil { if err != nil {
logFatal("There was an error getting the type of %s. Make sure that the 'file' command is installed.", realPath) LogFatal("There was an error getting the type of %s. Make sure that the 'file' command is installed.", realPath)
} }
// Test the output // Test the output

View File

@ -1,4 +1,4 @@
package main package shared
import ( import (
"fmt" "fmt"
@ -49,12 +49,12 @@ func makeLogger(lvl int) func(format string, a ...interface{}) {
} }
} }
var logDebug = makeLogger(debugV) var LogDebug = makeLogger(debugV)
var logInfo = makeLogger(infoV) var LogInfo = makeLogger(infoV)
var logWarning = makeLogger(warningV) var LogWarning = makeLogger(warningV)
var logError = makeLogger(errorV) var LogError = makeLogger(errorV)
func logFatal(format string, a ...interface{}) { func LogFatal(format string, a ...interface{}) {
logError(format, a...) LogError(format, a...)
os.Exit(1) os.Exit(1)
} }

View File

@ -1,4 +1,4 @@
package main package shared
import ( import (
"crypto/sha256" "crypto/sha256"

View File

@ -1,4 +1,4 @@
package main package shared
import ( import (
"os" "os"