Skip to content

Commit 4519360

Browse files
authored
Initial zephyr/west integration support
1 parent 3d41622 commit 4519360

File tree

19 files changed

+641
-8
lines changed

19 files changed

+641
-8
lines changed

cmd/cbuild2cmake/commands/root_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,4 +338,18 @@ set(OUTPUTS_1
338338
assert.Nil(err)
339339
assert.False(mismatch)
340340
})
341+
342+
t.Run("test west solution", func(t *testing.T) {
343+
cmd := commands.NewRootCmd()
344+
testCaseRoot := testRoot + "/run/solutions/west"
345+
cbuildIdxFile := testCaseRoot + "/solution.cbuild-idx.yml"
346+
cmd.SetArgs([]string{cbuildIdxFile, "--debug"})
347+
err := cmd.Execute()
348+
assert.Nil(err)
349+
350+
// check golden references
351+
err, mismatch := inittest.CompareFiles(testCaseRoot+"/ref", testCaseRoot+"/tmp")
352+
assert.Nil(err)
353+
assert.False(mismatch)
354+
})
341355
}

pkg/maker/contextlists.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func (m *Maker) CreateContextCMakeLists(index int) error {
4040
}
4141

4242
// Create toolchain.cmake
43-
err := m.CMakeCreateToolchain(index, contextDir)
43+
err := m.CMakeCreateToolchain(index, contextDir, true)
4444
if err != nil {
4545
return err
4646
}
@@ -161,14 +161,18 @@ include("components.cmake")
161161
return err
162162
}
163163

164-
func (m *Maker) CMakeCreateToolchain(index int, contextDir string) error {
164+
func (m *Maker) CMakeCreateToolchain(index int, contextDir string, inc bool) error {
165165
toolchainConfig, _ := filepath.Rel(m.EnvVars.CompilerRoot, m.SelectedToolchainConfig[index])
166166
toolchainConfig = "${CMSIS_COMPILER_ROOT}/" + filepath.ToSlash(toolchainConfig)
167+
var include string
168+
if inc {
169+
include = "include(\"" + toolchainConfig + "\")\n"
170+
}
167171
content := `# toolchain.cmake
168172
169173
set(REGISTERED_TOOLCHAIN_ROOT "` + m.RegisteredToolchains[m.SelectedToolchainVersion[index]].Path + `")
170174
set(REGISTERED_TOOLCHAIN_VERSION "` + m.SelectedToolchainVersion[index].String() + `")
171-
include("` + toolchainConfig + `")
175+
` + include + `
172176
`
173177
filename := path.Join(contextDir, "toolchain.cmake")
174178
err := utils.UpdateFile(filename, content)

pkg/maker/contextlists_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (c) 2025 Arm Limited. All rights reserved.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package maker_test
8+
9+
import (
10+
"testing"
11+
12+
"github.com/Open-CMSIS-Pack/cbuild2cmake/pkg/maker"
13+
"github.com/stretchr/testify/assert"
14+
)
15+
16+
func TestContextLists(t *testing.T) {
17+
assert := assert.New(t)
18+
19+
t.Run("test context cmakelists creation", func(t *testing.T) {
20+
var m maker.Maker
21+
m.Params.InputFile = testRoot + "/run/solutions/build-cpp/solution.cbuild-idx.yml"
22+
err := m.GenerateCMakeLists()
23+
assert.Nil(err)
24+
for index := range m.Cbuilds {
25+
err = m.CreateContextCMakeLists(index)
26+
assert.Nil(err)
27+
}
28+
})
29+
}

pkg/maker/maker.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,11 @@ func (m *Maker) GenerateCMakeLists() error {
9494

9595
// Create context specific CMake files
9696
for index := range m.Cbuilds {
97-
err = m.CreateContextCMakeLists(index)
97+
if m.CbuildIndex.BuildIdx.Cbuilds[index].West {
98+
err = m.CreateWestCMakeLists(index)
99+
} else {
100+
err = m.CreateContextCMakeLists(index)
101+
}
98102
if err != nil {
99103
return err
100104
}

pkg/maker/maker_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,11 @@ func TestMaker(t *testing.T) {
5151
err := m.GenerateCMakeLists()
5252
assert.Nil(err)
5353
})
54+
55+
t.Run("test maker with west solution", func(t *testing.T) {
56+
var m maker.Maker
57+
m.Params.InputFile = testRoot + "/run/solutions/west/solution.cbuild-idx.yml"
58+
err := m.GenerateCMakeLists()
59+
assert.Nil(err)
60+
})
5461
}

pkg/maker/parser.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ type Cbuild struct {
7474
Generators []struct{} `yaml:"generators"`
7575
ConstructedFiles []Files `yaml:"constructed-files"`
7676
Licenses []struct{} `yaml:"licenses"`
77+
West West `yaml:"west"`
7778
} `yaml:"build"`
7879
BaseDir string
7980
ContextRoot string
@@ -94,6 +95,7 @@ type Cbuilds struct {
9495
Project string `yaml:"project"`
9596
Configuration string `yaml:"configuration"`
9697
DependsOn []string `yaml:"depends-on"`
98+
West bool `yaml:"west"`
9799
}
98100

99101
type Clayers struct {
@@ -241,6 +243,15 @@ type Packs struct {
241243
Path string `yaml:"path"`
242244
}
243245

246+
type West struct {
247+
ProjectId string `yaml:"project-id"`
248+
AppPath string `yaml:"app-path"`
249+
Board string `yaml:"board"`
250+
Device string `yaml:"device"`
251+
WestDefs []interface{} `yaml:"west-defs"`
252+
WestOpt []string `yaml:"west-opt"`
253+
}
254+
244255
func (m *Maker) ParseCbuildIndexFile(cbuildIndexFile string) (data CbuildIndex, err error) {
245256
yfile, err := os.ReadFile(cbuildIndexFile)
246257
if err != nil {

pkg/maker/superlists.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@ const CMAKE_MIN_REQUIRED = "3.27"
2020

2121
func (m *Maker) CreateSuperCMakeLists() error {
2222
// Iterate over cbuilds
23-
var contexts, dirs, contextOutputs string
23+
var contexts, dirs, westContextFlags, contextOutputs string
24+
west := false
2425
for i, cbuild := range m.Cbuilds {
2526
contexts = contexts + " \"" + strings.ReplaceAll(cbuild.BuildDescType.Context, " ", "_") + "\"\n"
2627
dirs = dirs + " \"${CMAKE_CURRENT_SOURCE_DIR}/" + cbuild.BuildDescType.Context + "\"\n"
28+
west = west || (cbuild.BuildDescType.West.AppPath != "")
29+
westContextFlags = westContextFlags + " \"" + strconv.FormatBool(west) + "\"\n"
2730

2831
var contextOutputsName = "OUTPUTS_" + strconv.Itoa(i+1)
2932
contextOutputs += "\nset(" + contextOutputsName + "\n"
@@ -41,6 +44,13 @@ func (m *Maker) CreateSuperCMakeLists() error {
4144
contextOutputs += ")"
4245
}
4346

47+
var westContexts, westContextCheck, westTarget string
48+
if west {
49+
westContexts = "\nset(WEST_CONTEXTS\n" + westContextFlags + ")\n"
50+
westContextCheck = "\n list(GET WEST_CONTEXTS ${INDEX} WEST_CONTEXT)\n if(WEST_CONTEXT)\n set(WEST_TARGET \"--target west\")\n endif()"
51+
westTarget = " ${WEST_TARGET}"
52+
}
53+
4454
var verbosity, logConfigure, stepLog string
4555
if m.Options.Debug || m.Options.Verbose {
4656
verbosity = " --verbose"
@@ -68,7 +78,7 @@ math(EXPR CONTEXTS_LENGTH "${CONTEXTS_LENGTH}-1")
6878
6979
set(DIRS
7080
` + dirs + `)
71-
` + contextOutputs + `
81+
` + westContexts + contextOutputs + `
7282
7383
set(ARGS
7484
"-DSOLUTION_ROOT=${SOLUTION_ROOT}"
@@ -84,7 +94,7 @@ foreach(INDEX RANGE ${CONTEXTS_LENGTH})
8494
8595
math(EXPR N "${INDEX}+1")
8696
list(GET CONTEXTS ${INDEX} CONTEXT)
87-
list(GET DIRS ${INDEX} DIR)
97+
list(GET DIRS ${INDEX} DIR)` + westContextCheck + `
8898
8999
# Create external project, set configure and build steps
90100
ExternalProject_Add(${CONTEXT}
@@ -95,7 +105,7 @@ foreach(INDEX RANGE ${CONTEXTS_LENGTH})
95105
TEST_COMMAND ""
96106
CONFIGURE_COMMAND ${CMAKE_COMMAND} -G Ninja -S <SOURCE_DIR> -B <BINARY_DIR> ${ARGS}
97107
BUILD_COMMAND ${CMAKE_COMMAND} -E echo "Building CMake target '${CONTEXT}'"
98-
COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR>` + verbosity + `
108+
COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR>` + westTarget + verbosity + `
99109
BUILD_ALWAYS TRUE
100110
BUILD_BYPRODUCTS ${OUTPUTS_${N}}` + logConfigure + `
101111
USES_TERMINAL_BUILD ON

pkg/maker/west.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Copyright (c) 2025 Arm Limited. All rights reserved.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package maker
8+
9+
import (
10+
"path"
11+
"path/filepath"
12+
"strings"
13+
14+
"github.com/Open-CMSIS-Pack/cbuild2cmake/pkg/utils"
15+
)
16+
17+
var WestToolchainMap = map[string]string{
18+
"AC6": "armclang",
19+
"GCC": "gnuarmemb",
20+
"IAR": "iar",
21+
"CLANG": "llvm",
22+
}
23+
24+
func (m *Maker) CreateWestCMakeLists(index int) error {
25+
cbuild := &m.Cbuilds[index]
26+
cbuild.ContextRoot, _ = filepath.Rel(m.SolutionRoot, cbuild.BaseDir)
27+
cbuild.ContextRoot = filepath.ToSlash(cbuild.ContextRoot)
28+
cbuild.Toolchain = m.RegisteredToolchains[m.SelectedToolchainVersion[index]].Name
29+
outDir := cbuild.AddRootPrefix(cbuild.ContextRoot, cbuild.BuildDescType.OutputDirs.Outdir)
30+
contextDir := path.Join(m.SolutionTmpDir, cbuild.BuildDescType.Context)
31+
westApp := cbuild.AddRootPrefix(cbuild.ContextRoot, cbuild.BuildDescType.West.AppPath)
32+
westToolchain := WestToolchainMap[cbuild.BuildDescType.Compiler]
33+
34+
var westOptions, westDefs string
35+
var westOptionsRef, westDefsRef string
36+
for _, opt := range cbuild.BuildDescType.West.WestOpt {
37+
westOptions += "\n " + opt
38+
}
39+
if len(westOptions) > 0 {
40+
westOptions = "\nset(WEST_OPTIONS" + westOptions + "\n)"
41+
westOptionsRef = " ${WEST_OPTIONS}"
42+
}
43+
44+
for _, define := range cbuild.BuildDescType.West.WestDefs {
45+
key, value := utils.GetDefine(define)
46+
def := key
47+
if len(value) > 0 {
48+
def += "=" + value
49+
}
50+
westDefs += "\n -D" + def
51+
}
52+
if len(westDefs) > 0 {
53+
westDefs = "\nset(WEST_DEFS" + westDefs + "\n)"
54+
westDefsRef = " -- ${WEST_DEFS}"
55+
}
56+
57+
// Create toolchain.cmake
58+
err := m.CMakeCreateToolchain(index, contextDir, false)
59+
if err != nil {
60+
return err
61+
}
62+
63+
// Create CMakeLists content
64+
content := `cmake_minimum_required(VERSION 3.27)
65+
66+
# Roots
67+
include("../roots.cmake")
68+
69+
set(CONTEXT ` + strings.ReplaceAll(cbuild.BuildDescType.Context, " ", "_") + `)
70+
set(TARGET ${CONTEXT})
71+
set(OUT_DIR "` + outDir + `")
72+
set(WEST_BOARD "` + cbuild.BuildDescType.West.Board + `")
73+
set(WEST_APP "` + westApp + `")
74+
75+
# Toolchain config map
76+
include("toolchain.cmake")
77+
78+
# Setup project
79+
project(${CONTEXT} LANGUAGES NONE)
80+
` + westOptions + westDefs + `
81+
82+
# Environment variables
83+
set(ZEPHYR_TOOLCHAIN_PATH "${REGISTERED_TOOLCHAIN_ROOT}/..")
84+
cmake_path(ABSOLUTE_PATH ZEPHYR_TOOLCHAIN_PATH NORMALIZE OUTPUT_VARIABLE ZEPHYR_TOOLCHAIN_PATH)
85+
set(ENV_VARS
86+
` + strings.ToUpper(westToolchain) + `_TOOLCHAIN_PATH="${ZEPHYR_TOOLCHAIN_PATH}"
87+
ZEPHYR_TOOLCHAIN_VARIANT="` + westToolchain + `"
88+
)
89+
90+
# Compilation database
91+
add_custom_target(database
92+
COMMAND cmake -E env ${ENV_VARS} west build -b ${WEST_BOARD} -d "${OUT_DIR}" -p auto --cmake-only` + westOptionsRef + ` "${WEST_APP}"` + westDefsRef + `
93+
USES_TERMINAL
94+
)
95+
96+
# West build
97+
add_custom_target(west
98+
COMMAND cmake -E env ${ENV_VARS} west build -b ${WEST_BOARD} -d "${OUT_DIR}" -p auto` + westOptionsRef + ` "${WEST_APP}"` + westDefsRef + `
99+
USES_TERMINAL
100+
)
101+
`
102+
// Update CMakeLists.txt
103+
contextCMakeLists := path.Join(contextDir, "CMakeLists.txt")
104+
err = utils.UpdateFile(contextCMakeLists, content)
105+
if err != nil {
106+
return err
107+
}
108+
return err
109+
}

pkg/maker/west_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (c) 2025 Arm Limited. All rights reserved.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package maker_test
8+
9+
import (
10+
"testing"
11+
12+
"github.com/Open-CMSIS-Pack/cbuild2cmake/pkg/maker"
13+
"github.com/stretchr/testify/assert"
14+
)
15+
16+
func TestWest(t *testing.T) {
17+
assert := assert.New(t)
18+
19+
t.Run("test west cmakelists creation", func(t *testing.T) {
20+
var m maker.Maker
21+
m.Params.InputFile = testRoot + "/run/solutions/west/solution.cbuild-idx.yml"
22+
err := m.GenerateCMakeLists()
23+
assert.Nil(err)
24+
for index := range m.Cbuilds {
25+
err = m.CreateWestCMakeLists(index)
26+
assert.Nil(err)
27+
}
28+
})
29+
}

0 commit comments

Comments
 (0)