diff --git a/.github/workflows/test-go-task.yml b/.github/workflows/test-go-task.yml index f0bac8cb077..e11c59ba91e 100644 --- a/.github/workflows/test-go-task.yml +++ b/.github/workflows/test-go-task.yml @@ -154,11 +154,6 @@ jobs: - name: Run tests run: task go:test - - name: Run unit tests on the legacy package - # Run legacy tests on one platform only - if: runner.os == 'Linux' - run: task test-legacy - - name: Upload coverage data to workflow artifact if: runner.os == 'Linux' uses: actions/upload-artifact@v3 @@ -167,7 +162,6 @@ jobs: name: ${{ env.COVERAGE_ARTIFACT }} path: | ./coverage_unit.txt - ./coverage_legacy.txt coverage-upload: runs-on: ubuntu-latest diff --git a/Taskfile.yml b/Taskfile.yml index 1373e1adde8..b7a4522d033 100755 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -284,21 +284,11 @@ tasks: - task: go:build test: - desc: Run the full testsuite, `legacy` will be skipped + desc: Run the full testsuite cmds: - task: go:test - task: go:integration-test - test-legacy: - desc: Run tests for the `legacy` package - cmds: - - | - go test \ - {{ default "-v -failfast" .GOFLAGS }} \ - -coverprofile=coverage_legacy.txt \ - ./legacy/... \ - {{.TEST_LDFLAGS}} - test-unit-race: desc: Run unit tests only with race condition detection cmds: @@ -311,18 +301,12 @@ tasks: {{.TEST_LDFLAGS}} check: - desc: Check fmt and lint, `legacy` will be skipped + desc: Check fmt and lint cmds: - task: go:vet - task: go:lint - task: protoc:check - check-legacy: - desc: Check fmt and lint for the `legacy` package - cmds: - - test -z $(go fmt ./legacy/...) - - go vet ./legacy/... - rpc-client: desc: Run the rpc client test routine (server must be already started) cmds: @@ -376,10 +360,10 @@ tasks: vars: PROJECT_NAME: "arduino-cli" DIST_DIR: "dist" - # all modules of this project except for "legacy/..." module and integration test + # all modules of this project except for integration test DEFAULT_GO_PACKAGES: sh: | - echo $(cd {{default "./" .GO_MODULE_PATH}} && go list ./... | grep -v internal/integrationtest | grep -v legacy | tr '\n' ' ' || echo '"ERROR: Unable to discover Go packages"') + echo $(cd {{default "./" .GO_MODULE_PATH}} && go list ./... | grep -v internal/integrationtest | tr '\n' ' ' || echo '"ERROR: Unable to discover Go packages"') DEFAULT_INTEGRATIONTEST_GO_PACKAGES: sh: | echo $(cd {{default "./" .GO_MODULE_PATH}} && go list ./... | grep internal/integrationtest | tr '\n' ' ' || echo '"ERROR: Unable to discover Go packages"') diff --git a/arduino/builder/build_options_manager.go b/arduino/builder/build_options_manager.go index 3079ecf9ea6..0d097bdb1e7 100644 --- a/arduino/builder/build_options_manager.go +++ b/arduino/builder/build_options_manager.go @@ -154,14 +154,16 @@ func (m *BuildOptionsManager) wipeBuildPath() error { return wipe() } + // Since we might apply a side effect we clone it + currentOptions := m.currentOptions.Clone() // If SketchLocation path is different but filename is the same, consider it equal - if filepath.Base(m.currentOptions.Get("sketchLocation")) == filepath.Base(prevOpts.Get("sketchLocation")) { - m.currentOptions.Remove("sketchLocation") + if filepath.Base(currentOptions.Get("sketchLocation")) == filepath.Base(prevOpts.Get("sketchLocation")) { + currentOptions.Remove("sketchLocation") prevOpts.Remove("sketchLocation") } // If options are not changed check if core has - if m.currentOptions.Equals(prevOpts) { + if currentOptions.Equals(prevOpts) { // check if any of the files contained in the core folders has changed // since the json was generated - like platform.txt or similar // if so, trigger a "safety" wipe diff --git a/arduino/builder/builder.go b/arduino/builder/builder.go index a856106d574..64e06f82eb3 100644 --- a/arduino/builder/builder.go +++ b/arduino/builder/builder.go @@ -20,9 +20,11 @@ import ( "fmt" "github.com/arduino/arduino-cli/arduino/builder/compilation" + "github.com/arduino/arduino-cli/arduino/builder/detector" "github.com/arduino/arduino-cli/arduino/builder/logger" "github.com/arduino/arduino-cli/arduino/builder/progress" "github.com/arduino/arduino-cli/arduino/cores" + "github.com/arduino/arduino-cli/arduino/libraries/librariesmanager" "github.com/arduino/arduino-cli/arduino/sketch" "github.com/arduino/go-paths-helper" "github.com/arduino/go-properties-orderedmap" @@ -77,6 +79,7 @@ type Builder struct { buildArtifacts *BuildArtifacts + *detector.SketchLibrariesDetector *BuildOptionsManager } @@ -109,6 +112,9 @@ func NewBuilder( sourceOverrides map[string]string, onlyUpdateCompilationDatabase bool, targetPlatform, actualPlatform *cores.PlatformRelease, + useCachedLibrariesResolution bool, + librariesManager *librariesmanager.LibrariesManager, + libraryDirs paths.PathList, logger *logger.BuilderLogger, progressStats *progress.Struct, ) (*Builder, error) { @@ -163,6 +169,18 @@ func NewBuilder( progressStats = progress.New(nil) } + libsManager, libsResolver, verboseOut, err := detector.LibrariesLoader( + useCachedLibrariesResolution, librariesManager, + builtInLibrariesDirs, libraryDirs, otherLibrariesDirs, + actualPlatform, targetPlatform, + ) + if err != nil { + return nil, err + } + if logger.Verbose() { + logger.Warn(string(verboseOut)) + } + return &Builder{ sketch: sk, buildProperties: buildProperties, @@ -183,6 +201,12 @@ func NewBuilder( buildArtifacts: &BuildArtifacts{}, targetPlatform: targetPlatform, actualPlatform: actualPlatform, + SketchLibrariesDetector: detector.NewSketchLibrariesDetector( + libsManager, libsResolver, + useCachedLibrariesResolution, + onlyUpdateCompilationDatabase, + logger, + ), BuildOptionsManager: NewBuildOptionsManager( hardwareDirs, builtInToolsDirs, otherLibrariesDirs, builtInLibrariesDirs, buildPath, @@ -208,29 +232,243 @@ func (b *Builder) GetBuildPath() *paths.Path { return b.buildPath } -// GetSketchBuildPath returns the sketch build path -func (b *Builder) GetSketchBuildPath() *paths.Path { - return b.sketchBuildPath +// ExecutableSectionsSize fixdoc +func (b *Builder) ExecutableSectionsSize() ExecutablesFileSections { + return b.executableSectionsSize } -// GetLibrariesBuildPath returns the libraries build path -func (b *Builder) GetLibrariesBuildPath() *paths.Path { - return b.librariesBuildPath +// Preprocess fixdoc +func (b *Builder) Preprocess() error { + b.Progress.AddSubSteps(6) + defer b.Progress.RemoveSubSteps() + return b.preprocess() } -// ExecutableSectionsSize fixdoc -func (b *Builder) ExecutableSectionsSize() ExecutablesFileSections { - return b.executableSectionsSize +func (b *Builder) preprocess() error { + if err := b.buildPath.MkdirAll(); err != nil { + return err + } + + if err := b.BuildOptionsManager.WipeBuildPath(); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if err := b.RunRecipe("recipe.hooks.prebuild", ".pattern", false); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if err := b.prepareSketchBuildPath(); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + b.logIfVerbose(false, tr("Detecting libraries used...")) + err := b.SketchLibrariesDetector.FindIncludes( + b.buildPath, + b.buildProperties.GetPath("build.core.path"), + b.buildProperties.GetPath("build.variant.path"), + b.sketchBuildPath, + b.sketch, + b.librariesBuildPath, + b.buildProperties, + b.targetPlatform.Platform.Architecture, + ) + if err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + b.warnAboutArchIncompatibleLibraries(b.SketchLibrariesDetector.ImportedLibraries()) + b.Progress.CompleteStep() + b.Progress.PushProgress() + + b.logIfVerbose(false, tr("Generating function prototypes...")) + if err := b.preprocessSketch(b.SketchLibrariesDetector.IncludeFolders()); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + // Output arduino-preprocessed source + preprocessedSketch, err := b.sketchBuildPath.Join(b.sketch.MainFile.Base() + ".cpp").ReadFile() + if err != nil { + return err + } + b.logger.WriteStdout(preprocessedSketch) + + return nil } -// SaveCompilationDatabase fixdoc -func (b *Builder) SaveCompilationDatabase() { - if b.compilationDatabase != nil { - b.compilationDatabase.SaveToFile() +func (b *Builder) logIfVerbose(warn bool, msg string) { + if !b.logger.Verbose() { + return + } + if warn { + b.logger.Warn(msg) + return + } + b.logger.Info(msg) +} + +// Build fixdoc +func (b *Builder) Build() error { + b.Progress.AddSubSteps(6 /** preprocess **/ + 21 /** build **/) + defer b.Progress.RemoveSubSteps() + + if err := b.preprocess(); err != nil { + return err + } + + buildErr := b.build() + + b.SketchLibrariesDetector.PrintUsedAndNotUsedLibraries(buildErr != nil) + b.Progress.CompleteStep() + b.Progress.PushProgress() + + b.printUsedLibraries(b.SketchLibrariesDetector.ImportedLibraries()) + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if buildErr != nil { + return buildErr + } + if err := b.exportProjectCMake(b.SketchLibrariesDetector.ImportedLibraries(), b.SketchLibrariesDetector.IncludeFolders()); err != nil { + return err } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if err := b.size(); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + return nil } -// TargetPlatform fixdoc -func (b *Builder) TargetPlatform() *cores.PlatformRelease { - return b.targetPlatform +// Build fixdoc +func (b *Builder) build() error { + b.logIfVerbose(false, tr("Compiling sketch...")) + if err := b.RunRecipe("recipe.hooks.sketch.prebuild", ".pattern", false); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if err := b.BuildSketch(b.SketchLibrariesDetector.IncludeFolders()); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if err := b.RunRecipe("recipe.hooks.sketch.postbuild", ".pattern", true); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + b.logIfVerbose(false, tr("Compiling libraries...")) + if err := b.RunRecipe("recipe.hooks.libraries.prebuild", ".pattern", false); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if err := b.removeUnusedCompiledLibraries(b.SketchLibrariesDetector.ImportedLibraries()); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if err := b.buildLibraries(b.SketchLibrariesDetector.IncludeFolders(), b.SketchLibrariesDetector.ImportedLibraries()); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if err := b.RunRecipe("recipe.hooks.libraries.postbuild", ".pattern", true); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + b.logIfVerbose(false, tr("Compiling core...")) + if err := b.RunRecipe("recipe.hooks.core.prebuild", ".pattern", false); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if err := b.buildCore(); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if err := b.RunRecipe("recipe.hooks.core.postbuild", ".pattern", true); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + b.logIfVerbose(false, tr("Linking everything together...")) + if err := b.RunRecipe("recipe.hooks.linking.prelink", ".pattern", false); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if err := b.link(); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if err := b.RunRecipe("recipe.hooks.linking.postlink", ".pattern", true); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if err := b.RunRecipe("recipe.hooks.objcopy.preobjcopy", ".pattern", false); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if err := b.RunRecipe("recipe.objcopy.", ".pattern", true); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if err := b.RunRecipe("recipe.hooks.objcopy.postobjcopy", ".pattern", true); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if err := b.MergeSketchWithBootloader(); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if err := b.RunRecipe("recipe.hooks.postbuild", ".pattern", true); err != nil { + return err + } + b.Progress.CompleteStep() + b.Progress.PushProgress() + + if b.compilationDatabase != nil { + b.compilationDatabase.SaveToFile() + } + return nil } diff --git a/arduino/builder/core.go b/arduino/builder/core.go index 2fcbb682a7c..9617d22cc11 100644 --- a/arduino/builder/core.go +++ b/arduino/builder/core.go @@ -30,8 +30,8 @@ import ( "github.com/pkg/errors" ) -// BuildCore fixdoc -func (b *Builder) BuildCore() error { +// buildCore fixdoc +func (b *Builder) buildCore() error { if err := b.coreBuildPath.MkdirAll(); err != nil { return errors.WithStack(err) } diff --git a/arduino/builder/export_cmake.go b/arduino/builder/export_cmake.go index de7bdf6db88..06360a55ec9 100644 --- a/arduino/builder/export_cmake.go +++ b/arduino/builder/export_cmake.go @@ -34,12 +34,8 @@ import ( var lineMatcher = regexp.MustCompile(`^#line\s\d+\s"`) -// ExportProjectCMake fixdoc -func (b *Builder) ExportProjectCMake( - sketchError bool, // Was there an error while compiling the sketch? - importedLibraries libraries.List, - includeFolders paths.PathList, -) error { +// exportProjectCMake fixdoc +func (b *Builder) exportProjectCMake(importedLibraries libraries.List, includeFolders paths.PathList) error { // copies the contents of the file named src to the file named // by dst. The file will be created if it does not already exist. If the // destination file exists, all it's contents will be replaced by the contents @@ -175,8 +171,8 @@ func (b *Builder) ExportProjectCMake( } var validStaticLibExtensions = []string{".a"} - // If sketch error or cannot export Cmake project - if sketchError || b.buildProperties.Get("compiler.export_cmake") == "" { + // If cannot export Cmake project + if b.buildProperties.Get("compiler.export_cmake") == "" { return nil } @@ -241,7 +237,7 @@ func (b *Builder) ExportProjectCMake( fmt.Println(err) } - if err := b.PreprocessSketch(includeFolders); err != nil { + if err := b.preprocessSketch(includeFolders); err != nil { return err } diff --git a/arduino/builder/libraries.go b/arduino/builder/libraries.go index f5b6a46957b..9efa62df378 100644 --- a/arduino/builder/libraries.go +++ b/arduino/builder/libraries.go @@ -35,8 +35,8 @@ var ( FpuCflag = "fpu" ) -// BuildLibraries fixdoc -func (b *Builder) BuildLibraries(includesFolders paths.PathList, importedLibraries libraries.List) error { +// buildLibraries fixdoc +func (b *Builder) buildLibraries(includesFolders paths.PathList, importedLibraries libraries.List) error { includes := f.Map(includesFolders.AsStrings(), cpp.WrapWithHyphenI) libs := importedLibraries @@ -254,8 +254,8 @@ func (b *Builder) compileLibrary(library *libraries.Library, includes []string) return objectFiles, nil } -// RemoveUnusedCompiledLibraries fixdoc -func (b *Builder) RemoveUnusedCompiledLibraries(importedLibraries libraries.List) error { +// removeUnusedCompiledLibraries fixdoc +func (b *Builder) removeUnusedCompiledLibraries(importedLibraries libraries.List) error { if b.librariesBuildPath.NotExist() { return nil } @@ -287,8 +287,8 @@ func (b *Builder) RemoveUnusedCompiledLibraries(importedLibraries libraries.List return nil } -// WarnAboutArchIncompatibleLibraries fixdoc -func (b *Builder) WarnAboutArchIncompatibleLibraries(importedLibraries libraries.List) { +// warnAboutArchIncompatibleLibraries fixdoc +func (b *Builder) warnAboutArchIncompatibleLibraries(importedLibraries libraries.List) { archs := []string{b.targetPlatform.Platform.Architecture} overrides, _ := b.buildProperties.GetOk("architecture.override_check") if overrides != "" { @@ -306,10 +306,10 @@ func (b *Builder) WarnAboutArchIncompatibleLibraries(importedLibraries libraries } } -// PrintUsedLibraries fixdoc +// printUsedLibraries fixdoc // TODO here we can completly remove this part as it's duplicated in what we can // read in the gRPC response -func (b *Builder) PrintUsedLibraries(importedLibraries libraries.List) { +func (b *Builder) printUsedLibraries(importedLibraries libraries.List) { if !b.logger.Verbose() || len(importedLibraries) == 0 { return } diff --git a/arduino/builder/linker.go b/arduino/builder/linker.go index a4a2eba3bec..60c09bcf6dd 100644 --- a/arduino/builder/linker.go +++ b/arduino/builder/linker.go @@ -24,8 +24,8 @@ import ( "github.com/pkg/errors" ) -// Link fixdoc -func (b *Builder) Link() error { +// link fixdoc +func (b *Builder) link() error { if b.onlyUpdateCompilationDatabase { if b.logger.Verbose() { b.logger.Info(tr("Skip linking of final executable.")) @@ -43,14 +43,6 @@ func (b *Builder) Link() error { return errors.WithStack(err) } - if err := b.link(objectFiles, coreDotARelPath, b.buildArtifacts.coreArchiveFilePath); err != nil { - return errors.WithStack(err) - } - - return nil -} - -func (b *Builder) link(objectFiles paths.PathList, coreDotARelPath *paths.Path, coreArchiveFilePath *paths.Path) error { wrapWithDoubleQuotes := func(value string) string { return "\"" + value + "\"" } objectFileList := strings.Join(f.Map(objectFiles.AsStrings(), wrapWithDoubleQuotes), " ") @@ -101,7 +93,7 @@ func (b *Builder) link(objectFiles paths.PathList, coreDotARelPath *paths.Path, properties.Set("compiler.c.elf.flags", properties.Get("compiler.c.elf.flags")) properties.Set("compiler.warning_flags", properties.Get("compiler.warning_flags."+b.logger.WarningsLevel())) properties.Set("archive_file", coreDotARelPath.String()) - properties.Set("archive_file_path", coreArchiveFilePath.String()) + properties.Set("archive_file_path", b.buildArtifacts.coreArchiveFilePath.String()) properties.Set("object_files", objectFileList) command, err := utils.PrepareCommandForRecipe(properties, "recipe.c.combine.pattern", false) @@ -113,5 +105,8 @@ func (b *Builder) link(objectFiles paths.PathList, coreDotARelPath *paths.Path, if b.logger.Verbose() { b.logger.Info(string(verboseInfo)) } - return err + if err != nil { + return err + } + return nil } diff --git a/arduino/builder/preprocess_sketch.go b/arduino/builder/preprocess_sketch.go index cf6adb208a2..c871495c335 100644 --- a/arduino/builder/preprocess_sketch.go +++ b/arduino/builder/preprocess_sketch.go @@ -20,8 +20,8 @@ import ( "github.com/arduino/go-paths-helper" ) -// PreprocessSketch fixdoc -func (b *Builder) PreprocessSketch(includes paths.PathList) error { +// preprocessSketch fixdoc +func (b *Builder) preprocessSketch(includes paths.PathList) error { // In the future we might change the preprocessor normalOutput, verboseOutput, err := preprocessor.PreprocessSketchWithCtags( b.sketch, b.buildPath, includes, b.lineOffset, @@ -29,8 +29,9 @@ func (b *Builder) PreprocessSketch(includes paths.PathList) error { ) if b.logger.Verbose() { b.logger.WriteStdout(verboseOutput) + } else { + b.logger.WriteStdout(normalOutput) } - b.logger.WriteStdout(normalOutput) return err } diff --git a/arduino/builder/recipe.go b/arduino/builder/recipe.go index 1102e8d7568..385e6a03a87 100644 --- a/arduino/builder/recipe.go +++ b/arduino/builder/recipe.go @@ -27,10 +27,7 @@ import ( ) // RunRecipe fixdoc -func (b *Builder) RunRecipe( - prefix, suffix string, - skipIfOnlyUpdatingCompilationDatabase bool, -) error { +func (b *Builder) RunRecipe(prefix, suffix string, skipIfOnlyUpdatingCompilationDatabase bool) error { logrus.Debugf(fmt.Sprintf("Looking for recipes like %s", prefix+"*"+suffix)) // TODO is it necessary to use Clone? diff --git a/arduino/builder/sizer.go b/arduino/builder/sizer.go index 7f461f8292e..0924f9a62e4 100644 --- a/arduino/builder/sizer.go +++ b/arduino/builder/sizer.go @@ -50,9 +50,9 @@ func (s ExecutablesFileSections) ToRPCExecutableSectionSizeArray() []*rpc.Execut return res } -// Size fixdoc -func (b *Builder) Size(sketchError bool) error { - if b.onlyUpdateCompilationDatabase || sketchError { +// size fixdoc +func (b *Builder) size() error { + if b.onlyUpdateCompilationDatabase { return nil } diff --git a/arduino/builder/sketch.go b/arduino/builder/sketch.go index dbab5b521bc..f54461fb74a 100644 --- a/arduino/builder/sketch.go +++ b/arduino/builder/sketch.go @@ -25,7 +25,6 @@ import ( "github.com/arduino/arduino-cli/arduino/builder/cpp" "github.com/arduino/arduino-cli/arduino/builder/utils" - "github.com/arduino/arduino-cli/arduino/sketch" "github.com/arduino/arduino-cli/i18n" f "github.com/arduino/arduino-cli/internal/algorithms" "github.com/arduino/go-paths-helper" @@ -39,15 +38,10 @@ var ( tr = i18n.Tr ) -// Sketch fixdoc -func (b *Builder) Sketch() *sketch.Sketch { - return b.sketch -} - -// PrepareSketchBuildPath copies the sketch source files in the build path. +// prepareSketchBuildPath copies the sketch source files in the build path. // The .ino files are merged together to create a .cpp file (by the way, the // .cpp file still needs to be Arduino-preprocessed to compile). -func (b *Builder) PrepareSketchBuildPath() error { +func (b *Builder) prepareSketchBuildPath() error { if err := b.sketchBuildPath.MkdirAll(); err != nil { return errors.Wrap(err, tr("unable to create a folder to save the sketch")) } diff --git a/commands/compile/compile.go b/commands/compile/compile.go index 5dcd028c34c..cd728eb5fa1 100644 --- a/commands/compile/compile.go +++ b/commands/compile/compile.go @@ -24,8 +24,7 @@ import ( "strings" "github.com/arduino/arduino-cli/arduino" - bldr "github.com/arduino/arduino-cli/arduino/builder" - "github.com/arduino/arduino-cli/arduino/builder/detector" + "github.com/arduino/arduino-cli/arduino/builder" "github.com/arduino/arduino-cli/arduino/builder/logger" "github.com/arduino/arduino-cli/arduino/builder/progress" "github.com/arduino/arduino-cli/arduino/cores" @@ -37,8 +36,6 @@ import ( "github.com/arduino/arduino-cli/configuration" "github.com/arduino/arduino-cli/i18n" "github.com/arduino/arduino-cli/internal/inventory" - "github.com/arduino/arduino-cli/legacy/builder" - "github.com/arduino/arduino-cli/legacy/builder/types" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" paths "github.com/arduino/go-paths-helper" "github.com/sirupsen/logrus" @@ -174,16 +171,15 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream return nil, err } - builderCtx := &types.Context{} actualPlatform := buildPlatform - builtinLibrariesDir := configuration.IDEBuiltinLibrariesDir(configuration.Settings) otherLibrariesDirs := paths.NewPathList(req.GetLibraries()...) otherLibrariesDirs.Add(configuration.LibrariesDir(configuration.Settings)) - builderLogger := logger.New(outStream, errStream, req.GetVerbose(), req.GetWarnings()) - builderCtx.BuilderLogger = builderLogger - - sketchBuilder, err := bldr.NewBuilder( + var libsManager *librariesmanager.LibrariesManager + if pme.GetProfile() != nil { + libsManager = lm + } + sketchBuilder, err := builder.NewBuilder( sk, boardBuildProperties, buildPath, @@ -194,53 +190,29 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream configuration.HardwareDirectories(configuration.Settings), configuration.BuiltinToolsDirectories(configuration.Settings), otherLibrariesDirs, - builtinLibrariesDir, + configuration.IDEBuiltinLibrariesDir(configuration.Settings), fqbn, req.GetClean(), req.GetSourceOverride(), req.GetCreateCompilationDatabaseOnly(), - actualPlatform, targetPlatform, - builderLogger, + targetPlatform, actualPlatform, + req.GetSkipLibrariesDiscovery(), + libsManager, + paths.NewPathList(req.Library...), + logger.New(outStream, errStream, req.GetVerbose(), req.GetWarnings()), progress.New(progressCB), ) if err != nil { if strings.Contains(err.Error(), "invalid build properties") { return nil, &arduino.InvalidArgumentError{Message: tr("Invalid build properties"), Cause: err} } - if errors.Is(err, bldr.ErrSketchCannotBeLocatedInBuildPath) { + if errors.Is(err, builder.ErrSketchCannotBeLocatedInBuildPath) { return r, &arduino.CompileFailedError{ Message: tr("Sketch cannot be located in build path. Please specify a different build path"), } } return r, &arduino.CompileFailedError{Message: err.Error()} } - builderCtx.Builder = sketchBuilder - - var libsManager *librariesmanager.LibrariesManager - if pme.GetProfile() != nil { - libsManager = lm - } - useCachedLibrariesResolution := req.GetSkipLibrariesDiscovery() - libraryDir := paths.NewPathList(req.Library...) - libsManager, libsResolver, verboseOut, err := detector.LibrariesLoader( - useCachedLibrariesResolution, libsManager, - builtinLibrariesDir, libraryDir, otherLibrariesDirs, - actualPlatform, targetPlatform, - ) - if err != nil { - return r, &arduino.CompileFailedError{Message: err.Error()} - } - - if builderLogger.Verbose() { - builderLogger.Warn(string(verboseOut)) - } - - builderCtx.SketchLibrariesDetector = detector.NewSketchLibrariesDetector( - libsManager, libsResolver, - useCachedLibrariesResolution, - req.GetCreateCompilationDatabaseOnly(), - builderLogger, - ) defer func() { if p := sketchBuilder.GetBuildPath(); p != nil { @@ -270,7 +242,7 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream if req.GetPreprocess() { // Just output preprocessed source code and exit - compileErr := builder.RunPreprocess(builderCtx) + compileErr := sketchBuilder.Preprocess() if compileErr != nil { compileErr = &arduino.CompileFailedError{Message: compileErr.Error()} } @@ -279,7 +251,7 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream defer func() { importedLibs := []*rpc.Library{} - for _, lib := range builderCtx.SketchLibrariesDetector.ImportedLibraries() { + for _, lib := range sketchBuilder.SketchLibrariesDetector.ImportedLibraries() { rpcLib, err := lib.ToRPCLibrary() if err != nil { msg := tr("Error getting information for library %s", lib.Name) + ": " + err.Error() + "\n" @@ -315,7 +287,7 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream targetBoard.String(), "'build.board'", sketchBuilder.GetBuildProperties().Get("build.board")) + "\n")) } - if err := builder.RunBuilder(builderCtx); err != nil { + if err := sketchBuilder.Build(); err != nil { return r, &arduino.CompileFailedError{Message: err.Error()} } diff --git a/internal/integrationtest/daemon/daemon_test.go b/internal/integrationtest/daemon/daemon_test.go index cbb227293c4..d550ea2ed09 100644 --- a/internal/integrationtest/daemon/daemon_test.go +++ b/internal/integrationtest/daemon/daemon_test.go @@ -187,7 +187,7 @@ func TestDaemonCompileOptions(t *testing.T) { // https://github.com/arduino/arduino-cli/issues/2016 // assert that the task progress is increasing and doesn't contain multiple 100% values results := analyzer.Results[""] - require.True(t, results[len(results)-1].Completed) + require.True(t, results[len(results)-1].Completed, fmt.Sprintf("latest percent value: %v", results[len(results)-1].Percent)) require.IsNonDecreasing(t, f.Map(results, (*commands.TaskProgress).GetPercent)) } diff --git a/legacy/builder/.gitignore b/legacy/builder/.gitignore deleted file mode 100644 index 0df12e548b2..00000000000 --- a/legacy/builder/.gitignore +++ /dev/null @@ -1,81 +0,0 @@ -bin -src/github.com -src/golang.org -./arduino-builder - -# Created by .ignore support plugin (hsz.mobi) -### Go template -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof - - - -### JetBrains template -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm - -*.iml - -## Directory-based project format: -.idea/ -# if you remove the above rule, at least ignore the following: - -# User-specific stuff: -# .idea/workspace.xml -# .idea/tasks.xml -# .idea/dictionaries - -# Sensitive or high-churn files: -# .idea/dataSources.ids -# .idea/dataSources.xml -# .idea/sqlDataSources.xml -# .idea/dynamic.xml -# .idea/uiDesigner.xml - -# Gradle: -# .idea/gradle.xml -# .idea/libraries - -# Mongo Explorer plugin: -# .idea/mongoSettings.xml - -## File-based project format: -*.ipr -*.iws - -## Plugin-specific files: - -# IntelliJ -out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties diff --git a/legacy/builder/builder.go b/legacy/builder/builder.go deleted file mode 100644 index e7fa77fc7f4..00000000000 --- a/legacy/builder/builder.go +++ /dev/null @@ -1,311 +0,0 @@ -// This file is part of arduino-cli. -// -// Copyright 2020 ARDUINO SA (http://www.arduino.cc/) -// -// This software is released under the GNU General Public License version 3, -// which covers the main part of arduino-cli. -// The terms of this license can be found at: -// https://www.gnu.org/licenses/gpl-3.0.en.html -// -// You can be released from the requirements of the above licenses by purchasing -// a commercial license. Buying such a license is mandatory if you want to -// modify or otherwise use the software for commercial activities involving the -// Arduino software without disclosing the source code of your own applications. -// To purchase a commercial license, send an email to license@arduino.cc. - -package builder - -import ( - "reflect" - "time" - - "github.com/arduino/arduino-cli/i18n" - "github.com/arduino/arduino-cli/legacy/builder/types" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -var tr = i18n.Tr - -type Builder struct{} - -func (s *Builder) Run(ctx *types.Context) error { - if err := ctx.Builder.GetBuildPath().MkdirAll(); err != nil { - return err - } - - var mainErr error - commands := []types.Command{ - containerBuildOptions(ctx), - - types.BareCommand(func(ctx *types.Context) error { - return recipeByPrefixSuffixRunner(ctx, "recipe.hooks.prebuild", ".pattern", false) - }), - - types.BareCommand(func(ctx *types.Context) error { - return ctx.Builder.PrepareSketchBuildPath() - }), - - logIfVerbose(false, tr("Detecting libraries used...")), - findIncludes(ctx), - - warnAboutArchIncompatibleLibraries(ctx), - - logIfVerbose(false, tr("Generating function prototypes...")), - preprocessSketchCommand(ctx), - - logIfVerbose(false, tr("Compiling sketch...")), - - types.BareCommand(func(ctx *types.Context) error { - return recipeByPrefixSuffixRunner(ctx, "recipe.hooks.sketch.prebuild", ".pattern", false) - }), - - types.BareCommand(func(ctx *types.Context) error { - return ctx.Builder.BuildSketch(ctx.SketchLibrariesDetector.IncludeFolders()) - }), - - types.BareCommand(func(ctx *types.Context) error { - return recipeByPrefixSuffixRunner(ctx, "recipe.hooks.sketch.postbuild", ".pattern", true) - }), - - logIfVerbose(false, tr("Compiling libraries...")), - types.BareCommand(func(ctx *types.Context) error { - return recipeByPrefixSuffixRunner(ctx, "recipe.hooks.libraries.prebuild", ".pattern", false) - }), - - types.BareCommand(func(ctx *types.Context) error { - return ctx.Builder.RemoveUnusedCompiledLibraries( - ctx.SketchLibrariesDetector.ImportedLibraries(), - ) - }), - - types.BareCommand(func(ctx *types.Context) error { - return ctx.Builder.BuildLibraries(ctx.SketchLibrariesDetector.IncludeFolders(), ctx.SketchLibrariesDetector.ImportedLibraries()) - }), - types.BareCommand(func(ctx *types.Context) error { - return recipeByPrefixSuffixRunner(ctx, "recipe.hooks.libraries.postbuild", ".pattern", true) - }), - - logIfVerbose(false, tr("Compiling core...")), - types.BareCommand(func(ctx *types.Context) error { - return recipeByPrefixSuffixRunner(ctx, "recipe.hooks.core.prebuild", ".pattern", false) - }), - - types.BareCommand(func(ctx *types.Context) error { - return ctx.Builder.BuildCore() - }), - - types.BareCommand(func(ctx *types.Context) error { - return recipeByPrefixSuffixRunner(ctx, "recipe.hooks.core.postbuild", ".pattern", true) - }), - - logIfVerbose(false, tr("Linking everything together...")), - types.BareCommand(func(ctx *types.Context) error { - return recipeByPrefixSuffixRunner(ctx, "recipe.hooks.linking.prelink", ".pattern", false) - }), - - types.BareCommand(func(ctx *types.Context) error { - return ctx.Builder.Link() - }), - - types.BareCommand(func(ctx *types.Context) error { - return recipeByPrefixSuffixRunner(ctx, "recipe.hooks.linking.postlink", ".pattern", true) - }), - - types.BareCommand(func(ctx *types.Context) error { - return recipeByPrefixSuffixRunner(ctx, "recipe.hooks.objcopy.preobjcopy", ".pattern", false) - }), - types.BareCommand(func(ctx *types.Context) error { - return recipeByPrefixSuffixRunner(ctx, "recipe.objcopy.", ".pattern", true) - }), - types.BareCommand(func(ctx *types.Context) error { - return recipeByPrefixSuffixRunner(ctx, "recipe.hooks.objcopy.postobjcopy", ".pattern", true) - }), - - types.BareCommand(func(ctx *types.Context) error { - return ctx.Builder.MergeSketchWithBootloader() - }), - - types.BareCommand(func(ctx *types.Context) error { - return recipeByPrefixSuffixRunner(ctx, "recipe.hooks.postbuild", ".pattern", true) - }), - } - - ctx.Builder.Progress.AddSubSteps(len(commands) + 5) - defer ctx.Builder.Progress.RemoveSubSteps() - - for _, command := range commands { - PrintRingNameIfDebug(ctx, command) - err := command.Run(ctx) - if err != nil { - mainErr = errors.WithStack(err) - break - } - ctx.Builder.Progress.CompleteStep() - ctx.Builder.Progress.PushProgress() - } - - ctx.Builder.SaveCompilationDatabase() - - var otherErr error - commands = []types.Command{ - types.BareCommand(func(ctx *types.Context) error { - ctx.SketchLibrariesDetector.PrintUsedAndNotUsedLibraries(mainErr != nil) - return nil - }), - - types.BareCommand(func(ctx *types.Context) error { - ctx.Builder.PrintUsedLibraries(ctx.SketchLibrariesDetector.ImportedLibraries()) - return nil - }), - - types.BareCommand(func(ctx *types.Context) error { - return ctx.Builder.ExportProjectCMake( - mainErr != nil, - ctx.SketchLibrariesDetector.ImportedLibraries(), - ctx.SketchLibrariesDetector.IncludeFolders(), - ) - }), - - types.BareCommand(func(ctx *types.Context) error { - return ctx.Builder.Size(mainErr != nil) - }), - } - for _, command := range commands { - PrintRingNameIfDebug(ctx, command) - err := command.Run(ctx) - if err != nil { - otherErr = errors.WithStack(err) - break - } - ctx.Builder.Progress.CompleteStep() - ctx.Builder.Progress.PushProgress() - } - - if mainErr != nil { - return mainErr - } - - return otherErr -} - -func preprocessSketchCommand(ctx *types.Context) types.BareCommand { - return func(ctx *types.Context) error { - return ctx.Builder.PreprocessSketch(ctx.SketchLibrariesDetector.IncludeFolders()) - } -} - -type Preprocess struct{} - -func (s *Preprocess) Run(ctx *types.Context) error { - if err := ctx.Builder.GetBuildPath().MkdirAll(); err != nil { - return err - } - - commands := []types.Command{ - containerBuildOptions(ctx), - - types.BareCommand(func(ctx *types.Context) error { - return recipeByPrefixSuffixRunner(ctx, "recipe.hooks.prebuild", ".pattern", false) - }), - - types.BareCommand(func(ctx *types.Context) error { - return ctx.Builder.PrepareSketchBuildPath() - }), - - findIncludes(ctx), - - warnAboutArchIncompatibleLibraries(ctx), - - preprocessSketchCommand(ctx), - } - - if err := runCommands(ctx, commands); err != nil { - return err - } - - // Output arduino-preprocessed source - preprocessedSketch, err := ctx.Builder.GetSketchBuildPath().Join(ctx.Builder.Sketch().MainFile.Base() + ".cpp").ReadFile() - if err != nil { - return err - } - ctx.BuilderLogger.WriteStdout(preprocessedSketch) - return nil -} - -func runCommands(ctx *types.Context, commands []types.Command) error { - ctx.Builder.Progress.AddSubSteps(len(commands)) - defer ctx.Builder.Progress.RemoveSubSteps() - - for _, command := range commands { - PrintRingNameIfDebug(ctx, command) - err := command.Run(ctx) - if err != nil { - return errors.WithStack(err) - } - ctx.Builder.Progress.CompleteStep() - ctx.Builder.Progress.PushProgress() - } - return nil -} - -func PrintRingNameIfDebug(ctx *types.Context, command types.Command) { - logrus.Debugf("Ts: %d - Running: %s", time.Now().Unix(), reflect.Indirect(reflect.ValueOf(command)).Type().Name()) -} - -func RunBuilder(ctx *types.Context) error { - return runCommands(ctx, []types.Command{&Builder{}}) -} - -func RunPreprocess(ctx *types.Context) error { - command := Preprocess{} - return command.Run(ctx) -} - -func findIncludes(ctx *types.Context) types.BareCommand { - return types.BareCommand(func(ctx *types.Context) error { - return ctx.SketchLibrariesDetector.FindIncludes( - ctx.Builder.GetBuildPath(), - ctx.Builder.GetBuildProperties().GetPath("build.core.path"), - ctx.Builder.GetBuildProperties().GetPath("build.variant.path"), - ctx.Builder.GetSketchBuildPath(), - ctx.Builder.Sketch(), - ctx.Builder.GetLibrariesBuildPath(), - ctx.Builder.GetBuildProperties(), - ctx.Builder.TargetPlatform().Platform.Architecture, - ) - }) -} - -func logIfVerbose(warn bool, msg string) types.BareCommand { - return types.BareCommand(func(ctx *types.Context) error { - if !ctx.BuilderLogger.Verbose() { - return nil - } - if warn { - ctx.BuilderLogger.Warn(msg) - } else { - ctx.BuilderLogger.Info(msg) - } - return nil - }) -} - -func recipeByPrefixSuffixRunner(ctx *types.Context, prefix, suffix string, skipIfOnlyUpdatingCompilationDatabase bool) error { - return ctx.Builder.RunRecipe(prefix, suffix, skipIfOnlyUpdatingCompilationDatabase) -} - -func containerBuildOptions(ctx *types.Context) types.BareCommand { - return types.BareCommand(func(ctx *types.Context) error { - return ctx.Builder.BuildOptionsManager.WipeBuildPath() - }) -} - -func warnAboutArchIncompatibleLibraries(ctx *types.Context) types.BareCommand { - return types.BareCommand(func(ctx *types.Context) error { - ctx.Builder.WarnAboutArchIncompatibleLibraries( - ctx.SketchLibrariesDetector.ImportedLibraries(), - ) - return nil - }) -} diff --git a/legacy/builder/types/context.go b/legacy/builder/types/context.go deleted file mode 100644 index 64b85c93fe2..00000000000 --- a/legacy/builder/types/context.go +++ /dev/null @@ -1,29 +0,0 @@ -// This file is part of arduino-cli. -// -// Copyright 2020 ARDUINO SA (http://www.arduino.cc/) -// -// This software is released under the GNU General Public License version 3, -// which covers the main part of arduino-cli. -// The terms of this license can be found at: -// https://www.gnu.org/licenses/gpl-3.0.en.html -// -// You can be released from the requirements of the above licenses by purchasing -// a commercial license. Buying such a license is mandatory if you want to -// modify or otherwise use the software for commercial activities involving the -// Arduino software without disclosing the source code of your own applications. -// To purchase a commercial license, send an email to license@arduino.cc. - -package types - -import ( - "github.com/arduino/arduino-cli/arduino/builder" - "github.com/arduino/arduino-cli/arduino/builder/detector" - "github.com/arduino/arduino-cli/arduino/builder/logger" -) - -// Context structure -type Context struct { - Builder *builder.Builder - SketchLibrariesDetector *detector.SketchLibrariesDetector - BuilderLogger *logger.BuilderLogger -} diff --git a/legacy/builder/types/types.go b/legacy/builder/types/types.go deleted file mode 100644 index 8678fd2fe51..00000000000 --- a/legacy/builder/types/types.go +++ /dev/null @@ -1,26 +0,0 @@ -// This file is part of arduino-cli. -// -// Copyright 2020 ARDUINO SA (http://www.arduino.cc/) -// -// This software is released under the GNU General Public License version 3, -// which covers the main part of arduino-cli. -// The terms of this license can be found at: -// https://www.gnu.org/licenses/gpl-3.0.en.html -// -// You can be released from the requirements of the above licenses by purchasing -// a commercial license. Buying such a license is mandatory if you want to -// modify or otherwise use the software for commercial activities involving the -// Arduino software without disclosing the source code of your own applications. -// To purchase a commercial license, send an email to license@arduino.cc. - -package types - -type Command interface { - Run(ctx *Context) error -} - -type BareCommand func(ctx *Context) error - -func (cmd BareCommand) Run(ctx *Context) error { - return cmd(ctx) -}