Skip to content

Commit

Permalink
Fixed charset handling in reader for dep files
Browse files Browse the repository at this point in the history
  • Loading branch information
cmaglie committed Oct 15, 2024
1 parent fd490f7 commit 036aedb
Showing 1 changed file with 57 additions and 42 deletions.
99 changes: 57 additions & 42 deletions internal/arduino/builder/internal/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package utils

import (
"os"
"runtime"
"strings"
"unicode"

Expand Down Expand Up @@ -96,57 +97,71 @@ func ObjFileIsUpToDate(sourceFile, objectFile, dependencyFile *paths.Path) (bool
return f.Filter(rows, f.NotEquals("")), nil
}

rows, err := readDepFileWithEncoding(nil)
if err != nil {
logrus.Debugf("Could not read dependency file: %s", dependencyFile)
return false, err
}
if len(rows) == 0 {
return true, nil
}

firstRow := rows[0]
if !strings.HasSuffix(firstRow, ":") {
logrus.Debugf("No colon in first line of depfile")
return false, nil
}
objFileInDepFile := firstRow[:len(firstRow)-1]
if objFileInDepFile != objectFile.String() {
logrus.Debugf("Depfile is about different object file: %v", objFileInDepFile)
return false, nil
}

// The first line of the depfile contains the path to the object file to generate.
// The second line of the depfile contains the path to the source file.
// All subsequent lines contain the header files necessary to compile the object file.

// If we don't do this check it might happen that trying to compile a source file
// that has the same name but a different path wouldn't recreate the object file.
if sourceFile.String() != strings.Trim(rows[1], " ") {
logrus.Debugf("Depfile is about different source file: %v", strings.Trim(rows[1], " "))
return false, nil
}
checkDepFileWithEncoding := func(mapping *charmap.Charmap) (bool, error) {
rows, err := readDepFileWithEncoding(mapping)
if err != nil {
logrus.Debugf("Could not read dependency file: %s", dependencyFile)
return false, err
}
if len(rows) == 0 {
return true, nil
}

rows = rows[1:]
for _, row := range rows {
depStat, err := os.Stat(row)
if err != nil && !os.IsNotExist(err) {
// There is probably a parsing error of the dep file
// Ignore the error and trigger a full rebuild anyway
logrus.WithError(err).Debugf("Failed to read: %v", row)
firstRow := rows[0]
if !strings.HasSuffix(firstRow, ":") {
logrus.Debugf("No colon in first line of depfile")
return false, nil
}
if os.IsNotExist(err) {
logrus.Debugf("Not found: %v", row)
objFileInDepFile := firstRow[:len(firstRow)-1]
if objFileInDepFile != objectFile.String() {
logrus.Debugf("Depfile is about different object file: %v", objFileInDepFile)
return false, nil
}
if depStat.ModTime().After(objectFileStat.ModTime()) {
logrus.Debugf("%v newer than %v", row, objectFile)

// The first line of the depfile contains the path to the object file to generate.
// The second line of the depfile contains the path to the source file.
// All subsequent lines contain the header files necessary to compile the object file.

// If we don't do this check it might happen that trying to compile a source file
// that has the same name but a different path wouldn't recreate the object file.
if sourceFile.String() != strings.Trim(rows[1], " ") {
logrus.Debugf("Depfile is about different source file: %v", strings.Trim(rows[1], " "))
return false, nil
}

rows = rows[1:]
for _, row := range rows {
depStat, err := os.Stat(row)
if err != nil && !os.IsNotExist(err) {
// There is probably a parsing error of the dep file
// Ignore the error and trigger a full rebuild anyway
logrus.WithError(err).Debugf("Failed to read: %v", row)
return false, nil
}
if os.IsNotExist(err) {
logrus.Debugf("Not found: %v", row)
return false, nil
}
if depStat.ModTime().After(objectFileStat.ModTime()) {
logrus.Debugf("%v newer than %v", row, objectFile)
return false, nil
}
}

return true, nil
}

return true, nil
// This is required because on Windows we don't know which encoding is used
// by gcc to write the dep file (it could be UTF-8 or any of the Windows
// default mappings. Would ISO8859_1 be enough? Or we should differentiate the
// various ISO8859_XX based on selected locale? Only time will tell...).
if runtime.GOOS == "windows" {
if upToDate, err := checkDepFileWithEncoding(charmap.ISO8859_1); err == nil {
return upToDate, nil
}
// Fallback to UTF-8...
}
return checkDepFileWithEncoding(nil)
}

func removeEndingBackSlash(s string) string {
Expand Down

0 comments on commit 036aedb

Please sign in to comment.