From dedbacedf7a883b989a2b6dbca0e0361d3611867 Mon Sep 17 00:00:00 2001 From: Daniel Brondani Date: Fri, 9 May 2025 10:42:30 +0200 Subject: [PATCH] [cbuild2cmake] Add `link-time-optimize` handling --- pkg/maker/buildcontent.go | 39 ++++++++++++++----- pkg/maker/buildcontent_test.go | 7 ++-- pkg/maker/contextlists.go | 6 +-- pkg/maker/parser.go | 5 +++ pkg/maker/parser_test.go | 3 ++ test/data/generic/contextName0.cbuild.yml | 3 ++ .../project/project.GCC+ARMCM0.cbuild.yml | 10 ++++- .../abstractions/project/project.cproject.yml | 3 ++ .../ref/project.GCC+ARMCM0/CMakeLists.txt | 1 + .../ref/project.GCC+ARMCM0/components.cmake | 3 ++ .../ref/project.GCC+ARMCM0/groups.cmake | 6 +++ 11 files changed, 68 insertions(+), 18 deletions(-) diff --git a/pkg/maker/buildcontent.go b/pkg/maker/buildcontent.go index 07f87aec..2ad69861 100644 --- a/pkg/maker/buildcontent.go +++ b/pkg/maker/buildcontent.go @@ -345,7 +345,7 @@ func (c *Cbuild) CMakeTargetCompileOptionsGlobal(name string, scope string) stri } } // add global misc options - c.GetCompileOptionsLanguageMap(c.BuildDescType.Misc, &optionsMap) + c.GetCompileOptionsLanguageMap((c.BuildDescType.Lto), c.BuildDescType.Misc, &optionsMap) // pre-includes global for _, preInclude := range c.PreIncludeGlobal { @@ -370,11 +370,11 @@ func (c *Cbuild) CMakeTargetLinkLibraries(name string, scope string, libraries . return content } -func (c *Cbuild) CMakeTargetCompileOptions(name string, scope string, misc Misc, preIncludes []string, parent string) string { +func (c *Cbuild) CMakeTargetCompileOptions(name string, scope string, lto bool, misc Misc, preIncludes []string, parent string) string { content := "\ntarget_compile_options(" + name + " " + scope content += "\n $" optionsMap := make(map[string][]string) - c.GetCompileOptionsLanguageMap(misc, &optionsMap) + c.GetCompileOptionsLanguageMap(lto, misc, &optionsMap) for _, preInclude := range preIncludes { optionsMap["C,CXX"] = append(optionsMap["C,CXX"], "${_PI}\""+preInclude+"\"") } @@ -406,7 +406,7 @@ func (c *Cbuild) CMakeTargetCompileOptionsAbstractions(name string, abstractions return content } -func (c *Cbuild) GetCompileOptionsLanguageMap(misc Misc, optionsMap *map[string][]string) { +func (c *Cbuild) GetCompileOptionsLanguageMap(lto bool, misc Misc, optionsMap *map[string][]string) { for _, language := range c.Languages { switch language { case "ASM": @@ -414,11 +414,23 @@ func (c *Cbuild) GetCompileOptionsLanguageMap(misc Misc, optionsMap *map[string] (*optionsMap)[language] = append((*optionsMap)[language], misc.ASM...) } case "C", "CXX": - if language == "C" && len(misc.C) > 0 { - (*optionsMap)[language] = append((*optionsMap)[language], misc.C...) + if language == "C" { + if lto { + c.LinkerLto = true + (*optionsMap)[language] = append((*optionsMap)[language], "${CC_LTO}") + } + if len(misc.C) > 0 { + (*optionsMap)[language] = append((*optionsMap)[language], misc.C...) + } } - if language == "CXX" && len(misc.CPP) > 0 { - (*optionsMap)[language] = append((*optionsMap)[language], misc.CPP...) + if language == "CXX" { + if lto { + c.LinkerLto = true + (*optionsMap)[language] = append((*optionsMap)[language], "${CXX_LTO}") + } + if len(misc.CPP) > 0 { + (*optionsMap)[language] = append((*optionsMap)[language], misc.CPP...) + } } if len(misc.CCPP) > 0 { (*optionsMap)[language] = append((*optionsMap)[language], misc.CCPP...) @@ -460,6 +472,9 @@ func GetFileOptions(file Files, hasAbstractions bool, delimiter string) string { case "CXX": options = append(file.Misc.CPP, file.Misc.CCPP...) } + if file.Lto { + options = append(options, "${"+prefix+"_LTO}") + } if hasAbstractions { options = append(options, "${"+prefix+"_OPTIONS_FLAGS}") } @@ -759,6 +774,7 @@ func (c *Cbuild) CMakeSetFileProperties(file Files, abstractions CompilerAbstrac // file build options language := GetLanguage(file) hasMisc := !IsCompileMiscEmpty(file.Misc) + c.LinkerLto = c.LinkerLto || file.Lto // file compiler abstractions hasAbstractions := !AreAbstractionsEmpty(abstractions, []string{language}) if hasAbstractions { @@ -768,9 +784,9 @@ func (c *Cbuild) CMakeSetFileProperties(file Files, abstractions CompilerAbstrac filename := c.AddRootPrefix(c.ContextRoot, file.File) isGenerated := slices.Contains(c.GeneratedFiles, filename) // set file properties - if hasMisc || hasAbstractions || isGenerated { + if hasMisc || file.Lto || hasAbstractions || isGenerated { content += "\nset_source_files_properties(\"" + filename + "\" PROPERTIES" - if hasMisc || hasAbstractions { + if hasMisc || file.Lto || hasAbstractions { content += "\n COMPILE_OPTIONS \"" + GetFileOptions(file, hasAbstractions, ";") + "\"" } if isGenerated { @@ -834,6 +850,9 @@ func (c *Cbuild) LinkerOptions() (linkerVars string, linkerOptions string) { if len(c.BuildDescType.Processor.Trustzone) > 0 { linkerOptions += "\n " + AddShellPrefix("${LD_SECURE}") } + if c.LinkerLto { + linkerOptions += "\n " + AddShellPrefix("${LD_LTO}") + } options := c.BuildDescType.Misc.Link for _, language := range c.Languages { if language == "C" { diff --git a/pkg/maker/buildcontent_test.go b/pkg/maker/buildcontent_test.go index 5c6ae633..36dfa55e 100644 --- a/pkg/maker/buildcontent_test.go +++ b/pkg/maker/buildcontent_test.go @@ -152,13 +152,14 @@ func TestBuildContent(t *testing.T) { CPP: []string{"-cpp-flag"}, CCPP: []string{"-c-cpp-flag"}, } + lto := true var cbuild maker.Cbuild cbuild.Languages = []string{"ASM", "C", "CXX"} preIncludes := []string{"${SOLUTION_ROOT}/project/RTE/class/pre-include.h"} - content := cbuild.CMakeTargetCompileOptions("TARGET", "PUBLIC", misc, preIncludes, "${CONTEXT}") + content := cbuild.CMakeTargetCompileOptions("TARGET", "PUBLIC", lto, misc, preIncludes, "${CONTEXT}") assert.Contains(content, "$<$:\n \"SHELL:-asm-flag\"") - assert.Contains(content, "$<$:\n \"SHELL:-c-flag\"\n \"SHELL:-c-cpp-flag\"") - assert.Contains(content, "$<$:\n \"SHELL:-cpp-flag\"\n \"SHELL:-c-cpp-flag\"") + assert.Contains(content, "$<$:\n \"SHELL:${CC_LTO}\"\n \"SHELL:-c-flag\"\n \"SHELL:-c-cpp-flag\"") + assert.Contains(content, "$<$:\n \"SHELL:${CXX_LTO}\"\n \"SHELL:-cpp-flag\"\n \"SHELL:-c-cpp-flag\"") assert.Contains(content, "\"SHELL:${_PI}\\\"${SOLUTION_ROOT}/project/RTE/class/pre-include.h\\\"\"") }) diff --git a/pkg/maker/contextlists.go b/pkg/maker/contextlists.go index b342eb5c..16ef5b6e 100644 --- a/pkg/maker/contextlists.go +++ b/pkg/maker/contextlists.go @@ -244,7 +244,7 @@ func (c *Cbuild) CMakeCreateGroupRecursively(parent string, groups []Groups, } // target_compile_options if hasChildren || len(buildFiles.Source) > 0 || len(buildFiles.Custom) > 0 { - content += c.CMakeTargetCompileOptions(name, scope, group.Misc, buildFiles.PreIncludeLocal, parentName) + content += c.CMakeTargetCompileOptions(name, scope, group.Lto, group.Misc, buildFiles.PreIncludeLocal, parentName) } // target_link_libraries libraries = append(libraries, buildFiles.Library...) @@ -269,7 +269,7 @@ func (c *Cbuild) CMakeCreateGroupRecursively(parent string, groups []Groups, content += CMakeTargetCompileDefinitions(fileTargetName, name, "PUBLIC", file.Define, file.Undefine) } // target_compile_options - content += c.CMakeTargetCompileOptions(fileTargetName, "PUBLIC", Misc{}, []string{}, name) + content += c.CMakeTargetCompileOptions(fileTargetName, "PUBLIC", false, Misc{}, []string{}, name) } // asm defines are set in file properties if GetLanguage(file) == "ASM" { @@ -331,7 +331,7 @@ func (c *Cbuild) CMakeCreateComponents(contextDir string) error { } // target_compile_options if len(buildFiles.Source) > 0 || len(buildFiles.Custom) > 0 { - content += c.CMakeTargetCompileOptions(name, scope, component.Misc, buildFiles.PreIncludeLocal, "${CONTEXT}") + content += c.CMakeTargetCompileOptions(name, scope, component.Lto, component.Misc, buildFiles.PreIncludeLocal, "${CONTEXT}") } // target_link_libraries libraries = append(libraries, buildFiles.Library...) diff --git a/pkg/maker/parser.go b/pkg/maker/parser.go index 014b689f..30126814 100644 --- a/pkg/maker/parser.go +++ b/pkg/maker/parser.go @@ -57,6 +57,7 @@ type Cbuild struct { Warnings string `yaml:"warnings"` LanguageC string `yaml:"language-C"` LanguageCpp string `yaml:"language-CPP"` + Lto bool `yaml:"link-time-optimize"` Misc Misc `yaml:"misc"` Define []interface{} `yaml:"define"` DefineAsm []interface{} `yaml:"define-asm"` @@ -83,6 +84,7 @@ type Cbuild struct { BuildGroups []string Toolchain string GeneratedFiles []string + LinkerLto bool } type Cbuilds struct { @@ -122,6 +124,7 @@ type Components struct { Warnings string `yaml:"warnings"` LanguageC string `yaml:"language-C"` LanguageCpp string `yaml:"language-CPP"` + Lto bool `yaml:"link-time-optimize"` Define []interface{} `yaml:"define"` DefineAsm []interface{} `yaml:"define-asm"` Undefine []string `yaml:"undefine"` @@ -155,6 +158,7 @@ type Files struct { Warnings string `yaml:"warnings"` LanguageC string `yaml:"language-C"` LanguageCpp string `yaml:"language-CPP"` + Lto bool `yaml:"link-time-optimize"` Define []interface{} `yaml:"define"` DefineAsm []interface{} `yaml:"define-asm"` Undefine []string `yaml:"undefine"` @@ -180,6 +184,7 @@ type Groups struct { Warnings string `yaml:"warnings"` LanguageC string `yaml:"language-C"` LanguageCpp string `yaml:"language-CPP"` + Lto bool `yaml:"link-time-optimize"` Define []interface{} `yaml:"define"` DefineAsm []interface{} `yaml:"define-asm"` Undefine []string `yaml:"undefine"` diff --git a/pkg/maker/parser_test.go b/pkg/maker/parser_test.go index 12596a7c..38900117 100644 --- a/pkg/maker/parser_test.go +++ b/pkg/maker/parser_test.go @@ -51,6 +51,7 @@ func TestParser(t *testing.T) { assert.Equal("bti-signret", data.BuildDescType.Processor.BranchProtection) assert.Equal("non-secure", data.BuildDescType.Processor.Trustzone) assert.Equal("Cortex-M0", data.BuildDescType.Processor.Core) + assert.True(data.BuildDescType.Lto) assert.Equal("vendorName::DFP@8.8.8", data.BuildDescType.Packs[0].Pack) assert.Equal("${CMSIS_PACK_ROOT}/vendorName/DFP/8.8.8", data.BuildDescType.Packs[0].Path) @@ -83,6 +84,7 @@ func TestParser(t *testing.T) { assert.Equal("vendorName::DFP@8.8.8", data.BuildDescType.Components[0].FromPack) assert.Equal("DFP:CORE@1.1.1", data.BuildDescType.Components[0].Implements) assert.Equal("CORE", data.BuildDescType.Components[0].SelectedBy) + assert.True(data.BuildDescType.Components[0].Lto) assert.Equal("DFP:CORE@1.1.1", data.BuildDescType.Apis[0].API) assert.Equal("vendorName::DFP@8.8.8", data.BuildDescType.Apis[0].FromPack) @@ -90,6 +92,7 @@ func TestParser(t *testing.T) { assert.Equal("Source", data.BuildDescType.Groups[0].Group) assert.Equal("./TestSource.c", data.BuildDescType.Groups[0].Files[0].File) assert.Equal("sourceC", data.BuildDescType.Groups[0].Files[0].Category) + assert.True(data.BuildDescType.Groups[0].Files[0].Lto) assert.Equal("Subgroup", data.BuildDescType.Groups[0].Groups[0].Group) assert.Equal("./TestSubgroup.c", data.BuildDescType.Groups[0].Groups[0].Files[0].File) diff --git a/test/data/generic/contextName0.cbuild.yml b/test/data/generic/contextName0.cbuild.yml index 09487714..680afb47 100644 --- a/test/data/generic/contextName0.cbuild.yml +++ b/test/data/generic/contextName0.cbuild.yml @@ -36,6 +36,7 @@ build: from-pack: vendorName::DFP@8.8.8 implements: DFP:CORE@1.1.1 selected-by: CORE + link-time-optimize: true apis: - api: DFP:CORE@1.1.1 from-pack: vendorName::DFP@8.8.8 @@ -44,6 +45,7 @@ build: regions: regions_deviceName.h define: - LD_PP_DEF0 + link-time-optimize: true groups: - group: Source files: @@ -56,6 +58,7 @@ build: warnings: all language-C: c90 language-CPP: c++20 + link-time-optimize: true define: - DEF_FILE undefine: diff --git a/test/data/solutions/abstractions/project/project.GCC+ARMCM0.cbuild.yml b/test/data/solutions/abstractions/project/project.GCC+ARMCM0.cbuild.yml index 5ec5965e..8aff8c2f 100644 --- a/test/data/solutions/abstractions/project/project.GCC+ARMCM0.cbuild.yml +++ b/test/data/solutions/abstractions/project/project.GCC+ARMCM0.cbuild.yml @@ -1,11 +1,14 @@ build: - generated-by: csolution version 2.6.0 + generated-by: csolution version 0.0.0+gd100d305 solution: ../solution.csolution.yml project: project.cproject.yml context: project.GCC+ARMCM0 compiler: GCC - device: ARMCM0 + device: ARM::ARMCM0 device-pack: ARM::Cortex_DFP@1.1.0 + device-books: + - name: https://developer.arm.com/documentation/dui0497 + title: Cortex-M0 Processor Devices Generic Users Guide processor: fpu: off core: Cortex-M0 @@ -84,6 +87,7 @@ build: from-pack: ARM::Cortex_DFP@1.1.0 selected-by: ARM::Device:Startup&C Startup optimize: none + link-time-optimize: true files: - file: ${CMSIS_PACK_ROOT}/ARM/Cortex_DFP/1.1.0/Device/ARMCM0/Include/ARMCM0.h category: header @@ -104,6 +108,7 @@ build: script: RTE/Device/ARMCM0/ARMCM0_gcc.ld groups: - group: Group1 + link-time-optimize: true files: - file: main.c category: sourceC @@ -134,6 +139,7 @@ build: category: sourceC - file: optimize_size2.c category: sourceC + link-time-optimize: true constructed-files: - file: RTE/_GCC_ARMCM0/RTE_Components.h category: header diff --git a/test/data/solutions/abstractions/project/project.cproject.yml b/test/data/solutions/abstractions/project/project.cproject.yml index 93dc58f7..bfcd9dc3 100644 --- a/test/data/solutions/abstractions/project/project.cproject.yml +++ b/test/data/solutions/abstractions/project/project.cproject.yml @@ -6,11 +6,13 @@ project: - component: ARM::CMSIS:CORE - component: ARM::Device:Startup&C Startup optimize: none + link-time-optimize: #inherited from build-type: optimize: size groups: - group: Group1 + link-time-optimize: files: - file: ./main.c - group: Group2 @@ -34,3 +36,4 @@ project: files: - file: ./optimize_size1.c - file: ./optimize_size2.c + link-time-optimize: diff --git a/test/data/solutions/abstractions/ref/project.GCC+ARMCM0/CMakeLists.txt b/test/data/solutions/abstractions/ref/project.GCC+ARMCM0/CMakeLists.txt index 42376ddd..40fe5edf 100644 --- a/test/data/solutions/abstractions/ref/project.GCC+ARMCM0/CMakeLists.txt +++ b/test/data/solutions/abstractions/ref/project.GCC+ARMCM0/CMakeLists.txt @@ -89,6 +89,7 @@ target_link_libraries(${CONTEXT} PUBLIC target_link_options(${CONTEXT} PUBLIC "SHELL:${LD_CPU}" "SHELL:${_LS}\"${LD_SCRIPT_PP}\"" + "SHELL:${LD_LTO}" "SHELL:--specs=nano.specs" "SHELL:--specs=nosys.specs" "SHELL:-Wl,--gc-sections" diff --git a/test/data/solutions/abstractions/ref/project.GCC+ARMCM0/components.cmake b/test/data/solutions/abstractions/ref/project.GCC+ARMCM0/components.cmake index 027a72f0..f923d47d 100644 --- a/test/data/solutions/abstractions/ref/project.GCC+ARMCM0/components.cmake +++ b/test/data/solutions/abstractions/ref/project.GCC+ARMCM0/components.cmake @@ -34,6 +34,9 @@ target_compile_options(ARM_Device_Startup_C_Startup_2_2_0_ABSTRACTIONS INTERFACE ) target_compile_options(ARM_Device_Startup_C_Startup_2_2_0 PUBLIC $ + $<$: + "SHELL:${CC_LTO}" + > ) target_link_libraries(ARM_Device_Startup_C_Startup_2_2_0 PUBLIC ARM_Device_Startup_C_Startup_2_2_0_ABSTRACTIONS diff --git a/test/data/solutions/abstractions/ref/project.GCC+ARMCM0/groups.cmake b/test/data/solutions/abstractions/ref/project.GCC+ARMCM0/groups.cmake index 85573aef..6cbead33 100644 --- a/test/data/solutions/abstractions/ref/project.GCC+ARMCM0/groups.cmake +++ b/test/data/solutions/abstractions/ref/project.GCC+ARMCM0/groups.cmake @@ -16,6 +16,9 @@ target_link_libraries(Group_Group1_ABSTRACTIONS INTERFACE ) target_compile_options(Group_Group1 PUBLIC $ + $<$: + "SHELL:${CC_LTO}" + > ) target_link_libraries(Group_Group1 PUBLIC Group_Group1_ABSTRACTIONS @@ -137,3 +140,6 @@ target_compile_options(Group_EmptyParent_NestedChild PUBLIC target_link_libraries(Group_EmptyParent_NestedChild PUBLIC Group_EmptyParent_NestedChild_ABSTRACTIONS ) +set_source_files_properties("${SOLUTION_ROOT}/project/optimize_size2.c" PROPERTIES + COMPILE_OPTIONS "${CC_LTO}" +)