Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Fixed compiler-cache on Windows when there are non-ASCII characters in file path #2733

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fixed dependency file parsing on Windows
  • Loading branch information
cmaglie committed Oct 16, 2024
commit cff613fcfec47c628acf3cbd6214546e0ff3a8a5
2 changes: 1 addition & 1 deletion 2 go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ require (
go.bug.st/f v0.4.0
go.bug.st/relaxed-semver v0.12.0
go.bug.st/testifyjson v1.2.0
golang.org/x/sys v0.26.0
golang.org/x/term v0.25.0
golang.org/x/text v0.19.0
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142
Expand Down Expand Up @@ -100,7 +101,6 @@ require (
golang.org/x/mod v0.18.0 // indirect
golang.org/x/net v0.28.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/tools v0.22.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
Expand Down
27 changes: 27 additions & 0 deletions 27 internal/arduino/builder/internal/utils/ansi_others.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// This file is part of arduino-cli.
//
// Copyright 2024 ARDUINO SA (http://www.arduino.cc/)
//
// This software is released under the GNU General Public License version 3,
// which covers the main part of arduino-cli.
// The terms of this license can be found at:
// https://www.gnu.org/licenses/gpl-3.0.en.html
//
// You can be released from the requirements of the above licenses by purchasing
// a commercial license. Buying such a license is mandatory if you want to
// modify or otherwise use the software for commercial activities involving the
// Arduino software without disclosing the source code of your own applications.
// To purchase a commercial license, send an email to license@arduino.cc.

//go:build !windows

package utils

import (
"errors"
)

// placeholder for non-Windows machines
func convertAnsiBytesToString([]byte) (string, error) {
return "", errors.New("unimplemented")
}
33 changes: 33 additions & 0 deletions 33 internal/arduino/builder/internal/utils/ansi_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// This file is part of arduino-cli.
//
// Copyright 2024 ARDUINO SA (http://www.arduino.cc/)
//
// This software is released under the GNU General Public License version 3,
// which covers the main part of arduino-cli.
// The terms of this license can be found at:
// https://www.gnu.org/licenses/gpl-3.0.en.html
//
// You can be released from the requirements of the above licenses by purchasing
// a commercial license. Buying such a license is mandatory if you want to
// modify or otherwise use the software for commercial activities involving the
// Arduino software without disclosing the source code of your own applications.
// To purchase a commercial license, send an email to license@arduino.cc.

package utils

import (
"golang.org/x/sys/windows"
)

func convertAnsiBytesToString(data []byte) (string, error) {
dataSize := int32(len(data))
size, err := windows.MultiByteToWideChar(windows.GetACP(), 0, &data[0], dataSize, nil, 0)
if err != nil {
return "", err
}
utf16 := make([]uint16, size)
if _, err := windows.MultiByteToWideChar(windows.GetACP(), 0, &data[0], dataSize, &utf16[0], size); err != nil {
return "", err
}
return windows.UTF16ToString(utf16), nil
}
101 changes: 59 additions & 42 deletions 101 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 @@ -74,63 +75,79 @@ func ObjFileIsUpToDate(sourceFile, objectFile, dependencyFile *paths.Path) (bool
return false, nil
}

rows, err := dependencyFile.ReadFileAsLines()
depFileData, err := dependencyFile.ReadFile()
if err != nil {
logrus.Debugf("Could not read dependency file: %s", dependencyFile)
return false, err
}

rows = f.Map(rows, removeEndingBackSlash)
rows = f.Map(rows, strings.TrimSpace)
rows = f.Map(rows, unescapeDep)
rows = f.Filter(rows, f.NotEquals(""))
checkDepFile := func(depFile string) (bool, error) {
rows := strings.Split(strings.Replace(depFile, "\r\n", "\n", -1), "\n")
rows = f.Map(rows, removeEndingBackSlash)
rows = f.Map(rows, strings.TrimSpace)
rows = f.Map(rows, unescapeDep)
rows = f.Filter(rows, f.NotEquals(""))

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
}
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
if runtime.GOOS == "windows" {
// 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
// ANSI mappings).
if decoded, err := convertAnsiBytesToString(depFileData); err == nil {
if upToDate, err := checkDepFile(decoded); err == nil && upToDate {
return upToDate, nil
}
}
// Fallback to UTF-8...
}
return checkDepFile(string(depFileData))
}

func removeEndingBackSlash(s string) string {
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.