Skip to content

Commit 0d6e378

Browse files
author
Federico Fissore
committedOct 2, 2015
Implemented library to library dependency full discovery. Fixes #12
Signed-off-by: Federico Fissore <f.fissore@arduino.cc>
1 parent cf97b26 commit 0d6e378

18 files changed

+363
-45
lines changed
 

‎src/arduino.cc/builder/add_additional_entries_to_context.go

+6
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ package builder
3131

3232
import (
3333
"arduino.cc/builder/constants"
34+
"arduino.cc/builder/types"
3435
"arduino.cc/builder/utils"
3536
"path/filepath"
3637
)
@@ -79,5 +80,10 @@ func (s *AddAdditionalEntriesToContext) Run(context map[string]interface{}) erro
7980
context[constants.CTX_LIBRARY_DISCOVERY_RECURSION_DEPTH] = DEFAULT_LIBRARY_DISCOVERY_RECURSION_DEPTH
8081
}
8182

83+
sourceFiles := &types.UniqueStringQueue{}
84+
context[constants.CTX_COLLECTED_SOURCE_FILES_QUEUE] = sourceFiles
85+
foldersWithSources := &types.UniqueStringQueue{}
86+
context[constants.CTX_FOLDERS_WITH_SOURCES_QUEUE] = foldersWithSources
87+
8288
return nil
8389
}

‎src/arduino.cc/builder/builder.go

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import (
4141

4242
var MAIN_FILE_VALID_EXTENSIONS = map[string]bool{".ino": true, ".pde": true}
4343
var ADDITIONAL_FILE_VALID_EXTENSIONS = map[string]bool{".h": true, ".c": true, ".hpp": true, ".cpp": true}
44+
var ADDITIONAL_FILE_VALID_EXTENSIONS_NO_HEADERS = map[string]bool{".c": true, ".cpp": true}
4445

4546
var LIBRARY_MANDATORY_PROPERTIES = []string{constants.LIBRARY_NAME, constants.LIBRARY_VERSION, constants.LIBRARY_AUTHOR, constants.LIBRARY_MAINTAINER}
4647
var LIBRARY_NOT_SO_MANDATORY_PROPERTIES = []string{constants.LIBRARY_SENTENCE, constants.LIBRARY_PARAGRAPH, constants.LIBRARY_URL}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* This file is part of Arduino Builder.
3+
*
4+
* Arduino Builder is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program; if not, write to the Free Software
16+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
*
18+
* As a special exception, you may use this file as part of a free software
19+
* library without restriction. Specifically, if other files instantiate
20+
* templates or use macros or inline functions from this file, or you compile
21+
* this file and link it with other files to produce an executable, this
22+
* file does not by itself cause the resulting executable to be covered by
23+
* the GNU General Public License. This exception does not however
24+
* invalidate any other reasons why the executable file might be covered by
25+
* the GNU General Public License.
26+
*
27+
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
28+
*/
29+
30+
package builder
31+
32+
import (
33+
"arduino.cc/builder/constants"
34+
"arduino.cc/builder/gohasissues"
35+
"arduino.cc/builder/types"
36+
"arduino.cc/builder/utils"
37+
)
38+
39+
type CollectAllSourceFilesFromFoldersWithSources struct{}
40+
41+
func (s *CollectAllSourceFilesFromFoldersWithSources) Run(context map[string]interface{}) error {
42+
foldersWithSources := context[constants.CTX_FOLDERS_WITH_SOURCES_QUEUE].(*types.UniqueStringQueue)
43+
sourceFiles := context[constants.CTX_COLLECTED_SOURCE_FILES_QUEUE].(*types.UniqueStringQueue)
44+
45+
filePaths := []string{}
46+
for !foldersWithSources.Empty() {
47+
checkExtensionFunc := func(ext string) bool {
48+
return MAIN_FILE_VALID_EXTENSIONS[ext] || ADDITIONAL_FILE_VALID_EXTENSIONS_NO_HEADERS[ext]
49+
}
50+
walkFunc := utils.CollectAllReadableFiles(&filePaths, checkExtensionFunc)
51+
err := gohasissues.Walk(foldersWithSources.Pop().(string), walkFunc)
52+
if err != nil {
53+
return utils.WrapError(err)
54+
}
55+
}
56+
57+
for _, filePath := range filePaths {
58+
sourceFiles.Push(filePath)
59+
}
60+
61+
return nil
62+
}

‎src/arduino.cc/builder/constants/constants.go

+2
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,14 @@ const CTX_BUILD_OPTIONS_PREVIOUS_JSON = "buildOptionsPreviousJson"
8080
const CTX_BUILD_PATH = "buildPath"
8181
const CTX_BUILD_PROPERTIES = "buildProperties"
8282
const CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION = "runtime.ide.version"
83+
const CTX_COLLECTED_SOURCE_FILES_QUEUE = "collectedSourceFilesQueue"
8384
const CTX_CORE_BUILD_PATH = "coreBuildPath"
8485
const CTX_CTAGS_OUTPUT = "ctagsOutput"
8586
const CTX_CTAGS_TEMP_FILE_NAME = "ctagsTempFileName"
8687
const CTX_CUSTOM_BUILD_PROPERTIES = "customBuildProperties"
8788
const CTX_DEBUG_LEVEL = "debugLevel"
8889
const CTX_FIRST_FUNCTION_AT_LINE = "firstFunctionAtLine"
90+
const CTX_FOLDERS_WITH_SOURCES_QUEUE = "foldersWithSourcesQueue"
8991
const CTX_FQBN = "fqbn"
9092
const CTX_GCC_MINUS_E_SOURCE = "gccMinusESource"
9193
const CTX_GCC_MINUS_M_OUTPUT = "gccMinusMOutput"

‎src/arduino.cc/builder/container_find_includes.go

+37-1
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,18 @@ import (
3333
"arduino.cc/builder/constants"
3434
"arduino.cc/builder/types"
3535
"arduino.cc/builder/utils"
36+
"path/filepath"
3637
)
3738

3839
type ContainerFindIncludes struct{}
3940

4041
func (s *ContainerFindIncludes) Run(context map[string]interface{}) error {
42+
sketch := context[constants.CTX_SKETCH].(*types.Sketch)
43+
sketchBuildPath := context[constants.CTX_SKETCH_BUILD_PATH].(string)
4144
wheelSpins := context[constants.CTX_LIBRARY_DISCOVERY_RECURSION_DEPTH].(int)
4245
for i := 0; i < wheelSpins; i++ {
4346
commands := []types.Command{
44-
&IncludesFinderWithGCC{},
47+
&IncludesFinderWithGCC{SourceFile: filepath.Join(sketchBuildPath, filepath.Base(sketch.MainFile.Name)+".cpp")},
4548
&GCCMinusMOutputParser{},
4649
&IncludesToIncludeFolders{},
4750
}
@@ -55,5 +58,38 @@ func (s *ContainerFindIncludes) Run(context map[string]interface{}) error {
5558
}
5659
}
5760

61+
foldersWithSources := context[constants.CTX_FOLDERS_WITH_SOURCES_QUEUE].(*types.UniqueStringQueue)
62+
foldersWithSources.Push(context[constants.CTX_SKETCH_BUILD_PATH])
63+
if utils.MapHas(context, constants.CTX_IMPORTED_LIBRARIES) {
64+
for _, library := range context[constants.CTX_IMPORTED_LIBRARIES].([]*types.Library) {
65+
foldersWithSources.Push(library.SrcFolder)
66+
}
67+
}
68+
69+
command := &CollectAllSourceFilesFromFoldersWithSources{}
70+
err := command.Run(context)
71+
if err != nil {
72+
return utils.WrapError(err)
73+
}
74+
75+
sourceFiles := context[constants.CTX_COLLECTED_SOURCE_FILES_QUEUE].(*types.UniqueStringQueue)
76+
77+
for !sourceFiles.Empty() {
78+
commands := []types.Command{
79+
&IncludesFinderWithGCC{SourceFile: sourceFiles.Pop().(string)},
80+
&GCCMinusMOutputParser{},
81+
&IncludesToIncludeFolders{},
82+
&CollectAllSourceFilesFromFoldersWithSources{},
83+
}
84+
85+
for _, command := range commands {
86+
PrintRingNameIfDebug(context, command)
87+
err := command.Run(context)
88+
if err != nil {
89+
return utils.WrapError(err)
90+
}
91+
}
92+
}
93+
5894
return nil
5995
}

‎src/arduino.cc/builder/gohasissues/go_has_issues.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,15 @@ import (
3838
"strings"
3939
)
4040

41-
type WalkFunc func(path string, info os.FileInfo, err error) error
42-
43-
func Walk(root string, walkFn WalkFunc) error {
41+
func Walk(root string, walkFn filepath.WalkFunc) error {
4442
info, err := os.Stat(root)
4543
if err != nil {
4644
return walkFn(root, nil, err)
4745
}
4846
return walk(root, info, walkFn)
4947
}
5048

51-
func walk(path string, info os.FileInfo, walkFn WalkFunc) error {
49+
func walk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error {
5250
err := walkFn(path, info, nil)
5351
if err != nil {
5452
if info.IsDir() && err == filepath.SkipDir {

‎src/arduino.cc/builder/includes_finder_with_gcc.go

+4-6
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,16 @@ import (
3333
"arduino.cc/builder/builder_utils"
3434
"arduino.cc/builder/constants"
3535
"arduino.cc/builder/i18n"
36-
"arduino.cc/builder/types"
3736
"arduino.cc/builder/utils"
38-
"path/filepath"
3937
"strings"
4038
)
4139

42-
type IncludesFinderWithGCC struct{}
40+
type IncludesFinderWithGCC struct {
41+
SourceFile string
42+
}
4343

4444
func (s *IncludesFinderWithGCC) Run(context map[string]interface{}) error {
4545
buildProperties := utils.GetMapStringStringOrDefault(context, constants.CTX_BUILD_PROPERTIES)
46-
sketch := context[constants.CTX_SKETCH].(*types.Sketch)
47-
sketchBuildPath := context[constants.CTX_SKETCH_BUILD_PATH].(string)
4846
verbose := context[constants.CTX_VERBOSE].(bool)
4947
logger := context[constants.CTX_LOGGER].(i18n.Logger)
5048

@@ -56,7 +54,7 @@ func (s *IncludesFinderWithGCC) Run(context map[string]interface{}) error {
5654
}
5755

5856
properties := utils.MergeMapsOfStrings(make(map[string]string), buildProperties)
59-
properties[constants.BUILD_PROPERTIES_SOURCE_FILE] = filepath.Join(sketchBuildPath, filepath.Base(sketch.MainFile.Name)+".cpp")
57+
properties[constants.BUILD_PROPERTIES_SOURCE_FILE] = s.SourceFile
6058
properties[constants.BUILD_PROPERTIES_INCLUDES] = includesParams
6159
builder_utils.RemoveHyphenMDDFlagFromGCCCommandLine(properties)
6260

‎src/arduino.cc/builder/includes_to_include_folders.go

+15-5
Original file line numberDiff line numberDiff line change
@@ -52,19 +52,29 @@ func (s *IncludesToIncludeFolders) Run(context map[string]interface{}) error {
5252
platform := context[constants.CTX_TARGET_PLATFORM].(*types.Platform)
5353
actualPlatform := context[constants.CTX_ACTUAL_PLATFORM].(*types.Platform)
5454

55-
var previousImportedLibraries []*types.Library
55+
var importedLibraries []*types.Library
5656
if utils.MapHas(context, constants.CTX_IMPORTED_LIBRARIES) {
57-
previousImportedLibraries = context[constants.CTX_IMPORTED_LIBRARIES].([]*types.Library)
57+
importedLibraries = context[constants.CTX_IMPORTED_LIBRARIES].([]*types.Library)
5858
}
59-
importedLibraries, err := resolveLibraries(includes, headerToLibraries, previousImportedLibraries, []*types.Platform{platform, actualPlatform}, debugLevel, logger)
59+
newlyImportedLibraries, err := resolveLibraries(includes, headerToLibraries, importedLibraries, []*types.Platform{platform, actualPlatform}, debugLevel, logger)
6060
if err != nil {
6161
return utils.WrapError(err)
6262
}
63+
64+
foldersWithSources := context[constants.CTX_FOLDERS_WITH_SOURCES_QUEUE].(*types.UniqueStringQueue)
65+
66+
for _, newlyImportedLibrary := range newlyImportedLibraries {
67+
if !sliceContainsLibrary(importedLibraries, newlyImportedLibrary) {
68+
importedLibraries = append(importedLibraries, newlyImportedLibrary)
69+
foldersWithSources.Push(newlyImportedLibrary.SrcFolder)
70+
}
71+
}
72+
6373
context[constants.CTX_IMPORTED_LIBRARIES] = importedLibraries
6474

6575
buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string)
6676
verbose := context[constants.CTX_VERBOSE].(bool)
67-
includeFolders := resolveIncludeFolders(importedLibraries, buildProperties, verbose)
77+
includeFolders := resolveIncludeFolders(newlyImportedLibraries, buildProperties, verbose)
6878
context[constants.CTX_INCLUDE_FOLDERS] = includeFolders
6979

7080
return nil
@@ -250,7 +260,7 @@ func findLibWithNameContaining(name string, libraries []*types.Library) *types.L
250260
// thank you golang: I can not use/recycle/adapt utils.SliceContains
251261
func sliceContainsLibrary(slice []*types.Library, target *types.Library) bool {
252262
for _, value := range slice {
253-
if value == target {
263+
if value.SrcFolder == target.SrcFolder {
254264
return true
255265
}
256266
}

‎src/arduino.cc/builder/sketch_loader.go

+3-20
Original file line numberDiff line numberDiff line change
@@ -84,27 +84,10 @@ func (s *SketchLoader) Run(context map[string]interface{}) error {
8484

8585
func collectAllSketchFiles(from string) ([]string, error) {
8686
filePaths := []string{}
87-
walkFunc := func(currentPath string, info os.FileInfo, err error) error {
88-
if err != nil {
89-
return err
90-
}
91-
92-
if info.IsDir() {
93-
return nil
94-
}
95-
ext := strings.ToLower(filepath.Ext(currentPath))
96-
if !MAIN_FILE_VALID_EXTENSIONS[ext] && !ADDITIONAL_FILE_VALID_EXTENSIONS[ext] {
97-
return nil
98-
}
99-
currentFile, err := os.Open(currentPath)
100-
if err != nil {
101-
return nil
102-
}
103-
currentFile.Close()
104-
105-
filePaths = append(filePaths, currentPath)
106-
return nil
87+
checkExtensionFunc := func(ext string) bool {
88+
return MAIN_FILE_VALID_EXTENSIONS[ext] || ADDITIONAL_FILE_VALID_EXTENSIONS[ext]
10789
}
90+
walkFunc := utils.CollectAllReadableFiles(&filePaths, checkExtensionFunc)
10891
err := gohasissues.Walk(from, walkFunc)
10992
return filePaths, utils.WrapError(err)
11093
}

‎src/arduino.cc/builder/test/add_additional_entries_to_context_test.go

+7
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ package test
3232
import (
3333
"arduino.cc/builder"
3434
"arduino.cc/builder/constants"
35+
"arduino.cc/builder/types"
3536
"github.com/stretchr/testify/require"
3637
"path/filepath"
3738
"testing"
@@ -52,6 +53,9 @@ func TestAddAdditionalEntriesToContextNoBuildPath(t *testing.T) {
5253
require.NotNil(t, context[constants.CTX_VERBOSE])
5354
require.NotNil(t, context[constants.CTX_DEBUG_LEVEL])
5455
require.NotNil(t, context[constants.CTX_LIBRARY_DISCOVERY_RECURSION_DEPTH])
56+
57+
require.True(t, context[constants.CTX_COLLECTED_SOURCE_FILES_QUEUE].(*types.UniqueStringQueue).Empty())
58+
require.True(t, context[constants.CTX_FOLDERS_WITH_SOURCES_QUEUE].(*types.UniqueStringQueue).Empty())
5559
}
5660

5761
func TestAddAdditionalEntriesToContextWithBuildPath(t *testing.T) {
@@ -71,4 +75,7 @@ func TestAddAdditionalEntriesToContextWithBuildPath(t *testing.T) {
7175
require.NotNil(t, context[constants.CTX_VERBOSE])
7276
require.NotNil(t, context[constants.CTX_DEBUG_LEVEL])
7377
require.NotNil(t, context[constants.CTX_LIBRARY_DISCOVERY_RECURSION_DEPTH])
78+
79+
require.True(t, context[constants.CTX_COLLECTED_SOURCE_FILES_QUEUE].(*types.UniqueStringQueue).Empty())
80+
require.True(t, context[constants.CTX_FOLDERS_WITH_SOURCES_QUEUE].(*types.UniqueStringQueue).Empty())
7481
}

‎src/arduino.cc/builder/test/builder_utils_test.go

+29
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,32 @@
1+
/*
2+
* This file is part of Arduino Builder.
3+
*
4+
* Arduino Builder is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program; if not, write to the Free Software
16+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
*
18+
* As a special exception, you may use this file as part of a free software
19+
* library without restriction. Specifically, if other files instantiate
20+
* templates or use macros or inline functions from this file, or you compile
21+
* this file and link it with other files to produce an executable, this
22+
* file does not by itself cause the resulting executable to be covered by
23+
* the GNU General Public License. This exception does not however
24+
* invalidate any other reasons why the executable file might be covered by
25+
* the GNU General Public License.
26+
*
27+
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
28+
*/
29+
130
package test
231

332
import (

0 commit comments

Comments
 (0)
Please sign in to comment.