diff --git a/compileopts/target.go b/compileopts/target.go index 16d21f46c5..29b3733bd9 100644 --- a/compileopts/target.go +++ b/compileopts/target.go @@ -24,6 +24,7 @@ import ( // https://github.com/shepmaster/rust-arduino-blink-led-no-core-with-cargo/blob/master/blink/arduino.json type TargetSpec struct { Inherits []string `json:"inherits,omitempty"` + InheritableOnly bool `json:"inheritable-only"` // this target is only meant to be inherited from, not used directly Triple string `json:"llvm-target,omitempty"` CPU string `json:"cpu,omitempty"` ABI string `json:"target-abi,omitempty"` // roughly equivalent to -mabi= flag @@ -148,6 +149,11 @@ func (spec *TargetSpec) loadFromGivenStr(str string) error { // resolveInherits loads inherited targets, recursively. func (spec *TargetSpec) resolveInherits() error { + // Save InheritableOnly before resolving, since it must not propagate + // from parent to child (a board target should not become inheritable-only + // just because its parent processor target is). + inheritableOnly := spec.InheritableOnly + // First create a new spec with all the inherited properties. newSpec := &TargetSpec{} for _, name := range spec.Inherits { @@ -173,6 +179,9 @@ func (spec *TargetSpec) resolveInherits() error { } *spec = *newSpec + // Restore InheritableOnly from the original spec, not from parents. + spec.InheritableOnly = inheritableOnly + return nil } @@ -239,10 +248,17 @@ func GetTargetSpecs() (map[string]*TargetSpec, error) { continue } path := filepath.Join(dir, entry.Name()) + spec, err := LoadTarget(&Options{Target: path}) if err != nil { return nil, fmt.Errorf("could not list target: %w", err) } + + if spec.InheritableOnly { + // Skip targets that are only meant to be inherited from, not used directly. + continue + } + if spec.FlashMethod == "" && spec.FlashCommand == "" && spec.Emulator == "" { // This doesn't look like a regular target file, but rather like // a parent target (such as targets/cortex-m.json). diff --git a/compileopts/target_test.go b/compileopts/target_test.go index 579c54f67b..d8a17a5e34 100644 --- a/compileopts/target_test.go +++ b/compileopts/target_test.go @@ -23,6 +23,37 @@ func TestLoadTarget(t *testing.T) { } } +func TestGetTargetSpecs_InheritableOnlyTargetsExcluded(t *testing.T) { + specs, err := GetTargetSpecs() + if err != nil { + t.Fatal("GetTargetSpecs failed:", err) + } + + // Inheritable-only processor-level targets should not appear in the listing. + inheritableOnlyTargets := []string{"esp32", "esp32c3", "esp32s3", "esp8266", "rp2040", "rp2350", "rp2350b"} + for _, name := range inheritableOnlyTargets { + if _, ok := specs[name]; ok { + t.Errorf("inheritable-only target %q should not appear in GetTargetSpecs", name) + } + } + + // Board targets that inherit from inheritable-only targets should still appear. + boardTargets := []string{"esp32-coreboard-v2", "pico"} + for _, name := range boardTargets { + if _, ok := specs[name]; !ok { + t.Errorf("board target %q should appear in GetTargetSpecs", name) + } + } +} + +func TestLoadTarget_InheritableOnlyTargetStillLoadable(t *testing.T) { + // Inheritable-only targets should still be loadable directly (for building). + _, err := LoadTarget(&Options{Target: "esp32"}) + if err != nil { + t.Errorf("LoadTarget should still load inheritable-only target esp32: %v", err) + } +} + func TestOverrideProperties(t *testing.T) { baseAutoStackSize := true base := &TargetSpec{ diff --git a/targets/esp32.json b/targets/esp32.json index 7aad3da4e9..2c7abd6993 100644 --- a/targets/esp32.json +++ b/targets/esp32.json @@ -1,5 +1,6 @@ { "inherits": ["xtensa"], + "inheritable-only": true, "cpu": "esp32", "features": "+atomctl,+bool,+clamps,+coprocessor,+debug,+density,+dfpaccel,+div32,+exception,+fp,+highpriinterrupts,+interrupt,+loop,+mac16,+memctl,+minmax,+miscsr,+mul32,+mul32high,+nsa,+prid,+regprotect,+rvector,+s32c1i,+sext,+threadptr,+timerint,+windowed", "build-tags": ["esp32", "esp"], diff --git a/targets/esp32c3.json b/targets/esp32c3.json index ea46d07882..583506c19f 100644 --- a/targets/esp32c3.json +++ b/targets/esp32c3.json @@ -1,5 +1,6 @@ { "inherits": ["riscv32"], + "inheritable-only": true, "features": "+32bit,+c,+m,+zmmul,-a,-b,-d,-e,-experimental-sdext,-experimental-sdtrig,-experimental-smctr,-experimental-ssctr,-experimental-svukte,-experimental-xqcia,-experimental-xqciac,-experimental-xqcicli,-experimental-xqcicm,-experimental-xqcics,-experimental-xqcicsr,-experimental-xqciint,-experimental-xqcilo,-experimental-xqcilsm,-experimental-xqcisls,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-experimental-zvbc32e,-experimental-zvkgs,-f,-h,-relax,-sha,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smcdeleg,-smcsrind,-smdbltrp,-smepmp,-smmpm,-smnpm,-smrnmi,-smstateen,-ssaia,-ssccfg,-ssccptr,-sscofpmf,-sscounterenw,-sscsrind,-ssdbltrp,-ssnpm,-sspm,-ssqosid,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-supm,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-svvptc,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xesppie,-xmipscmove,-xmipslsp,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-xwchc,-za128rs,-za64rs,-zaamo,-zabha,-zacas,-zalrsc,-zama16b,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfbfmin,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zicsr,-zifencei,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-ztso,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfbfmin,-zvfbfwma,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b", "build-tags": ["esp32c3", "esp"], "serial": "usb", diff --git a/targets/esp32s3.json b/targets/esp32s3.json index e47c6784d2..4950848a92 100644 --- a/targets/esp32s3.json +++ b/targets/esp32s3.json @@ -1,5 +1,6 @@ { "inherits": ["xtensa"], + "inheritable-only": true, "cpu": "esp32s3", "features": "+atomctl,+bool,+clamps,+coprocessor,+debug,+density,+div32,+esp32s3,+exception,+fp,+highpriinterrupts,+interrupt,+loop,+mac16,+memctl,+minmax,+miscsr,+mul32,+mul32high,+nsa,+prid,+regprotect,+rvector,+s32c1i,+sext,+threadptr,+timerint,+windowed", "build-tags": ["esp32s3", "esp"], diff --git a/targets/esp8266.json b/targets/esp8266.json index b6e4a3500f..83d5bcd1bb 100644 --- a/targets/esp8266.json +++ b/targets/esp8266.json @@ -1,5 +1,6 @@ { "inherits": ["xtensa"], + "inheritable-only": true, "cpu": "esp8266", "features": "+debug,+density,+exception,+extendedl32r,+highpriinterrupts,+interrupt,+mul32,+nsa,+prid,+regprotect,+rvector,+timerint", "build-tags": ["esp8266", "esp"], diff --git a/targets/rp2040.json b/targets/rp2040.json index 6470d57f50..e2969fea5a 100644 --- a/targets/rp2040.json +++ b/targets/rp2040.json @@ -1,5 +1,6 @@ { "inherits": ["cortex-m0plus"], + "inheritable-only": true, "build-tags": ["rp2040", "rp"], "scheduler": "tasks", "flash-1200-bps-reset": "true", diff --git a/targets/rp2350.json b/targets/rp2350.json index e3a6549fd2..f4567652da 100644 --- a/targets/rp2350.json +++ b/targets/rp2350.json @@ -1,5 +1,6 @@ { "inherits": ["cortex-m33"], + "inheritable-only": true, "build-tags": ["rp2350", "rp"], "scheduler": "tasks", "flash-1200-bps-reset": "true", diff --git a/targets/rp2350b.json b/targets/rp2350b.json index 5db4d48492..6e628c6b77 100644 --- a/targets/rp2350b.json +++ b/targets/rp2350b.json @@ -1,5 +1,6 @@ { "inherits": ["rp2350"], + "inheritable-only": true, "build-tags": ["rp2350b"], "serial-port": ["2e8a:000f"] } \ No newline at end of file