Skip to content

Commit 469b339

Browse files
authored
Improve precompiled libraries handling (arduino#512)
General change: - library compilation bails out if the precompiled object is found. This allows mixed libraries that fallback using sources if no suitable precompiled object is found ARM float specification change: - Cortex M4+ allows specifying different flags for floating point ABI This patch introduces a second level of subfolder that MUST be used is -mfpu or -mfloat-abi are specified on the commandline Since there's no clear specification (unlike build.mcu), the values are extracted from c++ recipe For example, for a target which commandline contains `-mfloat-abi=hard -mfpu=fpv4-sp-d16` , the precompiled search path will be `$libfolder/cortex-m4/fpv4-sp-d16-hard` If that folder doesn't exist the library will be compiled from sources Fixes arduino/arduino-builder#256
1 parent fe48668 commit 469b339

File tree

2 files changed

+80
-15
lines changed

2 files changed

+80
-15
lines changed

Diff for: legacy/builder/constants/constants.go

+1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ const MSG_FIND_INCLUDES_FAILED = "Error while detecting libraries included by {0
9898
const MSG_INVALID_QUOTING = "Invalid quoting: no closing [{0}] char found."
9999
const MSG_LIB_LEGACY = "(legacy)"
100100
const MSG_LIBRARIES_MULTIPLE_LIBS_FOUND_FOR = "Multiple libraries were found for \"{0}\""
101+
const MSG_PRECOMPILED_LIBRARY_NOT_FOUND_FOR = "Library \"{0}\" declared precompiled but folder \"{1}\" does not exist"
101102
const MSG_LIBRARIES_NOT_USED = " Not used: {0}"
102103
const MSG_LIBRARIES_USED = " Used: {0}"
103104
const MSG_LIBRARY_CAN_USE_SRC_AND_UTILITY_FOLDERS = "Library can't use both 'src' and 'utility' folders. Double check {0}"

Diff for: legacy/builder/phases/libraries_builder.go

+79-15
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package phases
1717

1818
import (
19+
"os"
1920
"path/filepath"
2021
"strings"
2122

@@ -31,6 +32,8 @@ import (
3132

3233
var PRECOMPILED_LIBRARIES_VALID_EXTENSIONS_STATIC = map[string]bool{".a": true}
3334
var PRECOMPILED_LIBRARIES_VALID_EXTENSIONS_DYNAMIC = map[string]bool{".so": true}
35+
var FLOAT_ABI_CFLAG = "float-abi"
36+
var FPU_CFLAG = "fpu"
3437

3538
type LibrariesBuilder struct{}
3639

@@ -57,28 +60,83 @@ func (s *LibrariesBuilder) Run(ctx *types.Context) error {
5760
return nil
5861
}
5962

63+
func findExpectedPrecompiledLibFolder(ctx *types.Context, library *libraries.Library) *paths.Path {
64+
mcu := ctx.BuildProperties.Get(constants.BUILD_PROPERTIES_BUILD_MCU)
65+
// Add fpu specifications if they exist
66+
// To do so, resolve recipe.cpp.o.pattern,
67+
// search for -mfpu=xxx -mfloat-abi=yyy and add to a subfolder
68+
command, _ := builder_utils.PrepareCommandForRecipe(ctx, ctx.BuildProperties, constants.RECIPE_CPP_PATTERN, true)
69+
fpuSpecs := ""
70+
for _, el := range strings.Split(command.String(), " ") {
71+
if strings.Contains(el, FPU_CFLAG) {
72+
toAdd := strings.Split(el, "=")
73+
if len(toAdd) > 1 {
74+
fpuSpecs += strings.TrimSpace(toAdd[1]) + "-"
75+
break
76+
}
77+
}
78+
}
79+
for _, el := range strings.Split(command.String(), " ") {
80+
if strings.Contains(el, FLOAT_ABI_CFLAG) {
81+
toAdd := strings.Split(el, "=")
82+
if len(toAdd) > 1 {
83+
fpuSpecs += strings.TrimSpace(toAdd[1]) + "-"
84+
break
85+
}
86+
}
87+
}
88+
89+
logger := ctx.GetLogger()
90+
if len(fpuSpecs) > 0 {
91+
fpuSpecs = strings.TrimRight(fpuSpecs, "-")
92+
if library.SourceDir.Join(mcu).Join(fpuSpecs).Exist() {
93+
return library.SourceDir.Join(mcu).Join(fpuSpecs)
94+
} else {
95+
// we are unsure, compile from sources
96+
logger.Fprintln(os.Stdout, constants.LOG_LEVEL_INFO,
97+
constants.MSG_PRECOMPILED_LIBRARY_NOT_FOUND_FOR, library.Name, library.SourceDir.Join(mcu).Join(fpuSpecs))
98+
return nil
99+
}
100+
}
101+
102+
if library.SourceDir.Join(mcu).Exist() {
103+
return library.SourceDir.Join(mcu)
104+
}
105+
106+
logger.Fprintln(os.Stdout, constants.LOG_LEVEL_INFO,
107+
constants.MSG_PRECOMPILED_LIBRARY_NOT_FOUND_FOR, library.Name, library.SourceDir.Join(mcu))
108+
109+
return nil
110+
}
111+
60112
func fixLDFLAGforPrecompiledLibraries(ctx *types.Context, libs libraries.List) error {
61113

62114
for _, library := range libs {
63115
if library.Precompiled {
64116
// add library src path to compiler.c.elf.extra_flags
65117
// use library.Name as lib name and srcPath/{mcpu} as location
66-
mcu := ctx.BuildProperties.Get(constants.BUILD_PROPERTIES_BUILD_MCU)
67-
path := library.SourceDir.Join(mcu).String()
118+
path := findExpectedPrecompiledLibFolder(ctx, library)
119+
if path == nil {
120+
break
121+
}
68122
// find all library names in the folder and prepend -l
69123
filePaths := []string{}
70124
libs_cmd := library.LDflags + " "
71-
extensions := func(ext string) bool { return PRECOMPILED_LIBRARIES_VALID_EXTENSIONS_DYNAMIC[ext] }
72-
utils.FindFilesInFolder(&filePaths, path, extensions, true)
125+
extensions := func(ext string) bool {
126+
return PRECOMPILED_LIBRARIES_VALID_EXTENSIONS_DYNAMIC[ext] || PRECOMPILED_LIBRARIES_VALID_EXTENSIONS_STATIC[ext]
127+
}
128+
utils.FindFilesInFolder(&filePaths, path.String(), extensions, false)
73129
for _, lib := range filePaths {
74130
name := strings.TrimSuffix(filepath.Base(lib), filepath.Ext(lib))
75131
// strip "lib" first occurrence
76-
name = strings.Replace(name, "lib", "", 1)
77-
libs_cmd += "-l" + name + " "
132+
if strings.HasPrefix(name, "lib") {
133+
name = strings.Replace(name, "lib", "", 1)
134+
libs_cmd += "-l" + name + " "
135+
}
78136
}
79137

80138
currLDFlags := ctx.BuildProperties.Get(constants.BUILD_PROPERTIES_COMPILER_LIBRARIES_LDFLAGS)
81-
ctx.BuildProperties.Set(constants.BUILD_PROPERTIES_COMPILER_LIBRARIES_LDFLAGS, currLDFlags+"\"-L"+path+"\" "+libs_cmd+" ")
139+
ctx.BuildProperties.Set(constants.BUILD_PROPERTIES_COMPILER_LIBRARIES_LDFLAGS, currLDFlags+"\"-L"+path.String()+"\" "+libs_cmd+" ")
82140
}
83141
}
84142
return nil
@@ -115,15 +173,21 @@ func compileLibrary(ctx *types.Context, library *libraries.Library, buildPath *p
115173
extensions := func(ext string) bool { return PRECOMPILED_LIBRARIES_VALID_EXTENSIONS_STATIC[ext] }
116174

117175
filePaths := []string{}
118-
mcu := buildProperties.Get(constants.BUILD_PROPERTIES_BUILD_MCU)
119-
err := utils.FindFilesInFolder(&filePaths, library.SourceDir.Join(mcu).String(), extensions, true)
120-
if err != nil {
121-
return nil, i18n.WrapError(err)
122-
}
123-
for _, path := range filePaths {
124-
if strings.Contains(filepath.Base(path), library.RealName) {
125-
objectFiles.Add(paths.New(path))
176+
precompiledPath := findExpectedPrecompiledLibFolder(ctx, library)
177+
if precompiledPath != nil {
178+
// TODO: This codepath is just taken for .a with unusual names that would
179+
// be ignored by -L / -l methods.
180+
// Should we force precompiled libraries to start with "lib" ?
181+
err := utils.FindFilesInFolder(&filePaths, precompiledPath.String(), extensions, false)
182+
if err != nil {
183+
return nil, i18n.WrapError(err)
184+
}
185+
for _, path := range filePaths {
186+
if !strings.HasPrefix(filepath.Base(path), "lib") {
187+
objectFiles.Add(paths.New(path))
188+
}
126189
}
190+
return objectFiles, nil
127191
}
128192
}
129193

0 commit comments

Comments
 (0)