Skip to content

Commit 93ad99d

Browse files
committed
[cbuild2cmake] Add support for image-only solutions
1 parent 61a469f commit 93ad99d

File tree

10 files changed

+192
-26
lines changed

10 files changed

+192
-26
lines changed

cmd/cbuild2cmake/commands/root_test.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024 Arm Limited. All rights reserved.
2+
* Copyright (c) 2024-2025 Arm Limited. All rights reserved.
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -324,4 +324,18 @@ set(OUTPUTS_1
324324
assert.Nil(err)
325325
assert.False(mismatch)
326326
})
327+
328+
t.Run("test image-only solution", func(t *testing.T) {
329+
cmd := commands.NewRootCmd()
330+
testCaseRoot := testRoot + "/run/solutions/image-only"
331+
cbuildIdxFile := testCaseRoot + "/solution.cbuild-idx.yml"
332+
cmd.SetArgs([]string{cbuildIdxFile, "--debug"})
333+
err := cmd.Execute()
334+
assert.Nil(err)
335+
336+
// check golden references
337+
err, mismatch := inittest.CompareFiles(testCaseRoot+"/ref", testCaseRoot+"/tmp")
338+
assert.Nil(err)
339+
assert.False(mismatch)
340+
})
327341
}

pkg/maker/maker.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ type Vars struct {
4141
SelectedToolchainConfig []string
4242
SolutionTmpDir string
4343
SolutionRoot string
44+
SolutionName string
4445
}
4546

4647
type Maker struct {
@@ -62,17 +63,30 @@ func (m *Maker) GenerateCMakeLists() error {
6263
return err
6364
}
6465

66+
// Get tmp directory
67+
if len(m.CbuildIndex.BuildIdx.TmpDir) == 0 {
68+
m.CbuildIndex.BuildIdx.TmpDir = "tmp"
69+
}
70+
m.SolutionTmpDir = path.Join(m.CbuildIndex.BaseDir, m.CbuildIndex.BuildIdx.TmpDir)
71+
72+
// Create roots.cmake
73+
err = m.CMakeCreateRoots(m.SolutionRoot)
74+
if err != nil {
75+
return err
76+
}
77+
78+
// Create CMakeLists.txt for image only solution
79+
if m.CbuildIndex.BuildIdx.ImageOnly {
80+
return m.CreateCMakeListsImageOnly()
81+
}
82+
6583
// Process toolchain
6684
err = m.ProcessToolchain()
6785
if err != nil {
6886
return err
6987
}
7088

7189
// Create super project CMakeLists.txt
72-
if len(m.CbuildIndex.BuildIdx.TmpDir) == 0 {
73-
m.CbuildIndex.BuildIdx.TmpDir = "tmp"
74-
}
75-
m.SolutionTmpDir = path.Join(m.CbuildIndex.BaseDir, m.CbuildIndex.BuildIdx.TmpDir)
7690
err = m.CreateSuperCMakeLists()
7791
if err != nil {
7892
return err

pkg/maker/maker_test.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024 Arm Limited. All rights reserved.
2+
* Copyright (c) 2024-2025 Arm Limited. All rights reserved.
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -44,4 +44,11 @@ func TestMaker(t *testing.T) {
4444
err := m.GenerateCMakeLists()
4545
assert.Error(err)
4646
})
47+
48+
t.Run("test maker with image only solution", func(t *testing.T) {
49+
var m maker.Maker
50+
m.Params.InputFile = testRoot + "/run/generic/imageOnly.cbuild-idx.yml"
51+
err := m.GenerateCMakeLists()
52+
assert.Nil(err)
53+
})
4754
}

pkg/maker/parser.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"os"
1111
"path"
1212
"path/filepath"
13+
"regexp"
1314
"slices"
1415

1516
"gopkg.in/yaml.v3"
@@ -22,6 +23,7 @@ type CbuildIndex struct {
2223
GeneratedBy string `yaml:"generated-by"`
2324
Cdefault string `yaml:"cdefault"`
2425
Csolution string `yaml:"csolution"`
26+
ImageOnly bool `yaml:"image-only"`
2527
TmpDir string `yaml:"tmpdir"`
2628
Cprojects []Cprojects `yaml:"cprojects"`
2729
Cbuilds []Cbuilds `yaml:"cbuilds"`
@@ -275,7 +277,12 @@ func (m *Maker) ParseCbuildFiles() error {
275277
cbuildIndex.BaseDir, _ = filepath.Abs(path.Dir(m.Params.InputFile))
276278
cbuildIndex.BaseDir = filepath.ToSlash(cbuildIndex.BaseDir)
277279
m.CbuildIndex = cbuildIndex
278-
m.SolutionRoot = filepath.ToSlash(filepath.Dir(filepath.Join(cbuildIndex.BaseDir, cbuildIndex.BuildIdx.Csolution)))
280+
m.SolutionRoot = filepath.Dir(filepath.Join(cbuildIndex.BaseDir, cbuildIndex.BuildIdx.Csolution))
281+
m.SolutionRoot, _ = filepath.EvalSymlinks(m.SolutionRoot)
282+
m.SolutionRoot = filepath.ToSlash(m.SolutionRoot)
283+
m.SolutionName = filepath.Base(m.CbuildIndex.BuildIdx.Csolution)
284+
reg := regexp.MustCompile(`(.*)\.csolution.ya?ml`)
285+
m.SolutionName = reg.ReplaceAllString(m.SolutionName, "$1")
279286

280287
// Parse cbuild-set file
281288
if m.Options.UseContextSet {

pkg/maker/parser_test.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024 Arm Limited. All rights reserved.
2+
* Copyright (c) 2024-2025 Arm Limited. All rights reserved.
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -32,6 +32,7 @@ func TestParser(t *testing.T) {
3232
assert.Equal("projectName", data.BuildIdx.Cbuilds[0].Project)
3333
assert.Equal(".BuildType0+TargetType0", data.BuildIdx.Cbuilds[0].Configuration)
3434
assert.Equal("projectName.BuildType1+TargetType1.cbuild.yml", data.BuildIdx.Cbuilds[0].DependsOn[0])
35+
assert.False(data.BuildIdx.ImageOnly)
3536
})
3637

3738
t.Run("test parsing cbuild.yml", func(t *testing.T) {
@@ -174,4 +175,11 @@ func TestParser(t *testing.T) {
174175
assert.Equal("AC6", data.BuildSet.Compiler)
175176
assert.Equal("projectName.BuildType0+TargetType0", data.BuildSet.Contexts[0].Context)
176177
})
178+
179+
t.Run("test parsing image-only cbuild-idx.yml", func(t *testing.T) {
180+
data, err := m.ParseCbuildIndexFile(testRoot + "/run/generic/imageOnly.cbuild-idx.yml")
181+
assert.Nil(err)
182+
assert.Equal("csolution version 2.11.0", data.BuildIdx.GeneratedBy)
183+
assert.True(data.BuildIdx.ImageOnly)
184+
})
177185
}

pkg/maker/superlists.go

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024 Arm Limited. All rights reserved.
2+
* Copyright (c) 2024-2025 Arm Limited. All rights reserved.
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -9,19 +9,17 @@ package maker
99
import (
1010
"path"
1111
"path/filepath"
12-
"regexp"
1312
"strconv"
1413
"strings"
1514

1615
"github.com/Open-CMSIS-Pack/cbuild2cmake/pkg/utils"
1716
log "github.com/sirupsen/logrus"
1817
)
1918

20-
func (m *Maker) CreateSuperCMakeLists() error {
21-
csolution := filepath.Base(m.CbuildIndex.BuildIdx.Csolution)
22-
reg := regexp.MustCompile(`(.*)\.csolution.ya?ml`)
23-
csolution = reg.ReplaceAllString(csolution, "$1")
19+
const CMAKE_MIN_REQUIRED = "3.27"
2420

21+
func (m *Maker) CreateSuperCMakeLists() error {
22+
// Iterate over cbuilds
2523
var contexts, dirs, contextOutputs string
2624
for i, cbuild := range m.Cbuilds {
2725
contexts = contexts + " \"" + strings.ReplaceAll(cbuild.BuildDescType.Context, " ", "_") + "\"\n"
@@ -43,9 +41,6 @@ func (m *Maker) CreateSuperCMakeLists() error {
4341
contextOutputs += ")"
4442
}
4543

46-
solutionRoot, _ := filepath.EvalSymlinks(m.SolutionRoot)
47-
solutionRoot = filepath.ToSlash(solutionRoot)
48-
4944
var verbosity, logConfigure, stepLog string
5045
if m.Options.Debug || m.Options.Verbose {
5146
verbosity = " --verbose"
@@ -55,18 +50,12 @@ func (m *Maker) CreateSuperCMakeLists() error {
5550
stepLog = "\n LOG TRUE"
5651
}
5752

58-
// Create roots.cmake
59-
err := m.CMakeCreateRoots(solutionRoot)
60-
if err != nil {
61-
return err
62-
}
63-
6453
// Write content
6554
content :=
66-
`cmake_minimum_required(VERSION 3.27)
55+
`cmake_minimum_required(VERSION ` + CMAKE_MIN_REQUIRED + `)
6756
include(ExternalProject)
6857
69-
project("` + csolution + `" NONE)
58+
project("` + m.SolutionName + `" NONE)
7059
7160
# Roots
7261
include("roots.cmake")
@@ -135,7 +124,7 @@ foreach(INDEX RANGE ${CONTEXTS_LENGTH})
135124
endforeach()` + m.ExecutesCommands(m.CbuildIndex.BuildIdx.Executes) + m.BuildDependencies() + `
136125
`
137126
superCMakeLists := path.Join(m.SolutionTmpDir, "CMakeLists.txt")
138-
err = utils.UpdateFile(superCMakeLists, content)
127+
err := utils.UpdateFile(superCMakeLists, content)
139128
if err != nil {
140129
return err
141130
}
@@ -163,3 +152,23 @@ cmake_path(ABSOLUTE_PATH SOLUTION_ROOT NORMALIZE OUTPUT_VARIABLE SOLUTION_ROOT)
163152

164153
return err
165154
}
155+
156+
func (m *Maker) CreateCMakeListsImageOnly() error {
157+
// Write content
158+
content :=
159+
`cmake_minimum_required(VERSION ` + CMAKE_MIN_REQUIRED + `)
160+
161+
project("` + m.SolutionName + `" NONE)
162+
163+
# Roots
164+
include("roots.cmake")` + m.ExecutesCommands(m.CbuildIndex.BuildIdx.Executes) + m.BuildDependencies() + `
165+
`
166+
pathCMakeLists := path.Join(m.SolutionTmpDir, "CMakeLists.txt")
167+
err := utils.UpdateFile(pathCMakeLists, content)
168+
if err != nil {
169+
return err
170+
}
171+
172+
log.Info("CMakeLists was successfully generated in the " + m.SolutionTmpDir + " directory")
173+
return nil
174+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# dummy image
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
cmake_minimum_required(VERSION 3.27)
2+
3+
project("solution" NONE)
4+
5+
# Roots
6+
include("roots.cmake")
7+
8+
# Execute: Convert_Image1
9+
set(INPUT
10+
${SOLUTION_ROOT}/images/image1.elf
11+
)
12+
list(GET INPUT 0 INPUT_0)
13+
set(OUTPUT
14+
${SOLUTION_ROOT}/images/image2.hex
15+
)
16+
list(GET OUTPUT 0 OUTPUT_0)
17+
add_custom_target(Convert_Image1 ALL DEPENDS ${OUTPUT})
18+
add_custom_command(OUTPUT ${OUTPUT} DEPENDS ${INPUT}
19+
COMMAND ${CMAKE_COMMAND} -E echo "Executing: Convert_Image1"
20+
COMMAND ${CMAKE_COMMAND} -E echo "Simulate image conversion 1 > 2" && ${CMAKE_COMMAND} -E copy "${INPUT_0}" "${OUTPUT_0}"
21+
)
22+
23+
# Execute: Convert_Image2
24+
set(INPUT
25+
${SOLUTION_ROOT}/images/image2.hex
26+
)
27+
list(GET INPUT 0 INPUT_0)
28+
set(OUTPUT
29+
${SOLUTION_ROOT}/images/image3.bin
30+
)
31+
list(GET OUTPUT 0 OUTPUT_0)
32+
add_custom_target(Convert_Image2 ALL DEPENDS ${OUTPUT})
33+
add_custom_command(OUTPUT ${OUTPUT} DEPENDS ${INPUT}
34+
COMMAND ${CMAKE_COMMAND} -E echo "Executing: Convert_Image2"
35+
COMMAND ${CMAKE_COMMAND} -E echo "Simulate image conversion 2 > 3" && ${CMAKE_COMMAND} -E copy "${INPUT_0}" "${OUTPUT_0}"
36+
)
37+
38+
# Build dependencies
39+
add_dependencies(Convert_Image2
40+
Convert_Image1
41+
)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
build-idx:
2+
generated-by: csolution version 0.0.0
3+
csolution: solution.csolution.yml
4+
cbuild-run: out/solution+CM0.cbuild-run.yml
5+
tmpdir: tmp
6+
image-only: true
7+
cbuilds:
8+
- cbuild: out/solution/CM0/solution+CM0.cbuild.yml
9+
configuration: +CM0
10+
messages:
11+
info:
12+
- solution.cbuild-pack.yml - file generated successfully
13+
- solution+CM0.cbuild-run.yml - file generated successfully
14+
- solution+CM0.cbuild.yml - file generated successfully
15+
executes:
16+
- execute: Convert_Image1
17+
run: ${CMAKE_COMMAND} -E echo "Simulate image conversion 1 > 2" && ${CMAKE_COMMAND} -E copy ${INPUT_0} ${OUTPUT_0}
18+
input:
19+
- images/image1.elf
20+
output:
21+
- images/image2.hex
22+
- execute: Convert_Image2
23+
run: ${CMAKE_COMMAND} -E echo "Simulate image conversion 2 > 3" && ${CMAKE_COMMAND} -E copy ${INPUT_0} ${OUTPUT_0}
24+
input:
25+
- images/image2.hex
26+
output:
27+
- images/image3.bin
28+
depends-on:
29+
- Convert_Image1
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# yaml-language-server: $schema=https://raw.githubusercontent.com/Open-CMSIS-Pack/devtools/main/tools/projmgr/schemas/csolution.schema.json
2+
3+
solution:
4+
5+
packs:
6+
- pack: ARM::RteTest_DFP
7+
8+
target-types:
9+
- type: CM0
10+
device: RteTest_ARMCM0
11+
target-set:
12+
- set:
13+
debugger:
14+
name: CMSIS-DAP
15+
images:
16+
- image: ./images/image1.elf
17+
load: symbols
18+
- image: ./images/image2.hex
19+
load: image
20+
- image: ./images/image3.bin
21+
load: none
22+
23+
executes:
24+
- execute: Convert_Image1
25+
run: ${CMAKE_COMMAND} -E echo "Simulate image conversion 1 > 2" && ${CMAKE_COMMAND} -E copy $input(0)$ $output(0)$
26+
input:
27+
- $SolutionDir()$/images/image1.elf
28+
output:
29+
- $SolutionDir()$/images/image2.hex
30+
31+
- execute: Convert_Image2
32+
run: ${CMAKE_COMMAND} -E echo "Simulate image conversion 2 > 3" && ${CMAKE_COMMAND} -E copy $input(0)$ $output(0)$
33+
input:
34+
- $SolutionDir()$/images/image2.hex
35+
output:
36+
- $SolutionDir()$/images/image3.bin

0 commit comments

Comments
 (0)