Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion cmd/cbuild2cmake/commands/root_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Arm Limited. All rights reserved.
* Copyright (c) 2024-2025 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -324,4 +324,18 @@ set(OUTPUTS_1
assert.Nil(err)
assert.False(mismatch)
})

t.Run("test image-only solution", func(t *testing.T) {
cmd := commands.NewRootCmd()
testCaseRoot := testRoot + "/run/solutions/image-only"
cbuildIdxFile := testCaseRoot + "/solution.cbuild-idx.yml"
cmd.SetArgs([]string{cbuildIdxFile, "--debug"})
err := cmd.Execute()
assert.Nil(err)

// check golden references
err, mismatch := inittest.CompareFiles(testCaseRoot+"/ref", testCaseRoot+"/tmp")
assert.Nil(err)
assert.False(mismatch)
})
}
22 changes: 18 additions & 4 deletions pkg/maker/maker.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type Vars struct {
SelectedToolchainConfig []string
SolutionTmpDir string
SolutionRoot string
SolutionName string
}

type Maker struct {
Expand All @@ -62,17 +63,30 @@ func (m *Maker) GenerateCMakeLists() error {
return err
}

// Get tmp directory
if len(m.CbuildIndex.BuildIdx.TmpDir) == 0 {
m.CbuildIndex.BuildIdx.TmpDir = "tmp"
}
m.SolutionTmpDir = path.Join(m.CbuildIndex.BaseDir, m.CbuildIndex.BuildIdx.TmpDir)

// Create roots.cmake
err = m.CMakeCreateRoots(m.SolutionRoot)
if err != nil {
return err
}

// Create CMakeLists.txt for image only solution
if m.CbuildIndex.BuildIdx.ImageOnly {
return m.CreateCMakeListsImageOnly()
}

// Process toolchain
err = m.ProcessToolchain()
if err != nil {
return err
}

// Create super project CMakeLists.txt
if len(m.CbuildIndex.BuildIdx.TmpDir) == 0 {
m.CbuildIndex.BuildIdx.TmpDir = "tmp"
}
m.SolutionTmpDir = path.Join(m.CbuildIndex.BaseDir, m.CbuildIndex.BuildIdx.TmpDir)
err = m.CreateSuperCMakeLists()
if err != nil {
return err
Expand Down
9 changes: 8 additions & 1 deletion pkg/maker/maker_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Arm Limited. All rights reserved.
* Copyright (c) 2024-2025 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -44,4 +44,11 @@ func TestMaker(t *testing.T) {
err := m.GenerateCMakeLists()
assert.Error(err)
})

t.Run("test maker with image only solution", func(t *testing.T) {
var m maker.Maker
m.Params.InputFile = testRoot + "/run/generic/imageOnly.cbuild-idx.yml"
err := m.GenerateCMakeLists()
assert.Nil(err)
})
}
9 changes: 8 additions & 1 deletion pkg/maker/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"os"
"path"
"path/filepath"
"regexp"
"slices"

"gopkg.in/yaml.v3"
Expand All @@ -22,6 +23,7 @@ type CbuildIndex struct {
GeneratedBy string `yaml:"generated-by"`
Cdefault string `yaml:"cdefault"`
Csolution string `yaml:"csolution"`
ImageOnly bool `yaml:"image-only"`
TmpDir string `yaml:"tmpdir"`
Cprojects []Cprojects `yaml:"cprojects"`
Cbuilds []Cbuilds `yaml:"cbuilds"`
Expand Down Expand Up @@ -275,7 +277,12 @@ func (m *Maker) ParseCbuildFiles() error {
cbuildIndex.BaseDir, _ = filepath.Abs(path.Dir(m.Params.InputFile))
cbuildIndex.BaseDir = filepath.ToSlash(cbuildIndex.BaseDir)
m.CbuildIndex = cbuildIndex
m.SolutionRoot = filepath.ToSlash(filepath.Dir(filepath.Join(cbuildIndex.BaseDir, cbuildIndex.BuildIdx.Csolution)))
m.SolutionRoot = filepath.Dir(filepath.Join(cbuildIndex.BaseDir, cbuildIndex.BuildIdx.Csolution))
m.SolutionRoot, _ = filepath.EvalSymlinks(m.SolutionRoot)
m.SolutionRoot = filepath.ToSlash(m.SolutionRoot)
m.SolutionName = filepath.Base(m.CbuildIndex.BuildIdx.Csolution)
reg := regexp.MustCompile(`(.*)\.csolution.ya?ml`)
m.SolutionName = reg.ReplaceAllString(m.SolutionName, "$1")

// Parse cbuild-set file
if m.Options.UseContextSet {
Expand Down
10 changes: 9 additions & 1 deletion pkg/maker/parser_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Arm Limited. All rights reserved.
* Copyright (c) 2024-2025 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -32,6 +32,7 @@ func TestParser(t *testing.T) {
assert.Equal("projectName", data.BuildIdx.Cbuilds[0].Project)
assert.Equal(".BuildType0+TargetType0", data.BuildIdx.Cbuilds[0].Configuration)
assert.Equal("projectName.BuildType1+TargetType1.cbuild.yml", data.BuildIdx.Cbuilds[0].DependsOn[0])
assert.False(data.BuildIdx.ImageOnly)
})

t.Run("test parsing cbuild.yml", func(t *testing.T) {
Expand Down Expand Up @@ -174,4 +175,11 @@ func TestParser(t *testing.T) {
assert.Equal("AC6", data.BuildSet.Compiler)
assert.Equal("projectName.BuildType0+TargetType0", data.BuildSet.Contexts[0].Context)
})

t.Run("test parsing image-only cbuild-idx.yml", func(t *testing.T) {
data, err := m.ParseCbuildIndexFile(testRoot + "/run/generic/imageOnly.cbuild-idx.yml")
assert.Nil(err)
assert.Equal("csolution version 2.11.0", data.BuildIdx.GeneratedBy)
assert.True(data.BuildIdx.ImageOnly)
})
}
45 changes: 27 additions & 18 deletions pkg/maker/superlists.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Arm Limited. All rights reserved.
* Copyright (c) 2024-2025 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -9,19 +9,17 @@ package maker
import (
"path"
"path/filepath"
"regexp"
"strconv"
"strings"

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

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

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

solutionRoot, _ := filepath.EvalSymlinks(m.SolutionRoot)
solutionRoot = filepath.ToSlash(solutionRoot)

var verbosity, logConfigure, stepLog string
if m.Options.Debug || m.Options.Verbose {
verbosity = " --verbose"
Expand All @@ -55,18 +50,12 @@ func (m *Maker) CreateSuperCMakeLists() error {
stepLog = "\n LOG TRUE"
}

// Create roots.cmake
err := m.CMakeCreateRoots(solutionRoot)
if err != nil {
return err
}

// Write content
content :=
`cmake_minimum_required(VERSION 3.27)
`cmake_minimum_required(VERSION ` + CMAKE_MIN_REQUIRED + `)
include(ExternalProject)

project("` + csolution + `" NONE)
project("` + m.SolutionName + `" NONE)

# Roots
include("roots.cmake")
Expand Down Expand Up @@ -135,7 +124,7 @@ foreach(INDEX RANGE ${CONTEXTS_LENGTH})
endforeach()` + m.ExecutesCommands(m.CbuildIndex.BuildIdx.Executes) + m.BuildDependencies() + `
`
superCMakeLists := path.Join(m.SolutionTmpDir, "CMakeLists.txt")
err = utils.UpdateFile(superCMakeLists, content)
err := utils.UpdateFile(superCMakeLists, content)
if err != nil {
return err
}
Expand Down Expand Up @@ -163,3 +152,23 @@ cmake_path(ABSOLUTE_PATH SOLUTION_ROOT NORMALIZE OUTPUT_VARIABLE SOLUTION_ROOT)

return err
}

func (m *Maker) CreateCMakeListsImageOnly() error {
// Write content
content :=
`cmake_minimum_required(VERSION ` + CMAKE_MIN_REQUIRED + `)

project("` + m.SolutionName + `" NONE)

# Roots
include("roots.cmake")` + m.ExecutesCommands(m.CbuildIndex.BuildIdx.Executes) + m.BuildDependencies() + `
`
pathCMakeLists := path.Join(m.SolutionTmpDir, "CMakeLists.txt")
err := utils.UpdateFile(pathCMakeLists, content)
if err != nil {
return err
}

log.Info("CMakeLists was successfully generated in the " + m.SolutionTmpDir + " directory")
return nil
}
8 changes: 8 additions & 0 deletions test/data/generic/imageOnly.cbuild-idx.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
build-idx:
generated-by: csolution version 2.11.0
csolution: iamgeOnly.csolution.yml
tmpdir: custom/tmp/path
image-only: true
cbuilds:
- cbuild: iamgeOnly+TargetType0.cbuild.yml
configuration: +TargetType0
1 change: 1 addition & 0 deletions test/data/solutions/image-only/images/image1.elf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# dummy image
41 changes: 41 additions & 0 deletions test/data/solutions/image-only/ref/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
cmake_minimum_required(VERSION 3.27)

project("solution" NONE)

# Roots
include("roots.cmake")

# Execute: Convert_Image1
set(INPUT
${SOLUTION_ROOT}/images/image1.elf
)
list(GET INPUT 0 INPUT_0)
set(OUTPUT
${SOLUTION_ROOT}/images/image2.hex
)
list(GET OUTPUT 0 OUTPUT_0)
add_custom_target(Convert_Image1 ALL DEPENDS ${OUTPUT})
add_custom_command(OUTPUT ${OUTPUT} DEPENDS ${INPUT}
COMMAND ${CMAKE_COMMAND} -E echo "Executing: Convert_Image1"
COMMAND ${CMAKE_COMMAND} -E echo "Simulate image conversion 1 > 2" && ${CMAKE_COMMAND} -E copy "${INPUT_0}" "${OUTPUT_0}"
)

# Execute: Convert_Image2
set(INPUT
${SOLUTION_ROOT}/images/image2.hex
)
list(GET INPUT 0 INPUT_0)
set(OUTPUT
${SOLUTION_ROOT}/images/image3.bin
)
list(GET OUTPUT 0 OUTPUT_0)
add_custom_target(Convert_Image2 ALL DEPENDS ${OUTPUT})
add_custom_command(OUTPUT ${OUTPUT} DEPENDS ${INPUT}
COMMAND ${CMAKE_COMMAND} -E echo "Executing: Convert_Image2"
COMMAND ${CMAKE_COMMAND} -E echo "Simulate image conversion 2 > 3" && ${CMAKE_COMMAND} -E copy "${INPUT_0}" "${OUTPUT_0}"
)

# Build dependencies
add_dependencies(Convert_Image2
Convert_Image1
)
29 changes: 29 additions & 0 deletions test/data/solutions/image-only/solution.cbuild-idx.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
build-idx:
generated-by: csolution version 0.0.0
csolution: solution.csolution.yml
cbuild-run: out/solution+CM0.cbuild-run.yml
tmpdir: tmp
image-only: true
cbuilds:
- cbuild: out/solution/CM0/solution+CM0.cbuild.yml
configuration: +CM0
messages:
info:
- solution.cbuild-pack.yml - file generated successfully
- solution+CM0.cbuild-run.yml - file generated successfully
- solution+CM0.cbuild.yml - file generated successfully
executes:
- execute: Convert_Image1
run: ${CMAKE_COMMAND} -E echo "Simulate image conversion 1 > 2" && ${CMAKE_COMMAND} -E copy ${INPUT_0} ${OUTPUT_0}
input:
- images/image1.elf
output:
- images/image2.hex
- execute: Convert_Image2
run: ${CMAKE_COMMAND} -E echo "Simulate image conversion 2 > 3" && ${CMAKE_COMMAND} -E copy ${INPUT_0} ${OUTPUT_0}
input:
- images/image2.hex
output:
- images/image3.bin
depends-on:
- Convert_Image1
36 changes: 36 additions & 0 deletions test/data/solutions/image-only/solution.csolution.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/Open-CMSIS-Pack/devtools/main/tools/projmgr/schemas/csolution.schema.json

solution:

packs:
- pack: ARM::RteTest_DFP

target-types:
- type: CM0
device: RteTest_ARMCM0
target-set:
- set:
debugger:
name: CMSIS-DAP
images:
- image: ./images/image1.elf
load: symbols
- image: ./images/image2.hex
load: image
- image: ./images/image3.bin
load: none

executes:
- execute: Convert_Image1
run: ${CMAKE_COMMAND} -E echo "Simulate image conversion 1 > 2" && ${CMAKE_COMMAND} -E copy $input(0)$ $output(0)$
input:
- $SolutionDir()$/images/image1.elf
output:
- $SolutionDir()$/images/image2.hex

- execute: Convert_Image2
run: ${CMAKE_COMMAND} -E echo "Simulate image conversion 2 > 3" && ${CMAKE_COMMAND} -E copy $input(0)$ $output(0)$
input:
- $SolutionDir()$/images/image2.hex
output:
- $SolutionDir()$/images/image3.bin
Loading