Skip to content

Commit b9edb78

Browse files
authored
bugfix: compile ... --dump-profile now produces a clean output (only the profile) (#2852)
* Output a clean profile with --dump-profile * Use bytes.NewBuffer for creation of bytes buffers * Added integration test
1 parent 079a28f commit b9edb78

File tree

6 files changed

+140
-52
lines changed

6 files changed

+140
-52
lines changed

internal/cli/compile/compile.go

Lines changed: 61 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,9 @@ func runCompileCommand(cmd *cobra.Command, args []string, srv rpc.ArduinoCoreSer
211211

212212
var stdOut, stdErr io.Writer
213213
var stdIORes func() *feedback.OutputStreamsResult
214-
if showProperties != arguments.ShowPropertiesDisabled {
214+
if showProperties != arguments.ShowPropertiesDisabled || dumpProfile {
215+
// When dumping profile or showing properties, we buffer the output
216+
// to avoid mixing compilation output with profile/properties output
215217
stdOut, stdErr, stdIORes = feedback.NewBufferedStreams()
216218
} else {
217219
stdOut, stdErr, stdIORes = feedback.OutputStreams()
@@ -312,60 +314,69 @@ func runCompileCommand(cmd *cobra.Command, args []string, srv rpc.ArduinoCoreSer
312314
}
313315
}
314316

317+
successful := (compileError == nil)
315318
profileOut := ""
316-
if dumpProfile && compileError == nil {
317-
// Output profile
318-
319-
libs := ""
320-
hasVendoredLibs := false
321-
for _, lib := range builderRes.GetUsedLibraries() {
322-
if lib.GetLocation() != rpc.LibraryLocation_LIBRARY_LOCATION_USER && lib.GetLocation() != rpc.LibraryLocation_LIBRARY_LOCATION_UNMANAGED {
323-
continue
319+
stdIO := stdIORes()
320+
321+
if dumpProfile {
322+
if successful {
323+
// Output profile
324+
325+
libs := ""
326+
hasVendoredLibs := false
327+
for _, lib := range builderRes.GetUsedLibraries() {
328+
if lib.GetLocation() != rpc.LibraryLocation_LIBRARY_LOCATION_USER && lib.GetLocation() != rpc.LibraryLocation_LIBRARY_LOCATION_UNMANAGED {
329+
continue
330+
}
331+
if lib.GetVersion() == "" {
332+
hasVendoredLibs = true
333+
continue
334+
}
335+
libs += fmt.Sprintln(" - " + lib.GetName() + " (" + lib.GetVersion() + ")")
324336
}
325-
if lib.GetVersion() == "" {
326-
hasVendoredLibs = true
327-
continue
337+
if hasVendoredLibs {
338+
msg := "\n"
339+
msg += i18n.Tr("WARNING: The sketch is compiled using one or more custom libraries.") + "\n"
340+
msg += i18n.Tr("Currently, Build Profiles only support libraries available through Arduino Library Manager.")
341+
feedback.Warning(msg)
328342
}
329-
libs += fmt.Sprintln(" - " + lib.GetName() + " (" + lib.GetVersion() + ")")
330-
}
331-
if hasVendoredLibs {
332-
msg := "\n"
333-
msg += i18n.Tr("WARNING: The sketch is compiled using one or more custom libraries.") + "\n"
334-
msg += i18n.Tr("Currently, Build Profiles only support libraries available through Arduino Library Manager.")
335-
feedback.Warning(msg)
336-
}
337-
338-
newProfileName := "my_profile_name"
339-
if split := strings.Split(compileRequest.GetFqbn(), ":"); len(split) > 2 {
340-
newProfileName = split[2]
341-
}
342-
profileOut = fmt.Sprintln("profiles:")
343-
profileOut += fmt.Sprintln(" " + newProfileName + ":")
344-
profileOut += fmt.Sprintln(" fqbn: " + compileRequest.GetFqbn())
345-
profileOut += fmt.Sprintln(" platforms:")
346-
boardPlatform := builderRes.GetBoardPlatform()
347-
profileOut += fmt.Sprintln(" - platform: " + boardPlatform.GetId() + " (" + boardPlatform.GetVersion() + ")")
348-
if url := boardPlatform.GetPackageUrl(); url != "" {
349-
profileOut += fmt.Sprintln(" platform_index_url: " + url)
350-
}
351343

352-
if buildPlatform := builderRes.GetBuildPlatform(); buildPlatform != nil &&
353-
buildPlatform.GetId() != boardPlatform.GetId() &&
354-
buildPlatform.GetVersion() != boardPlatform.GetVersion() {
355-
profileOut += fmt.Sprintln(" - platform: " + buildPlatform.GetId() + " (" + buildPlatform.GetVersion() + ")")
356-
if url := buildPlatform.GetPackageUrl(); url != "" {
344+
newProfileName := "my_profile_name"
345+
if split := strings.Split(compileRequest.GetFqbn(), ":"); len(split) > 2 {
346+
newProfileName = split[2]
347+
}
348+
profileOut = fmt.Sprintln("profiles:")
349+
profileOut += fmt.Sprintln(" " + newProfileName + ":")
350+
profileOut += fmt.Sprintln(" fqbn: " + compileRequest.GetFqbn())
351+
profileOut += fmt.Sprintln(" platforms:")
352+
boardPlatform := builderRes.GetBoardPlatform()
353+
profileOut += fmt.Sprintln(" - platform: " + boardPlatform.GetId() + " (" + boardPlatform.GetVersion() + ")")
354+
if url := boardPlatform.GetPackageUrl(); url != "" {
357355
profileOut += fmt.Sprintln(" platform_index_url: " + url)
358356
}
357+
358+
if buildPlatform := builderRes.GetBuildPlatform(); buildPlatform != nil &&
359+
buildPlatform.GetId() != boardPlatform.GetId() &&
360+
buildPlatform.GetVersion() != boardPlatform.GetVersion() {
361+
profileOut += fmt.Sprintln(" - platform: " + buildPlatform.GetId() + " (" + buildPlatform.GetVersion() + ")")
362+
if url := buildPlatform.GetPackageUrl(); url != "" {
363+
profileOut += fmt.Sprintln(" platform_index_url: " + url)
364+
}
365+
}
366+
if len(libs) > 0 {
367+
profileOut += fmt.Sprintln(" libraries:")
368+
profileOut += fmt.Sprint(libs)
369+
}
370+
profileOut += fmt.Sprintln()
371+
} else {
372+
// An error occurred, output the buffered build errors instead of the profile
373+
if stdOut, stdErr, err := feedback.DirectStreams(); err == nil {
374+
stdOut.Write([]byte(stdIO.Stdout))
375+
stdErr.Write([]byte(stdIO.Stderr))
376+
}
359377
}
360-
if len(libs) > 0 {
361-
profileOut += fmt.Sprintln(" libraries:")
362-
profileOut += fmt.Sprint(libs)
363-
}
364-
profileOut += fmt.Sprintln()
365378
}
366379

367-
stdIO := stdIORes()
368-
successful := (compileError == nil)
369380
res := &compileResult{
370381
CompilerOut: stdIO.Stdout,
371382
CompilerErr: stdIO.Stderr,
@@ -437,6 +448,10 @@ func (r *compileResult) String() string {
437448
return strings.Join(r.BuilderResult.BuildProperties, fmt.Sprintln())
438449
}
439450

451+
if r.Success && r.ProfileOut != "" {
452+
return r.ProfileOut
453+
}
454+
440455
if r.hideStats {
441456
return ""
442457
}
@@ -485,9 +500,6 @@ func (r *compileResult) String() string {
485500
}
486501
res += fmt.Sprintln(platforms.Render())
487502
}
488-
if r.ProfileOut != "" {
489-
res += fmt.Sprintln(r.ProfileOut)
490-
}
491503
return strings.TrimRight(res, fmt.Sprintln())
492504
}
493505

internal/cli/feedback/feedback.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ func reset() {
8484
stdErr = os.Stderr
8585
feedbackOut = os.Stdout
8686
feedbackErr = os.Stderr
87-
bufferOut = &bytes.Buffer{}
88-
bufferErr = &bytes.Buffer{}
87+
bufferOut = bytes.NewBuffer(nil)
88+
bufferErr = bytes.NewBuffer(nil)
8989
bufferWarnings = nil
9090
format = Text
9191
formatSelected = false

internal/cli/feedback/stdio.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func OutputStreams() (io.Writer, io.Writer, func() *OutputStreamsResult) {
6868
// object that can be used as a Result or to retrieve the accumulated output
6969
// to embed it in another object.
7070
func NewBufferedStreams() (io.Writer, io.Writer, func() *OutputStreamsResult) {
71-
out, err := &bytes.Buffer{}, &bytes.Buffer{}
71+
out, err := bytes.NewBuffer(nil), bytes.NewBuffer(nil)
7272
return out, err, func() *OutputStreamsResult {
7373
return &OutputStreamsResult{
7474
Stdout: out.String(),
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// This file is part of arduino-cli.
2+
//
3+
// Copyright 2023 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This software is released under the GNU General Public License version 3,
6+
// which covers the main part of arduino-cli.
7+
// The terms of this license can be found at:
8+
// https://www.gnu.org/licenses/gpl-3.0.en.html
9+
//
10+
// You can be released from the requirements of the above licenses by purchasing
11+
// a commercial license. Buying such a license is mandatory if you want to
12+
// modify or otherwise use the software for commercial activities involving the
13+
// Arduino software without disclosing the source code of your own applications.
14+
// To purchase a commercial license, send an email to license@arduino.cc.
15+
16+
package compile_test
17+
18+
import (
19+
"strings"
20+
"testing"
21+
22+
"github.com/arduino/arduino-cli/internal/integrationtest"
23+
"github.com/arduino/go-paths-helper"
24+
"github.com/stretchr/testify/require"
25+
)
26+
27+
func TestDumpProfileClean(t *testing.T) {
28+
env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
29+
t.Cleanup(env.CleanUp)
30+
31+
// Install Arduino AVR Boards
32+
_, _, err := cli.Run("core", "install", "arduino:avr@1.8.6")
33+
require.NoError(t, err)
34+
35+
validSketchPath, err := paths.New("testdata", "ValidSketch").Abs()
36+
require.NoError(t, err)
37+
invalidSketchPath, err := paths.New("testdata", "InvalidSketch").Abs()
38+
require.NoError(t, err)
39+
40+
validProfile := `profiles:
41+
uno:
42+
fqbn: arduino:avr:uno
43+
platforms:
44+
- platform: arduino:avr (1.8.6)`
45+
t.Run("NoVerbose", func(t *testing.T) {
46+
stdout, stderr, err := cli.Run("compile", "-b", "arduino:avr:uno", validSketchPath.String(), "--dump-profile")
47+
require.NoError(t, err)
48+
require.Empty(t, stderr)
49+
profile := strings.TrimSpace(string(stdout))
50+
require.Equal(t, validProfile, profile)
51+
})
52+
t.Run("Verbose", func(t *testing.T) {
53+
stdout, stderr, err := cli.Run("compile", "-b", "arduino:avr:uno", validSketchPath.String(), "--dump-profile", "--verbose")
54+
require.NoError(t, err)
55+
require.Empty(t, stderr)
56+
profile := strings.TrimSpace(string(stdout))
57+
require.Equal(t, validProfile, profile)
58+
})
59+
t.Run("ErrorNoVerbose", func(t *testing.T) {
60+
stdout, stderr, err := cli.Run("compile", "-b", "arduino:avr:uno", invalidSketchPath.String(), "--dump-profile")
61+
require.Error(t, err)
62+
require.NotEmpty(t, stderr)
63+
require.NotContains(t, string(stdout), validProfile)
64+
})
65+
t.Run("ErrorVerbose", func(t *testing.T) {
66+
stdout, stderr, err := cli.Run("compile", "-b", "arduino:avr:uno", invalidSketchPath.String(), "--dump-profile", "--verbose")
67+
require.Error(t, err)
68+
require.NotEmpty(t, stderr)
69+
require.NotContains(t, string(stdout), validProfile)
70+
})
71+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
void setup() {}
2+
void loop() {}
3+
aaaaaa
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
void setup() {}
2+
void loop() {}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

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:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy