From 2a661e850f99c8df601d8297f0d618dbb2cfe45f Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Wed, 16 Jul 2025 10:26:27 +0200 Subject: [PATCH 1/2] builder: RunRecipe: run either a set of recipes or a single recipe Recipes must follow the 'prefix.NNN.suffix' pattern, where 'NNN' is a number. When there is also a single 'prefix.suffix' property defined, make sure to not include that in the list of recipes to run. However, if no numbered recipes are found, use the single 'prefix.suffix' form if it exists. This allows to have both a single recipe and a set of numbered recipes in the same build properties, for backwards compatibility. Signed-off-by: Luca Burelli --- internal/arduino/builder/builder.go | 2 +- internal/arduino/builder/recipe.go | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/internal/arduino/builder/builder.go b/internal/arduino/builder/builder.go index 0c711273a5d..cf4af5974cf 100644 --- a/internal/arduino/builder/builder.go +++ b/internal/arduino/builder/builder.go @@ -455,7 +455,7 @@ func (b *Builder) build() error { } b.Progress.CompleteStep() - if err := b.RunRecipe("recipe.objcopy.", ".pattern", true); err != nil { + if err := b.RunRecipe("recipe.objcopy", ".pattern", true); err != nil { return err } b.Progress.CompleteStep() diff --git a/internal/arduino/builder/recipe.go b/internal/arduino/builder/recipe.go index b4c456e360f..fdae8e784a1 100644 --- a/internal/arduino/builder/recipe.go +++ b/internal/arduino/builder/recipe.go @@ -60,12 +60,20 @@ func (b *Builder) RunRecipe(prefix, suffix string, skipIfOnlyUpdatingCompilation func findRecipes(buildProperties *properties.Map, patternPrefix string, patternSuffix string) []string { var recipes []string + + exactKey := patternPrefix + patternSuffix + for _, key := range buildProperties.Keys() { - if strings.HasPrefix(key, patternPrefix) && strings.HasSuffix(key, patternSuffix) && buildProperties.Get(key) != "" { + if key != exactKey && strings.HasPrefix(key, patternPrefix) && strings.HasSuffix(key, patternSuffix) && buildProperties.Get(key) != "" { recipes = append(recipes, key) } } + // If no recipes were found, check if the exact key exists + if len(recipes) == 0 && buildProperties.Get(exactKey) != "" { + recipes = append(recipes, exactKey) + } + sort.Strings(recipes) return recipes From 2baed3cbc79feb63f929a02b95df59a9e9718415 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Wed, 16 Jul 2025 11:31:29 +0200 Subject: [PATCH 2/2] linker: switch 'recipe.c.combine.pattern' to a recipe Enable the use of recipes for the `recipe.c.combine.pattern` command. Allows for more flexibility in the build process. Signed-off-by: Luca Burelli --- docs/platform-specification.md | 4 ++++ internal/arduino/builder/linker.go | 7 +------ internal/arduino/builder/recipe.go | 7 +++++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/platform-specification.md b/docs/platform-specification.md index 43d7bac827a..c9f3cfec476 100644 --- a/docs/platform-specification.md +++ b/docs/platform-specification.md @@ -302,6 +302,10 @@ compiler.libraries.ldflags= recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} -o "{build.path}/{build.project_name}.elf" {object_files} {compiler.libraries.ldflags} "{archive_file_path}" "-L{build.path}" -lm ``` +If the linking process requires multiple steps, the recipe can be written using the **recipe.c.combine.NUMBER.pattern** +syntax. In this case, each step will be executed in the order specified by the number. When multiple steps are defined, +the **recipe.c.combine.pattern** property is ignored. + #### Recipes for extraction of executable files and other binary data An arbitrary number of extra steps can be performed at the end of objects linking. These steps can be used to extract diff --git a/internal/arduino/builder/linker.go b/internal/arduino/builder/linker.go index 77f450a9182..f69ef31b91f 100644 --- a/internal/arduino/builder/linker.go +++ b/internal/arduino/builder/linker.go @@ -90,10 +90,5 @@ func (b *Builder) link() error { properties.Set("archive_file_path", b.buildArtifacts.coreArchiveFilePath.String()) properties.Set("object_files", objectFileList) - command, err := b.prepareCommandForRecipe(properties, "recipe.c.combine.pattern", false) - if err != nil { - return err - } - - return b.execCommand(command) + return b.RunRecipeWithProps("recipe.c.combine", ".pattern", properties, false) } diff --git a/internal/arduino/builder/recipe.go b/internal/arduino/builder/recipe.go index fdae8e784a1..33143bcb182 100644 --- a/internal/arduino/builder/recipe.go +++ b/internal/arduino/builder/recipe.go @@ -27,10 +27,13 @@ import ( // RunRecipe fixdoc func (b *Builder) RunRecipe(prefix, suffix string, skipIfOnlyUpdatingCompilationDatabase bool) error { + // TODO is it necessary to use Clone? + return b.RunRecipeWithProps(prefix, suffix, b.buildProperties.Clone(), skipIfOnlyUpdatingCompilationDatabase) +} + +func (b *Builder) RunRecipeWithProps(prefix, suffix string, buildProperties *properties.Map, skipIfOnlyUpdatingCompilationDatabase bool) error { logrus.Debugf("Looking for recipes like %s", prefix+"*"+suffix) - // TODO is it necessary to use Clone? - buildProperties := b.buildProperties.Clone() recipes := findRecipes(buildProperties, prefix, suffix) // TODO is it necessary to use Clone?