@@ -111,45 +111,63 @@ import (
111
111
type ContainerFindIncludes struct {}
112
112
113
113
func (s * ContainerFindIncludes ) Run (ctx * types.Context ) error {
114
- cache := loadCacheFrom (ctx .BuildPath .Join ("includes.cache" ))
114
+ finder := & CppIncludesFinder {
115
+ ctx : ctx ,
116
+ }
117
+ if err := finder .DetectLibraries (); err != nil {
118
+ return err
119
+ }
120
+ if err := runCommand (ctx , & FailIfImportedLibraryIsWrong {}); err != nil {
121
+ return errors .WithStack (err )
122
+ }
115
123
116
- appendIncludeFolder (ctx , cache , nil , "" , ctx .BuildProperties .GetPath ("build.core.path" ))
117
- if ctx .BuildProperties .Get ("build.variant.path" ) != "" {
118
- appendIncludeFolder (ctx , cache , nil , "" , ctx .BuildProperties .GetPath ("build.variant.path" ))
124
+ return nil
125
+ }
126
+
127
+ // CppIncludesFinder implements an algorithm to automatically detect
128
+ // libraries used in a sketch and a way to cache this result for
129
+ // increasing detection speed on already processed sketches.
130
+ type CppIncludesFinder struct {
131
+ ctx * types.Context
132
+ cache * includeCache
133
+ sketch * types.Sketch
134
+ queue * UniqueSourceFileQueue
135
+ }
136
+
137
+ func (f * CppIncludesFinder ) DetectLibraries () error {
138
+ f .cache = loadCacheFrom (f .ctx .BuildPath .Join ("includes.cache" ))
139
+ f .sketch = f .ctx .Sketch
140
+ f .queue = & UniqueSourceFileQueue {}
141
+
142
+ f .appendIncludeFolder (nil , "" , f .ctx .BuildProperties .GetPath ("build.core.path" ))
143
+ if f .ctx .BuildProperties .Get ("build.variant.path" ) != "" {
144
+ f .appendIncludeFolder (nil , "" , f .ctx .BuildProperties .GetPath ("build.variant.path" ))
119
145
}
120
146
121
- sketch := ctx .Sketch
122
- mergedfile , err := MakeSourceFilee (ctx , sketch , paths .New (sketch .MainFile .Name .Base ()+ ".cpp" ))
147
+ mergedfile , err := MakeSourceFile (f .ctx , f .sketch , paths .New (f .sketch .MainFile .Name .Base ()+ ".cpp" ))
123
148
if err != nil {
124
149
return errors .WithStack (err )
125
150
}
126
- queue := & UniqueSourceFileQueue {}
127
- queue .Push (mergedfile )
151
+ f .queue .Push (mergedfile )
128
152
129
- queueSourceFilesFromFolder (ctx , queue , sketch , ctx .SketchBuildPath , false /* recurse */ )
130
- srcSubfolderPath := ctx .SketchBuildPath .Join ("src" )
153
+ f . queueSourceFilesFromFolder (f . sketch , f . ctx .SketchBuildPath , false /* recurse */ )
154
+ srcSubfolderPath := f . ctx .SketchBuildPath .Join ("src" )
131
155
if srcSubfolderPath .IsDir () {
132
- queueSourceFilesFromFolder (ctx , queue , sketch , srcSubfolderPath , true /* recurse */ )
156
+ f . queueSourceFilesFromFolder (f . sketch , srcSubfolderPath , true /* recurse */ )
133
157
}
134
158
135
- for ! queue .Empty () {
136
- if err := findIncludesUntilDone (ctx , cache , queue , queue .Pop ()); err != nil {
137
- cache .Remove ()
159
+ for ! f . queue .Empty () {
160
+ if err := f . findIncludesUntilDone (f . queue .Pop ()); err != nil {
161
+ f . cache .Remove ()
138
162
return errors .WithStack (err )
139
163
}
140
164
}
141
165
142
166
// Finalize the cache
143
- cache .ExpectEnd ()
144
- if err := cache .WriteToFile (); err != nil {
167
+ f . cache .ExpectEnd ()
168
+ if err := f . cache .WriteToFile (); err != nil {
145
169
return errors .WithStack (err )
146
170
}
147
-
148
- err = runCommand (ctx , & FailIfImportedLibraryIsWrong {})
149
- if err != nil {
150
- return errors .WithStack (err )
151
- }
152
-
153
171
return nil
154
172
}
155
173
@@ -158,9 +176,9 @@ func (s *ContainerFindIncludes) Run(ctx *types.Context) error {
158
176
// include (e.g. what #include line in what file it was resolved from)
159
177
// and should be the empty string for the default include folders, like
160
178
// the core or variant.
161
- func appendIncludeFolder ( ctx * types. Context , cache * includeCache , sourceFilePath * paths.Path , include string , folder * paths.Path ) {
162
- ctx .IncludeFolders = append (ctx .IncludeFolders , folder )
163
- cache .ExpectEntry (sourceFilePath , include , folder )
179
+ func ( f * CppIncludesFinder ) appendIncludeFolder ( sourceFilePath * paths.Path , include string , folder * paths.Path ) {
180
+ f . ctx .IncludeFolders = append (f . ctx .IncludeFolders , folder )
181
+ f . cache .ExpectEntry (sourceFilePath , include , folder )
164
182
}
165
183
166
184
func runCommand (ctx * types.Context , command types.Command ) error {
@@ -285,11 +303,11 @@ func (cache *includeCache) WriteToFile() error {
285
303
return nil
286
304
}
287
305
288
- func findIncludesUntilDone ( ctx * types. Context , cache * includeCache , queue * UniqueSourceFileQueue , sourceFile SourceFile ) error {
289
- sourcePath := sourceFile .SourcePath (ctx )
306
+ func ( f * CppIncludesFinder ) findIncludesUntilDone ( sourceFile SourceFile ) error {
307
+ sourcePath := sourceFile .SourcePath (f . ctx )
290
308
targetFilePath := paths .NullPath ()
291
- depPath := sourceFile .DepfilePath (ctx )
292
- objPath := sourceFile .ObjectPath (ctx )
309
+ depPath := sourceFile .DepfilePath (f . ctx )
310
+ objPath := sourceFile .ObjectPath (f . ctx )
293
311
294
312
// TODO: This should perhaps also compare against the
295
313
// include.cache file timestamp. Now, it only checks if the file
@@ -303,29 +321,29 @@ func findIncludesUntilDone(ctx *types.Context, cache *includeCache, queue *Uniqu
303
321
// TODO: This reads the dependency file, but the actual building
304
322
// does it again. Should the result be somehow cached? Perhaps
305
323
// remove the object file if it is found to be stale?
306
- unchanged , err := builder_utils .ObjFileIsUpToDate (ctx , sourcePath , objPath , depPath )
324
+ unchanged , err := builder_utils .ObjFileIsUpToDate (f . ctx , sourcePath , objPath , depPath )
307
325
if err != nil {
308
326
return errors .WithStack (err )
309
327
}
310
328
311
329
first := true
312
330
for {
313
331
var include string
314
- cache .ExpectFile (sourcePath )
332
+ f . cache .ExpectFile (sourcePath )
315
333
316
- includes := ctx .IncludeFolders
334
+ includes := f . ctx .IncludeFolders
317
335
if library , ok := sourceFile .Origin .(* libraries.Library ); ok && library .UtilityDir != nil {
318
336
includes = append (includes , library .UtilityDir )
319
337
}
320
338
var preproc_err error
321
339
var preproc_stderr []byte
322
- if unchanged && cache .valid {
323
- include = cache .Next ().Include
324
- if first && ctx .Verbose {
325
- ctx .GetLogger ().Println (constants .LOG_LEVEL_INFO , constants .MSG_USING_CACHED_INCLUDES , sourcePath )
340
+ if unchanged && f . cache .valid {
341
+ include = f . cache .Next ().Include
342
+ if first && f . ctx .Verbose {
343
+ f . ctx .GetLogger ().Println (constants .LOG_LEVEL_INFO , constants .MSG_USING_CACHED_INCLUDES , sourcePath )
326
344
}
327
345
} else {
328
- preproc_stderr , preproc_err = GCCPreprocRunnerForDiscoveringIncludes (ctx , sourcePath , targetFilePath , includes )
346
+ preproc_stderr , preproc_err = GCCPreprocRunnerForDiscoveringIncludes (f . ctx , sourcePath , targetFilePath , includes )
329
347
// Unwrap error and see if it is an ExitError.
330
348
_ , is_exit_error := errors .Cause (preproc_err ).(* exec.ExitError )
331
349
if preproc_err == nil {
@@ -338,26 +356,26 @@ func findIncludesUntilDone(ctx *types.Context, cache *includeCache, queue *Uniqu
338
356
return errors .WithStack (preproc_err )
339
357
} else {
340
358
include = IncludesFinderWithRegExp (string (preproc_stderr ))
341
- if include == "" && ctx .Verbose {
342
- ctx .GetLogger ().Println (constants .LOG_LEVEL_DEBUG , constants .MSG_FIND_INCLUDES_FAILED , sourcePath )
359
+ if include == "" && f . ctx .Verbose {
360
+ f . ctx .GetLogger ().Println (constants .LOG_LEVEL_DEBUG , constants .MSG_FIND_INCLUDES_FAILED , sourcePath )
343
361
}
344
362
}
345
363
}
346
364
347
365
if include == "" {
348
366
// No missing includes found, we're done
349
- cache .ExpectEntry (sourcePath , "" , nil )
367
+ f . cache .ExpectEntry (sourcePath , "" , nil )
350
368
return nil
351
369
}
352
370
353
- library := ResolveLibrary (ctx , include )
371
+ library := ResolveLibrary (f . ctx , include )
354
372
if library == nil {
355
373
// Library could not be resolved, show error
356
374
// err := runCommand(ctx, &GCCPreprocRunner{SourceFilePath: sourcePath, TargetFileName: paths.New(constants.FILE_CTAGS_TARGET_FOR_GCC_MINUS_E), Includes: includes})
357
375
// return errors.WithStack(err)
358
376
if preproc_err == nil || preproc_stderr == nil {
359
377
// Filename came from cache, so run preprocessor to obtain error to show
360
- preproc_stderr , preproc_err = GCCPreprocRunnerForDiscoveringIncludes (ctx , sourcePath , targetFilePath , includes )
378
+ preproc_stderr , preproc_err = GCCPreprocRunnerForDiscoveringIncludes (f . ctx , sourcePath , targetFilePath , includes )
361
379
if preproc_err == nil {
362
380
// If there is a missing #include in the cache, but running
363
381
// gcc does not reproduce that, there is something wrong.
@@ -373,17 +391,17 @@ func findIncludesUntilDone(ctx *types.Context, cache *includeCache, queue *Uniqu
373
391
// Add this library to the list of libraries, the
374
392
// include path and queue its source files for further
375
393
// include scanning
376
- ctx .ImportedLibraries = append (ctx .ImportedLibraries , library )
377
- appendIncludeFolder (ctx , cache , sourcePath , include , library .SourceDir )
394
+ f . ctx .ImportedLibraries = append (f . ctx .ImportedLibraries , library )
395
+ f . appendIncludeFolder (sourcePath , include , library .SourceDir )
378
396
sourceDirs := library .SourceDirs ()
379
397
for _ , sourceDir := range sourceDirs {
380
- queueSourceFilesFromFolder (ctx , queue , library , sourceDir .Dir , sourceDir .Recurse )
398
+ f . queueSourceFilesFromFolder (library , sourceDir .Dir , sourceDir .Recurse )
381
399
}
382
400
first = false
383
401
}
384
402
}
385
403
386
- func queueSourceFilesFromFolder ( ctx * types. Context , queue * UniqueSourceFileQueue , origin interface {}, folder * paths.Path , recurse bool ) error {
404
+ func ( f * CppIncludesFinder ) queueSourceFilesFromFolder ( origin interface {}, folder * paths.Path , recurse bool ) error {
387
405
extensions := func (ext string ) bool { return ADDITIONAL_FILE_VALID_EXTENSIONS_NO_HEADERS [ext ] }
388
406
389
407
filePaths := []string {}
@@ -393,11 +411,11 @@ func queueSourceFilesFromFolder(ctx *types.Context, queue *UniqueSourceFileQueue
393
411
}
394
412
395
413
for _ , filePath := range filePaths {
396
- sourceFile , err := MakeSourceFilee ( ctx , origin , paths .New (filePath ))
414
+ sourceFile , err := MakeSourceFile ( f . ctx , origin , paths .New (filePath ))
397
415
if err != nil {
398
416
return errors .WithStack (err )
399
417
}
400
- queue .Push (sourceFile )
418
+ f . queue .Push (sourceFile )
401
419
}
402
420
403
421
return nil
@@ -413,7 +431,7 @@ type SourceFile struct {
413
431
// Create a SourceFile containing the given source file path within the
414
432
// given origin. The given path can be absolute, or relative within the
415
433
// origin's root source folder
416
- func MakeSourceFilee (ctx * types.Context , origin interface {}, path * paths.Path ) (SourceFile , error ) {
434
+ func MakeSourceFile (ctx * types.Context , origin interface {}, path * paths.Path ) (SourceFile , error ) {
417
435
if path .IsAbs () {
418
436
var err error
419
437
path , err = sourceRoot (ctx , origin ).RelTo (path )
0 commit comments