Skip to content

Commit 3db4ad8

Browse files
authored
Allow platforms without fixed version in profiles. (#2940)
* Allow platforms without fixed version in profiles. * Correctly mark package manager instance as "under profile" even in case an unversioned platform is requsted. * Improved error checks in profile loading * Updated docs
1 parent cff56cd commit 3db4ad8

File tree

7 files changed

+121
-15
lines changed

7 files changed

+121
-15
lines changed

commands/instances.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ func (s *arduinoCoreServerImpl) Init(req *rpc.InitRequest, stream rpc.ArduinoCor
248248
s := &cmderrors.PlatformLoadingError{Cause: err}
249249
responseError(s.GRPCStatus())
250250
}
251+
} else if profile.RequireSystemInstalledPlatform() {
252+
for _, err := range pmb.LoadGlobalHardwareForProfile(profile) {
253+
s := &cmderrors.PlatformLoadingError{Cause: err}
254+
responseError(s.GRPCStatus())
255+
}
251256
} else {
252257
// Load platforms from profile
253258
errs := pmb.LoadHardwareForProfile(ctx, profile, true, downloadCallback, taskCallback, s.settings)

docs/sketch-project-file.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ profiles:
2828
fqbn: <FQBN>
2929
programmer: <PROGRAMMER>
3030
platforms:
31-
- platform: <PLATFORM> (<PLATFORM_VERSION>)
31+
- platform: <PLATFORM> [(<PLATFORM_VERSION>)]
3232
platform_index_url: <3RD_PARTY_PLATFORM_URL>
33-
- platform: <PLATFORM_DEPENDENCY> (<PLATFORM_DEPENDENCY_VERSION>)
33+
- platform: <PLATFORM_DEPENDENCY> [(<PLATFORM_DEPENDENCY_VERSION>)]
3434
platform_index_url: <3RD_PARTY_PLATFORM_DEPENDENCY_URL>
3535
libraries:
3636
- <INDEX_LIB_NAME> (<INDEX_LIB_VERSION>)
@@ -73,6 +73,14 @@ The following fields are available since Arduino CLI 1.1.0:
7373
`baudrate: 115200`) but any setting/value can be specified. Multiple settings can be set. These fields are optional.
7474
- `<PORT_PROTOCOL>` is the protocol for the port used to upload and monitor the board. This field is optional.
7575

76+
#### Using a system-installed platform.
77+
78+
The fields `<PLATFORM_VERSION>` and `<PLATFORM_DEPENDENCY_VERSION>` are optional, if they are omitted, the sketch
79+
compilation will use the platforms installed system-wide. This could be helpful during the development of a platform
80+
(where a specific release is not yet available), or if a specific version of a platform is not a strict requirement.
81+
82+
#### An example of a complete project file.
83+
7684
A complete example of a sketch project file may be the following:
7785

7886
```

internal/arduino/cores/packagemanager/profiles.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ import (
3333
"github.com/sirupsen/logrus"
3434
)
3535

36+
// LoadGlobalHardwareForProfile loads the hardware platforms for the given profile.
37+
// It uses the global package manager and does not download or install any missing tools or platforms.
38+
func (pmb *Builder) LoadGlobalHardwareForProfile(p *sketch.Profile) []error {
39+
pmb.profile = p
40+
return pmb.LoadHardware()
41+
}
42+
3643
// LoadHardwareForProfile load the hardware platforms for the given profile.
3744
// If installMissing is true then possibly missing tools and platforms will be downloaded and installed.
3845
func (pmb *Builder) LoadHardwareForProfile(ctx context.Context, p *sketch.Profile, installMissing bool, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB, settings *configuration.Settings) []error {

internal/arduino/sketch/profiles.go

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ type Profile struct {
120120
Libraries ProfileRequiredLibraries `yaml:"libraries"`
121121
}
122122

123+
// UsesSystemPlatform checks if this profile requires a system installed platform.
124+
func (p *Profile) RequireSystemInstalledPlatform() bool {
125+
return p.Platforms[0].RequireSystemInstalledPlatform()
126+
}
127+
123128
// ToRpc converts this Profile to an rpc.SketchProfile
124129
func (p *Profile) ToRpc() *rpc.SketchProfile {
125130
var portConfig *rpc.MonitorPortConfiguration
@@ -182,6 +187,20 @@ func (p *ProfileRequiredPlatforms) AsYaml() string {
182187
return res
183188
}
184189

190+
func (p *ProfileRequiredPlatforms) UnmarshalYAML(unmarshal func(interface{}) error) error {
191+
_p := (*[]*ProfilePlatformReference)(p)
192+
if err := unmarshal(_p); err != nil {
193+
return err
194+
}
195+
requireSystemPlatform := (*_p)[0].RequireSystemInstalledPlatform()
196+
for _, platform := range *_p {
197+
if platform.RequireSystemInstalledPlatform() != requireSystemPlatform {
198+
return errors.New(i18n.Tr("all platforms in a profile must either require a specific version or not"))
199+
}
200+
}
201+
return nil
202+
}
203+
185204
// ProfileRequiredLibraries is a list of ProfileLibraryReference (libraries
186205
// required to build the sketch using this profile)
187206
type ProfileRequiredLibraries []*ProfileLibraryReference
@@ -206,6 +225,12 @@ type ProfilePlatformReference struct {
206225
PlatformIndexURL *url.URL
207226
}
208227

228+
// RequireSystemInstalledPlatform returns true if the platform reference
229+
// does not specify a version, meaning it requires the system installed platform.
230+
func (p *ProfilePlatformReference) RequireSystemInstalledPlatform() bool {
231+
return p.Version == nil
232+
}
233+
209234
// InternalUniqueIdentifier returns the unique identifier for this object
210235
func (p *ProfilePlatformReference) InternalUniqueIdentifier() string {
211236
id := p.String()
@@ -224,20 +249,38 @@ func (p *ProfilePlatformReference) String() string {
224249

225250
// AsYaml outputs the platform reference as Yaml
226251
func (p *ProfilePlatformReference) AsYaml() string {
227-
res := fmt.Sprintf(" - platform: %s:%s (%s)\n", p.Packager, p.Architecture, p.Version)
252+
res := ""
253+
if p.Version != nil {
254+
res += fmt.Sprintf(" - platform: %s:%s (%s)\n", p.Packager, p.Architecture, p.Version)
255+
} else {
256+
res += fmt.Sprintf(" - platform: %s:%s\n", p.Packager, p.Architecture)
257+
}
228258
if p.PlatformIndexURL != nil {
229259
res += fmt.Sprintf(" platform_index_url: %s\n", p.PlatformIndexURL)
230260
}
231261
return res
232262
}
233263

234264
func parseNameAndVersion(in string) (string, string, bool) {
235-
re := regexp.MustCompile(`^([a-zA-Z0-9.\-_ :]+) \((.+)\)$`)
236-
split := re.FindAllStringSubmatch(in, -1)
237-
if len(split) != 1 || len(split[0]) != 3 {
238-
return "", "", false
265+
{
266+
// Try to parse the input string in the format "VENDOR:ARCH (VERSION)"
267+
re := regexp.MustCompile(`^([a-zA-Z0-9.\-_ :]+) \((.+)\)$`)
268+
split := re.FindAllStringSubmatch(in, -1)
269+
if len(split) == 1 && len(split[0]) == 3 {
270+
return split[0][1], split[0][2], true
271+
}
272+
}
273+
274+
{
275+
// Try to parse the input string in the format "VENDOR:ARCH"
276+
re := regexp.MustCompile(`^([a-zA-Z0-9.\-_ :]+)$`)
277+
split := re.FindAllStringSubmatch(in, -1)
278+
if len(split) == 1 && len(split[0]) == 2 {
279+
return split[0][1], "", true
280+
}
239281
}
240-
return split[0][1], split[0][2], true
282+
283+
return "", "", false
241284
}
242285

243286
// UnmarshalYAML decodes a ProfilePlatformReference from YAML source.
@@ -250,14 +293,23 @@ func (p *ProfilePlatformReference) UnmarshalYAML(unmarshal func(interface{}) err
250293
return errors.New(i18n.Tr("missing '%s' directive", "platform"))
251294
} else if platformID, platformVersion, ok := parseNameAndVersion(platformID); !ok {
252295
return errors.New(i18n.Tr("invalid '%s' directive", "platform"))
253-
} else if c, err := semver.Parse(platformVersion); err != nil {
254-
return fmt.Errorf("%s: %w", i18n.Tr("error parsing version constraints"), err)
255-
} else if split := strings.SplitN(platformID, ":", 2); len(split) != 2 {
256-
return fmt.Errorf("%s: %s", i18n.Tr("invalid platform identifier"), platformID)
257296
} else {
258-
p.Packager = split[0]
259-
p.Architecture = split[1]
260-
p.Version = c
297+
var version *semver.Version
298+
if platformVersion != "" {
299+
if v, err := semver.Parse(platformVersion); err != nil {
300+
return fmt.Errorf("%s: %w", i18n.Tr("error parsing version constraints"), err)
301+
} else {
302+
version = v
303+
}
304+
}
305+
306+
if split := strings.SplitN(platformID, ":", 2); len(split) != 2 {
307+
return fmt.Errorf("%s: %s", i18n.Tr("invalid platform identifier"), platformID)
308+
} else {
309+
p.Packager = split[0]
310+
p.Architecture = split[1]
311+
p.Version = version
312+
}
261313
}
262314

263315
if rawIndexURL, ok := data["platform_index_url"]; ok {

internal/arduino/sketch/profiles_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,17 @@ func TestProjectFileLoading(t *testing.T) {
3939
require.NoError(t, err)
4040
require.Equal(t, proj.AsYaml(), string(golden))
4141
}
42+
{
43+
sketchProj := paths.New("testdata", "profiles", "profile_1.yml")
44+
proj, err := LoadProjectFile(sketchProj)
45+
require.NoError(t, err)
46+
golden, err := sketchProj.ReadFile()
47+
require.NoError(t, err)
48+
require.Equal(t, string(golden), proj.AsYaml())
49+
}
50+
{
51+
sketchProj := paths.New("testdata", "profiles", "bad_profile_1.yml")
52+
_, err := LoadProjectFile(sketchProj)
53+
require.Error(t, err)
54+
}
4255
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
profiles:
2+
tiny:
3+
notes: Invalid profile mixing versioned and non-versioned platforms.
4+
fqbn: attiny:avr:ATtinyX5:cpu=attiny85,clock=internal16
5+
platforms:
6+
- platform: attiny:avr
7+
platform_index_url: http://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json
8+
- platform: arduino:avr (1.8.3)
9+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
profiles:
2+
giga:
3+
fqbn: arduino:mbed_giga:giga
4+
platforms:
5+
- platform: arduino:mbed_giga (4.3.1)
6+
7+
giga_any:
8+
fqbn: arduino:mbed_giga:giga
9+
platforms:
10+
- platform: arduino:mbed_giga
11+
12+
default_profile: giga_any

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