diff --git a/tools/buildmgr/cbuildgen/config/AC6.6.16.2.cmake b/tools/buildmgr/cbuildgen/config/AC6.6.16.2.cmake index 7a5af5f4c..8f82678d4 100644 --- a/tools/buildmgr/cbuildgen/config/AC6.6.16.2.cmake +++ b/tools/buildmgr/cbuildgen/config/AC6.6.16.2.cmake @@ -679,6 +679,7 @@ set(CC_CPU "--target=${ARMCLANG_TARGET} ${ARMCLANG_CPU}") set(CC_DEFINES ${ASM_DEFINES}) set(CC_BYTE_ORDER ${ASM_BYTE_ORDER}) set(CC_FLAGS ${ASM_FLAGS}) +set(CC_LTO "-flto") set(_PI "-include ") set(_ISYS "-isystem ") set(CC_OPTIONS_FLAGS) @@ -704,6 +705,7 @@ set(CXX_BYTE_ORDER "${CC_BYTE_ORDER}") set(CXX_SECURE "${CC_SECURE}") set(CXX_BRANCHPROT "${CC_BRANCHPROT}") set(CXX_FLAGS "${CC_FLAGS}") +set(CXX_LTO "${CC_LTO}") set(CXX_OPTIONS_FLAGS) cbuild_set_options_flags(CXX "${OPTIMIZE}" "${DEBUG}" "${WARNINGS}" "${LANGUAGE_CXX}" CXX_OPTIONS_FLAGS) @@ -721,6 +723,7 @@ if(SECURE STREQUAL "Secure") set(LD_SECURE "--import-cmse-lib-out \"${OUT_DIR}/${CMSE_LIB}\"") endif() +set(LD_LTO "--lto") set(LD_FLAGS "") set(LD_OPTIONS_FLAGS) cbuild_set_options_flags(LD "${OPTIMIZE}" "${DEBUG}" "${WARNINGS}" "" LD_OPTIONS_FLAGS) diff --git a/tools/buildmgr/cbuildgen/config/CLANG.17.0.1.cmake b/tools/buildmgr/cbuildgen/config/CLANG.17.0.1.cmake index 712770225..6684f88d5 100644 --- a/tools/buildmgr/cbuildgen/config/CLANG.17.0.1.cmake +++ b/tools/buildmgr/cbuildgen/config/CLANG.17.0.1.cmake @@ -388,6 +388,7 @@ set(CC_CPU "${CLANG_CPU}") set(CC_DEFINES ${ASM_DEFINES}) set(CC_BYTE_ORDER ${ASM_BYTE_ORDER}) set(CC_FLAGS "") +set(CC_LTO "-flto") set(_PI "-include ") set(_ISYS "-isystem ") set(CC_OPTIONS_FLAGS) @@ -409,6 +410,7 @@ set(CXX_BYTE_ORDER "${CC_BYTE_ORDER}") set(CXX_SECURE "${CC_SECURE}") set(CXX_BRANCHPROT "${CC_BRANCHPROT}") set(CXX_FLAGS "${CC_FLAGS}") +set(CXX_LTO "${CC_LTO}") set(CXX_OPTIONS_FLAGS) cbuild_set_options_flags(CXX "${OPTIMIZE}" "${DEBUG}" "${WARNINGS}" "${LANGUAGE_CXX}" CXX_OPTIONS_FLAGS) @@ -421,6 +423,7 @@ if(SECURE STREQUAL "Secure") set(LD_SECURE "-Wl,--cmse-implib -Wl,--out-implib=\"${OUT_DIR}/${CMSE_LIB}\"") endif() +set(LD_LTO "-flto") set(LD_FLAGS) set(LD_OPTIONS_FLAGS) cbuild_set_options_flags(LD "${OPTIMIZE}" "${DEBUG}" "${WARNINGS}" "" LD_OPTIONS_FLAGS) diff --git a/tools/buildmgr/cbuildgen/config/CLANG_TI.4.0.1.cmake b/tools/buildmgr/cbuildgen/config/CLANG_TI.4.0.1.cmake index 7f2b4f0e9..a7bc5d751 100644 --- a/tools/buildmgr/cbuildgen/config/CLANG_TI.4.0.1.cmake +++ b/tools/buildmgr/cbuildgen/config/CLANG_TI.4.0.1.cmake @@ -155,6 +155,7 @@ set(CC_CPU "${TIARMCLANG_CPU}") set(CC_DEFINES ${ASM_DEFINES}) set(CC_BYTE_ORDER ${ASM_BYTE_ORDER}) set(CC_FLAGS "") +set(CC_LTO "-flto") set(_PI "-include ") set(_ISYS "-isystem ") set(CC_OPTIONS_FLAGS) @@ -176,6 +177,7 @@ set(CXX_BYTE_ORDER "${CC_BYTE_ORDER}") set(CXX_SECURE "${CC_SECURE}") set(CXX_BRANCHPROT "${CC_BRANCHPROT}") set(CXX_FLAGS "${CC_FLAGS}") +set(CXX_LTO "${CC_LTO}") set(CXX_OPTIONS_FLAGS) cbuild_set_options_flags(CXX "${OPTIMIZE}" "${DEBUG}" "${WARNINGS}" "${LANGUAGE_CXX}" CXX_OPTIONS_FLAGS) @@ -188,6 +190,7 @@ if(SECURE STREQUAL "Secure") set(LD_SECURE "-Wl,--import_cmse_lib_out=\"${OUT_DIR}/${CMSE_LIB}\"") endif() +set(LD_LTO "-flto") set(LD_FLAGS) set(LD_OPTIONS_FLAGS) cbuild_set_options_flags(LD "${OPTIMIZE}" "${DEBUG}" "${WARNINGS}" "" LD_OPTIONS_FLAGS) diff --git a/tools/buildmgr/cbuildgen/config/GCC.10.3.1.cmake b/tools/buildmgr/cbuildgen/config/GCC.10.3.1.cmake index 6fd98061f..2cba06e62 100644 --- a/tools/buildmgr/cbuildgen/config/GCC.10.3.1.cmake +++ b/tools/buildmgr/cbuildgen/config/GCC.10.3.1.cmake @@ -258,6 +258,7 @@ set(CC_CPU "${GNUASM_CPU}") set(CC_DEFINES ${ASM_DEFINES}) set(CC_BYTE_ORDER ${ASM_BYTE_ORDER}) set(CC_FLAGS) +set(CC_LTO "-flto") set(_PI "-include ") set(_ISYS "-isystem ") set(CC_OPTIONS_FLAGS) @@ -285,6 +286,7 @@ set(CXX_BYTE_ORDER "${CC_BYTE_ORDER}") set(CXX_SECURE "${CC_SECURE}") set(CXX_BRANCHPROT "${CC_BRANCHPROT}") set(CXX_FLAGS "${CC_FLAGS}") +set(CXX_LTO "${CC_LTO}") set(CXX_OPTIONS_FLAGS) cbuild_set_options_flags(CXX "${OPTIMIZE}" "${DEBUG}" "${WARNINGS}" "${LANGUAGE_CXX}" CXX_OPTIONS_FLAGS) @@ -304,6 +306,7 @@ if(SECURE STREQUAL "Secure") set(LD_SECURE "-Wl,--cmse-implib -Wl,--out-implib=\"${OUT_DIR}/${CMSE_LIB}\"") endif() +set(LD_LTO "-flto") set(LD_FLAGS) set(LD_OPTIONS_FLAGS) cbuild_set_options_flags(LD "${OPTIMIZE}" "${DEBUG}" "${WARNINGS}" "" LD_OPTIONS_FLAGS) diff --git a/tools/projmgr/include/ProjMgrParser.h b/tools/projmgr/include/ProjMgrParser.h index fc6b2a4fc..8f710c60f 100644 --- a/tools/projmgr/include/ProjMgrParser.h +++ b/tools/projmgr/include/ProjMgrParser.h @@ -199,6 +199,7 @@ struct BuildType { std::string warnings; std::string languageC; std::string languageCpp; + bool lto = false; std::vector defines; std::vector definesAsm; std::vector undefines; diff --git a/tools/projmgr/include/ProjMgrYamlParser.h b/tools/projmgr/include/ProjMgrYamlParser.h index 75e134f6f..243294cd1 100644 --- a/tools/projmgr/include/ProjMgrYamlParser.h +++ b/tools/projmgr/include/ProjMgrYamlParser.h @@ -146,6 +146,7 @@ static constexpr const char* YAML_LICENSE = "license"; static constexpr const char* YAML_LICENSES = "licenses"; static constexpr const char* YAML_LICENSE_AGREEMENT = "license-agreement"; static constexpr const char* YAML_LINKER = "linker"; +static constexpr const char* YAML_LINK_TIME_OPTIMIZE = "link-time-optimize"; static constexpr const char* YAML_MAP = "map"; static constexpr const char* YAML_MASK = "mask"; static constexpr const char* YAML_MEMORY = "memory"; diff --git a/tools/projmgr/schemas/common.schema.json b/tools/projmgr/schemas/common.schema.json index 5067ec930..a306148b6 100644 --- a/tools/projmgr/schemas/common.schema.json +++ b/tools/projmgr/schemas/common.schema.json @@ -235,6 +235,11 @@ "enum": [ "size", "speed", "balanced", "none", "debug" ], "description": "Generic optimization levels for code generation (size, speed, balanced, none, debug)." }, + "LinkTimeOptimizeType": { + "title": "link-time-optimize:", + "type": ["null", "boolean"], + "description": "Enable Link Time Optimization (LTO)" + }, "DebugType": { "title": "debug:\nDocumentation: https://open-cmsis-pack.github.io/cmsis-toolbox/YML-Input-Format/#debug", "enum": [ "on", "off" ], @@ -577,6 +582,7 @@ "device": { "$ref": "#/definitions/DeviceType" }, "language-C": { "$ref": "#/definitions/LanguageCType" }, "language-CPP": { "$ref": "#/definitions/LanguageCppType" }, + "link-time-optimize": { "$ref": "#/definitions/LinkTimeOptimizeType" }, "misc": { "$ref": "#/definitions/MiscTypes" }, "memory": { "$ref": "#/definitions/MemoryType" }, "optimize": { "$ref": "#/definitions/OptimizeType" }, @@ -615,6 +621,7 @@ "del-path": { "$ref": "#/definitions/DelpathsType" }, "language-C": { "$ref": "#/definitions/LanguageCType" }, "language-CPP": { "$ref": "#/definitions/LanguageCppType" }, + "link-time-optimize": { "$ref": "#/definitions/LinkTimeOptimizeType" }, "misc": { "$ref": "#/definitions/MiscTypes" }, "optimize": { "$ref": "#/definitions/OptimizeType" }, "processor": { "$ref": "#/definitions/ProcessorType" }, @@ -745,6 +752,7 @@ "groups": { "$ref": "#/definitions/GroupsType" }, "language-C": { "$ref": "#/definitions/LanguageCType" }, "language-CPP": { "$ref": "#/definitions/LanguageCppType" }, + "link-time-optimize": { "$ref": "#/definitions/LinkTimeOptimizeType" }, "misc": { "$ref": "#/definitions/MiscTypes" }, "not-for-context": { "$ref": "#/definitions/NotForContext" }, "optimize": { "$ref": "#/definitions/OptimizeType" }, @@ -781,6 +789,7 @@ "warnings": { "$ref": "#/definitions/WarningsType" }, "language-C": { "$ref": "#/definitions/LanguageCType" }, "language-CPP": { "$ref": "#/definitions/LanguageCppType" }, + "link-time-optimize": { "$ref": "#/definitions/LinkTimeOptimizeType" }, "define": { "$ref": "#/definitions/DefinesType" }, "define-asm": { "$ref": "#/definitions/DefinesAsmType" }, "undefine": { "$ref": "#/definitions/UndefinesType" }, @@ -849,6 +858,7 @@ "language": { "$ref": "#/definitions/FileLanguageType" }, "language-C": { "$ref": "#/definitions/LanguageCType" }, "language-CPP": { "$ref": "#/definitions/LanguageCppType" }, + "link-time-optimize": { "$ref": "#/definitions/LinkTimeOptimizeType" }, "misc": { "$ref": "#/definitions/MiscTypes" }, "not-for-context": { "$ref": "#/definitions/NotForContext" }, "optimize": { "$ref": "#/definitions/OptimizeType" }, @@ -968,6 +978,7 @@ "instances": { "$ref": "#/definitions/InstancesType" }, "language-C": { "$ref": "#/definitions/LanguageCType" }, "language-CPP": { "$ref": "#/definitions/LanguageCppType" }, + "link-time-optimize": { "$ref": "#/definitions/LinkTimeOptimizeType" }, "misc": { "$ref": "#/definitions/MiscTypes" }, "not-for-context": { "$ref": "#/definitions/NotForContext" }, "optimize": { "$ref": "#/definitions/OptimizeType" }, @@ -1127,6 +1138,7 @@ "generators": { "$ref": "#/definitions/GeneratorsOutputType" }, "language-C": { "$ref": "#/definitions/LanguageCType" }, "language-CPP": { "$ref": "#/definitions/LanguageCppType" }, + "link-time-optimize": { "$ref": "#/definitions/LinkTimeOptimizeType" }, "misc": { "$ref": "#/definitions/MiscTypes" }, "optimize": { "$ref": "#/definitions/OptimizeType" }, "output-dirs": { "$ref": "#/definitions/OutputDirectoriesType" }, @@ -1173,6 +1185,7 @@ "language-CPP": { "$ref": "#/definitions/LanguageCppType" }, "layers": { "$ref": "#/definitions/LayersType" }, "linker": { "$ref": "#/definitions/LinkersType" }, + "link-time-optimize": { "$ref": "#/definitions/LinkTimeOptimizeType" }, "misc": { "$ref": "#/definitions/MiscTypes" }, "optimize": { "$ref": "#/definitions/OptimizeType" }, "output": { "$ref": "#/definitions/OutputType" }, @@ -1373,6 +1386,7 @@ "warnings": { "$ref": "#/definitions/WarningsType" }, "language-C": { "$ref": "#/definitions/LanguageCType" }, "language-CPP": { "$ref": "#/definitions/LanguageCppType" }, + "link-time-optimize": { "$ref": "#/definitions/LinkTimeOptimizeType" }, "misc": { "$ref": "#/definitions/MiscType" }, "define": { "$ref": "#/definitions/BuildDefinesType" }, "define-asm": { "$ref": "#/definitions/BuildDefinesType" }, @@ -1455,6 +1469,7 @@ "language-C": { "$ref": "#/definitions/LanguageCType" }, "language-CPP": { "$ref": "#/definitions/LanguageCppType" }, "linker": { "$ref": "#/definitions/LinkersType" }, + "link-time-optimize": { "$ref": "#/definitions/LinkTimeOptimizeType" }, "misc": { "$ref": "#/definitions/MiscTypes" }, "packs": { "$ref": "#/definitions/PacksType" }, "processor": { "$ref": "#/definitions/ProcessorType" }, @@ -1629,6 +1644,7 @@ "warnings": { "$ref": "#/definitions/WarningsType" }, "language-C": { "$ref": "#/definitions/LanguageCType" }, "language-CPP": { "$ref": "#/definitions/LanguageCppType" }, + "link-time-optimize": { "$ref": "#/definitions/LinkTimeOptimizeType" }, "define": { "$ref": "#/definitions/DefinesType" }, "define-asm": { "$ref": "#/definitions/DefinesType" }, "undefine": { "$ref": "#/definitions/UndefinesType" }, @@ -1697,6 +1713,7 @@ "language-C": { "$ref": "#/definitions/LanguageCType" }, "language-CPP": { "$ref": "#/definitions/LanguageCppType" }, "linker": { "$ref": "#/definitions/LinkersType" }, + "link-time-optimize": { "$ref": "#/definitions/LinkTimeOptimizeType" }, "misc": { "$ref": "#/definitions/MiscTypes" }, "not-for-context": { "$ref": "#/definitions/NotForContext" }, "optimize": { "$ref": "#/definitions/OptimizeType" }, diff --git a/tools/projmgr/src/ProjMgrCbuild.cpp b/tools/projmgr/src/ProjMgrCbuild.cpp index 5c593f130..3b6f913d6 100644 --- a/tools/projmgr/src/ProjMgrCbuild.cpp +++ b/tools/projmgr/src/ProjMgrCbuild.cpp @@ -460,6 +460,9 @@ void ProjMgrCbuild::SetControlsNode(YAML::Node node, const ContextItem* context, SetNodeValue(node[YAML_WARNINGS], controls.warnings); SetNodeValue(node[YAML_LANGUAGE_C], controls.languageC); SetNodeValue(node[YAML_LANGUAGE_CPP], controls.languageCpp); + if (controls.lto) { + node[YAML_LINK_TIME_OPTIMIZE] = true; + } SetMiscNode(node[YAML_MISC], controls.misc); SetDefineNode(node[YAML_DEFINE], controls.defines); SetDefineNode(node[YAML_DEFINE_ASM], controls.definesAsm); diff --git a/tools/projmgr/src/ProjMgrWorker.cpp b/tools/projmgr/src/ProjMgrWorker.cpp index 6096b565c..4698f12c8 100644 --- a/tools/projmgr/src/ProjMgrWorker.cpp +++ b/tools/projmgr/src/ProjMgrWorker.cpp @@ -2923,6 +2923,19 @@ bool ProjMgrWorker::ProcessPrecedences(ContextItem& context, BoardOrDevice proce error |= true; } + // Link Time Optimize + context.controls.processed.lto = + context.controls.cproject.lto || + context.controls.csolution.lto || + context.controls.target.lto || + context.controls.build.lto; + for (auto& setup : context.controls.setups) { + context.controls.processed.lto |= setup.lto; + } + for (auto& [_, clayer] : context.controls.clayers) { + context.controls.processed.lto |= clayer.lto; + } + // Misc vector*> miscVec = { &context.controls.cproject.misc, diff --git a/tools/projmgr/src/ProjMgrYamlParser.cpp b/tools/projmgr/src/ProjMgrYamlParser.cpp index f73e09b08..349bf5b89 100644 --- a/tools/projmgr/src/ProjMgrYamlParser.cpp +++ b/tools/projmgr/src/ProjMgrYamlParser.cpp @@ -960,6 +960,7 @@ bool ProjMgrYamlParser::ParseBuildType(const YAML::Node& parent, const string& f for (const auto& item : buildChildren) { ParseString(parent, item.first, item.second); } + buildType.lto = parent[YAML_LINK_TIME_OPTIMIZE].IsDefined(); ParseProcessor(parent, buildType.processor); ParseMisc(parent, buildType.misc); if (!ParseDefine(parent[YAML_DEFINE], buildType.defines)) { @@ -1089,6 +1090,7 @@ const set solutionKeys = { YAML_WARNINGS, YAML_LANGUAGE_C, YAML_LANGUAGE_CPP, + YAML_LINK_TIME_OPTIMIZE, YAML_DEFINE, YAML_DEFINE_ASM, YAML_UNDEFINE, @@ -1123,6 +1125,7 @@ const set projectKeys = { YAML_WARNINGS, YAML_LANGUAGE_C, YAML_LANGUAGE_CPP, + YAML_LINK_TIME_OPTIMIZE, YAML_DEFINE, YAML_DEFINE_ASM, YAML_UNDEFINE, @@ -1152,6 +1155,7 @@ const set setupKeys = { YAML_WARNINGS, YAML_LANGUAGE_C, YAML_LANGUAGE_CPP, + YAML_LINK_TIME_OPTIMIZE, YAML_DEFINE, YAML_DEFINE_ASM, YAML_UNDEFINE, @@ -1178,6 +1182,7 @@ const set layerKeys = { YAML_WARNINGS, YAML_LANGUAGE_C, YAML_LANGUAGE_CPP, + YAML_LINK_TIME_OPTIMIZE, YAML_DEFINE, YAML_DEFINE_ASM, YAML_UNDEFINE, @@ -1215,6 +1220,7 @@ const set targetTypeKeys = { YAML_WARNINGS, YAML_LANGUAGE_C, YAML_LANGUAGE_CPP, + YAML_LINK_TIME_OPTIMIZE, YAML_DEFINE, YAML_DEFINE_ASM, YAML_UNDEFINE, @@ -1236,6 +1242,7 @@ const set buildTypeKeys = { YAML_WARNINGS, YAML_LANGUAGE_C, YAML_LANGUAGE_CPP, + YAML_LINK_TIME_OPTIMIZE, YAML_DEFINE, YAML_DEFINE_ASM, YAML_UNDEFINE, @@ -1317,6 +1324,7 @@ const set componentsKeys = { YAML_WARNINGS, YAML_LANGUAGE_C, YAML_LANGUAGE_CPP, + YAML_LINK_TIME_OPTIMIZE, YAML_DEFINE, YAML_DEFINE_ASM, YAML_UNDEFINE, @@ -1366,6 +1374,7 @@ const set groupsKeys = { YAML_WARNINGS, YAML_LANGUAGE_C, YAML_LANGUAGE_CPP, + YAML_LINK_TIME_OPTIMIZE, YAML_DEFINE, YAML_DEFINE_ASM, YAML_UNDEFINE, @@ -1387,6 +1396,7 @@ const set filesKeys = { YAML_WARNINGS, YAML_LANGUAGE_C, YAML_LANGUAGE_CPP, + YAML_LINK_TIME_OPTIMIZE, YAML_DEFINE, YAML_DEFINE_ASM, YAML_UNDEFINE, diff --git a/tools/projmgr/test/data/TestLTO/main.c b/tools/projmgr/test/data/TestLTO/main.c new file mode 100644 index 000000000..7e06c94d0 --- /dev/null +++ b/tools/projmgr/test/data/TestLTO/main.c @@ -0,0 +1 @@ +/* Dummy */ diff --git a/tools/projmgr/test/data/TestLTO/project.cproject.yml b/tools/projmgr/test/data/TestLTO/project.cproject.yml new file mode 100644 index 000000000..5d2a553b6 --- /dev/null +++ b/tools/projmgr/test/data/TestLTO/project.cproject.yml @@ -0,0 +1,14 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/Open-CMSIS-Pack/devtools/main/tools/projmgr/schemas/cproject.schema.json + +project: + + components: + - component: CORE + - component: Startup + link-time-optimize: + + groups: + - group: Source + files: + - file: main.c + link-time-optimize: diff --git a/tools/projmgr/test/data/TestLTO/solution.csolution.yml b/tools/projmgr/test/data/TestLTO/solution.csolution.yml new file mode 100644 index 000000000..24568a286 --- /dev/null +++ b/tools/projmgr/test/data/TestLTO/solution.csolution.yml @@ -0,0 +1,16 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/Open-CMSIS-Pack/devtools/main/tools/projmgr/schemas/csolution.schema.json + +solution: + + compiler: AC6 + + target-types: + - type: CM0 + device: RteTest_ARMCM0 + link-time-optimize: + + projects: + - project: project.cproject.yml + + packs: + - pack: ARM::RteTest_DFP diff --git a/tools/projmgr/test/src/ProjMgrUnitTests.cpp b/tools/projmgr/test/src/ProjMgrUnitTests.cpp index 94c938678..e754cd5b4 100644 --- a/tools/projmgr/test/src/ProjMgrUnitTests.cpp +++ b/tools/projmgr/test/src/ProjMgrUnitTests.cpp @@ -6855,3 +6855,15 @@ TEST_F(ProjMgrUnitTests, ConvertActiveTargetSet) { errStr = streamRedirect.GetErrorString(); EXPECT_STREQ(errStr.c_str(), "error csolution: unknown selected context(s):\n UnknownContext+Type1\n"); } + +TEST_F(ProjMgrUnitTests, LinkTimeOptimize) { + char* argv[3]; + const string& csolution = testinput_folder + "/TestLTO/solution.csolution.yml"; + argv[1] = (char*)"convert"; + argv[2] = (char*)csolution.c_str(); + EXPECT_EQ(0, RunProjMgr(3, argv, m_envp)); + const YAML::Node& cbuild = YAML::LoadFile(testinput_folder + "/TestLTO/project+CM0.cbuild.yml"); + EXPECT_TRUE(cbuild["build"]["link-time-optimize"].IsDefined()); + EXPECT_TRUE(cbuild["build"]["components"][0]["link-time-optimize"].IsDefined()); + EXPECT_TRUE(cbuild["build"]["groups"][0]["files"][0]["link-time-optimize"].IsDefined()); +}