From 6a32d41839821d73338a2421ae33b24d4bac8107 Mon Sep 17 00:00:00 2001 From: MatteoPologruto Date: Tue, 30 May 2023 17:00:53 +0200 Subject: [PATCH 1/7] Add support for default profile to compile command --- internal/cli/compile/compile.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/internal/cli/compile/compile.go b/internal/cli/compile/compile.go index baa1dff5f89..dfd5d4c70ba 100644 --- a/internal/cli/compile/compile.go +++ b/internal/cli/compile/compile.go @@ -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 != "" { From cdef08236e3b292bc30b0646bb0786bb7ad8393a Mon Sep 17 00:00:00 2001 From: MatteoPologruto Date: Wed, 31 May 2023 15:53:06 +0200 Subject: [PATCH 2/7] Add support for default profiles to upload command --- internal/cli/upload/upload.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/internal/cli/upload/upload.go b/internal/cli/upload/upload.go index 1fa91086ac0..0f2a798d979 100644 --- a/internal/cli/upload/upload.go +++ b/internal/cli/upload/upload.go @@ -95,17 +95,25 @@ func runUploadCommand(command *cobra.Command, args []string) { 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(sk.Project.DefaultProfile, 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) + 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, }) @@ -122,7 +130,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], @@ -156,7 +164,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, From 4d747c87cafebedab40192141cdf0df62802e7e1 Mon Sep 17 00:00:00 2001 From: MatteoPologruto Date: Mon, 21 Aug 2023 15:30:27 +0200 Subject: [PATCH 3/7] Add TestCompileWithDefaultProfile to integration tests --- .../integrationtest/profiles/profiles_test.go | 22 +++++++++++++++++++ .../testdata/sketch_with_profile/sketch.yaml | 3 +++ 2 files changed, 25 insertions(+) diff --git a/internal/integrationtest/profiles/profiles_test.go b/internal/integrationtest/profiles/profiles_test.go index 9cd1ffcb556..08395c3d7e8 100644 --- a/internal/integrationtest/profiles/profiles_test.go +++ b/internal/integrationtest/profiles/profiles_test.go @@ -69,3 +69,25 @@ 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) + + // copy sketch_with_profile into the working directory + sketchPath := cli.CopySketch("sketch_with_profile") + + // compile using the default profile with its fqbn + stdout, _, err := cli.Run("compile", sketchPath.String()) + require.NoError(t, err) + require.Contains(t, string(stdout), "arduino:avr") + + // compile using a different fbqn -> should have priority over the one in the default profile + stdout, _, err = cli.Run("compile", "-b", "arduino:samd:mkr1000", sketchPath.String()) + require.NoError(t, err) + require.Contains(t, string(stdout), "arduino:samd") +} diff --git a/internal/integrationtest/testdata/sketch_with_profile/sketch.yaml b/internal/integrationtest/testdata/sketch_with_profile/sketch.yaml index ed40ce874f3..e653fd3ede1 100644 --- a/internal/integrationtest/testdata/sketch_with_profile/sketch.yaml +++ b/internal/integrationtest/testdata/sketch_with_profile/sketch.yaml @@ -8,5 +8,8 @@ profiles: fqbn: arduino:avr:uno platforms: - platform: arduino:avr (1.8.5) + - platform: arduino:samd (1.8.13) libraries: - Arduino_JSON (0.1.0) + +default_profile: avr2 From 2167e4584bd0336feb70ff0588009a59c559659c Mon Sep 17 00:00:00 2001 From: MatteoPologruto Date: Mon, 21 Aug 2023 15:35:30 +0200 Subject: [PATCH 4/7] Get the profile's FQBN if it's not already specified in the request --- commands/compile/compile.go | 6 +++++- commands/upload/upload.go | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/commands/compile/compile.go b/commands/compile/compile.go index ba904fddad0..92858dd68d6 100644 --- a/commands/compile/compile.go +++ b/commands/compile/compile.go @@ -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{} diff --git a/commands/upload/upload.go b/commands/upload/upload.go index 75f8aae9238..aa74023b0e3 100644 --- a/commands/upload/upload.go +++ b/commands/upload/upload.go @@ -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(), From 4d3bb2c67a0b73c20d1f635fa19acae6f22f3eb6 Mon Sep 17 00:00:00 2001 From: MatteoPologruto Date: Mon, 21 Aug 2023 16:12:09 +0200 Subject: [PATCH 5/7] Update documentation regarding sketch projects --- docs/sketch-project-file.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/docs/sketch-project-file.md b/docs/sketch-project-file.md index 01a5607c8db..640ede7505e 100644 --- a/docs/sketch-project-file.md +++ b/docs/sketch-project-file.md @@ -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 @@ -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 @@ -124,6 +136,7 @@ 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: @@ -131,8 +144,9 @@ 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. From 8b37244b555044a55aab07ff108ad6643a7798d5 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 23 Aug 2023 12:48:52 +0200 Subject: [PATCH 6/7] Added integration tests for all default_profile cases --- .../integrationtest/profiles/profiles_test.go | 79 ++++++++++++++++--- .../sketch_with_default_profile/sketch.yaml | 12 +++ .../sketch_with_default_profile.ino | 2 + .../sketch.yaml | 10 +++ .../sketch_without_default_profile.ino | 2 + 5 files changed, 95 insertions(+), 10 deletions(-) create mode 100644 internal/integrationtest/testdata/sketch_with_default_profile/sketch.yaml create mode 100644 internal/integrationtest/testdata/sketch_with_default_profile/sketch_with_default_profile.ino create mode 100644 internal/integrationtest/testdata/sketch_without_default_profile/sketch.yaml create mode 100644 internal/integrationtest/testdata/sketch_without_default_profile/sketch_without_default_profile.ino diff --git a/internal/integrationtest/profiles/profiles_test.go b/internal/integrationtest/profiles/profiles_test.go index 08395c3d7e8..4915bed5cf7 100644 --- a/internal/integrationtest/profiles/profiles_test.go +++ b/internal/integrationtest/profiles/profiles_test.go @@ -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) { @@ -78,16 +79,74 @@ func TestCompileWithDefaultProfile(t *testing.T) { _, _, err := cli.Run("core", "update-index") require.NoError(t, err) - // copy sketch_with_profile into the working directory - sketchPath := cli.CopySketch("sketch_with_profile") - - // compile using the default profile with its fqbn - stdout, _, err := cli.Run("compile", sketchPath.String()) + // Installa core/libs globally + _, _, err = cli.Run("core", "install", "arduino:avr@1.8.3") require.NoError(t, err) - require.Contains(t, string(stdout), "arduino:avr") - // compile using a different fbqn -> should have priority over the one in the default profile - stdout, _, err = cli.Run("compile", "-b", "arduino:samd:mkr1000", sketchPath.String()) - require.NoError(t, err) - require.Contains(t, string(stdout), "arduino:samd") + // 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" ]`) + } } diff --git a/internal/integrationtest/testdata/sketch_with_default_profile/sketch.yaml b/internal/integrationtest/testdata/sketch_with_default_profile/sketch.yaml new file mode 100644 index 00000000000..95d13d5754e --- /dev/null +++ b/internal/integrationtest/testdata/sketch_with_default_profile/sketch.yaml @@ -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 diff --git a/internal/integrationtest/testdata/sketch_with_default_profile/sketch_with_default_profile.ino b/internal/integrationtest/testdata/sketch_with_default_profile/sketch_with_default_profile.ino new file mode 100644 index 00000000000..660bdbccfdb --- /dev/null +++ b/internal/integrationtest/testdata/sketch_with_default_profile/sketch_with_default_profile.ino @@ -0,0 +1,2 @@ +void setup() {} +void loop() {} diff --git a/internal/integrationtest/testdata/sketch_without_default_profile/sketch.yaml b/internal/integrationtest/testdata/sketch_without_default_profile/sketch.yaml new file mode 100644 index 00000000000..1344a8fa507 --- /dev/null +++ b/internal/integrationtest/testdata/sketch_without_default_profile/sketch.yaml @@ -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) diff --git a/internal/integrationtest/testdata/sketch_without_default_profile/sketch_without_default_profile.ino b/internal/integrationtest/testdata/sketch_without_default_profile/sketch_without_default_profile.ino new file mode 100644 index 00000000000..660bdbccfdb --- /dev/null +++ b/internal/integrationtest/testdata/sketch_without_default_profile/sketch_without_default_profile.ino @@ -0,0 +1,2 @@ +void setup() {} +void loop() {} From f028e755fb985c95a169bec3e1b6626604bf8dd4 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 23 Aug 2023 12:49:15 +0200 Subject: [PATCH 7/7] Reverted old sketch_with_profile test --- .../integrationtest/testdata/sketch_with_profile/sketch.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/internal/integrationtest/testdata/sketch_with_profile/sketch.yaml b/internal/integrationtest/testdata/sketch_with_profile/sketch.yaml index e653fd3ede1..ed40ce874f3 100644 --- a/internal/integrationtest/testdata/sketch_with_profile/sketch.yaml +++ b/internal/integrationtest/testdata/sketch_with_profile/sketch.yaml @@ -8,8 +8,5 @@ profiles: fqbn: arduino:avr:uno platforms: - platform: arduino:avr (1.8.5) - - platform: arduino:samd (1.8.13) libraries: - Arduino_JSON (0.1.0) - -default_profile: avr2