Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Improve precompiled libraries handling
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
  • Loading branch information
facchinm committed Dec 11, 2019
commit 48e453aa75abdd4ca18129b8868895a82472f7e3
1 change: 1 addition & 0 deletions legacy/builder/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ const MSG_FIND_INCLUDES_FAILED = "Error while detecting libraries included by {0
const MSG_INVALID_QUOTING = "Invalid quoting: no closing [{0}] char found."
const MSG_LIB_LEGACY = "(legacy)"
const MSG_LIBRARIES_MULTIPLE_LIBS_FOUND_FOR = "Multiple libraries were found for \"{0}\""
const MSG_PRECOMPILED_LIBRARY_NOT_FOUND_FOR = "Library \"{0}\" declared precompiled but folder \"{1}\" does not exist"
const MSG_LIBRARIES_NOT_USED = " Not used: {0}"
const MSG_LIBRARIES_USED = " Used: {0}"
const MSG_LIBRARY_CAN_USE_SRC_AND_UTILITY_FOLDERS = "Library can't use both 'src' and 'utility' folders. Double check {0}"
Expand Down
94 changes: 79 additions & 15 deletions legacy/builder/phases/libraries_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
package phases

import (
"os"
"path/filepath"
"strings"

Expand All @@ -45,6 +46,8 @@ import (

var PRECOMPILED_LIBRARIES_VALID_EXTENSIONS_STATIC = map[string]bool{".a": true}
var PRECOMPILED_LIBRARIES_VALID_EXTENSIONS_DYNAMIC = map[string]bool{".so": true}
var FLOAT_ABI_CFLAG = "float-abi"
var FPU_CFLAG = "fpu"

type LibrariesBuilder struct{}

Expand All @@ -71,28 +74,83 @@ func (s *LibrariesBuilder) Run(ctx *types.Context) error {
return nil
}

func findExpectedPrecompiledLibFolder(ctx *types.Context, library *libraries.Library) *paths.Path {
mcu := ctx.BuildProperties.Get(constants.BUILD_PROPERTIES_BUILD_MCU)
// Add fpu specifications if they exist
// To do so, resolve recipe.cpp.o.pattern,
// search for -mfpu=xxx -mfloat-abi=yyy and add to a subfolder
command, _ := builder_utils.PrepareCommandForRecipe(ctx, ctx.BuildProperties, constants.RECIPE_CPP_PATTERN, true)
fpuSpecs := ""
for _, el := range strings.Split(command.String(), " ") {
if strings.Contains(el, FPU_CFLAG) {
toAdd := strings.Split(el, "=")
if len(toAdd) > 1 {
fpuSpecs += strings.TrimSpace(toAdd[1]) + "-"
break
}
}
}
for _, el := range strings.Split(command.String(), " ") {
if strings.Contains(el, FLOAT_ABI_CFLAG) {
toAdd := strings.Split(el, "=")
if len(toAdd) > 1 {
fpuSpecs += strings.TrimSpace(toAdd[1]) + "-"
break
}
}
}

logger := ctx.GetLogger()
if len(fpuSpecs) > 0 {
fpuSpecs = strings.TrimRight(fpuSpecs, "-")
if library.SourceDir.Join(mcu).Join(fpuSpecs).Exist() {
return library.SourceDir.Join(mcu).Join(fpuSpecs)
} else {
// we are unsure, compile from sources
logger.Fprintln(os.Stdout, constants.LOG_LEVEL_INFO,
constants.MSG_PRECOMPILED_LIBRARY_NOT_FOUND_FOR, library.Name, library.SourceDir.Join(mcu).Join(fpuSpecs))
return nil
}
}

if library.SourceDir.Join(mcu).Exist() {
return library.SourceDir.Join(mcu)
}

logger.Fprintln(os.Stdout, constants.LOG_LEVEL_INFO,
constants.MSG_PRECOMPILED_LIBRARY_NOT_FOUND_FOR, library.Name, library.SourceDir.Join(mcu))

return nil
}

func fixLDFLAGforPrecompiledLibraries(ctx *types.Context, libs libraries.List) error {

for _, library := range libs {
if library.Precompiled {
// add library src path to compiler.c.elf.extra_flags
// use library.Name as lib name and srcPath/{mcpu} as location
mcu := ctx.BuildProperties.Get(constants.BUILD_PROPERTIES_BUILD_MCU)
path := library.SourceDir.Join(mcu).String()
path := findExpectedPrecompiledLibFolder(ctx, library)
if path == nil {
break
}
// find all library names in the folder and prepend -l
filePaths := []string{}
libs_cmd := library.LDflags + " "
extensions := func(ext string) bool { return PRECOMPILED_LIBRARIES_VALID_EXTENSIONS_DYNAMIC[ext] }
utils.FindFilesInFolder(&filePaths, path, extensions, true)
extensions := func(ext string) bool {
return PRECOMPILED_LIBRARIES_VALID_EXTENSIONS_DYNAMIC[ext] || PRECOMPILED_LIBRARIES_VALID_EXTENSIONS_STATIC[ext]
}
utils.FindFilesInFolder(&filePaths, path.String(), extensions, false)
for _, lib := range filePaths {
name := strings.TrimSuffix(filepath.Base(lib), filepath.Ext(lib))
// strip "lib" first occurrence
name = strings.Replace(name, "lib", "", 1)
libs_cmd += "-l" + name + " "
if strings.HasPrefix(name, "lib") {
name = strings.Replace(name, "lib", "", 1)
libs_cmd += "-l" + name + " "
}
}

currLDFlags := ctx.BuildProperties.Get(constants.BUILD_PROPERTIES_COMPILER_LIBRARIES_LDFLAGS)
ctx.BuildProperties.Set(constants.BUILD_PROPERTIES_COMPILER_LIBRARIES_LDFLAGS, currLDFlags+"\"-L"+path+"\" "+libs_cmd+" ")
ctx.BuildProperties.Set(constants.BUILD_PROPERTIES_COMPILER_LIBRARIES_LDFLAGS, currLDFlags+"\"-L"+path.String()+"\" "+libs_cmd+" ")
}
}
return nil
Expand Down Expand Up @@ -129,15 +187,21 @@ func compileLibrary(ctx *types.Context, library *libraries.Library, buildPath *p
extensions := func(ext string) bool { return PRECOMPILED_LIBRARIES_VALID_EXTENSIONS_STATIC[ext] }

filePaths := []string{}
mcu := buildProperties.Get(constants.BUILD_PROPERTIES_BUILD_MCU)
err := utils.FindFilesInFolder(&filePaths, library.SourceDir.Join(mcu).String(), extensions, true)
if err != nil {
return nil, i18n.WrapError(err)
}
for _, path := range filePaths {
if strings.Contains(filepath.Base(path), library.RealName) {
objectFiles.Add(paths.New(path))
precompiledPath := findExpectedPrecompiledLibFolder(ctx, library)
if precompiledPath != nil {
// TODO: This codepath is just taken for .a with unusual names that would
// be ignored by -L / -l methods.
// Should we force precompiled libraries to start with "lib" ?
err := utils.FindFilesInFolder(&filePaths, precompiledPath.String(), extensions, false)
if err != nil {
return nil, i18n.WrapError(err)
}
for _, path := range filePaths {
if !strings.HasPrefix(filepath.Base(path), "lib") {
objectFiles.Add(paths.New(path))
}
}
return objectFiles, nil
}
}

Expand Down