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

Commit cff613f

Browse filesBrowse files
committed
Fixed dependency file parsing on Windows
1 parent c1b290a commit cff613f
Copy full SHA for cff613f

File tree

Expand file treeCollapse file tree

4 files changed

+120
-43
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+120
-43
lines changed

‎go.mod

Copy file name to clipboardExpand all lines: go.mod
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ require (
3939
go.bug.st/f v0.4.0
4040
go.bug.st/relaxed-semver v0.12.0
4141
go.bug.st/testifyjson v1.2.0
42+
golang.org/x/sys v0.26.0
4243
golang.org/x/term v0.25.0
4344
golang.org/x/text v0.19.0
4445
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142
@@ -100,7 +101,6 @@ require (
100101
golang.org/x/mod v0.18.0 // indirect
101102
golang.org/x/net v0.28.0 // indirect
102103
golang.org/x/sync v0.8.0 // indirect
103-
golang.org/x/sys v0.26.0 // indirect
104104
golang.org/x/tools v0.22.0 // indirect
105105
gopkg.in/ini.v1 v1.67.0 // indirect
106106
gopkg.in/warnings.v0 v0.1.2 // indirect
+27Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// This file is part of arduino-cli.
2+
//
3+
// Copyright 2024 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This software is released under the GNU General Public License version 3,
6+
// which covers the main part of arduino-cli.
7+
// The terms of this license can be found at:
8+
// https://www.gnu.org/licenses/gpl-3.0.en.html
9+
//
10+
// You can be released from the requirements of the above licenses by purchasing
11+
// a commercial license. Buying such a license is mandatory if you want to
12+
// modify or otherwise use the software for commercial activities involving the
13+
// Arduino software without disclosing the source code of your own applications.
14+
// To purchase a commercial license, send an email to license@arduino.cc.
15+
16+
//go:build !windows
17+
18+
package utils
19+
20+
import (
21+
"errors"
22+
)
23+
24+
// placeholder for non-Windows machines
25+
func convertAnsiBytesToString([]byte) (string, error) {
26+
return "", errors.New("unimplemented")
27+
}
+33Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// This file is part of arduino-cli.
2+
//
3+
// Copyright 2024 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This software is released under the GNU General Public License version 3,
6+
// which covers the main part of arduino-cli.
7+
// The terms of this license can be found at:
8+
// https://www.gnu.org/licenses/gpl-3.0.en.html
9+
//
10+
// You can be released from the requirements of the above licenses by purchasing
11+
// a commercial license. Buying such a license is mandatory if you want to
12+
// modify or otherwise use the software for commercial activities involving the
13+
// Arduino software without disclosing the source code of your own applications.
14+
// To purchase a commercial license, send an email to license@arduino.cc.
15+
16+
package utils
17+
18+
import (
19+
"golang.org/x/sys/windows"
20+
)
21+
22+
func convertAnsiBytesToString(data []byte) (string, error) {
23+
dataSize := int32(len(data))
24+
size, err := windows.MultiByteToWideChar(windows.GetACP(), 0, &data[0], dataSize, nil, 0)
25+
if err != nil {
26+
return "", err
27+
}
28+
utf16 := make([]uint16, size)
29+
if _, err := windows.MultiByteToWideChar(windows.GetACP(), 0, &data[0], dataSize, &utf16[0], size); err != nil {
30+
return "", err
31+
}
32+
return windows.UTF16ToString(utf16), nil
33+
}

‎internal/arduino/builder/internal/utils/utils.go

Copy file name to clipboardExpand all lines: internal/arduino/builder/internal/utils/utils.go
+59-42Lines changed: 59 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package utils
1717

1818
import (
1919
"os"
20+
"runtime"
2021
"strings"
2122
"unicode"
2223

@@ -74,63 +75,79 @@ func ObjFileIsUpToDate(sourceFile, objectFile, dependencyFile *paths.Path) (bool
7475
return false, nil
7576
}
7677

77-
rows, err := dependencyFile.ReadFileAsLines()
78+
depFileData, err := dependencyFile.ReadFile()
7879
if err != nil {
7980
logrus.Debugf("Could not read dependency file: %s", dependencyFile)
8081
return false, err
8182
}
8283

83-
rows = f.Map(rows, removeEndingBackSlash)
84-
rows = f.Map(rows, strings.TrimSpace)
85-
rows = f.Map(rows, unescapeDep)
86-
rows = f.Filter(rows, f.NotEquals(""))
84+
checkDepFile := func(depFile string) (bool, error) {
85+
rows := strings.Split(strings.Replace(depFile, "\r\n", "\n", -1), "\n")
86+
rows = f.Map(rows, removeEndingBackSlash)
87+
rows = f.Map(rows, strings.TrimSpace)
88+
rows = f.Map(rows, unescapeDep)
89+
rows = f.Filter(rows, f.NotEquals(""))
8790

88-
if len(rows) == 0 {
89-
return true, nil
90-
}
91-
92-
firstRow := rows[0]
93-
if !strings.HasSuffix(firstRow, ":") {
94-
logrus.Debugf("No colon in first line of depfile")
95-
return false, nil
96-
}
97-
objFileInDepFile := firstRow[:len(firstRow)-1]
98-
if objFileInDepFile != objectFile.String() {
99-
logrus.Debugf("Depfile is about different object file: %v", objFileInDepFile)
100-
return false, nil
101-
}
102-
103-
// The first line of the depfile contains the path to the object file to generate.
104-
// The second line of the depfile contains the path to the source file.
105-
// All subsequent lines contain the header files necessary to compile the object file.
106-
107-
// If we don't do this check it might happen that trying to compile a source file
108-
// that has the same name but a different path wouldn't recreate the object file.
109-
if sourceFile.String() != strings.Trim(rows[1], " ") {
110-
logrus.Debugf("Depfile is about different source file: %v", strings.Trim(rows[1], " "))
111-
return false, nil
112-
}
91+
if len(rows) == 0 {
92+
return true, nil
93+
}
11394

114-
rows = rows[1:]
115-
for _, row := range rows {
116-
depStat, err := os.Stat(row)
117-
if err != nil && !os.IsNotExist(err) {
118-
// There is probably a parsing error of the dep file
119-
// Ignore the error and trigger a full rebuild anyway
120-
logrus.WithError(err).Debugf("Failed to read: %v", row)
95+
firstRow := rows[0]
96+
if !strings.HasSuffix(firstRow, ":") {
97+
logrus.Debugf("No colon in first line of depfile")
12198
return false, nil
12299
}
123-
if os.IsNotExist(err) {
124-
logrus.Debugf("Not found: %v", row)
100+
objFileInDepFile := firstRow[:len(firstRow)-1]
101+
if objFileInDepFile != objectFile.String() {
102+
logrus.Debugf("Depfile is about different object file: %v", objFileInDepFile)
125103
return false, nil
126104
}
127-
if depStat.ModTime().After(objectFileStat.ModTime()) {
128-
logrus.Debugf("%v newer than %v", row, objectFile)
105+
106+
// The first line of the depfile contains the path to the object file to generate.
107+
// The second line of the depfile contains the path to the source file.
108+
// All subsequent lines contain the header files necessary to compile the object file.
109+
110+
// If we don't do this check it might happen that trying to compile a source file
111+
// that has the same name but a different path wouldn't recreate the object file.
112+
if sourceFile.String() != strings.Trim(rows[1], " ") {
113+
logrus.Debugf("Depfile is about different source file: %v", strings.Trim(rows[1], " "))
129114
return false, nil
130115
}
116+
117+
rows = rows[1:]
118+
for _, row := range rows {
119+
depStat, err := os.Stat(row)
120+
if err != nil && !os.IsNotExist(err) {
121+
// There is probably a parsing error of the dep file
122+
// Ignore the error and trigger a full rebuild anyway
123+
logrus.WithError(err).Debugf("Failed to read: %v", row)
124+
return false, nil
125+
}
126+
if os.IsNotExist(err) {
127+
logrus.Debugf("Not found: %v", row)
128+
return false, nil
129+
}
130+
if depStat.ModTime().After(objectFileStat.ModTime()) {
131+
logrus.Debugf("%v newer than %v", row, objectFile)
132+
return false, nil
133+
}
134+
}
135+
136+
return true, nil
131137
}
132138

133-
return true, nil
139+
if runtime.GOOS == "windows" {
140+
// This is required because on Windows we don't know which encoding is used
141+
// by gcc to write the dep file (it could be UTF-8 or any of the Windows
142+
// ANSI mappings).
143+
if decoded, err := convertAnsiBytesToString(depFileData); err == nil {
144+
if upToDate, err := checkDepFile(decoded); err == nil && upToDate {
145+
return upToDate, nil
146+
}
147+
}
148+
// Fallback to UTF-8...
149+
}
150+
return checkDepFile(string(depFileData))
134151
}
135152

136153
func removeEndingBackSlash(s string) string {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.