Skip to content

[breaking] Improved compile report / temporary support for profile creation #1745

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jun 1, 2022
Merged
14 changes: 10 additions & 4 deletions arduino/cores/cores.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,10 +359,16 @@ func (release *PlatformRelease) String() string {
}

// ToRPCPlatformReference creates a gRPC PlatformReference message out of this PlatformRelease
func (release *PlatformRelease) ToRPCPlatformReference() *rpc.PlatformReference {
return &rpc.PlatformReference{
Id: release.Platform.String(),
Version: release.Version.String(),
func (release *PlatformRelease) ToRPCPlatformReference() *rpc.InstalledPlatformReference {
url := release.Platform.Package.URL
if strings.HasPrefix(url, "https://downloads.arduino.cc/packages/package_index.") {
url = ""
}
return &rpc.InstalledPlatformReference{
Id: release.Platform.String(),
Version: release.Version.String(),
InstallDir: release.InstallDir.String(),
PackageUrl: url,
}
}

Expand Down
95 changes: 93 additions & 2 deletions cli/compile/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import (
"github.com/arduino/arduino-cli/commands"
"github.com/arduino/arduino-cli/configuration"
"github.com/arduino/arduino-cli/i18n"
"github.com/arduino/arduino-cli/table"
"github.com/fatih/color"
"github.com/sirupsen/logrus"

"github.com/arduino/arduino-cli/cli/errorcodes"
Expand Down Expand Up @@ -68,6 +70,7 @@ var (
clean bool // Cleanup the build folder and do not use any cached build
compilationDatabaseOnly bool // Only create compilation database without actually compiling
sourceOverrides string // Path to a .json file that contains a set of replacements of the sketch source code.
dumpProfile bool // Create and print a profile configuration from the build
// library and libraries sound similar but they're actually different.
// library expects a path to the root folder of one single library.
// libraries expects a path to a directory containing multiple libraries, similarly to the <directories.user>/libraries path.
Expand All @@ -93,6 +96,7 @@ func NewCommand() *cobra.Command {

fqbnArg.AddToCommand(compileCommand)
profileArg.AddToCommand(compileCommand)
compileCommand.Flags().BoolVar(&dumpProfile, "dump-profile", false, tr("Create and print a profile configuration from the build."))
compileCommand.Flags().BoolVar(&showProperties, "show-properties", false, tr("Show all build properties used instead of compiling."))
compileCommand.Flags().BoolVar(&preprocess, "preprocess", false, tr("Print preprocessed code to stdout instead of compiling."))
compileCommand.Flags().StringVar(&buildCachePath, "build-cache-path", "", tr("Builds of 'core.a' are saved into this path to be cached and reused."))
Expand Down Expand Up @@ -268,6 +272,54 @@ func runCompileCommand(cmd *cobra.Command, args []string) {
}
}

if dumpProfile {
libs := ""
hasVendoredLibs := false
for _, lib := range compileRes.GetUsedLibraries() {
if lib.Location != rpc.LibraryLocation_LIBRARY_LOCATION_USER && lib.Location != rpc.LibraryLocation_LIBRARY_LOCATION_UNMANAGED {
continue
}
if lib.GetVersion() == "" {
hasVendoredLibs = true
continue
}
libs += fmt.Sprintln(" - " + lib.GetName() + " (" + lib.GetVersion() + ")")
}
if hasVendoredLibs {
fmt.Println()
fmt.Println(tr("WARNING: The sketch is compiled using one or more custom libraries."))
fmt.Println(tr("Currently, Build Profiles only support libraries available through Arduino Library Manager."))
}

newProfileName := "my_profile_name"
if split := strings.Split(compileRequest.GetFqbn(), ":"); len(split) > 2 {
newProfileName = split[2]
}
fmt.Println()
fmt.Println("profile:")
fmt.Println(" " + newProfileName + ":")
fmt.Println(" fqbn: " + compileRequest.GetFqbn())
fmt.Println(" platforms:")
boardPlatform := compileRes.GetBoardPlatform()
fmt.Println(" - platform: " + boardPlatform.GetId() + " (" + boardPlatform.GetVersion() + ")")
if url := boardPlatform.GetPackageUrl(); url != "" {
fmt.Println(" platform_index_url: " + url)
}

if buildPlatform := compileRes.GetBuildPlatform(); buildPlatform != nil &&
buildPlatform.Id != boardPlatform.Id &&
buildPlatform.Version != boardPlatform.Version {
fmt.Println(" - platform: " + buildPlatform.GetId() + " (" + buildPlatform.GetVersion() + ")")
if url := buildPlatform.GetPackageUrl(); url != "" {
fmt.Println(" platform_index_url: " + url)
}
}
if len(libs) > 0 {
fmt.Println(" libraries:")
fmt.Print(libs)
}
}

feedback.PrintResult(&compileResult{
CompileOut: compileStdOut.String(),
CompileErr: compileStdErr.String(),
Expand Down Expand Up @@ -316,6 +368,45 @@ func (r *compileResult) Data() interface{} {
}

func (r *compileResult) String() string {
// The output is already printed via os.Stdout/os.Stdin
return ""
titleColor := color.New(color.FgHiGreen)
nameColor := color.New(color.FgHiYellow)
pathColor := color.New(color.FgHiBlack)
build := r.BuilderResult

res := "\n"
libraries := table.New()
if len(build.GetUsedLibraries()) > 0 {
libraries.SetHeader(
table.NewCell(tr("Used library"), titleColor),
table.NewCell(tr("Version"), titleColor),
table.NewCell(tr("Path"), pathColor))
for _, l := range build.GetUsedLibraries() {
libraries.AddRow(
table.NewCell(l.GetName(), nameColor),
l.GetVersion(),
table.NewCell(l.GetInstallDir(), pathColor))
}
}
res += libraries.Render() + "\n"

platforms := table.New()
platforms.SetHeader(
table.NewCell(tr("Used platform"), titleColor),
table.NewCell(tr("Version"), titleColor),
table.NewCell(tr("Path"), pathColor))
boardPlatform := build.GetBoardPlatform()
platforms.AddRow(
table.NewCell(boardPlatform.GetId(), nameColor),
boardPlatform.GetVersion(),
table.NewCell(boardPlatform.GetInstallDir(), pathColor))
if buildPlatform := build.GetBuildPlatform(); buildPlatform != nil &&
buildPlatform.Id != boardPlatform.Id &&
buildPlatform.Version != boardPlatform.Version {
platforms.AddRow(
table.NewCell(buildPlatform.GetId(), nameColor),
buildPlatform.GetVersion(),
table.NewCell(buildPlatform.GetInstallDir(), pathColor))
}
res += platforms.Render()
return res
}
23 changes: 13 additions & 10 deletions commands/compile/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,19 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
return r, compileErr
}

defer func() {
importedLibs := []*rpc.Library{}
for _, lib := range builderCtx.ImportedLibraries {
rpcLib, err := lib.ToRPCLibrary()
if err != nil {
msg := tr("Error getting information for library %s", lib.Name) + ": " + err.Error() + "\n"
errStream.Write([]byte(msg))
}
importedLibs = append(importedLibs, rpcLib)
}
r.UsedLibraries = importedLibs
}()

// if it's a regular build, go on...
if err := builder.RunBuilder(builderCtx); err != nil {
return r, &arduino.CompileFailedError{Message: err.Error()}
Expand Down Expand Up @@ -268,16 +281,6 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
}
}

importedLibs := []*rpc.Library{}
for _, lib := range builderCtx.ImportedLibraries {
rpcLib, err := lib.ToRPCLibrary()
if err != nil {
return r, &arduino.PermissionDeniedError{Message: tr("Error getting information for library %s", lib.Name), Cause: err}
}
importedLibs = append(importedLibs, rpcLib)
}
r.UsedLibraries = importedLibs

r.ExecutableSectionsSize = builderCtx.ExecutableSectionsSize.ToRPCExecutableSectionSizeArray()

logrus.Tracef("Compile %s for %s successful", sk.Name, fqbnIn)
Expand Down
11 changes: 11 additions & 0 deletions docs/UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ but since it has been the default behaviour from a very long time we decided to
If a compilation fail for a missing bundled library, you can fix it just by installing the missing library from the
library manager as usual.

### gRPC: Changes in message `cc.arduino.cli.commands.v1.PlatformReference`

The gRPC message structure `cc.arduino.cli.commands.v1.PlatformReference` has been renamed to
`cc.arduino.cli.commands.v1.InstalledPlatformReference`, and some new fields have been added:

- `install_dir` is the installation directory of the platform
- `package_url` is the 3rd party platform URL of the platform

It is currently used only in `cc.arduino.cli.commands.v1.CompileResponse`, so the field type has been changed as well.
Old gRPC clients must only update gRPC bindings. They can safely ignore the new fields if not needed.

### golang API: PackageManager.DownloadPlatformRelease no longer need `label` parameter

```go
Expand Down
94 changes: 58 additions & 36 deletions rpc/cc/arduino/cli/commands/v1/common.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion rpc/cc/arduino/cli/commands/v1/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,15 @@ message Platform {
bool deprecated = 10;
}

message PlatformReference {
message InstalledPlatformReference {
// Platform ID (e.g., `arduino:avr`).
string id = 1;
// Version of the platform.
string version = 2;
// Installation directory of the platform
string install_dir = 3;
// 3rd party platform URL
string package_url = 4;
}

message Board {
Expand Down
Loading