Skip to content

Commit de128a9

Browse files
committed
Create CppIncludesFinder object to handle library discovery.
All the fields needed to perform library discovery have been moved into the CppIncludeFinder so there is no more need to pass them around as parameters making it much more lightweight.
1 parent f8cf6e6 commit de128a9

File tree

1 file changed

+67
-49
lines changed

1 file changed

+67
-49
lines changed

legacy/builder/container_find_includes.go

Lines changed: 67 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -111,45 +111,63 @@ import (
111111
type ContainerFindIncludes struct{}
112112

113113
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+
}
115123

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"))
119145
}
120146

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"))
123148
if err != nil {
124149
return errors.WithStack(err)
125150
}
126-
queue := &UniqueSourceFileQueue{}
127-
queue.Push(mergedfile)
151+
f.queue.Push(mergedfile)
128152

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")
131155
if srcSubfolderPath.IsDir() {
132-
queueSourceFilesFromFolder(ctx, queue, sketch, srcSubfolderPath, true /* recurse */)
156+
f.queueSourceFilesFromFolder(f.sketch, srcSubfolderPath, true /* recurse */)
133157
}
134158

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()
138162
return errors.WithStack(err)
139163
}
140164
}
141165

142166
// 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 {
145169
return errors.WithStack(err)
146170
}
147-
148-
err = runCommand(ctx, &FailIfImportedLibraryIsWrong{})
149-
if err != nil {
150-
return errors.WithStack(err)
151-
}
152-
153171
return nil
154172
}
155173

@@ -158,9 +176,9 @@ func (s *ContainerFindIncludes) Run(ctx *types.Context) error {
158176
// include (e.g. what #include line in what file it was resolved from)
159177
// and should be the empty string for the default include folders, like
160178
// 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)
164182
}
165183

166184
func runCommand(ctx *types.Context, command types.Command) error {
@@ -285,11 +303,11 @@ func (cache *includeCache) WriteToFile() error {
285303
return nil
286304
}
287305

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)
290308
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)
293311

294312
// TODO: This should perhaps also compare against the
295313
// include.cache file timestamp. Now, it only checks if the file
@@ -303,29 +321,29 @@ func findIncludesUntilDone(ctx *types.Context, cache *includeCache, queue *Uniqu
303321
// TODO: This reads the dependency file, but the actual building
304322
// does it again. Should the result be somehow cached? Perhaps
305323
// 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)
307325
if err != nil {
308326
return errors.WithStack(err)
309327
}
310328

311329
first := true
312330
for {
313331
var include string
314-
cache.ExpectFile(sourcePath)
332+
f.cache.ExpectFile(sourcePath)
315333

316-
includes := ctx.IncludeFolders
334+
includes := f.ctx.IncludeFolders
317335
if library, ok := sourceFile.Origin.(*libraries.Library); ok && library.UtilityDir != nil {
318336
includes = append(includes, library.UtilityDir)
319337
}
320338
var preproc_err error
321339
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)
326344
}
327345
} else {
328-
preproc_stderr, preproc_err = GCCPreprocRunnerForDiscoveringIncludes(ctx, sourcePath, targetFilePath, includes)
346+
preproc_stderr, preproc_err = GCCPreprocRunnerForDiscoveringIncludes(f.ctx, sourcePath, targetFilePath, includes)
329347
// Unwrap error and see if it is an ExitError.
330348
_, is_exit_error := errors.Cause(preproc_err).(*exec.ExitError)
331349
if preproc_err == nil {
@@ -338,26 +356,26 @@ func findIncludesUntilDone(ctx *types.Context, cache *includeCache, queue *Uniqu
338356
return errors.WithStack(preproc_err)
339357
} else {
340358
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)
343361
}
344362
}
345363
}
346364

347365
if include == "" {
348366
// No missing includes found, we're done
349-
cache.ExpectEntry(sourcePath, "", nil)
367+
f.cache.ExpectEntry(sourcePath, "", nil)
350368
return nil
351369
}
352370

353-
library := ResolveLibrary(ctx, include)
371+
library := ResolveLibrary(f.ctx, include)
354372
if library == nil {
355373
// Library could not be resolved, show error
356374
// err := runCommand(ctx, &GCCPreprocRunner{SourceFilePath: sourcePath, TargetFileName: paths.New(constants.FILE_CTAGS_TARGET_FOR_GCC_MINUS_E), Includes: includes})
357375
// return errors.WithStack(err)
358376
if preproc_err == nil || preproc_stderr == nil {
359377
// 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)
361379
if preproc_err == nil {
362380
// If there is a missing #include in the cache, but running
363381
// gcc does not reproduce that, there is something wrong.
@@ -373,17 +391,17 @@ func findIncludesUntilDone(ctx *types.Context, cache *includeCache, queue *Uniqu
373391
// Add this library to the list of libraries, the
374392
// include path and queue its source files for further
375393
// 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)
378396
sourceDirs := library.SourceDirs()
379397
for _, sourceDir := range sourceDirs {
380-
queueSourceFilesFromFolder(ctx, queue, library, sourceDir.Dir, sourceDir.Recurse)
398+
f.queueSourceFilesFromFolder(library, sourceDir.Dir, sourceDir.Recurse)
381399
}
382400
first = false
383401
}
384402
}
385403

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 {
387405
extensions := func(ext string) bool { return ADDITIONAL_FILE_VALID_EXTENSIONS_NO_HEADERS[ext] }
388406

389407
filePaths := []string{}
@@ -393,11 +411,11 @@ func queueSourceFilesFromFolder(ctx *types.Context, queue *UniqueSourceFileQueue
393411
}
394412

395413
for _, filePath := range filePaths {
396-
sourceFile, err := MakeSourceFilee(ctx, origin, paths.New(filePath))
414+
sourceFile, err := MakeSourceFile(f.ctx, origin, paths.New(filePath))
397415
if err != nil {
398416
return errors.WithStack(err)
399417
}
400-
queue.Push(sourceFile)
418+
f.queue.Push(sourceFile)
401419
}
402420

403421
return nil
@@ -413,7 +431,7 @@ type SourceFile struct {
413431
// Create a SourceFile containing the given source file path within the
414432
// given origin. The given path can be absolute, or relative within the
415433
// 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) {
417435
if path.IsAbs() {
418436
var err error
419437
path, err = sourceRoot(ctx, origin).RelTo(path)

0 commit comments

Comments
 (0)