diff options
-rw-r--r-- | Source/cmLocalGenerator.cxx | 87 | ||||
-rw-r--r-- | Source/cmLocalGenerator.h | 12 | ||||
-rw-r--r-- | Tests/RunCMake/UnityBuild/RunCMakeTest.cmake | 16 | ||||
-rw-r--r-- | Tests/RunCMake/UnityBuild/per_config_c.c | 16 | ||||
-rw-r--r-- | Tests/RunCMake/UnityBuild/per_config_c.cmake | 12 | ||||
-rw-r--r-- | Tests/RunCMake/UnityBuild/per_config_c_debug.c | 9 | ||||
-rw-r--r-- | Tests/RunCMake/UnityBuild/per_config_c_other.c | 9 |
7 files changed, 130 insertions, 31 deletions
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 3ac77c1..c106137 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2808,7 +2808,7 @@ inline void RegisterUnitySources(cmGeneratorTarget* target, cmSourceFile* sf, } cmLocalGenerator::UnitySource cmLocalGenerator::WriteUnitySource( - cmGeneratorTarget* target, + cmGeneratorTarget* target, std::vector<std::string> const& configs, cmRange<std::vector<UnityBatchedSource>::const_iterator> sources, cmValue beforeInclude, cmValue afterInclude, std::string filename) const { @@ -2818,21 +2818,36 @@ cmLocalGenerator::UnitySource cmLocalGenerator::WriteUnitySource( file.SetCopyIfDifferent(true); file << "/* generated by CMake */\n\n"; + bool perConfig = false; for (UnityBatchedSource const& ubs : sources) { + cm::optional<std::string> cond; + if (ubs.Configs.size() != configs.size()) { + perConfig = true; + cond = std::string(); + cm::string_view sep; + for (size_t ci : ubs.Configs) { + cond = cmStrCat(*cond, sep, "defined(CMAKE_UNITY_CONFIG_", + cmSystemTools::UpperCase(configs[ci]), ")"); + sep = " || "_s; + } + } RegisterUnitySources(target, ubs.Source, filename); - WriteUnitySourceInclude(file, ubs.Source->ResolveFullPath(), beforeInclude, - afterInclude, uniqueIdName); + WriteUnitySourceInclude(file, cond, ubs.Source->ResolveFullPath(), + beforeInclude, afterInclude, uniqueIdName); } - return UnitySource(std::move(filename)); + return UnitySource(std::move(filename), perConfig); } -void cmLocalGenerator::WriteUnitySourceInclude(std::ostream& unity_file, - std::string const& sf_full_path, - cmValue beforeInclude, - cmValue afterInclude, - cmValue uniqueIdName) const +void cmLocalGenerator::WriteUnitySourceInclude( + std::ostream& unity_file, cm::optional<std::string> const& cond, + std::string const& sf_full_path, cmValue beforeInclude, cmValue afterInclude, + cmValue uniqueIdName) const { + if (cond) { + unity_file << "#if " << *cond << "\n"; + } + if (cmNonempty(uniqueIdName)) { std::string pathToHash; auto PathEqOrSubDir = [](std::string const& a, std::string const& b) { @@ -2867,12 +2882,16 @@ void cmLocalGenerator::WriteUnitySourceInclude(std::ostream& unity_file, if (afterInclude) { unity_file << *afterInclude << "\n"; } + if (cond) { + unity_file << "#endif\n"; + } unity_file << "\n"; } std::vector<cmLocalGenerator::UnitySource> cmLocalGenerator::AddUnityFilesModeAuto( cmGeneratorTarget* target, std::string const& lang, + std::vector<std::string> const& configs, std::vector<UnityBatchedSource> const& filtered_sources, cmValue beforeInclude, cmValue afterInclude, std::string const& filename_base, size_t batchSize) @@ -2891,9 +2910,9 @@ cmLocalGenerator::AddUnityFilesModeAuto( (lang == "C") ? "_c.c" : "_cxx.cxx"); auto const begin = filtered_sources.begin() + batch * batchSize; auto const end = begin + chunk; - unity_files.emplace_back( - this->WriteUnitySource(target, cmMakeRange(begin, end), beforeInclude, - afterInclude, std::move(filename))); + unity_files.emplace_back(this->WriteUnitySource( + target, configs, cmMakeRange(begin, end), beforeInclude, afterInclude, + std::move(filename))); } return unity_files; } @@ -2901,6 +2920,7 @@ cmLocalGenerator::AddUnityFilesModeAuto( std::vector<cmLocalGenerator::UnitySource> cmLocalGenerator::AddUnityFilesModeGroup( cmGeneratorTarget* target, std::string const& lang, + std::vector<std::string> const& configs, std::vector<UnityBatchedSource> const& filtered_sources, cmValue beforeInclude, cmValue afterInclude, std::string const& filename_base) @@ -2927,9 +2947,9 @@ cmLocalGenerator::AddUnityFilesModeGroup( auto const& name = item.first; std::string filename = cmStrCat(filename_base, "unity_", name, (lang == "C") ? "_c.c" : "_cxx.cxx"); - unity_files.emplace_back( - this->WriteUnitySource(target, cmMakeRange(item.second), beforeInclude, - afterInclude, std::move(filename))); + unity_files.emplace_back(this->WriteUnitySource( + target, configs, cmMakeRange(item.second), beforeInclude, afterInclude, + std::move(filename))); } return unity_files; @@ -2943,19 +2963,24 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) std::vector<UnityBatchedSource> unitySources; - { - // FIXME: Handle all configurations in multi-config generators. - std::string config; - if (!this->GetGlobalGenerator()->IsMultiConfig()) { - config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); - } + std::vector<std::string> configs = + this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); + + std::map<cmSourceFile const*, size_t> index; + for (size_t ci = 0; ci < configs.size(); ++ci) { // FIXME: Refactor collection of sources to not evaluate object libraries. std::vector<cmSourceFile*> sources; - target->GetSourceFiles(sources, config); - + target->GetSourceFiles(sources, configs[ci]); for (cmSourceFile* sf : sources) { - unitySources.emplace_back(sf); + auto mi = index.find(sf); + if (mi == index.end()) { + unitySources.emplace_back(sf); + std::map<cmSourceFile const*, size_t>::value_type entry( + sf, unitySources.size() - 1); + mi = index.insert(entry).first; + } + unitySources[mi->second].Configs.emplace_back(ci); } } @@ -2990,13 +3015,13 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) std::vector<UnitySource> unity_files; if (!unityMode || *unityMode == "BATCH") { - unity_files = - AddUnityFilesModeAuto(target, lang, filtered_sources, beforeInclude, - afterInclude, filename_base, unityBatchSize); + unity_files = AddUnityFilesModeAuto( + target, lang, configs, filtered_sources, beforeInclude, afterInclude, + filename_base, unityBatchSize); } else if (unityMode && *unityMode == "GROUP") { unity_files = - AddUnityFilesModeGroup(target, lang, filtered_sources, beforeInclude, - afterInclude, filename_base); + AddUnityFilesModeGroup(target, lang, configs, filtered_sources, + beforeInclude, afterInclude, filename_base); } else { // unity mode is set to an unsupported value std::string e("Invalid UNITY_BUILD_MODE value of " + *unityMode + @@ -3010,6 +3035,10 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) target->AddSource(file.Path, true); unity->SetProperty("SKIP_UNITY_BUILD_INCLUSION", "ON"); unity->SetProperty("UNITY_SOURCE_FILE", file.Path); + if (file.PerConfig) { + unity->SetProperty("COMPILE_DEFINITIONS", + "CMAKE_UNITY_CONFIG_$<UPPER_CASE:$<CONFIG>>"); + } } } } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 4c9714b..726817a 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -14,6 +14,8 @@ #include <utility> #include <vector> +#include <cm/optional> + #include <cm3p/kwiml/int.h> #include "cmCustomCommandTypes.h" @@ -664,6 +666,7 @@ private: struct UnityBatchedSource { cmSourceFile* Source = nullptr; + std::vector<size_t> Configs; UnityBatchedSource(cmSourceFile* sf) : Source(sf) { @@ -672,27 +675,32 @@ private: struct UnitySource { std::string Path; - UnitySource(std::string path) + bool PerConfig = false; + UnitySource(std::string path, bool perConfig) : Path(std::move(path)) + , PerConfig(perConfig) { } }; UnitySource WriteUnitySource( - cmGeneratorTarget* target, + cmGeneratorTarget* target, std::vector<std::string> const& configs, cmRange<std::vector<UnityBatchedSource>::const_iterator> sources, cmValue beforeInclude, cmValue afterInclude, std::string filename) const; void WriteUnitySourceInclude(std::ostream& unity_file, + cm::optional<std::string> const& cond, std::string const& sf_full_path, cmValue beforeInclude, cmValue afterInclude, cmValue uniqueIdName) const; std::vector<UnitySource> AddUnityFilesModeAuto( cmGeneratorTarget* target, std::string const& lang, + std::vector<std::string> const& configs, std::vector<UnityBatchedSource> const& filtered_sources, cmValue beforeInclude, cmValue afterInclude, std::string const& filename_base, size_t batchSize); std::vector<UnitySource> AddUnityFilesModeGroup( cmGeneratorTarget* target, std::string const& lang, + std::vector<std::string> const& configs, std::vector<UnityBatchedSource> const& filtered_sources, cmValue beforeInclude, cmValue afterInclude, std::string const& filename_base); diff --git a/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake b/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake index 8019f09..e3643c0 100644 --- a/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake +++ b/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake @@ -26,6 +26,22 @@ run_build(unitybuild_anon_ns) run_build(unitybuild_anon_ns_no_unity_build) run_build(unitybuild_anon_ns_group_mode) +function(run_per_config name) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build) + run_cmake(${name}) + set(RunCMake_TEST_NO_CLEAN 1) + if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + run_cmake_command(${name}-build-debug ${CMAKE_COMMAND} --build . --config Debug) + run_cmake_command(${name}-build-release ${CMAKE_COMMAND} --build . --config Release) + else() + run_cmake_command(${name}-build ${CMAKE_COMMAND} --build .) + endif() +endfunction() + +if(NOT RunCMake_GENERATOR STREQUAL "Xcode") + run_per_config(per_config_c) +endif() + function(run_test name) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build) run_cmake(${name}) diff --git a/Tests/RunCMake/UnityBuild/per_config_c.c b/Tests/RunCMake/UnityBuild/per_config_c.c new file mode 100644 index 0000000..081c7d3 --- /dev/null +++ b/Tests/RunCMake/UnityBuild/per_config_c.c @@ -0,0 +1,16 @@ +#ifdef CFG_DEBUG +extern void per_config_c_debug(void); +#endif +#ifdef CFG_OTHER +extern void per_config_c_other(void); +#endif +int main(void) +{ +#ifdef CFG_DEBUG + per_config_c_debug(); +#endif +#ifdef CFG_OTHER + per_config_c_other(); +#endif + return 0; +} diff --git a/Tests/RunCMake/UnityBuild/per_config_c.cmake b/Tests/RunCMake/UnityBuild/per_config_c.cmake new file mode 100644 index 0000000..9f2ee48 --- /dev/null +++ b/Tests/RunCMake/UnityBuild/per_config_c.cmake @@ -0,0 +1,12 @@ +enable_language(C) + +add_executable(per_config_c per_config_c.c + "$<$<CONFIG:Debug>:per_config_c_debug.c>" + "$<$<NOT:$<CONFIG:Debug>>:per_config_c_other.c>" + ) + +set_target_properties(per_config_c PROPERTIES UNITY_BUILD ON) +target_compile_definitions(per_config_c PRIVATE + "$<$<CONFIG:Debug>:CFG_DEBUG>" + "$<$<NOT:$<CONFIG:Debug>>:CFG_OTHER>" + ) diff --git a/Tests/RunCMake/UnityBuild/per_config_c_debug.c b/Tests/RunCMake/UnityBuild/per_config_c_debug.c new file mode 100644 index 0000000..6d32ead --- /dev/null +++ b/Tests/RunCMake/UnityBuild/per_config_c_debug.c @@ -0,0 +1,9 @@ +#ifndef CFG_DEBUG +# error "per_config_c_debug built without CFG_DEBUG" +#endif +#ifdef CFG_OTHER +# error "per_config_c_debug built with CFG_OTHER" +#endif +void per_config_c_debug(void) +{ +} diff --git a/Tests/RunCMake/UnityBuild/per_config_c_other.c b/Tests/RunCMake/UnityBuild/per_config_c_other.c new file mode 100644 index 0000000..89c7a6b --- /dev/null +++ b/Tests/RunCMake/UnityBuild/per_config_c_other.c @@ -0,0 +1,9 @@ +#ifdef CFG_DEBUG +# error "per_config_c_other built with CFG_DEBUG" +#endif +#ifndef CFG_OTHER +# error "per_config_c_other built without CFG_OTHER" +#endif +void per_config_c_other(void) +{ +} |