Skip to content

Commit

Permalink
add support for includes relative to file
Browse files Browse the repository at this point in the history
previously includes had to be relative to the current path when the compilation runs, this made it really annoying to, for example, build the same project from two different places. by using relative paths from files, you can avoid this
  • Loading branch information
JLaferri committed Dec 24, 2018
1 parent 3812c72 commit cb3414e
Showing 1 changed file with 75 additions and 12 deletions.
87 changes: 75 additions & 12 deletions gecko.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
)

type Config struct {
Settings GeckoSettings
OutputFiles []string
Codes []CodeDescription
}
Expand All @@ -42,6 +43,10 @@ type GeckoCode struct {
Value string
}

type GeckoSettings struct {
AreIncludesRelativeFromFile bool
}

type compileResult struct {
Order int
Lines []string
Expand All @@ -59,6 +64,7 @@ const (
)

var output []string
var globalSettings GeckoSettings

func timeTrack(start time.Time) {
elapsed := time.Since(start)
Expand Down Expand Up @@ -97,6 +103,7 @@ func main() {
log.Panic("Must have at least one output file configured in the outputFiles field\n")
}

globalSettings = config.Settings
buildBody(config)
outputFilePaths = config.OutputFiles
case "assemble":
Expand All @@ -116,8 +123,17 @@ func main() {
true,
"If true, will recursively find all .asm files within the sub-directories as well as the root directory.",
)
irffPtr := assembleFlags.Bool(
"irff",
false,
"Stands for \"includes relative from file\". The default behavior is that includes are relative "+
"from the current directory. This can be problematic if you need to, for example, build your "+
"project from more than one location. Setting this to true adds a pre-processing step where "+
"include statements are translated to make them be relative from the file's location.",
)
assembleFlags.Parse(os.Args[2:])

globalSettings = GeckoSettings{AreIncludesRelativeFromFile: *irffPtr}
outputFilePaths = append(outputFilePaths, *outputFilePtr)
output = generateInjectionFolderLines(*assemblePathPtr, *isRecursivePtr)
case "-h":
Expand Down Expand Up @@ -365,10 +381,16 @@ func generateInjectionFolderLines(rootFolder string, isRecursive bool) []string
results := []compileResult{}
for i := 0; i < processedFileCount; i++ {
var result = <-resultsChan
results = append(results, result)
}

// If any results returned an error, panic after all goroutines complete,
// this is primarily done so that all of the defer calls actually execute
// and the asmtemp files get properly cleaned up.
for _, result := range results {
if result.IsError {
log.Panicf("Failed to compile at least one file\n")
}
results = append(results, result)
}

// Sort the results based on their order
Expand Down Expand Up @@ -484,17 +506,7 @@ func compile(file string) []byte {
// Technically this shouldn't be necessary but for some reason if the last line
// or the asm file has one of more spaces at the end and no new line, the last
// instruction is ignored and not compiled
asmContents, err := ioutil.ReadFile(file)
if err != nil {
log.Panicf("Failed to read asm file: %s\n%s\n", file, err.Error())
}

// Explicitly add a new line at the end of the file, which should prevent line skip
asmContents = append(asmContents, []byte("\r\n")...)
err = ioutil.WriteFile(compileFilePath, asmContents, 0644)
if err != nil {
log.Panicf("Failed to write temporary asm file\n%s\n", err.Error())
}
buildTempAsmFile(file, compileFilePath)

if runtime.GOOS == "windows" {
cmd := exec.Command("powerpc-gekko-as.exe", "-a32", "-mbig", "-mregnames", "-mgekko", "-o", outputFilePath, compileFilePath)
Expand Down Expand Up @@ -541,6 +553,57 @@ func compile(file string) []byte {
return nil
}

func buildTempAsmFile(sourceFilePath, targetFilePath string) {
asmContents, err := ioutil.ReadFile(sourceFilePath)
if err != nil {
log.Panicf("Failed to read asm file: %s\n%s\n", sourceFilePath, err.Error())
}

includeString := ".include "
targetFileDirectory := filepath.Dir(targetFilePath)

// If global settings say includes should be relative from the file, we need
// to post-process all the .include statements and convert their paths
if globalSettings.AreIncludesRelativeFromFile {
lines := bytes.Split(asmContents, []byte{'\n'})
for idx, line := range lines {
trimmedLine := strings.TrimSpace(string(line))
isLineTooShort := len(trimmedLine) < len(includeString)
if isLineTooShort {
continue
}

isIncludeStatement := trimmedLine[:len(includeString)] == includeString
if !isIncludeStatement {
continue
}

// Here we have an include statement, so let's get the include path
includePath := strings.Trim(trimmedLine[len(includeString)+1:], " \t\"")
if filepath.IsAbs(includePath) {
// Don't change anything for an absolute path
continue
}

// Combine relative include path with the path of the file
includePath = filepath.Join(targetFileDirectory, includePath)
includePath = filepath.ToSlash(includePath) // No backslashes

// Store back newly generated absolute path
lines[idx] = []byte(includeString + "\"" + includePath + "\"")
}

asmContents = bytes.Join(lines, []byte{'\n'})
}

// Explicitly add a new line at the end of the file, which should prevent line skip
asmContents = append(asmContents, []byte("\r\n")...)
err = ioutil.WriteFile(targetFilePath, asmContents, 0644)
if err != nil {
log.Panicf("Failed to write temporary asm file\n%s\n", err.Error())
}
}

func writeOutput(outputFile string) {
fmt.Printf("Writing to %s...\n", outputFile)
ext := filepath.Ext(outputFile)
Expand Down

0 comments on commit cb3414e

Please sign in to comment.