From c96877439c2af5d18b85c91a6a239c064279c75b Mon Sep 17 00:00:00 2001 From: Daniel Brondani Date: Fri, 9 Feb 2024 11:23:05 +0100 Subject: [PATCH] Generate compile options at context, component, group and file levels --- pkg/maker/buildcontent.go | 232 +++++++++++++++++----- pkg/maker/buildcontent_test.go | 52 +++++ pkg/maker/contextlists.go | 44 +++- pkg/maker/parser_test.go | 4 + test/data/generic/contextName0.cbuild.yml | 5 + 5 files changed, 273 insertions(+), 64 deletions(-) diff --git a/pkg/maker/buildcontent.go b/pkg/maker/buildcontent.go index 9be787e..3007908 100644 --- a/pkg/maker/buildcontent.go +++ b/pkg/maker/buildcontent.go @@ -128,61 +128,6 @@ func CMakeAddLibrary(name string, buildFiles BuildFiles) string { return content } -func CMakeTargetIncludeDirectoriesFromFiles(name string, buildFiles BuildFiles) string { - content := "\ntarget_include_directories(" + name - for _, scope := range sortedmap.AsSortedMap(buildFiles.Include) { - content += "\n " + scope.Key - for _, language := range sortedmap.AsSortedMap(scope.Value) { - if language.Key == "ALL" { - for _, file := range language.Value { - content += "\n \"" + file + "\"" - } - } else { - content += "\n " + "$<$:" - for _, file := range language.Value { - content += "\n \"" + file + "\"" - } - content += "\n >" - } - } - } - content += "\n)" - return content -} - -func CMakeTargetIncludeDirectories(name string, scope string, includes []string) string { - content := "\ntarget_include_directories(" + name + " " + scope - for _, include := range includes { - content += "\n \"" + include + "\"" - } - content += "\n)" - return content -} - -func CMakeTargetCompileDefinitions(name string, scope string, defines []interface{}) string { - content := "\ntarget_compile_definitions(" + name + " " + scope - for _, define := range defines { - key, value := utils.GetDefine(define) - content += "\n " + key - if len(value) > 0 { - content += "=" + value - } - } - content += "\n)" - return content -} - -func GroupsAndComponentsList(cbuild Cbuild) string { - var content string - for _, groups := range cbuild.BuildDescType.Groups { - content += "\n Group_" + ReplaceDelimiters(groups.Group) - } - for _, component := range cbuild.BuildDescType.Components { - content += "\n " + ReplaceDelimiters(component.Component) - } - return content -} - func ProcessorOptions(cbuild Cbuild) string { content := "\nset(CPU " + cbuild.BuildDescType.Processor.Core + ")" @@ -246,6 +191,183 @@ func ProcessorOptions(cbuild Cbuild) string { return content } +func CMakeTargetIncludeDirectoriesFromFiles(name string, buildFiles BuildFiles) string { + content := "\ntarget_include_directories(" + name + for _, scope := range sortedmap.AsSortedMap(buildFiles.Include) { + content += "\n " + scope.Key + for _, language := range sortedmap.AsSortedMap(scope.Value) { + if language.Key == "ALL" { + for _, file := range language.Value { + content += "\n \"" + file + "\"" + } + } else { + content += "\n " + "$<$:" + for _, file := range language.Value { + content += "\n \"" + file + "\"" + } + content += "\n >" + } + } + } + content += "\n)" + return content +} + +func CMakeTargetIncludeDirectories(name string, scope string, includes []string) string { + content := "\ntarget_include_directories(" + name + " " + scope + "\n " + content += ListIncludeDirectories(includes, "\n ", true) + content += "\n)" + return content +} + +func CMakeSetFileProperties(file Files) string { + var content string + hasIncludes := len(file.AddPath) > 0 + hasDefines := len(file.Define) > 0 + hasMisc := !IsCompileMiscEmpty(file.Misc) + if hasIncludes || hasDefines || hasMisc { + content = "\nset_source_files_properties(\"" + file.File + "\" PROPERTIES" + if hasIncludes { + content += "\n INCLUDE_DIRECTORIES \"" + ListIncludeDirectories(file.AddPath, ";", false) + "\"" + } + if hasDefines { + content += "\n COMPILE_DEFINITIONS \"" + ListCompileDefinitions(file.Define, ";") + "\"" + } + if hasMisc { + content += "\n COMPILE_OPTIONS \"" + GetFileMisc(file, ";") + "\"" + } + content += "\n)\n" + } + return content +} + +func CMakeTargetCompileDefinitions(name string, scope string, defines []interface{}) string { + content := "\ntarget_compile_definitions(" + name + " " + scope + "\n " + content += ListCompileDefinitions(defines, "\n ") + content += "\n)" + return content +} + +func ListIncludeDirectories(includes []string, delimiter string, quoted bool) string { + if quoted { + var includesList []string + for _, include := range includes { + includesList = append(includesList, "\""+include+"\"") + } + return strings.Join(includesList, delimiter) + } + return strings.Join(includes, delimiter) +} + +func ListCompileDefinitions(defines []interface{}, delimiter string) string { + var definesList []string + for _, define := range defines { + key, value := utils.GetDefine(define) + pair := key + if len(value) > 0 { + pair += "=" + value + } + definesList = append(definesList, pair) + } + return strings.Join(definesList, delimiter) +} + +func ListGroupsAndComponents(cbuild Cbuild) string { + // get last child group names + content := GetLastChildGroupNamesRecursively("Group", cbuild.BuildDescType.Groups) + // get component names + for _, component := range cbuild.BuildDescType.Components { + content += "\n " + ReplaceDelimiters(component.Component) + } + return content +} + +func GetLastChildGroupNamesRecursively(parent string, groups []Groups) string { + var content string + for _, group := range groups { + name := parent + "_" + ReplaceDelimiters(group.Group) + if len(group.Groups) > 0 { + // get children group names recursively + content += GetLastChildGroupNamesRecursively(name, group.Groups) + } else { + // last child + content += "\n " + name + } + } + return content +} + +func CMakeTargetCompileOptionsGlobal(name string, scope string, cbuild Cbuild) string { + // options from context settings + content := "\ntarget_compile_options(" + name + " " + scope + "\n ${CC_CPU}" + if len(cbuild.BuildDescType.Processor.Trustzone) > 0 { + content += "\n ${CC_SECURE}" + } + if len(cbuild.BuildDescType.Processor.BranchProtection) > 0 { + content += "\n ${CC_BRANCHPROT}" + } + if len(cbuild.BuildDescType.Processor.Endian) > 0 { + content += "\n ${CC_BYTE_ORDER}" + } + // misc options + content += ListMiscOptions(cbuild.BuildDescType.Misc) + content += "\n)" + return content +} + +func CMakeTargetCompileOptions(name string, scope string, misc Misc) string { + content := "\ntarget_compile_options(" + name + " " + scope + content += ListMiscOptions(misc) + content += "\n)" + return content +} + +func IsCompileMiscEmpty(misc Misc) bool { + if len(misc.ASM) > 0 || len(misc.C) > 0 || len(misc.CPP) > 0 || len(misc.CCPP) > 0 { + return false + } + return true +} + +func ListMiscOptions(misc Misc) string { + var content string + if len(misc.ASM) > 0 { + content += LangugeSpecificCompileOptions("ASM", misc.ASM) + } + if len(misc.C) > 0 { + content += LangugeSpecificCompileOptions("C", misc.C) + } + if len(misc.CPP) > 0 { + content += LangugeSpecificCompileOptions("CXX", misc.CPP) + } + if len(misc.CCPP) > 0 { + content += LangugeSpecificCompileOptions("C,CXX", misc.CCPP) + } + return content +} + +func GetFileMisc(file Files, delimiter string) string { + var misc []string + switch file.Category { + case "sourceAsm": + misc = file.Misc.ASM + case "sourceC": + misc = file.Misc.C + case "sourceCpp": + misc = file.Misc.CPP + } + return strings.Join(misc, delimiter) +} + +func LangugeSpecificCompileOptions(language string, misc []string) string { + content := "\n " + "$<$:" + for _, option := range misc { + content += "\n " + option + } + content += "\n >" + return content +} + func LinkerOptions(cbuild Cbuild) string { content := ` set(LD_SCRIPT "` + cbuild.BuildDescType.Linker.Script + `") diff --git a/pkg/maker/buildcontent_test.go b/pkg/maker/buildcontent_test.go index 11c2fff..34f5879 100644 --- a/pkg/maker/buildcontent_test.go +++ b/pkg/maker/buildcontent_test.go @@ -103,4 +103,56 @@ func TestBuildContent(t *testing.T) { assert.Contains(content, "includes") assert.Contains(content, "includes-c") }) + + t.Run("test cmake target compile options", func(t *testing.T) { + var misc = maker.Misc{ + ASM: []string{"-asm-flag"}, + C: []string{"-c-flag"}, + CPP: []string{"-cpp-flag"}, + CCPP: []string{"-c-cpp-flag"}, + } + content := maker.CMakeTargetCompileOptions("TARGET", "PUBLIC", misc) + assert.Contains(content, "$<$:\n -asm-flag") + assert.Contains(content, "$<$:\n -c-flag") + assert.Contains(content, "$<$:\n -cpp-flag") + assert.Contains(content, "$<$:\n -c-cpp-flag") + }) + + t.Run("test language specific compile options", func(t *testing.T) { + var misc = maker.Misc{ + ASM: []string{"-asm-flag"}, + } + content := maker.LangugeSpecificCompileOptions("ASM", misc.ASM) + assert.Contains(content, "$<$:\n -asm-flag") + }) + + t.Run("test get file misc", func(t *testing.T) { + var files = []maker.Files{ + { + Category: "sourceAsm", + Misc: maker.Misc{ + ASM: []string{"-asm-flag"}, + }, + }, + { + Category: "sourceC", + Misc: maker.Misc{ + C: []string{"-c-flag"}, + }, + }, + { + Category: "sourceCpp", + Misc: maker.Misc{ + CPP: []string{"-cpp-flag"}, + }, + }, + } + content := maker.GetFileMisc(files[0], ";") + assert.Contains(content, "-asm-flag") + content = maker.GetFileMisc(files[1], ";") + assert.Contains(content, "-c-flag") + content = maker.GetFileMisc(files[2], ";") + assert.Contains(content, "-cpp-flag") + }) + } diff --git a/pkg/maker/contextlists.go b/pkg/maker/contextlists.go index 2fbceb0..5b01905 100644 --- a/pkg/maker/contextlists.go +++ b/pkg/maker/contextlists.go @@ -70,11 +70,13 @@ add_library(${CONTEXT}_GLOBAL INTERFACE) # Defines` + CMakeTargetCompileDefinitions("${CONTEXT}_GLOBAL", "INTERFACE", cbuild.BuildDescType.Define) + ` +# Compile options` + CMakeTargetCompileOptionsGlobal("${CONTEXT}_GLOBAL", "INTERFACE", cbuild) + ` + # Add groups and components include("groups.cmake") include("components.cmake") target_link_libraries(${CONTEXT} - ${CONTEXT}_GLOBAL` + GroupsAndComponentsList(cbuild) + ` + ${CONTEXT}_GLOBAL` + ListGroupsAndComponents(cbuild) + ` ) # Linker options` + LinkerOptions(cbuild) + ` @@ -105,7 +107,6 @@ target_link_libraries(${CONTEXT} func (m *Maker) CMakeCreateGroups(groups []Groups, contextDir string) error { content := "# groups.cmake\n" content += CMakeCreateGroupRecursively("Group", groups) - content += "\n" filename := path.Join(contextDir, "groups.cmake") err := utils.UpdateFile(filename, content) @@ -116,11 +117,18 @@ func (m *Maker) CMakeCreateGroups(groups []Groups, contextDir string) error { return err } -func CMakeCreateGroupRecursively(name string, groups []Groups) string { +func CMakeCreateGroupRecursively(parent string, groups []Groups) string { var content string for _, group := range groups { buildFiles := ClassifyFiles(group.Files) - name += "_" + ReplaceDelimiters(group.Group) + name := parent + "_" + ReplaceDelimiters(group.Group) + hasChildren := len(group.Groups) > 0 + // default private scope + scope := "PRIVATE" + if hasChildren { + // make scope public to its children + scope = "PUBLIC" + } // add_library content += "\n# group " + group.Group content += CMakeAddLibrary(name, buildFiles) @@ -129,16 +137,30 @@ func CMakeCreateGroupRecursively(name string, groups []Groups) string { content += CMakeTargetIncludeDirectoriesFromFiles(name, buildFiles) } if len(group.AddPath) > 0 { - content += CMakeTargetIncludeDirectories(name, "PRIVATE", group.AddPath) + content += CMakeTargetIncludeDirectories(name, scope, group.AddPath) } // target_compile_definitions if len(group.Define) > 0 { - content += CMakeTargetCompileDefinitions(name, "PRIVATE", group.Define) + content += CMakeTargetCompileDefinitions(name, scope, group.Define) + } + // target_compile_options + if !IsCompileMiscEmpty(group.Misc) { + content += CMakeTargetCompileOptions(name, scope, group.Misc) } // target_link_libraries - content += "\ntarget_link_libraries(" + name + " PRIVATE ${CONTEXT}_GLOBAL)\n" - - content += CMakeCreateGroupRecursively(name, group.Groups) + content += "\ntarget_link_libraries(" + name + " PRIVATE ${CONTEXT}_GLOBAL" + if len(parent) > 5 { + content += " " + parent + } + content += ")\n" + // file properties + for _, file := range group.Files { + content += CMakeSetFileProperties(file) + } + // create children groups recursively + if hasChildren { + content += CMakeCreateGroupRecursively(name, group.Groups) + } } return content } @@ -162,6 +184,10 @@ func (m *Maker) CMakeCreateComponents(components []Components, contextDir string if len(component.Define) > 0 { content += CMakeTargetCompileDefinitions(name, "PRIVATE", component.Define) } + // target_compile_options + if !IsCompileMiscEmpty(component.Misc) { + content += CMakeTargetCompileOptions(name, "PRIVATE", component.Misc) + } // target_link_libraries content += "\ntarget_link_libraries(" + name + " PRIVATE ${CONTEXT}_GLOBAL)\n" } diff --git a/pkg/maker/parser_test.go b/pkg/maker/parser_test.go index 4a7601c..6f0a499 100644 --- a/pkg/maker/parser_test.go +++ b/pkg/maker/parser_test.go @@ -86,6 +86,10 @@ func TestParser(t *testing.T) { assert.Equal("./TestSource.c", data.BuildDescType.Groups[0].Files[0].File) assert.Equal("sourceC", data.BuildDescType.Groups[0].Files[0].Category) + assert.Equal("Subgroup", data.BuildDescType.Groups[0].Groups[0].Group) + assert.Equal("./TestSubgroup.c", data.BuildDescType.Groups[0].Groups[0].Files[0].File) + assert.Equal("sourceC", data.BuildDescType.Groups[0].Groups[0].Files[0].Category) + assert.Equal("config", data.BuildDescType.Groups[0].Files[0].Attr) assert.Equal("9.9.9", data.BuildDescType.Groups[0].Files[0].Version) assert.Equal("speed", data.BuildDescType.Groups[0].Files[0].Optimize) diff --git a/test/data/generic/contextName0.cbuild.yml b/test/data/generic/contextName0.cbuild.yml index cd8af61..66646f4 100644 --- a/test/data/generic/contextName0.cbuild.yml +++ b/test/data/generic/contextName0.cbuild.yml @@ -79,6 +79,11 @@ build: - -Link-C-file Link-CPP: - -Link-CPP-file + groups: + - group: Subgroup + files: + - file: ./TestSubgroup.c + category: sourceC constructed-files: - file: RTE/__BuildType_TargetType/RTE_Components.h category: header