@@ -17,6 +17,7 @@ package utils
1717
1818import (
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 (string (decoded )); err == nil && upToDate {
145+ return upToDate , nil
146+ }
147+ }
148+ // Fallback to UTF-8...
149+ }
150+ return checkDepFile (string (depFileData ))
134151}
135152
136153func removeEndingBackSlash (s string ) string {
0 commit comments