diff --git a/commands/service_compile.go b/commands/service_compile.go index a71195382cf..24cbfd52b2c 100644 --- a/commands/service_compile.go +++ b/commands/service_compile.go @@ -28,6 +28,7 @@ import ( "github.com/arduino/arduino-cli/commands/cmderrors" "github.com/arduino/arduino-cli/commands/internal/instances" "github.com/arduino/arduino-cli/internal/arduino/builder" + "github.com/arduino/arduino-cli/internal/arduino/builder/logger" "github.com/arduino/arduino-cli/internal/arduino/libraries/librariesmanager" "github.com/arduino/arduino-cli/internal/arduino/sketch" "github.com/arduino/arduino-cli/internal/arduino/utils" @@ -244,6 +245,13 @@ func (s *arduinoCoreServerImpl) Compile(req *rpc.CompileRequest, stream rpc.Ardu Message: &rpc.CompileResponse_Progress{Progress: p}, }) } + var verbosity logger.Verbosity = logger.VerbosityNormal + if req.GetQuiet() { + verbosity = logger.VerbosityQuiet + } + if req.GetVerbose() { + verbosity = logger.VerbosityVerbose + } sketchBuilder, err := builder.NewBuilder( ctx, sk, @@ -265,7 +273,7 @@ func (s *arduinoCoreServerImpl) Compile(req *rpc.CompileRequest, stream rpc.Ardu req.GetSkipLibrariesDiscovery(), libsManager, paths.NewPathList(req.GetLibrary()...), - outStream, errStream, req.GetVerbose(), req.GetWarnings(), + outStream, errStream, verbosity, req.GetWarnings(), progressCB, pme.GetEnvVarsForSpawnedProcess(), ) diff --git a/internal/arduino/builder/archive_compiled_files.go b/internal/arduino/builder/archive_compiled_files.go index ed87225e2ff..32208a59092 100644 --- a/internal/arduino/builder/archive_compiled_files.go +++ b/internal/arduino/builder/archive_compiled_files.go @@ -16,6 +16,7 @@ package builder import ( + "github.com/arduino/arduino-cli/internal/arduino/builder/logger" "github.com/arduino/arduino-cli/internal/i18n" "github.com/arduino/go-paths-helper" ) @@ -23,7 +24,7 @@ import ( // ArchiveCompiledFiles fixdoc func (b *Builder) archiveCompiledFiles(archiveFilePath *paths.Path, objectFilesToArchive paths.PathList) (*paths.Path, error) { if b.onlyUpdateCompilationDatabase { - if b.logger.Verbose() { + if b.logger.VerbosityLevel() == logger.VerbosityVerbose { b.logger.Info(i18n.Tr("Skipping archive creation of: %[1]s", archiveFilePath)) } return archiveFilePath, nil @@ -46,7 +47,7 @@ func (b *Builder) archiveCompiledFiles(archiveFilePath *paths.Path, objectFilesT return nil, err } } else { - if b.logger.Verbose() { + if b.logger.VerbosityLevel() == logger.VerbosityVerbose { b.logger.Info(i18n.Tr("Using previously compiled file: %[1]s", archiveFilePath)) } return archiveFilePath, nil diff --git a/internal/arduino/builder/builder.go b/internal/arduino/builder/builder.go index 58d607c827a..0c711273a5d 100644 --- a/internal/arduino/builder/builder.go +++ b/internal/arduino/builder/builder.go @@ -27,9 +27,9 @@ import ( "github.com/arduino/arduino-cli/internal/arduino/builder/internal/compilation" "github.com/arduino/arduino-cli/internal/arduino/builder/internal/detector" "github.com/arduino/arduino-cli/internal/arduino/builder/internal/diagnostics" - "github.com/arduino/arduino-cli/internal/arduino/builder/internal/logger" "github.com/arduino/arduino-cli/internal/arduino/builder/internal/progress" "github.com/arduino/arduino-cli/internal/arduino/builder/internal/utils" + "github.com/arduino/arduino-cli/internal/arduino/builder/logger" "github.com/arduino/arduino-cli/internal/arduino/cores" "github.com/arduino/arduino-cli/internal/arduino/libraries" "github.com/arduino/arduino-cli/internal/arduino/libraries/librariesmanager" @@ -136,7 +136,7 @@ func NewBuilder( useCachedLibrariesResolution bool, librariesManager *librariesmanager.LibrariesManager, libraryDirs paths.PathList, - stdout, stderr io.Writer, verbose bool, warningsLevel string, + stdout, stderr io.Writer, verbosity logger.Verbosity, warningsLevel string, progresCB rpc.TaskProgressCB, toolEnv []string, ) (*Builder, error) { @@ -189,7 +189,7 @@ func NewBuilder( return nil, ErrSketchCannotBeLocatedInBuildPath } - logger := logger.New(stdout, stderr, verbose, warningsLevel) + log := logger.New(stdout, stderr, verbosity, warningsLevel) libsManager, libsResolver, verboseOut, err := detector.LibrariesLoader( useCachedLibrariesResolution, librariesManager, builtInLibrariesDirs, libraryDirs, otherLibrariesDirs, @@ -198,8 +198,8 @@ func NewBuilder( if err != nil { return nil, err } - if logger.Verbose() { - logger.Warn(string(verboseOut)) + if log.VerbosityLevel() == logger.VerbosityVerbose { + log.Warn(string(verboseOut)) } diagnosticStore := diagnostics.NewStore() @@ -215,7 +215,7 @@ func NewBuilder( customBuildProperties: customBuildPropertiesArgs, coreBuildCachePath: coreBuildCachePath, extraCoreBuildCachePaths: extraCoreBuildCachePaths, - logger: logger, + logger: log, clean: clean, sourceOverrides: sourceOverrides, onlyUpdateCompilationDatabase: onlyUpdateCompilationDatabase, @@ -242,7 +242,7 @@ func NewBuilder( libsManager, libsResolver, useCachedLibrariesResolution, onlyUpdateCompilationDatabase, - logger, + log, diagnosticStore, ), } @@ -341,7 +341,7 @@ func (b *Builder) preprocess() error { } func (b *Builder) logIfVerbose(warn bool, msg string) { - if !b.logger.Verbose() { + if b.logger.VerbosityLevel() != logger.VerbosityVerbose { return } if warn { @@ -526,7 +526,7 @@ func (b *Builder) prepareCommandForRecipe(buildProperties *properties.Map, recip } func (b *Builder) execCommand(command *paths.Process) error { - if b.logger.Verbose() { + if b.logger.VerbosityLevel() == logger.VerbosityVerbose { b.logger.Info(utils.PrintableCommand(command.GetArgs())) command.RedirectStdoutTo(b.logger.Stdout()) } diff --git a/internal/arduino/builder/compilation.go b/internal/arduino/builder/compilation.go index d3a1459da25..c739a2e37de 100644 --- a/internal/arduino/builder/compilation.go +++ b/internal/arduino/builder/compilation.go @@ -23,6 +23,7 @@ import ( "sync" "github.com/arduino/arduino-cli/internal/arduino/builder/internal/utils" + "github.com/arduino/arduino-cli/internal/arduino/builder/logger" "github.com/arduino/arduino-cli/internal/arduino/globals" "github.com/arduino/arduino-cli/internal/i18n" "github.com/arduino/go-paths-helper" @@ -152,7 +153,7 @@ func (b *Builder) compileFileWithRecipe( command.RedirectStdoutTo(commandStdout) command.RedirectStderrTo(commandStderr) - if b.logger.Verbose() { + if b.logger.VerbosityLevel() == logger.VerbosityVerbose { b.logger.Info(utils.PrintableCommand(command.GetArgs())) } // Since this compile could be multithreaded, we first capture the command output @@ -161,7 +162,7 @@ func (b *Builder) compileFileWithRecipe( } err := command.Wait() // and transfer all at once at the end... - if b.logger.Verbose() { + if b.logger.VerbosityLevel() == logger.VerbosityVerbose { b.logger.WriteStdout(commandStdout.Bytes()) } b.logger.WriteStderr(commandStderr.Bytes()) @@ -176,7 +177,7 @@ func (b *Builder) compileFileWithRecipe( if err != nil { return nil, err } - } else if b.logger.Verbose() { + } else if b.logger.VerbosityLevel() == logger.VerbosityVerbose { if objIsUpToDate { b.logger.Info(i18n.Tr("Using previously compiled file: %[1]s", objectFile)) } else { diff --git a/internal/arduino/builder/core.go b/internal/arduino/builder/core.go index f541eaeda41..c6d87ec7d66 100644 --- a/internal/arduino/builder/core.go +++ b/internal/arduino/builder/core.go @@ -24,6 +24,7 @@ import ( "github.com/arduino/arduino-cli/internal/arduino/builder/cpp" "github.com/arduino/arduino-cli/internal/arduino/builder/internal/utils" + "github.com/arduino/arduino-cli/internal/arduino/builder/logger" "github.com/arduino/arduino-cli/internal/buildcache" "github.com/arduino/arduino-cli/internal/i18n" "github.com/arduino/go-paths-helper" @@ -116,7 +117,7 @@ func (b *Builder) compileCore() (*paths.Path, paths.PathList, error) { return nil, nil, errors.New(i18n.Tr("creating core cache folder: %s", err)) } // use archived core - if b.logger.Verbose() { + if b.logger.VerbosityLevel() == logger.VerbosityVerbose { b.logger.Info(i18n.Tr("Using precompiled core: %[1]s", targetArchivedCore)) } return targetArchivedCore, variantObjectFiles, nil @@ -128,7 +129,7 @@ func (b *Builder) compileCore() (*paths.Path, paths.PathList, error) { extraTargetArchivedCore := extraCoreBuildCachePath.Join(archivedCoreName, "core.a") if canUseArchivedCore(extraTargetArchivedCore) { // use archived core - if b.logger.Verbose() { + if b.logger.VerbosityLevel() == logger.VerbosityVerbose { b.logger.Info(i18n.Tr("Using precompiled core: %[1]s", extraTargetArchivedCore)) } return extraTargetArchivedCore, variantObjectFiles, nil @@ -158,7 +159,7 @@ func (b *Builder) compileCore() (*paths.Path, paths.PathList, error) { // archive core.a if targetArchivedCore != nil && !b.onlyUpdateCompilationDatabase { err := archiveFile.CopyTo(targetArchivedCore) - if b.logger.Verbose() { + if b.logger.VerbosityLevel() == logger.VerbosityVerbose { if err == nil { b.logger.Info(i18n.Tr("Archiving built core (caching) in: %[1]s", targetArchivedCore)) } else if os.IsNotExist(err) { diff --git a/internal/arduino/builder/internal/detector/detector.go b/internal/arduino/builder/internal/detector/detector.go index eb3d887d3fe..a983370b075 100644 --- a/internal/arduino/builder/internal/detector/detector.go +++ b/internal/arduino/builder/internal/detector/detector.go @@ -28,9 +28,9 @@ import ( "time" "github.com/arduino/arduino-cli/internal/arduino/builder/internal/diagnostics" - "github.com/arduino/arduino-cli/internal/arduino/builder/internal/logger" "github.com/arduino/arduino-cli/internal/arduino/builder/internal/preprocessor" "github.com/arduino/arduino-cli/internal/arduino/builder/internal/utils" + "github.com/arduino/arduino-cli/internal/arduino/builder/logger" "github.com/arduino/arduino-cli/internal/arduino/cores" "github.com/arduino/arduino-cli/internal/arduino/globals" "github.com/arduino/arduino-cli/internal/arduino/libraries" @@ -87,7 +87,7 @@ func (l *SketchLibrariesDetector) resolveLibrary(header, platformArch string) *l importedLibraries := l.importedLibraries candidates := l.librariesResolver.AlternativesFor(header) - if l.logger.Verbose() { + if l.logger.VerbosityLevel() == logger.VerbosityVerbose { l.logger.Info(i18n.Tr("Alternatives for %[1]s: %[2]s", header, candidates)) l.logger.Info(fmt.Sprintf("ResolveLibrary(%s)", header)) l.logger.Info(fmt.Sprintf(" -> %s: %s", i18n.Tr("candidates"), candidates)) @@ -144,7 +144,7 @@ func (l *SketchLibrariesDetector) PrintUsedAndNotUsedLibraries(sketchError bool) // - as warning, when the sketch didn't compile // - as info, when verbose is on // - otherwise, output nothing - if !sketchError && !l.logger.Verbose() { + if !sketchError && l.logger.VerbosityLevel() != logger.VerbosityVerbose { return } @@ -239,7 +239,7 @@ func (l *SketchLibrariesDetector) findIncludes( if err := json.Unmarshal(d, &l.includeFolders); err != nil { return err } - if l.logger.Verbose() { + if l.logger.VerbosityLevel() == logger.VerbosityVerbose { l.logger.Info("Using cached library discovery: " + librariesResolutionCache.String()) } return nil @@ -347,12 +347,12 @@ func (l *SketchLibrariesDetector) findIncludesUntilDone( var missingIncludeH string if unchanged && cache.valid { missingIncludeH = cache.Next().Include - if first && l.logger.Verbose() { + if first && l.logger.VerbosityLevel() == logger.VerbosityVerbose { l.logger.Info(i18n.Tr("Using cached library dependencies for file: %[1]s", sourcePath)) } } else { preprocFirstResult, preprocErr = preprocessor.GCC(ctx, sourcePath, targetFilePath, includeFolders, buildProperties) - if l.logger.Verbose() { + if l.logger.VerbosityLevel() == logger.VerbosityVerbose { l.logger.WriteStdout(preprocFirstResult.Stdout()) } // Unwrap error and see if it is an ExitError. @@ -365,7 +365,7 @@ func (l *SketchLibrariesDetector) findIncludesUntilDone( return preprocErr } else { missingIncludeH = IncludesFinderWithRegExp(string(preprocFirstResult.Stderr())) - if missingIncludeH == "" && l.logger.Verbose() { + if missingIncludeH == "" && l.logger.VerbosityLevel() == logger.VerbosityVerbose { l.logger.Info(i18n.Tr("Error while detecting libraries included by %[1]s", sourcePath)) } } @@ -383,7 +383,7 @@ func (l *SketchLibrariesDetector) findIncludesUntilDone( if preprocErr == nil || preprocFirstResult.Stderr() == nil { // Filename came from cache, so run preprocessor to obtain error to show result, err := preprocessor.GCC(ctx, sourcePath, targetFilePath, includeFolders, buildProperties) - if l.logger.Verbose() { + if l.logger.VerbosityLevel() == logger.VerbosityVerbose { l.logger.WriteStdout(result.Stdout()) } if err == nil { @@ -410,7 +410,7 @@ func (l *SketchLibrariesDetector) findIncludesUntilDone( if library.Precompiled && library.PrecompiledWithSources { // Fully precompiled libraries should have no dependencies to avoid ABI breakage - if l.logger.Verbose() { + if l.logger.VerbosityLevel() == logger.VerbosityVerbose { l.logger.Info(i18n.Tr("Skipping dependencies detection for precompiled library %[1]s", library.Name)) } } else { diff --git a/internal/arduino/builder/internal/preprocessor/ctags.go b/internal/arduino/builder/internal/preprocessor/ctags.go index fe36cfc89e5..c77d22e783b 100644 --- a/internal/arduino/builder/internal/preprocessor/ctags.go +++ b/internal/arduino/builder/internal/preprocessor/ctags.go @@ -83,8 +83,9 @@ func PreprocessSketchWithCtags( } // Run CTags on gcc-preprocessed source - ctagsOutput, ctagsStdErr, err := RunCTags(ctx, ctagsTarget, buildProperties) + ctagsOutput, ctagsStdErr, ctagsCmdLine, err := RunCTags(ctx, ctagsTarget, buildProperties) if verbose { + stdout.Write([]byte(ctagsCmdLine + "\n")) stderr.Write(ctagsStdErr) } if err != nil { @@ -178,7 +179,7 @@ func isFirstFunctionOutsideOfSource(firstFunctionLine int, sourceRows []string) } // RunCTags performs a run of ctags on the given source file. Returns the ctags output and the stderr contents. -func RunCTags(ctx context.Context, sourceFile *paths.Path, buildProperties *properties.Map) ([]byte, []byte, error) { +func RunCTags(ctx context.Context, sourceFile *paths.Path, buildProperties *properties.Map) ([]byte, []byte, string, error) { ctagsBuildProperties := properties.NewMap() ctagsBuildProperties.Set("tools.ctags.path", "{runtime.tools.ctags.path}") ctagsBuildProperties.Set("tools.ctags.cmd.path", "{path}/ctags") @@ -189,24 +190,22 @@ func RunCTags(ctx context.Context, sourceFile *paths.Path, buildProperties *prop pattern := ctagsBuildProperties.Get("pattern") if pattern == "" { - return nil, nil, errors.New(i18n.Tr("%s pattern is missing", "ctags")) + return nil, nil, "", errors.New(i18n.Tr("%s pattern is missing", "ctags")) } commandLine := ctagsBuildProperties.ExpandPropsInString(pattern) parts, err := properties.SplitQuotedString(commandLine, `"'`, false) if err != nil { - return nil, nil, err + return nil, nil, "", err } proc, err := paths.NewProcess(nil, parts...) if err != nil { - return nil, nil, err + return nil, nil, "", err } stdout, stderr, err := proc.RunAndCaptureOutput(ctx) - // Append ctags arguments to stderr args := fmt.Sprintln(strings.Join(parts, " ")) - stderr = append([]byte(args), stderr...) - return stdout, stderr, err + return stdout, stderr, args, err } func filterSketchSource(sketch *sketch.Sketch, source io.Reader, removeLineMarkers bool) string { diff --git a/internal/arduino/builder/libraries.go b/internal/arduino/builder/libraries.go index 6bb28f96ed2..d2558e4954f 100644 --- a/internal/arduino/builder/libraries.go +++ b/internal/arduino/builder/libraries.go @@ -21,6 +21,7 @@ import ( "time" "github.com/arduino/arduino-cli/internal/arduino/builder/cpp" + "github.com/arduino/arduino-cli/internal/arduino/builder/logger" "github.com/arduino/arduino-cli/internal/arduino/libraries" "github.com/arduino/arduino-cli/internal/i18n" "github.com/arduino/go-paths-helper" @@ -129,7 +130,7 @@ func (b *Builder) compileLibraries(libraries libraries.List, includes []string) } func (b *Builder) compileLibrary(library *libraries.Library, includes []string) (paths.PathList, error) { - if b.logger.Verbose() { + if b.logger.VerbosityLevel() == logger.VerbosityVerbose { b.logger.Info(i18n.Tr(`Compiling library "%[1]s"`, library.Name)) } libraryBuildPath := b.librariesBuildPath.Join(library.DirName) @@ -292,7 +293,7 @@ func (b *Builder) warnAboutArchIncompatibleLibraries(importedLibraries libraries // 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) { - if !b.logger.Verbose() || len(importedLibraries) == 0 { + if b.logger.VerbosityLevel() != logger.VerbosityVerbose || len(importedLibraries) == 0 { return } diff --git a/internal/arduino/builder/linker.go b/internal/arduino/builder/linker.go index 20032608db5..77f450a9182 100644 --- a/internal/arduino/builder/linker.go +++ b/internal/arduino/builder/linker.go @@ -18,6 +18,7 @@ package builder import ( "strings" + "github.com/arduino/arduino-cli/internal/arduino/builder/logger" "github.com/arduino/arduino-cli/internal/i18n" "github.com/arduino/go-paths-helper" "go.bug.st/f" @@ -26,7 +27,7 @@ import ( // link fixdoc func (b *Builder) link() error { if b.onlyUpdateCompilationDatabase { - if b.logger.Verbose() { + if b.logger.VerbosityLevel() == logger.VerbosityVerbose { b.logger.Info(i18n.Tr("Skip linking of final executable.")) } return nil diff --git a/internal/arduino/builder/internal/logger/logger.go b/internal/arduino/builder/logger/logger.go similarity index 76% rename from internal/arduino/builder/internal/logger/logger.go rename to internal/arduino/builder/logger/logger.go index 992c15a25b2..347c98ce9f8 100644 --- a/internal/arduino/builder/internal/logger/logger.go +++ b/internal/arduino/builder/logger/logger.go @@ -22,18 +22,27 @@ import ( "sync" ) +// Verbosity is the verbosity level of the Logger +type Verbosity int + +const ( + VerbosityQuiet Verbosity = -1 + VerbosityNormal Verbosity = 0 + VerbosityVerbose Verbosity = 1 +) + // BuilderLogger fixdoc type BuilderLogger struct { stdLock sync.Mutex stdout io.Writer stderr io.Writer - verbose bool + verbosity Verbosity warningsLevel string } -// New fixdoc -func New(stdout, stderr io.Writer, verbose bool, warningsLevel string) *BuilderLogger { +// New creates a new Logger to the given output streams with the specified verbosity and warnings level +func New(stdout, stderr io.Writer, verbosity Verbosity, warningsLevel string) *BuilderLogger { if stdout == nil { stdout = os.Stdout } @@ -46,13 +55,16 @@ func New(stdout, stderr io.Writer, verbose bool, warningsLevel string) *BuilderL return &BuilderLogger{ stdout: stdout, stderr: stderr, - verbose: verbose, + verbosity: verbosity, warningsLevel: warningsLevel, } } // Info fixdoc func (l *BuilderLogger) Info(msg string) { + if msg == "" { + return + } l.stdLock.Lock() defer l.stdLock.Unlock() fmt.Fprintln(l.stdout, msg) @@ -60,6 +72,9 @@ func (l *BuilderLogger) Info(msg string) { // Warn fixdoc func (l *BuilderLogger) Warn(msg string) { + if msg == "" { + return + } l.stdLock.Lock() defer l.stdLock.Unlock() fmt.Fprintln(l.stderr, msg) @@ -79,9 +94,9 @@ func (l *BuilderLogger) WriteStderr(data []byte) (int, error) { return l.stderr.Write(data) } -// Verbose fixdoc -func (l *BuilderLogger) Verbose() bool { - return l.verbose +// VerbosityLevel returns the verbosity level of the logger +func (l *BuilderLogger) VerbosityLevel() Verbosity { + return l.verbosity } // WarningsLevel fixdoc diff --git a/internal/arduino/builder/preprocess_sketch.go b/internal/arduino/builder/preprocess_sketch.go index b7fe178db02..290b2963664 100644 --- a/internal/arduino/builder/preprocess_sketch.go +++ b/internal/arduino/builder/preprocess_sketch.go @@ -17,6 +17,7 @@ package builder import ( "github.com/arduino/arduino-cli/internal/arduino/builder/internal/preprocessor" + "github.com/arduino/arduino-cli/internal/arduino/builder/logger" "github.com/arduino/go-paths-helper" ) @@ -26,10 +27,11 @@ func (b *Builder) preprocessSketch(includes paths.PathList) error { result, err := preprocessor.PreprocessSketchWithCtags( b.ctx, b.sketch, b.buildPath, includes, b.lineOffset, - b.buildProperties, b.onlyUpdateCompilationDatabase, b.logger.Verbose(), + b.buildProperties, b.onlyUpdateCompilationDatabase, + b.logger.VerbosityLevel() == logger.VerbosityVerbose, ) if result != nil { - if b.logger.Verbose() { + if b.logger.VerbosityLevel() == logger.VerbosityVerbose { b.logger.WriteStdout(result.Stdout()) } b.logger.WriteStderr(result.Stderr()) diff --git a/internal/arduino/builder/recipe.go b/internal/arduino/builder/recipe.go index c8fa8962850..b4c456e360f 100644 --- a/internal/arduino/builder/recipe.go +++ b/internal/arduino/builder/recipe.go @@ -19,6 +19,7 @@ import ( "sort" "strings" + "github.com/arduino/arduino-cli/internal/arduino/builder/logger" "github.com/arduino/arduino-cli/internal/i18n" properties "github.com/arduino/go-properties-orderedmap" "github.com/sirupsen/logrus" @@ -43,7 +44,7 @@ func (b *Builder) RunRecipe(prefix, suffix string, skipIfOnlyUpdatingCompilation } if b.onlyUpdateCompilationDatabase && skipIfOnlyUpdatingCompilationDatabase { - if b.logger.Verbose() { + if b.logger.VerbosityLevel() == logger.VerbosityVerbose { b.logger.Info(i18n.Tr("Skipping: %[1]s", strings.Join(command.GetArgs(), " "))) } return nil diff --git a/internal/arduino/builder/sizer.go b/internal/arduino/builder/sizer.go index 84cf8012a32..ae188b48f2b 100644 --- a/internal/arduino/builder/sizer.go +++ b/internal/arduino/builder/sizer.go @@ -24,6 +24,7 @@ import ( "strconv" "github.com/arduino/arduino-cli/internal/arduino/builder/internal/utils" + "github.com/arduino/arduino-cli/internal/arduino/builder/logger" "github.com/arduino/arduino-cli/internal/i18n" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/arduino/go-properties-orderedmap" @@ -78,7 +79,7 @@ func (b *Builder) checkSizeAdvanced() (ExecutablesFileSections, error) { if err != nil { return nil, errors.New(i18n.Tr("Error while determining sketch size: %s", err)) } - if b.logger.Verbose() { + if b.logger.VerbosityLevel() == logger.VerbosityVerbose { b.logger.Info(utils.PrintableCommand(command.GetArgs())) } out := &bytes.Buffer{} @@ -155,19 +156,21 @@ func (b *Builder) checkSize() (ExecutablesFileSections, error) { return nil, nil } - b.logger.Info(i18n.Tr("Sketch uses %[1]s bytes (%[3]s%%) of program storage space. Maximum is %[2]s bytes.", - strconv.Itoa(textSize), - strconv.Itoa(maxTextSize), - strconv.Itoa(textSize*100/maxTextSize))) - if dataSize >= 0 { - if maxDataSize > 0 { - b.logger.Info(i18n.Tr("Global variables use %[1]s bytes (%[3]s%%) of dynamic memory, leaving %[4]s bytes for local variables. Maximum is %[2]s bytes.", - strconv.Itoa(dataSize), - strconv.Itoa(maxDataSize), - strconv.Itoa(dataSize*100/maxDataSize), - strconv.Itoa(maxDataSize-dataSize))) - } else { - b.logger.Info(i18n.Tr("Global variables use %[1]s bytes of dynamic memory.", strconv.Itoa(dataSize))) + if b.logger.VerbosityLevel() > logger.VerbosityQuiet { + b.logger.Info(i18n.Tr("Sketch uses %[1]s bytes (%[3]s%%) of program storage space. Maximum is %[2]s bytes.", + strconv.Itoa(textSize), + strconv.Itoa(maxTextSize), + strconv.Itoa(textSize*100/maxTextSize))) + if dataSize >= 0 { + if maxDataSize > 0 { + b.logger.Info(i18n.Tr("Global variables use %[1]s bytes (%[3]s%%) of dynamic memory, leaving %[4]s bytes for local variables. Maximum is %[2]s bytes.", + strconv.Itoa(dataSize), + strconv.Itoa(maxDataSize), + strconv.Itoa(dataSize*100/maxDataSize), + strconv.Itoa(maxDataSize-dataSize))) + } else { + b.logger.Info(i18n.Tr("Global variables use %[1]s bytes of dynamic memory.", strconv.Itoa(dataSize))) + } } } @@ -215,7 +218,7 @@ func (b *Builder) execSizeRecipe(properties *properties.Map) (textSize int, data resErr = errors.New(i18n.Tr("Error while determining sketch size: %s", err)) return } - if b.logger.Verbose() { + if b.logger.VerbosityLevel() == logger.VerbosityVerbose { b.logger.Info(utils.PrintableCommand(command.GetArgs())) } commandStdout := &bytes.Buffer{} diff --git a/internal/arduino/builder/sketch.go b/internal/arduino/builder/sketch.go index 1f64d207c81..76e77f4c8e8 100644 --- a/internal/arduino/builder/sketch.go +++ b/internal/arduino/builder/sketch.go @@ -26,6 +26,7 @@ import ( "fortio.org/safecast" "github.com/arduino/arduino-cli/internal/arduino/builder/cpp" + "github.com/arduino/arduino-cli/internal/arduino/builder/logger" "github.com/arduino/arduino-cli/internal/i18n" "github.com/arduino/go-paths-helper" "github.com/marcinbor85/gohex" @@ -240,7 +241,7 @@ func (b *Builder) mergeSketchWithBootloader() error { bootloaderPath := b.buildProperties.GetPath("runtime.platform.path").Join("bootloaders", bootloader) if bootloaderPath.NotExist() { - if b.logger.Verbose() { + if b.logger.VerbosityLevel() == logger.VerbosityVerbose { b.logger.Warn(i18n.Tr("Bootloader file specified but missing: %[1]s", bootloaderPath)) } return nil @@ -255,7 +256,7 @@ func (b *Builder) mergeSketchWithBootloader() error { maximumBinSize *= 2 } err := merge(builtSketchPath, bootloaderPath, mergedSketchPath, maximumBinSize) - if err != nil && b.logger.Verbose() { + if err != nil && b.logger.VerbosityLevel() == logger.VerbosityVerbose { b.logger.Info(err.Error()) } diff --git a/internal/cli/compile/compile.go b/internal/cli/compile/compile.go index 5cccf62ad46..69ec3d52966 100644 --- a/internal/cli/compile/compile.go +++ b/internal/cli/compile/compile.go @@ -85,6 +85,9 @@ func NewCommand(srv rpc.ArduinoCoreServiceServer, settings *rpc.Configuration) * " " + os.Args[0] + ` compile -b arduino:avr:uno --build-property "build.extra_flags=-DPIN=2 \"-DMY_DEFINE=\"hello world\"\"" /home/user/Arduino/MySketch` + "\n" + " " + os.Args[0] + ` compile -b arduino:avr:uno --build-property build.extra_flags=-DPIN=2 --build-property "compiler.cpp.extra_flags=\"-DSSID=\"hello world\"\"" /home/user/Arduino/MySketch` + "\n", Args: cobra.MaximumNArgs(1), + PreRun: func(cmd *cobra.Command, args []string) { + arguments.CheckFlagsConflicts(cmd, "quiet", "verbose") + }, Run: func(cmd *cobra.Command, args []string) { if cmd.Flag("build-cache-path").Changed { feedback.Warning(i18n.Tr("The flag --build-cache-path has been deprecated. Please use just --build-path alone or configure the build cache path in the Arduino CLI settings.")) @@ -116,7 +119,7 @@ func NewCommand(srv rpc.ArduinoCoreServiceServer, settings *rpc.Configuration) * compileCommand.Flags().StringVar(&warnings, "warnings", "none", i18n.Tr(`Optional, can be: %s. Used to tell gcc which warning level to use (-W flag).`, "none, default, more, all")) compileCommand.Flags().BoolVarP(&verbose, "verbose", "v", false, i18n.Tr("Optional, turns on verbose mode.")) - compileCommand.Flags().BoolVar(&quiet, "quiet", false, i18n.Tr("Optional, suppresses almost every output.")) + compileCommand.Flags().BoolVarP(&quiet, "quiet", "q", false, i18n.Tr("Optional, suppresses almost every output.")) compileCommand.Flags().BoolVarP(&uploadAfterCompile, "upload", "u", false, i18n.Tr("Upload the binary after the compilation.")) portArgs.AddToCommand(compileCommand, srv) compileCommand.Flags().BoolVarP(&verify, "verify", "t", false, i18n.Tr("Verify uploaded binary after the upload.")) @@ -362,6 +365,7 @@ func runCompileCommand(cmd *cobra.Command, args []string, srv rpc.ArduinoCoreSer } stdIO := stdIORes() + successful := (compileError == nil) res := &compileResult{ CompilerOut: stdIO.Stdout, CompilerErr: stdIO.Stderr, @@ -370,9 +374,9 @@ func runCompileCommand(cmd *cobra.Command, args []string, srv rpc.ArduinoCoreSer UpdatedUploadPort: result.NewPort(uploadRes.GetUpdatedUploadPort()), }, ProfileOut: profileOut, - Success: compileError == nil, + Success: successful, showPropertiesMode: showProperties, - hideStats: preprocess, + hideStats: preprocess || quiet || (!verbose && successful), } if compileError != nil { diff --git a/internal/integrationtest/compile_3/compile_verbosity_test.go b/internal/integrationtest/compile_3/compile_verbosity_test.go new file mode 100644 index 00000000000..db87afa7562 --- /dev/null +++ b/internal/integrationtest/compile_3/compile_verbosity_test.go @@ -0,0 +1,103 @@ +// This file is part of arduino-cli. +// +// Copyright 2022 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 compile_test + +import ( + "testing" + + "github.com/arduino/arduino-cli/internal/integrationtest" + "github.com/arduino/go-paths-helper" + "github.com/stretchr/testify/require" +) + +func TestCompileVerbosity(t *testing.T) { + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + + _, _, err := cli.Run("core", "update-index") + require.NoError(t, err) + _, _, err = cli.Run("core", "install", "arduino:avr") + require.NoError(t, err) + + goodSketch, err := paths.New("testdata", "bare_minimum").Abs() + require.NoError(t, err) + badSketch, err := paths.New("testdata", "blink_with_error_directive").Abs() + require.NoError(t, err) + + hasSketchSize := func(t *testing.T, out []byte) { + require.Contains(t, string(out), "Sketch uses") + } + noSketchSize := func(t *testing.T, out []byte) { + require.NotContains(t, string(out), "Sketch uses") + } + hasRecapTable := func(t *testing.T, out []byte) { + require.Contains(t, string(out), "Used platform") + } + noRecapTable := func(t *testing.T, out []byte) { + require.NotContains(t, string(out), "Used platform") + } + + t.Run("DefaultVerbosity/SuccessfulBuild", func(t *testing.T) { + stdout, stderr, err := cli.Run("compile", "--fqbn", "arduino:avr:uno", goodSketch.String()) + require.NoError(t, err) + hasSketchSize(t, stdout) + noRecapTable(t, stdout) + require.Empty(t, stderr) + }) + + t.Run("DefaultVerbosity/BuildWithErrors", func(t *testing.T) { + stdout, stderr, err := cli.Run("compile", "--fqbn", "arduino:avr:uno", badSketch.String()) + require.Error(t, err) + hasRecapTable(t, stdout) + require.NotEmpty(t, stderr) + }) + + t.Run("VerboseVerbosity/SuccessfulBuild", func(t *testing.T) { + stdout, stderr, err := cli.Run("compile", "--fqbn", "arduino:avr:uno", "-v", goodSketch.String()) + require.NoError(t, err) + hasSketchSize(t, stdout) + hasRecapTable(t, stdout) + require.Empty(t, stderr) + }) + + t.Run("VerboseVerbosity/BuildWithErrors", func(t *testing.T) { + stdout, stderr, err := cli.Run("compile", "--fqbn", "arduino:avr:uno", "-v", badSketch.String()) + require.Error(t, err) + hasRecapTable(t, stdout) + require.NotEmpty(t, stderr) + }) + + t.Run("QuietVerbosity/SuccessfulBuild", func(t *testing.T) { + stdout, stderr, err := cli.Run("compile", "--fqbn", "arduino:avr:uno", "-q", goodSketch.String()) + require.NoError(t, err) + noSketchSize(t, stdout) + noRecapTable(t, stdout) + require.Empty(t, stdout) // Empty output + require.Empty(t, stderr) + }) + + t.Run("QuietVerbosity/BuildWithErrors", func(t *testing.T) { + stdout, stderr, err := cli.Run("compile", "--fqbn", "arduino:avr:uno", "-q", badSketch.String()) + require.Error(t, err) + noRecapTable(t, stdout) + require.NotEmpty(t, stderr) + }) + + t.Run("ConflictingVerbosityOptions", func(t *testing.T) { + _, _, err := cli.Run("compile", "--fqbn", "arduino:avr:uno", "-v", "-q", goodSketch.String()) + require.Error(t, err) + }) +}
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: