mirror of
https://github.com/danog/gllvm.git
synced 2024-11-30 07:09:01 +01:00
Wonderful (not) adventures in multi-binary go projects.
This commit is contained in:
parent
e2631c2c4a
commit
16cddf6fc9
10
Makefile
10
Makefile
@ -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
22
cmd/gclang++/main.go
Normal 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
21
cmd/gclang/main.go
Normal 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
19
cmd/get-bc/main.go
Normal 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)
|
||||||
|
|
||||||
|
}
|
32
gllvm.go
32
gllvm.go
@ -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)
|
|
||||||
|
|
||||||
}
|
|
@ -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 ""
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package main
|
package shared
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
@ -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)
|
||||||
}
|
}
|
@ -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
|
@ -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)
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package main
|
package shared
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
@ -1,4 +1,4 @@
|
|||||||
package main
|
package shared
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
Loading…
Reference in New Issue
Block a user