Skip to content

Commit

Permalink
regression: Import fix for compile --input-dir . regression found in
Browse files Browse the repository at this point in the history
…#2304 (#2305)

* Add support for default build profile (#2203)

* Add support for default profile to compile command

* Add support for default profiles to upload command

* Add TestCompileWithDefaultProfile to integration tests

* Get the profile's FQBN if it's not already specified in the request

* Update documentation regarding sketch projects

* Added integration tests for all default_profile cases

* Reverted old sketch_with_profile test

---------

Co-authored-by: Cristian Maglie <c.maglie@arduino.cc>

* [skip-changelog] Use `LoadSketch` in upload function and return `rpc.Port` in `GetPort` (#2297)

* Change GetPort's returned type to rpc.Port

* Use LoadSketch in runUploadCommand

---------

Co-authored-by: MatteoPologruto <109663225+MatteoPologruto@users.noreply.github.com>
  • Loading branch information
cmaglie and MatteoPologruto committed Sep 11, 2023
1 parent 048415c commit 963c1a7
Show file tree
Hide file tree
Showing 13 changed files with 172 additions and 25 deletions.
6 changes: 5 additions & 1 deletion commands/compile/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,11 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream

fqbnIn := req.GetFqbn()
if fqbnIn == "" && sk != nil {
fqbnIn = sk.GetDefaultFQBN()
if pme.GetProfile() != nil {
fqbnIn = pme.GetProfile().FQBN
} else {
fqbnIn = sk.GetDefaultFQBN()
}
}
if fqbnIn == "" {
return nil, &arduino.MissingFQBNError{}
Expand Down
7 changes: 6 additions & 1 deletion commands/upload/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,17 @@ func Upload(ctx context.Context, req *rpc.UploadRequest, outStream io.Writer, er
}
defer pmeRelease()

fqbn := req.GetFqbn()
if fqbn == "" && pme.GetProfile() != nil {
fqbn = pme.GetProfile().FQBN
}

updatedPort, err := runProgramAction(
pme,
sk,
req.GetImportFile(),
req.GetImportDir(),
req.GetFqbn(),
fqbn,
req.GetPort(),
req.GetProgrammer(),
req.GetVerbose(),
Expand Down
18 changes: 16 additions & 2 deletions docs/sketch-project-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ profiles:
- ArduinoIoTCloud (1.0.2)
- Arduino_ConnectionHandler (0.6.4)
- TinyDHT sensor library (1.1.0)
default_profile: nanorp
```

### Building a sketch
Expand All @@ -116,6 +118,16 @@ not be used in any way. In other words, the build is isolated from the system an
specified in the profile: this will ensure that the build is portable and reproducible independently from the platforms
and libraries installed in the system.

### Using a default profile

If a `default_profile` is specified in the `sketch.yaml` then the “classic” compile command:

```
arduino-cli compile [sketch]
```

will, instead, trigger a profile-based build using the default profile indicated in the `sketch.yaml`.

## Default flags for Arduino CLI usage

The sketch project file may be used to set the default value for some command line flags of the Arduino CLI, in
Expand All @@ -124,15 +136,17 @@ particular:
- The `default_fqbn` key sets the default value for the `--fqbn` flag
- The `default_port` key sets the default value for the `--port` flag
- The `default_protocol` key sets the default value for the `--protocol` flag
- The `default_profile` key sets the default value for the `--profile` flag

For example:

```
default_fqbn: arduino:avr:uno
default_port: /dev/ttyACM0
default_protocol: serial
default_profile: myprofile
```

With this configuration set, it is not necessary to specify the `--fqbn`, `--port`, or `--protocol` flags to the
[`arduino-cli compile`](commands/arduino-cli_compile.md) or [`arduino-cli upload`](commands/arduino-cli_upload.md)
With this configuration set, it is not necessary to specify the `--fqbn`, `--port`, `--protocol` or `--profile` flags to
the [`arduino-cli compile`](commands/arduino-cli_compile.md) or [`arduino-cli upload`](commands/arduino-cli_upload.md)
commands when compiling or uploading the sketch.
2 changes: 1 addition & 1 deletion internal/cli/arguments/fqbn.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,5 @@ func CalculateFQBNAndPort(portArgs *Port, fqbnArg *Fqbn, instance *rpc.Instance,
if err != nil {
feedback.Fatal(tr("Error getting port metadata: %v", err), feedback.ErrGeneric)
}
return fqbn, port.ToRPC()
return fqbn, port
}
10 changes: 4 additions & 6 deletions internal/cli/arguments/port.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"time"

"github.com/arduino/arduino-cli/arduino"
"github.com/arduino/arduino-cli/arduino/discovery"
"github.com/arduino/arduino-cli/commands"
"github.com/arduino/arduino-cli/commands/board"
"github.com/arduino/arduino-cli/internal/cli/feedback"
Expand Down Expand Up @@ -70,8 +69,7 @@ func (p *Port) GetPortAddressAndProtocol(instance *rpc.Instance, defaultAddress,

// GetPort returns the Port obtained by parsing command line arguments.
// The extra metadata for the ports is obtained using the pluggable discoveries.
func (p *Port) GetPort(instance *rpc.Instance, defaultAddress, defaultProtocol string) (*discovery.Port, error) {
// TODO: REMOVE discovery from here (use board.List instead)
func (p *Port) GetPort(instance *rpc.Instance, defaultAddress, defaultProtocol string) (*rpc.Port, error) {

address := p.address
protocol := p.protocol
Expand All @@ -84,7 +82,7 @@ func (p *Port) GetPort(instance *rpc.Instance, defaultAddress, defaultProtocol s
// the attached board without specifying explictly a port.
// Tools that work this way must be specified using the property
// "BOARD_ID.upload.tool.default" in the platform's boards.txt.
return &discovery.Port{
return &rpc.Port{
Protocol: "default",
}, nil
}
Expand Down Expand Up @@ -113,13 +111,13 @@ func (p *Port) GetPort(instance *rpc.Instance, defaultAddress, defaultProtocol s
}
port := portEvent.Port
if (protocol == "" || protocol == port.Protocol) && address == port.Address {
return port, nil
return port.ToRPC(), nil
}

case <-deadline:
// No matching port found
if protocol == "" {
return &discovery.Port{
return &rpc.Port{
Address: address,
Protocol: "serial",
}, nil
Expand Down
2 changes: 1 addition & 1 deletion internal/cli/burnbootloader/burnbootloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func runBootloaderCommand(command *cobra.Command, args []string) {
if _, err := upload.BurnBootloader(context.Background(), &rpc.BurnBootloaderRequest{
Instance: instance,
Fqbn: fqbn.String(),
Port: discoveryPort.ToRPC(),
Port: discoveryPort,
Verbose: verbose,
Verify: verify,
Programmer: programmer.String(),
Expand Down
18 changes: 14 additions & 4 deletions internal/cli/compile/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,25 @@ func runCompileCommand(cmd *cobra.Command, args []string) {
}

sketchPath := arguments.InitSketchPath(path)
inst, profile := instance.CreateAndInitWithProfile(profileArg.Get(), sketchPath)
if fqbnArg.String() == "" {
fqbnArg.Set(profile.GetFqbn())
}

sk, err := sketch.LoadSketch(context.Background(), &rpc.LoadSketchRequest{SketchPath: sketchPath.String()})
if err != nil {
feedback.FatalError(err, feedback.ErrGeneric)
}

var inst *rpc.Instance
var profile *rpc.Profile

if profileArg.Get() == "" {
inst, profile = instance.CreateAndInitWithProfile(sk.GetDefaultProfile().GetName(), sketchPath)
} else {
inst, profile = instance.CreateAndInitWithProfile(profileArg.Get(), sketchPath)
}

if fqbnArg.String() == "" {
fqbnArg.Set(profile.GetFqbn())
}

fqbn, port := arguments.CalculateFQBNAndPort(&portArgs, &fqbnArg, inst, sk.GetDefaultFqbn(), sk.GetDefaultPort(), sk.GetDefaultProtocol())

if keysKeychain != "" || signKey != "" || encryptKey != "" {
Expand Down
27 changes: 18 additions & 9 deletions internal/cli/upload/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import (

"github.com/arduino/arduino-cli/arduino"
"github.com/arduino/arduino-cli/arduino/cores/packagemanager"
"github.com/arduino/arduino-cli/arduino/sketch"
"github.com/arduino/arduino-cli/commands"
sk "github.com/arduino/arduino-cli/commands/sketch"
"github.com/arduino/arduino-cli/commands/upload"
"github.com/arduino/arduino-cli/i18n"
"github.com/arduino/arduino-cli/internal/cli/arguments"
Expand Down Expand Up @@ -90,22 +90,31 @@ func runUploadCommand(command *cobra.Command, args []string) {
arguments.WarnDeprecatedFiles(sketchPath)
}

sk, err := sketch.New(sketchPath)
sketch, err := sk.LoadSketch(context.Background(), &rpc.LoadSketchRequest{SketchPath: sketchPath.String()})
if err != nil && importDir == "" && importFile == "" {
feedback.Fatal(tr("Error during Upload: %v", err), feedback.ErrGeneric)
}

instance, profile := instance.CreateAndInitWithProfile(profileArg.Get(), sketchPath)
var inst *rpc.Instance
var profile *rpc.Profile

if profileArg.Get() == "" {
inst, profile = instance.CreateAndInitWithProfile(sketch.GetDefaultProfile().GetName(), sketchPath)
} else {
inst, profile = instance.CreateAndInitWithProfile(profileArg.Get(), sketchPath)
}

if fqbnArg.String() == "" {
fqbnArg.Set(profile.GetFqbn())
}

defaultFQBN := sk.GetDefaultFQBN()
defaultAddress, defaultProtocol := sk.GetDefaultPortAddressAndProtocol()
fqbn, port := arguments.CalculateFQBNAndPort(&portArgs, &fqbnArg, instance, defaultFQBN, defaultAddress, defaultProtocol)
defaultFQBN := sketch.GetDefaultFqbn()
defaultAddress := sketch.GetDefaultPort()
defaultProtocol := sketch.GetDefaultProtocol()
fqbn, port := arguments.CalculateFQBNAndPort(&portArgs, &fqbnArg, inst, defaultFQBN, defaultAddress, defaultProtocol)

userFieldRes, err := upload.SupportedUserFields(context.Background(), &rpc.SupportedUserFieldsRequest{
Instance: instance,
Instance: inst,
Fqbn: fqbn,
Protocol: port.Protocol,
})
Expand All @@ -122,7 +131,7 @@ func runUploadCommand(command *cobra.Command, args []string) {
}

// FIXME: Here we must not access package manager...
pme, release := commands.GetPackageManagerExplorer(&rpc.UploadRequest{Instance: instance})
pme, release := commands.GetPackageManagerExplorer(&rpc.UploadRequest{Instance: inst})
platform := pme.FindPlatform(&packagemanager.PlatformReference{
Package: split[0],
PlatformArchitecture: split[1],
Expand Down Expand Up @@ -156,7 +165,7 @@ func runUploadCommand(command *cobra.Command, args []string) {

stdOut, stdErr, stdIOResult := feedback.OutputStreams()
req := &rpc.UploadRequest{
Instance: instance,
Instance: inst,
Fqbn: fqbn,
SketchPath: path,
Port: port,
Expand Down
81 changes: 81 additions & 0 deletions internal/integrationtest/profiles/profiles_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

"github.com/arduino/arduino-cli/internal/integrationtest"
"github.com/stretchr/testify/require"
"go.bug.st/testifyjson/requirejson"
)

func TestCompileWithProfiles(t *testing.T) {
Expand Down Expand Up @@ -69,3 +70,83 @@ func TestBuilderDidNotCatchLibsFromUnusedPlatforms(t *testing.T) {
require.NotContains(t, string(stdout), "samd")
require.NotContains(t, string(stderr), "samd")
}

func TestCompileWithDefaultProfile(t *testing.T) {
env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
defer env.CleanUp()

// Init the environment explicitly
_, _, err := cli.Run("core", "update-index")
require.NoError(t, err)

// Installa core/libs globally
_, _, err = cli.Run("core", "install", "arduino:avr@1.8.3")
require.NoError(t, err)

// copy sketch_with_profile into the working directory
sketchWithoutDefProfilePath := cli.CopySketch("sketch_without_default_profile")
sketchWithDefProfilePath := cli.CopySketch("sketch_with_default_profile")

{
// no default profile -> error missing FQBN
_, _, err := cli.Run("compile", sketchWithoutDefProfilePath.String(), "--format", "json")
require.Error(t, err)
}
{
// specified fbqn -> compile with specified FQBN and use global installation
stdout, _, err := cli.Run("compile", "-b", "arduino:avr:nano", sketchWithoutDefProfilePath.String(), "--format", "json")
require.NoError(t, err)
jsonOut := requirejson.Parse(t, stdout)
jsonOut.Query(".builder_result.build_platform").MustContain(`{"id":"arduino:avr", "version":"1.8.3"}`)
jsonOut.Query(".builder_result.build_properties").MustContain(`[ "build.fqbn=arduino:avr:nano" ]`)
}
{
// specified profile -> use the specified profile
stdout, _, err := cli.Run("compile", "--profile", "avr1", sketchWithoutDefProfilePath.String(), "--format", "json")
require.NoError(t, err)
jsonOut := requirejson.Parse(t, stdout)
jsonOut.Query(".builder_result.build_platform").MustContain(`{"id":"arduino:avr", "version":"1.8.4"}`)
jsonOut.Query(".builder_result.build_properties").MustContain(`[ "build.fqbn=arduino:avr:uno" ]`)
}
{
// specified profile and fqbn -> use the specified profile and override fqbn
stdout, _, err := cli.Run("compile", "--profile", "avr1", "-b", "arduino:avr:nano", sketchWithoutDefProfilePath.String(), "--format", "json")
require.NoError(t, err)
jsonOut := requirejson.Parse(t, stdout)
jsonOut.Query(".builder_result.build_platform").MustContain(`{"id":"arduino:avr", "version":"1.8.4"}`)
jsonOut.Query(".builder_result.build_properties").MustContain(`[ "build.fqbn=arduino:avr:nano" ]`)
}

{
// default profile -> use default profile
stdout, _, err := cli.Run("compile", sketchWithDefProfilePath.String(), "--format", "json")
require.NoError(t, err)
jsonOut := requirejson.Parse(t, stdout)
jsonOut.Query(".builder_result.build_platform").MustContain(`{"id":"arduino:avr", "version":"1.8.5"}`)
jsonOut.Query(".builder_result.build_properties").MustContain(`[ "build.fqbn=arduino:avr:leonardo" ]`)
}
{
// default profile, specified fbqn -> use default profile, override fqbn
stdout, _, err := cli.Run("compile", "-b", "arduino:avr:nano", sketchWithDefProfilePath.String(), "--format", "json")
require.NoError(t, err)
jsonOut := requirejson.Parse(t, stdout)
jsonOut.Query(".builder_result.build_platform").MustContain(`{"id":"arduino:avr", "version":"1.8.5"}`)
jsonOut.Query(".builder_result.build_properties").MustContain(`[ "build.fqbn=arduino:avr:nano" ]`)
}
{
// default profile, specified different profile -> use the specified profile
stdout, _, err := cli.Run("compile", "--profile", "avr1", sketchWithDefProfilePath.String(), "--format", "json")
require.NoError(t, err)
jsonOut := requirejson.Parse(t, stdout)
jsonOut.Query(".builder_result.build_platform").MustContain(`{"id":"arduino:avr", "version":"1.8.4"}`)
jsonOut.Query(".builder_result.build_properties").MustContain(`[ "build.fqbn=arduino:avr:uno" ]`)
}
{
// default profile, specified different profile and fqbn -> use the specified profile and override fqbn
stdout, _, err := cli.Run("compile", "--profile", "avr1", "-b", "arduino:avr:nano", sketchWithDefProfilePath.String(), "--format", "json")
require.NoError(t, err)
jsonOut := requirejson.Parse(t, stdout)
jsonOut.Query(".builder_result.build_platform").MustContain(`{"id":"arduino:avr", "version":"1.8.4"}`)
jsonOut.Query(".builder_result.build_properties").MustContain(`[ "build.fqbn=arduino:avr:nano" ]`)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
profiles:
avr1:
fqbn: arduino:avr:uno
platforms:
- platform: arduino:avr (1.8.4)

avr2:
fqbn: arduino:avr:leonardo
platforms:
- platform: arduino:avr (1.8.5)

default_profile: avr2
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
void setup() {}
void loop() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
profiles:
avr1:
fqbn: arduino:avr:uno
platforms:
- platform: arduino:avr (1.8.4)

avr2:
fqbn: arduino:avr:leonardo
platforms:
- platform: arduino:avr (1.8.5)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
void setup() {}
void loop() {}

0 comments on commit 963c1a7

Please sign in to comment.