From 31e62ad0365e08af3927f367687becc7564b1623 Mon Sep 17 00:00:00 2001 From: Michal Gorecki Date: Mon, 2 Feb 2026 14:13:06 +0100 Subject: [PATCH 1/2] newt/sysinit: Add possibility to override sysinit prio from target This change allows overridding sysinit functions priority in target.yml. Example: pkg.init: ble_transport_ll_init: 10 modlog_init: MYNEWT_VAL(MODLOG_SYSINIT_STAGE) ble_transport_init: 202 Restrictions: 1. All sysinit functions included by the target must be explicitly overridden in target.yml. Additional functions may be listed, but they will be ignored if not included by the target. 2. The $before and $after keywords are not supported. --- newt/builder/targetbuild.go | 5 +-- newt/resolve/resolve.go | 11 +++--- newt/sysinit/sysinit.go | 69 ++++++++++++++++++++++++++++++++++--- 3 files changed, 74 insertions(+), 11 deletions(-) diff --git a/newt/builder/targetbuild.go b/newt/builder/targetbuild.go index 3792c4600f..acff56f049 100644 --- a/newt/builder/targetbuild.go +++ b/newt/builder/targetbuild.go @@ -23,12 +23,13 @@ import ( "bufio" "fmt" "io/ioutil" - "mynewt.apache.org/newt/newt/cfgv" "os" "path/filepath" "sort" "strings" + "mynewt.apache.org/newt/newt/cfgv" + log "github.com/sirupsen/logrus" "github.com/apache/mynewt-artifact/flash" @@ -240,7 +241,7 @@ func (t *TargetBuilder) ensureResolved(detectErr bool) error { var err error t.res, err = resolve.ResolveFull( - loaderSeeds, appSeeds, t.injectedSettings, t.bspPkg.FlashMap, detectErr) + loaderSeeds, appSeeds, t.injectedSettings, t.bspPkg.FlashMap, t.target.TargetY, detectErr) if err != nil { return err } diff --git a/newt/resolve/resolve.go b/newt/resolve/resolve.go index d930aa25bc..35f6969935 100644 --- a/newt/resolve/resolve.go +++ b/newt/resolve/resolve.go @@ -21,10 +21,12 @@ package resolve import ( "fmt" - "mynewt.apache.org/newt/newt/cfgv" "sort" "strings" + "mynewt.apache.org/newt/newt/cfgv" + "mynewt.apache.org/newt/newt/ycfg" + log "github.com/sirupsen/logrus" "mynewt.apache.org/newt/newt/extcmd" @@ -1026,7 +1028,7 @@ func (r *Resolver) resolveDeps() ([]*ResolvePackage, error) { // 1. Calculates the system configuration (syscfg). // 2. Determines which packages satisfy which API requirements. // 3. Resolves package dependencies by populating the resolver's package map. -func (r *Resolver) resolveDepsAndCfg() error { +func (r *Resolver) resolveDepsAndCfg(targetCfg ycfg.YCfg) error { if err := r.resolveHardDeps(); err != nil { return err } @@ -1071,7 +1073,7 @@ func (r *Resolver) resolveDepsAndCfg() error { lpkgs := RpkgSliceToLpkgSlice(r.rpkgSlice()) r.lcfg = logcfg.Read(lpkgs, &r.cfg) - r.sysinitCfg = sysinit.Read(lpkgs, &r.cfg) + r.sysinitCfg = sysinit.Read(lpkgs, &r.cfg, targetCfg) r.sysdownCfg = sysdown.Read(lpkgs, &r.cfg) r.preBuildCmdCfg = extcmd.Read("pre_build_cmds", lpkgs, &r.cfg, @@ -1169,6 +1171,7 @@ func ResolveFull( appSeeds []*pkg.LocalPackage, injectedSettings *cfgv.Settings, flashMap flashmap.FlashMap, + targetCfg ycfg.YCfg, detectErr bool) (*Resolution, error) { // First, calculate syscfg and determine which package provides each @@ -1180,7 +1183,7 @@ func ResolveFull( allSeeds := append(loaderSeeds, appSeeds...) r := newResolver(allSeeds, injectedSettings, flashMap) - if err := r.resolveDepsAndCfg(); err != nil { + if err := r.resolveDepsAndCfg(targetCfg); err != nil { return nil, err } diff --git a/newt/sysinit/sysinit.go b/newt/sysinit/sysinit.go index ee1caf3cf2..7ec9b9637b 100644 --- a/newt/sysinit/sysinit.go +++ b/newt/sysinit/sysinit.go @@ -22,12 +22,14 @@ package sysinit import ( "bytes" "fmt" - "github.com/spf13/cast" "io" - "mynewt.apache.org/newt/util" "sort" "strings" + "github.com/spf13/cast" + "mynewt.apache.org/newt/newt/ycfg" + "mynewt.apache.org/newt/util" + "mynewt.apache.org/newt/newt/newtutil" "mynewt.apache.org/newt/newt/pkg" "mynewt.apache.org/newt/newt/stage" @@ -169,7 +171,7 @@ func ResolveStageFuncsOrder(sfs []stage.StageFunc) ([]stage.StageFunc, error) { } return true }) - + // Put nodes without stages first, so they are resolved and put to // stack first - we do not want them to precede all nodes with stages. // While technically correct, it's better not to start sysinit with @@ -233,7 +235,51 @@ func ResolveStageFuncsOrder(sfs []stage.StageFunc) ([]stage.StageFunc, error) { return sfs, nil } -func Read(lpkgs []*pkg.LocalPackage, cfg *syscfg.Cfg) SysinitCfg { +func getTargetStageFuncs(tCfg ycfg.YCfg, cfg *syscfg.Cfg) ([]stage.StageFunc, error) { + initMap, _ := tCfg.GetValStringMap("pkg.init", nil) + var sfs []stage.StageFunc + + for name, stageDef := range initMap { + stageStr := cast.ToString(stageDef) + sf, err := stage.NewStageFunc(name, stageStr, nil, cfg) + if err != nil { + return nil, err + } + + sfs = append(sfs, sf) + } + + return sfs, nil +} + +func targetStageFuncsOverride(tStageFuncs []stage.StageFunc, pStageFuncs []stage.StageFunc) error { + indexByName := make(map[string]int, len(pStageFuncs)) + + for i := range pStageFuncs { + indexByName[pStageFuncs[i].Name] = i + } + + for _, tSF := range tStageFuncs { + if idx, ok := indexByName[tSF.Name]; ok { + pStageFuncs[idx].Stage = tSF.Stage + delete(indexByName, tSF.Name) + } + } + + missing := make([]string, 0, len(indexByName)) + for name := range indexByName { + missing = append(missing, name) + } + + if len(missing) != 0 { + sort.Strings(missing) + return util.NewNewtError("Missing pkg.init functions in target.yml:\n\t" + strings.Join(missing, "\n\t")) + } + + return nil +} + +func Read(lpkgs []*pkg.LocalPackage, cfg *syscfg.Cfg, tCfg ycfg.YCfg) SysinitCfg { scfg := SysinitCfg{ Conflicts: map[string][]stage.StageFunc{}, } @@ -242,6 +288,20 @@ func Read(lpkgs []*pkg.LocalPackage, cfg *syscfg.Cfg) SysinitCfg { scfg.readOnePkg(lpkg, cfg) } + tStageFuncs, err := getTargetStageFuncs(tCfg, cfg) + if err != nil { + scfg.InvalidSettings = append(scfg.InvalidSettings, err.Error()) + return scfg + } + + if tStageFuncs != nil { + err := targetStageFuncsOverride(tStageFuncs, scfg.StageFuncs) + if err != nil { + scfg.InvalidSettings = append(scfg.InvalidSettings, err.Error()) + return scfg + } + } + scfg.detectConflicts() // Don't try to resolve order if there are name conflicts since that @@ -251,7 +311,6 @@ func Read(lpkgs []*pkg.LocalPackage, cfg *syscfg.Cfg) SysinitCfg { return scfg } - var err error scfg.StageFuncs, err = ResolveStageFuncsOrder(scfg.StageFuncs) if err != nil { scfg.InvalidSettings = append(scfg.InvalidSettings, err.Error()) From bde842d173d936878efa883cf137570174bc4607 Mon Sep 17 00:00:00 2001 From: Michal Gorecki Date: Mon, 2 Feb 2026 11:17:04 +0100 Subject: [PATCH 2/2] ci: Add tests for sysinit prio override from target This adds unit tests for new functionality --- .github/newt_sysinit/{ => brief}/expected.txt | 0 .../newt_sysinit/override_fail/expected.txt | 5 ++++ .../override_success/expected.txt | 18 +++++++++++++ .github/targets/sysinit_override_fail/pkg.yml | 5 ++++ .../targets/sysinit_override_fail/target.yml | 24 +++++++++++++++++ .../targets/sysinit_override_success/pkg.yml | 5 ++++ .../sysinit_override_success/target.yml | 26 +++++++++++++++++++ .github/workflows/test_sysinit.yml | 21 ++++++++++++++- 8 files changed, 103 insertions(+), 1 deletion(-) rename .github/newt_sysinit/{ => brief}/expected.txt (100%) create mode 100644 .github/newt_sysinit/override_fail/expected.txt create mode 100644 .github/newt_sysinit/override_success/expected.txt create mode 100644 .github/targets/sysinit_override_fail/pkg.yml create mode 100644 .github/targets/sysinit_override_fail/target.yml create mode 100644 .github/targets/sysinit_override_success/pkg.yml create mode 100644 .github/targets/sysinit_override_success/target.yml diff --git a/.github/newt_sysinit/expected.txt b/.github/newt_sysinit/brief/expected.txt similarity index 100% rename from .github/newt_sysinit/expected.txt rename to .github/newt_sysinit/brief/expected.txt diff --git a/.github/newt_sysinit/override_fail/expected.txt b/.github/newt_sysinit/override_fail/expected.txt new file mode 100644 index 0000000000..b1f27081cd --- /dev/null +++ b/.github/newt_sysinit/override_fail/expected.txt @@ -0,0 +1,5 @@ +Error: Invalid sysinit definitions detected: + Missing pkg.init functions in target.yml: + ble_store_config_init + ble_transport_hs_init + diff --git a/.github/newt_sysinit/override_success/expected.txt b/.github/newt_sysinit/override_success/expected.txt new file mode 100644 index 0000000000..b34af68c6c --- /dev/null +++ b/.github/newt_sysinit/override_success/expected.txt @@ -0,0 +1,18 @@ +Brief sysinit config for targets/sysinit_override_success: + STAGE | PACKAGE | FUNCTION | SETTING +---------+---------------------------------------------------+-------------------------+------------------------ + 10 | @apache-mynewt-nimble/nimble/transport | ble_transport_ll_init | + 11 | @apache-mynewt-nimble/nimble/host/services/gatt | ble_svc_gatt_init | + 12 | @apache-mynewt-core/sys/stats/full | stats_module_init | + 100 | @apache-mynewt-core/sys/log/modlog | modlog_init | MODLOG_SYSINIT_STAGE + 101 | @apache-mynewt-nimble/nimble/host/store/config | ble_store_config_init | + 102 | @apache-mynewt-nimble/nimble/transport | ble_transport_hs_init | + 200 | @apache-mynewt-core/sys/shell | shell_init | + 201 | @apache-mynewt-nimble/nimble/controller | ble_ll_init | + 202 | @apache-mynewt-nimble/nimble/transport | ble_transport_init | + 300 | @apache-mynewt-nimble/nimble/host/services/ans | ble_svc_ans_init | + 400 | @apache-mynewt-nimble/nimble/host/services/gap | ble_svc_gap_init | + 401 | @apache-mynewt-core/sys/flash_map | flash_map_init | + 402 | @apache-mynewt-core/sys/log/full | log_init | + 403 | @apache-mynewt-core/sys/console/full | console_pkg_init | + 404 | @apache-mynewt-core/kernel/os | os_pkg_init | diff --git a/.github/targets/sysinit_override_fail/pkg.yml b/.github/targets/sysinit_override_fail/pkg.yml new file mode 100644 index 0000000000..3bfff4d55c --- /dev/null +++ b/.github/targets/sysinit_override_fail/pkg.yml @@ -0,0 +1,5 @@ +pkg.name: "targets/sysinit_override_fail" +pkg.type: target +pkg.description: +pkg.author: +pkg.homepage: diff --git a/.github/targets/sysinit_override_fail/target.yml b/.github/targets/sysinit_override_fail/target.yml new file mode 100644 index 0000000000..ebfd7c8414 --- /dev/null +++ b/.github/targets/sysinit_override_fail/target.yml @@ -0,0 +1,24 @@ +target.app: "@apache-mynewt-nimble/apps/btshell" +target.bsp: "@apache-mynewt-core/hw/bsp/nordic_pca10056" +target.build_profile: optimized + +pkg.init: + ble_transport_ll_init: 10 + ble_svc_gatt_init: 11 + stats_module_init: 12 + modlog_init: MYNEWT_VAL(MODLOG_SYSINIT_STAGE) + shell_init: 200 + ble_ll_init: 201 + ble_transport_init: 202 + + ble_svc_ans_init: 300 + ble_svc_gap_init: 400 + flash_map_init: 401 + log_init: 402 + console_pkg_init: 403 + os_pkg_init: 404 + + # Redundant init functions shall be ignored + dummy_1: 1 + dummy_2: 205 + dummy_3: 500 diff --git a/.github/targets/sysinit_override_success/pkg.yml b/.github/targets/sysinit_override_success/pkg.yml new file mode 100644 index 0000000000..ba10f2385b --- /dev/null +++ b/.github/targets/sysinit_override_success/pkg.yml @@ -0,0 +1,5 @@ +pkg.name: "targets/sysinit_override_success" +pkg.type: target +pkg.description: +pkg.author: +pkg.homepage: diff --git a/.github/targets/sysinit_override_success/target.yml b/.github/targets/sysinit_override_success/target.yml new file mode 100644 index 0000000000..fa3d7472d0 --- /dev/null +++ b/.github/targets/sysinit_override_success/target.yml @@ -0,0 +1,26 @@ +target.app: "@apache-mynewt-nimble/apps/btshell" +target.bsp: "@apache-mynewt-core/hw/bsp/nordic_pca10056" +target.build_profile: optimized + +pkg.init: + ble_transport_ll_init: 10 + ble_svc_gatt_init: 11 + stats_module_init: 12 + modlog_init: MYNEWT_VAL(MODLOG_SYSINIT_STAGE) + ble_store_config_init: 101 + ble_transport_hs_init: 102 + shell_init: 200 + ble_ll_init: 201 + ble_transport_init: 202 + + ble_svc_ans_init: 300 + ble_svc_gap_init: 400 + flash_map_init: 401 + log_init: 402 + console_pkg_init: 403 + os_pkg_init: 404 + + # Redundant init functions shall be ignored + dummy_1: 1 + dummy_2: 205 + dummy_3: 500 diff --git a/.github/workflows/test_sysinit.yml b/.github/workflows/test_sysinit.yml index f437cabfdd..3a9e1efa90 100644 --- a/.github/workflows/test_sysinit.yml +++ b/.github/workflows/test_sysinit.yml @@ -58,4 +58,23 @@ jobs: newt upgrade -v --escape=false apache-mynewt-core apache-mynewt-nimble newt info newt target sysinit brief nordic_pca10056_btshell > tmp.txt - diff -w tmp.txt ../.github/newt_sysinit/expected.txt + diff -w tmp.txt ../.github/newt_sysinit/brief/expected.txt + - name: Test_sysinit_override (success) + shell: bash + run: | + cp -r .github/targets/sysinit_override_success project/targets + cd project/ + newt upgrade -v --escape=false apache-mynewt-core apache-mynewt-nimble + newt info + newt build sysinit_override_success + newt target sysinit brief sysinit_override_success > tmp.txt + diff -w tmp.txt ../.github/newt_sysinit/override_success/expected.txt + - name: Test_sysinit_override (fail) + shell: bash + run: | + cp -r .github/targets/sysinit_override_fail project/targets + cd project/ + newt upgrade -v --escape=false apache-mynewt-core apache-mynewt-nimble + newt info + newt build sysinit_override_fail 2> tmp.txt || true + diff -w tmp.txt ../.github/newt_sysinit/override_fail/expected.txt