mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-07 06:40:16 -05:00
Merge topic 'unity_explicit_groups'
9f4eb352feUnity Builds: Support explicit specification of sources to groupsb00585adccUnity: Refactor implementation to make it easier to extend Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !4716
This commit is contained in:
@@ -346,6 +346,7 @@ Properties on Targets
|
||||
/prop_tgt/UNITY_BUILD_BATCH_SIZE
|
||||
/prop_tgt/UNITY_BUILD_CODE_AFTER_INCLUDE
|
||||
/prop_tgt/UNITY_BUILD_CODE_BEFORE_INCLUDE
|
||||
/prop_tgt/UNITY_BUILD_MODE
|
||||
/prop_tgt/VERSION
|
||||
/prop_tgt/VISIBILITY_INLINES_HIDDEN
|
||||
/prop_tgt/VS_CONFIGURATION_TYPE
|
||||
@@ -484,6 +485,7 @@ Properties on Source Files
|
||||
/prop_sf/Swift_DEPENDENCIES_FILE
|
||||
/prop_sf/Swift_DIAGNOSTICS_FILE
|
||||
/prop_sf/SYMBOLIC
|
||||
/prop_sf/UNITY_GROUP
|
||||
/prop_sf/VS_COPY_TO_OUT_DIR
|
||||
/prop_sf/VS_CSHARP_tagname
|
||||
/prop_sf/VS_DEPLOYMENT_CONTENT
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
UNITY_GROUP
|
||||
-----------
|
||||
|
||||
This property controls which *bucket* the source will be part of when
|
||||
the :prop_tgt:`UNITY_BUILD_MODE` is set to ``GROUP``.
|
||||
@@ -5,8 +5,28 @@ When this property is set to true, the target source files will be combined
|
||||
into batches for faster compilation. This is done by creating a (set of)
|
||||
unity sources which ``#include`` the original sources, then compiling these
|
||||
unity sources instead of the originals. This is known as a *Unity* or *Jumbo*
|
||||
build. The :prop_tgt:`UNITY_BUILD_BATCH_SIZE` property controls the upper
|
||||
limit on how many sources can be combined per unity source file.
|
||||
build.
|
||||
|
||||
CMake provides different algorithms for selecting which sources are grouped
|
||||
together into a *bucket*. Algorithm selection is decided by the
|
||||
:prop_tgt:`UNITY_BUILD_MODE` target property, which has the following acceptable
|
||||
values:
|
||||
|
||||
* ``BATCH``
|
||||
When in this mode CMake determines which files are grouped together.
|
||||
The :prop_tgt:`UNITY_BUILD_BATCH_SIZE` property controls the upper limit on
|
||||
how many sources can be combined per unity source file.
|
||||
|
||||
* ``GROUP``
|
||||
When in this mode each target explicitly specifies how to group
|
||||
source files. Each source file that has the same
|
||||
:prop_sf:`UNITY_GROUP` value will be grouped together. Any sources
|
||||
that don't have this property will be compiled individually. The
|
||||
:prop_tgt:`UNITY_BUILD_BATCH_SIZE` property is ignored when using
|
||||
this mode.
|
||||
|
||||
If no explicit :prop_tgt:`UNITY_BUILD_MODE` has been specified, CMake will
|
||||
default to ``BATCH``.
|
||||
|
||||
Unity builds are not currently supported for all languages. CMake version
|
||||
|release| supports combining ``C`` and ``CXX`` source files. For targets that
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
UNITY_BUILD_MODE
|
||||
----------------
|
||||
|
||||
CMake provides different algorithms for selecting which sources are grouped
|
||||
together into a *bucket*. Selection is decided by this property,
|
||||
which has the following acceptable values:
|
||||
|
||||
* ``BATCH``
|
||||
When in this mode CMake determines which files are grouped together.
|
||||
The :prop_tgt:`UNITY_BUILD_BATCH_SIZE` property controls the upper limit on
|
||||
how many sources can be combined per unity source file.
|
||||
|
||||
* ``GROUP``
|
||||
When in this mode each target explicitly specifies how to group
|
||||
source files. Each source file that has the same
|
||||
:prop_sf:`UNITY_GROUP` value will be grouped together. Any sources
|
||||
that don't have this property will be compiled individually. The
|
||||
:prop_tgt:`UNITY_BUILD_BATCH_SIZE` property is ignored when using
|
||||
this mode.
|
||||
|
||||
If no explicit :prop_tgt:`UNITY_BUILD_MODE` has been specified, CMake will
|
||||
default to ``BATCH``.
|
||||
@@ -0,0 +1,6 @@
|
||||
grouped-unity-build-mode
|
||||
------------------------
|
||||
|
||||
* The :prop_tgt:`UNITY_BUILD_MODE` target property was added to tell
|
||||
generators which algorithm to use for grouping included source
|
||||
files.
|
||||
+134
-44
@@ -2758,6 +2758,120 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
inline void RegisterUnitySources(cmGeneratorTarget* target, cmSourceFile* sf,
|
||||
std::string const& filename)
|
||||
{
|
||||
target->AddSourceFileToUnityBatch(sf->ResolveFullPath());
|
||||
sf->SetProperty("UNITY_SOURCE_FILE", filename.c_str());
|
||||
}
|
||||
|
||||
inline void IncludeFileInUnitySources(cmGeneratedFileStream& unity_file,
|
||||
std::string const& sf_full_path,
|
||||
cmProp beforeInclude,
|
||||
cmProp afterInclude)
|
||||
{
|
||||
if (beforeInclude) {
|
||||
unity_file << *beforeInclude << "\n";
|
||||
}
|
||||
|
||||
unity_file << "#include \"" << sf_full_path << "\"\n";
|
||||
|
||||
if (afterInclude) {
|
||||
unity_file << *afterInclude << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> AddUnityFilesModeAuto(
|
||||
cmGeneratorTarget* target, std::string const& lang,
|
||||
std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude,
|
||||
cmProp afterInclude, std::string const& filename_base, size_t batchSize)
|
||||
{
|
||||
if (batchSize == 0) {
|
||||
batchSize = filtered_sources.size();
|
||||
}
|
||||
|
||||
std::vector<std::string> unity_files;
|
||||
for (size_t itemsLeft = filtered_sources.size(), chunk, batch = 0;
|
||||
itemsLeft > 0; itemsLeft -= chunk, ++batch) {
|
||||
|
||||
chunk = std::min(itemsLeft, batchSize);
|
||||
|
||||
std::string filename = cmStrCat(filename_base, "unity_", batch,
|
||||
(lang == "C") ? "_c.c" : "_cxx.cxx");
|
||||
|
||||
const std::string filename_tmp = cmStrCat(filename, ".tmp");
|
||||
{
|
||||
size_t begin = batch * batchSize;
|
||||
size_t end = begin + chunk;
|
||||
|
||||
cmGeneratedFileStream file(
|
||||
filename_tmp, false,
|
||||
target->GetGlobalGenerator()->GetMakefileEncoding());
|
||||
file << "/* generated by CMake */\n\n";
|
||||
|
||||
for (; begin != end; ++begin) {
|
||||
cmSourceFile* sf = filtered_sources[begin];
|
||||
RegisterUnitySources(target, sf, filename);
|
||||
IncludeFileInUnitySources(file, sf->ResolveFullPath(), beforeInclude,
|
||||
afterInclude);
|
||||
}
|
||||
}
|
||||
cmSystemTools::MoveFileIfDifferent(filename_tmp, filename);
|
||||
unity_files.emplace_back(std::move(filename));
|
||||
}
|
||||
return unity_files;
|
||||
}
|
||||
|
||||
std::vector<std::string> AddUnityFilesModeGroup(
|
||||
cmGeneratorTarget* target, std::string const& lang,
|
||||
std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude,
|
||||
cmProp afterInclude, std::string const& filename_base)
|
||||
{
|
||||
std::vector<std::string> unity_files;
|
||||
|
||||
// sources organized by group name. Drop any source
|
||||
// without a group
|
||||
std::unordered_map<std::string, std::vector<cmSourceFile*>> explicit_mapping;
|
||||
for (cmSourceFile* sf : filtered_sources) {
|
||||
if (cmProp value = sf->GetProperty("UNITY_GROUP")) {
|
||||
auto i = explicit_mapping.find(*value);
|
||||
if (i == explicit_mapping.end()) {
|
||||
std::vector<cmSourceFile*> sources{ sf };
|
||||
explicit_mapping.emplace(*value, sources);
|
||||
} else {
|
||||
i->second.emplace_back(sf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto const& item : explicit_mapping) {
|
||||
auto const& name = item.first;
|
||||
std::string filename = cmStrCat(filename_base, "unity_", name,
|
||||
(lang == "C") ? "_c.c" : "_cxx.cxx");
|
||||
|
||||
const std::string filename_tmp = cmStrCat(filename, ".tmp");
|
||||
{
|
||||
cmGeneratedFileStream file(
|
||||
filename_tmp, false,
|
||||
target->GetGlobalGenerator()->GetMakefileEncoding());
|
||||
file << "/* generated by CMake */\n\n";
|
||||
|
||||
for (cmSourceFile* sf : item.second) {
|
||||
RegisterUnitySources(target, sf, filename);
|
||||
IncludeFileInUnitySources(file, sf->ResolveFullPath(), beforeInclude,
|
||||
afterInclude);
|
||||
}
|
||||
}
|
||||
cmSystemTools::MoveFileIfDifferent(filename_tmp, filename);
|
||||
unity_files.emplace_back(std::move(filename));
|
||||
}
|
||||
|
||||
return unity_files;
|
||||
}
|
||||
}
|
||||
|
||||
void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
|
||||
{
|
||||
if (!target->GetPropertyAsBool("UNITY_BUILD")) {
|
||||
@@ -2786,6 +2900,7 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
|
||||
cmProp beforeInclude =
|
||||
target->GetProperty("UNITY_BUILD_CODE_BEFORE_INCLUDE");
|
||||
cmProp afterInclude = target->GetProperty("UNITY_BUILD_CODE_AFTER_INCLUDE");
|
||||
cmProp unityMode = target->GetProperty("UNITY_BUILD_MODE");
|
||||
|
||||
for (std::string lang : { "C", "CXX" }) {
|
||||
std::vector<cmSourceFile*> filtered_sources;
|
||||
@@ -2800,53 +2915,28 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
|
||||
!sf->GetProperty("INCLUDE_DIRECTORIES");
|
||||
});
|
||||
|
||||
size_t batchSize = unityBatchSize;
|
||||
if (unityBatchSize == 0) {
|
||||
batchSize = filtered_sources.size();
|
||||
std::vector<std::string> unity_files;
|
||||
if (!unityMode || *unityMode == "BATCH") {
|
||||
unity_files =
|
||||
AddUnityFilesModeAuto(target, lang, filtered_sources, beforeInclude,
|
||||
afterInclude, filename_base, unityBatchSize);
|
||||
} else if (unityMode && *unityMode == "GROUP") {
|
||||
unity_files =
|
||||
AddUnityFilesModeGroup(target, lang, 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 +
|
||||
" assigned to target " + target->GetName() +
|
||||
". Acceptable values are BATCH and GROUP.");
|
||||
this->IssueMessage(MessageType::FATAL_ERROR, e);
|
||||
}
|
||||
|
||||
for (size_t itemsLeft = filtered_sources.size(), chunk, batch = 0;
|
||||
itemsLeft > 0; itemsLeft -= chunk, ++batch) {
|
||||
|
||||
chunk = std::min(itemsLeft, batchSize);
|
||||
|
||||
std::string filename = cmStrCat(filename_base, "unity_", batch,
|
||||
(lang == "C") ? "_c.c" : "_cxx.cxx");
|
||||
|
||||
const std::string filename_tmp = cmStrCat(filename, ".tmp");
|
||||
{
|
||||
size_t begin = batch * batchSize;
|
||||
size_t end = begin + chunk;
|
||||
|
||||
cmGeneratedFileStream file(
|
||||
filename_tmp, false,
|
||||
this->GetGlobalGenerator()->GetMakefileEncoding());
|
||||
file << "/* generated by CMake */\n\n";
|
||||
|
||||
for (; begin != end; ++begin) {
|
||||
cmSourceFile* sf = filtered_sources[begin];
|
||||
|
||||
target->AddSourceFileToUnityBatch(sf->ResolveFullPath());
|
||||
sf->SetProperty("UNITY_SOURCE_FILE", filename.c_str());
|
||||
|
||||
if (beforeInclude) {
|
||||
file << *beforeInclude << "\n";
|
||||
}
|
||||
|
||||
file << "#include \"" << sf->ResolveFullPath() << "\"\n";
|
||||
|
||||
if (afterInclude) {
|
||||
file << *afterInclude << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
cmSystemTools::MoveFileIfDifferent(filename_tmp, filename);
|
||||
|
||||
target->AddSource(filename, true);
|
||||
|
||||
auto unity = this->Makefile->GetOrCreateSource(filename);
|
||||
for (auto const& file : unity_files) {
|
||||
auto unity = this->GetMakefile()->GetOrCreateSource(file);
|
||||
target->AddSource(file, true);
|
||||
unity->SetProperty("SKIP_UNITY_BUILD_INCLUSION", "ON");
|
||||
unity->SetProperty("UNITY_SOURCE_FILE", filename.c_str());
|
||||
unity->SetProperty("UNITY_SOURCE_FILE", file.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,6 +372,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
|
||||
initProp("DISABLE_PRECOMPILE_HEADERS");
|
||||
initProp("UNITY_BUILD");
|
||||
initPropValue("UNITY_BUILD_BATCH_SIZE", "8");
|
||||
initPropValue("UNITY_BUILD_MODE", "BATCH");
|
||||
initPropValue("PCH_WARN_INVALID", "ON");
|
||||
#ifdef __APPLE__
|
||||
if (this->GetGlobalGenerator()->IsXcode()) {
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
include(RunCMake)
|
||||
|
||||
run_cmake(unitybuild_c)
|
||||
run_cmake(unitybuild_c_batch)
|
||||
run_cmake(unitybuild_c_group)
|
||||
run_cmake(unitybuild_cxx)
|
||||
run_cmake(unitybuild_cxx_group)
|
||||
run_cmake(unitybuild_c_and_cxx)
|
||||
run_cmake(unitybuild_c_and_cxx_group)
|
||||
run_cmake(unitybuild_batchsize)
|
||||
run_cmake(unitybuild_default_batchsize)
|
||||
run_cmake(unitybuild_skip)
|
||||
run_cmake(unitybuild_code_before_and_after_include)
|
||||
run_cmake(unitybuild_c_no_unity_build)
|
||||
run_cmake(unitybuild_c_no_unity_build_group)
|
||||
run_cmake(unitybuild_order)
|
||||
run_cmake(unitybuild_invalid_mode)
|
||||
|
||||
function(run_test name)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
int f(int x)
|
||||
{
|
||||
(void)x;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
set(unitybuild_a_c "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_a_c.c")
|
||||
if(NOT EXISTS "${unitybuild_a_c}")
|
||||
set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_a_c} does not exist.")
|
||||
return()
|
||||
else()
|
||||
#verify that the 4 c file is part of this grouping and therefore UNITY_BUILD_BATCH_SIZE
|
||||
#was ignored
|
||||
file(STRINGS ${unitybuild_a_c} unitybuild_a_c_strings)
|
||||
string(REGEX MATCH ".*#include.*s1.c.*#include.*s2.c.*#include.*s3.c.*#include.*s4.c.*" matched_code ${unitybuild_a_c_strings})
|
||||
if(NOT matched_code)
|
||||
set(RunCMake_TEST_FAILED "Generated unity file doesn't include expected source files")
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(unitybuild_b_c "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_b_c.c")
|
||||
if(NOT EXISTS "${unitybuild_b_c}")
|
||||
set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_b_c} does not exist.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
|
||||
set(unitybuild_a_cxx "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_a_cxx.cxx")
|
||||
if(NOT EXISTS "${unitybuild_a_cxx}")
|
||||
set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_a_cxx} does not exist.")
|
||||
return()
|
||||
else()
|
||||
#verify that the 4 cxx file are part of this grouping and therefore UNITY_BUILD_BATCH_SIZE
|
||||
#was ignored
|
||||
file(STRINGS ${unitybuild_a_cxx} unitybuild_a_cxx_strings)
|
||||
string(REGEX MATCH ".*#include.*s1.cxx.*#include.*s2.cxx.*#include.*s3.cxx.*#include.*s4.cxx.*" matched_code ${unitybuild_a_cxx_strings})
|
||||
if(NOT matched_code)
|
||||
set(RunCMake_TEST_FAILED "Generated unity file doesn't include expected source files")
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(unitybuild_b_cxx "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_b_cxx.cxx")
|
||||
if(NOT EXISTS "${unitybuild_b_cxx}")
|
||||
set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_b_cxx} does not exist.")
|
||||
return()
|
||||
endif()
|
||||
@@ -0,0 +1,39 @@
|
||||
project(unitybuild_c_and_cxx C CXX)
|
||||
|
||||
set(srcs f.c)
|
||||
foreach(s RANGE 1 8)
|
||||
set(src_c "${CMAKE_CURRENT_BINARY_DIR}/s${s}.c")
|
||||
file(WRITE "${src_c}" "
|
||||
int f(int);\n
|
||||
int s${s}(void) { return f(${s}); }\n"
|
||||
)
|
||||
|
||||
set(src_cxx "${CMAKE_CURRENT_BINARY_DIR}/s${s}.cxx")
|
||||
file(WRITE "${src_cxx}" "
|
||||
extern \"C\" { \n
|
||||
int f(int); \n
|
||||
}\n
|
||||
int s${s}(void) { return f(${s}); }\n"
|
||||
)
|
||||
|
||||
list(APPEND srcs "${src_c}")
|
||||
list(APPEND srcs "${src_cxx}")
|
||||
endforeach()
|
||||
|
||||
|
||||
|
||||
add_library(tgt SHARED ${srcs})
|
||||
|
||||
set_target_properties(tgt PROPERTIES UNITY_BUILD ON
|
||||
UNITY_BUILD_MODE GROUP
|
||||
#UNITY_BUILD_BATCH_SIZE will be ignored
|
||||
UNITY_BUILD_BATCH_SIZE 2)
|
||||
|
||||
set_source_files_properties(s1.c s2.c s3.c s4.c
|
||||
s1.cxx s2.cxx s3.cxx s4.cxx
|
||||
PROPERTIES UNITY_GROUP "a"
|
||||
)
|
||||
set_source_files_properties(s5.c s6.c s7.c s8.c
|
||||
s5.cxx s6.cxx s7.cxx s8.cxx
|
||||
PROPERTIES UNITY_GROUP "b"
|
||||
)
|
||||
@@ -0,0 +1,5 @@
|
||||
set(unitybuild_c "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0_c.c")
|
||||
if(NOT EXISTS "${unitybuild_c}")
|
||||
set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_c} does not exist.")
|
||||
return()
|
||||
endif()
|
||||
@@ -0,0 +1,15 @@
|
||||
project(unitybuild_c C)
|
||||
|
||||
set(srcs "")
|
||||
foreach(s RANGE 1 8)
|
||||
set(src "${CMAKE_CURRENT_BINARY_DIR}/s${s}.c")
|
||||
file(WRITE "${src}" "int s${s}(void) { return 0; }\n")
|
||||
list(APPEND srcs "${src}")
|
||||
endforeach()
|
||||
|
||||
add_library(tgt SHARED ${srcs})
|
||||
|
||||
set_target_properties(tgt PROPERTIES
|
||||
UNITY_BUILD ON
|
||||
UNITY_BUILD_MODE BATCH
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
set(unitybuild_a_c "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_a_c.c")
|
||||
if(NOT EXISTS "${unitybuild_a_c}")
|
||||
set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_a_c} does not exist.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(unitybuild_b_c "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_b_c.c")
|
||||
if(NOT EXISTS "${unitybuild_b_c}")
|
||||
set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_b_c} does not exist.")
|
||||
return()
|
||||
endif()
|
||||
@@ -0,0 +1,17 @@
|
||||
project(unitybuild_c C)
|
||||
|
||||
set(srcs "")
|
||||
foreach(s RANGE 1 8)
|
||||
set(src "${CMAKE_CURRENT_BINARY_DIR}/s${s}.c")
|
||||
file(WRITE "${src}" "int s${s}(void) { return 0; }\n")
|
||||
list(APPEND srcs "${src}")
|
||||
endforeach()
|
||||
|
||||
add_library(tgt SHARED ${srcs})
|
||||
|
||||
set_target_properties(tgt PROPERTIES UNITY_BUILD ON
|
||||
UNITY_BUILD_MODE GROUP)
|
||||
|
||||
set_source_files_properties(s1.c PROPERTIES UNITY_GROUP "a")
|
||||
set_source_files_properties(s2.c PROPERTIES UNITY_GROUP "a")
|
||||
set_source_files_properties(s3.c s4.c PROPERTIES UNITY_GROUP "b")
|
||||
@@ -0,0 +1,5 @@
|
||||
set(unitybuild_c "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_a_c.c")
|
||||
if(EXISTS "${unitybuild_c}")
|
||||
set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_c} should not exist.")
|
||||
return()
|
||||
endif()
|
||||
@@ -0,0 +1,16 @@
|
||||
project(unitybuild_c_no_unity_build C)
|
||||
|
||||
set(srcs "")
|
||||
foreach(s RANGE 1 8)
|
||||
set(src "${CMAKE_CURRENT_BINARY_DIR}/s${s}.c")
|
||||
file(WRITE "${src}" "int s${s}(void) { return 0; }\n")
|
||||
list(APPEND srcs "${src}")
|
||||
endforeach()
|
||||
|
||||
add_library(tgt SHARED ${srcs})
|
||||
|
||||
#These should be ignored as UNITY_BUILD is off
|
||||
set_target_properties(tgt PROPERTIES UNITY_BUILD_MODE GROUP)
|
||||
set_source_files_properties(s1.c s2.c s3.c s4.c s5.c s6.c s7.c s8.c
|
||||
PROPERTIES UNITY_GROUP "a"
|
||||
)
|
||||
@@ -0,0 +1,27 @@
|
||||
set(unitybuild_a_cxx "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_a_cxx.cxx")
|
||||
if(NOT EXISTS "${unitybuild_a_cxx}")
|
||||
set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_a_cxx} does not exist.")
|
||||
return()
|
||||
else()
|
||||
#verify that odr2 is not part of this source set
|
||||
file(STRINGS ${unitybuild_a_cxx} unitybuild_a_cxx_strings)
|
||||
string(REGEX MATCH ".*#include.*odr2.cxx" matched_code ${unitybuild_a_cxx_strings})
|
||||
if(matched_code)
|
||||
set(RunCMake_TEST_FAILED "Generated unity file includes un-expected ord2.cxx source file")
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(unitybuild_b_cxx "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_b_cxx.cxx")
|
||||
if(NOT EXISTS "${unitybuild_b_cxx}")
|
||||
set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_b_cxx} does not exist.")
|
||||
return()
|
||||
else()
|
||||
#verify that odr1 is not part of this source set
|
||||
file(STRINGS ${unitybuild_b_cxx} unitybuild_b_cxx_strings)
|
||||
string(REGEX MATCH ".*#include.*odr1.cxx" matched_code ${unitybuild_b_cxx_strings})
|
||||
if(matched_code)
|
||||
set(RunCMake_TEST_FAILED "Generated unity file includes un-expected ord1.cxx source file")
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,27 @@
|
||||
project(unitybuild_cxx CXX)
|
||||
|
||||
set(srcs "")
|
||||
foreach(s RANGE 1 4)
|
||||
set(src "${CMAKE_CURRENT_BINARY_DIR}/s${s}.cxx")
|
||||
file(WRITE "${src}" "int s${s}(void) { return 0; }\n")
|
||||
list(APPEND srcs "${src}")
|
||||
endforeach()
|
||||
|
||||
foreach(s RANGE 1 2)
|
||||
set(src "${CMAKE_CURRENT_BINARY_DIR}/odr${s}.cxx")
|
||||
file(WRITE "${src}" "namespace odr { int s${s}(void) { return 0; } }\n")
|
||||
list(APPEND srcs "${src}")
|
||||
endforeach()
|
||||
|
||||
add_library(tgt SHARED ${srcs})
|
||||
|
||||
set_target_properties(tgt PROPERTIES UNITY_BUILD ON
|
||||
UNITY_BUILD_MODE GROUP
|
||||
)
|
||||
|
||||
set_source_files_properties(s1.cxx s2.cxx odr1.cxx
|
||||
PROPERTIES UNITY_GROUP "a"
|
||||
)
|
||||
set_source_files_properties(s3.cxx s4.cxx odr2.cxx
|
||||
PROPERTIES UNITY_GROUP "b"
|
||||
)
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
^CMake Error in CMakeLists.txt:
|
||||
Invalid UNITY_BUILD_MODE value of INVALID assigned to target tgt\.
|
||||
Acceptable values are BATCH and GROUP\.
|
||||
.*
|
||||
CMake Generate step failed\. Build files cannot be regenerated correctly\.$
|
||||
@@ -0,0 +1,12 @@
|
||||
project(unitybuild_c C)
|
||||
|
||||
set(srcs "")
|
||||
foreach(s RANGE 1 8)
|
||||
set(src "${CMAKE_CURRENT_BINARY_DIR}/s${s}.c")
|
||||
file(WRITE "${src}" "int s${s}(void) { return 0; }\n")
|
||||
list(APPEND srcs "${src}")
|
||||
endforeach()
|
||||
|
||||
add_library(tgt SHARED ${srcs})
|
||||
|
||||
set_target_properties(tgt PROPERTIES UNITY_BUILD ON UNITY_BUILD_MODE INVALID)
|
||||
@@ -56,6 +56,7 @@ if (RunCMake_GENERATOR MATCHES "Visual Studio 1[0-4] 201[0-5]" OR
|
||||
run_cmake(UnityBuildPre2017)
|
||||
else()
|
||||
run_cmake(UnityBuildNative)
|
||||
run_cmake(UnityBuildNativeGrouped)
|
||||
endif()
|
||||
|
||||
run_cmake(VsDotnetTargetFramework)
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
set(unitybuild_c0 "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_poolA_c.c")
|
||||
if(NOT EXISTS "${unitybuild_c0}")
|
||||
set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_c0} does not exist.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(unitybuild_c1 "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_poolB_c.c")
|
||||
if(NOT EXISTS "${unitybuild_c1}")
|
||||
set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_c1} does not exist.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(tgt_project "${RunCMake_TEST_BINARY_DIR}/tgt.vcxproj")
|
||||
if (NOT EXISTS "${tgt_project}")
|
||||
set(RunCMake_TEST_FAILED "Generated project file ${tgt_project} doesn't exist.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
file(STRINGS ${tgt_project} tgt_projects_strings)
|
||||
|
||||
foreach(line IN LISTS tgt_projects_strings)
|
||||
if (line MATCHES "<EnableUnitySupport>true</EnableUnitySupport>")
|
||||
set(have_unity_support ON)
|
||||
endif()
|
||||
|
||||
if (line MATCHES "<ClCompile Include=.*IncludeInUnityFile=\"false\" CustomUnityFile=\"true\"")
|
||||
list(APPEND unity_source_lines ${line})
|
||||
endif()
|
||||
|
||||
if (line MATCHES "<ClCompile Include=.*IncludeInUnityFile=\"true\" CustomUnityFile=\"true\"")
|
||||
list(APPEND sources_list ${line})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if (NOT have_unity_support)
|
||||
set(RunCMake_TEST_FAILED "Generated project should include the <EnableUnitySupport> block.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
string(REPLACE "\\" "/" unity_source_lines "${unity_source_lines}")
|
||||
string(FIND "${unity_source_lines}" "CMakeFiles/tgt.dir/Unity/unity_poolA_c.c" unity_source_file_position)
|
||||
if (unity_source_file_position EQUAL "-1")
|
||||
set(RunCMake_TEST_FAILED "Generated project should include the generated unity source file 'poolA'.")
|
||||
return()
|
||||
endif()
|
||||
string(FIND "${unity_source_lines}" "CMakeFiles/tgt.dir/Unity/unity_poolB_c.c" unity_source_file_position)
|
||||
if (unity_source_file_position EQUAL "-1")
|
||||
set(RunCMake_TEST_FAILED "Generated project should include the generated unity source file 'poolB'.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
list(LENGTH sources_list number_of_sources)
|
||||
if(NOT number_of_sources EQUAL 7)
|
||||
set(RunCMake_TEST_FAILED "Generated project doesn't include the expect number of files.")
|
||||
return()
|
||||
endif()
|
||||
@@ -0,0 +1,20 @@
|
||||
project(unitybuild_c C)
|
||||
|
||||
set(srcs "")
|
||||
foreach(s RANGE 1 8)
|
||||
set(src "${CMAKE_CURRENT_BINARY_DIR}/s${s}.c")
|
||||
file(WRITE "${src}" "int s${s}(void) { return 0; }\n")
|
||||
list(APPEND srcs "${src}")
|
||||
endforeach()
|
||||
|
||||
add_library(tgt SHARED ${srcs})
|
||||
|
||||
set_target_properties(tgt PROPERTIES UNITY_BUILD ON UNITY_BUILD_MODE GROUP)
|
||||
|
||||
set_source_files_properties(s1.c s2.c s3.c s4.c
|
||||
PROPERTIES UNITY_GROUP "poolA"
|
||||
)
|
||||
|
||||
set_source_files_properties(s5.c s6.c s7.c
|
||||
PROPERTIES UNITY_GROUP "poolB"
|
||||
)
|
||||
@@ -0,0 +1,59 @@
|
||||
set(unitybuild_c0 "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_poolA.c")
|
||||
if(NOT EXISTS "${unitybuild_c0}")
|
||||
set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_c0} does not exist.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(unitybuild_c1 "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_poolB.c")
|
||||
if(NOT EXISTS "${unitybuild_c1}")
|
||||
set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_c1} does not exist.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(tgt_project "${RunCMake_TEST_BINARY_DIR}/tgt.vcxproj")
|
||||
if (NOT EXISTS "${tgt_project}")
|
||||
set(RunCMake_TEST_FAILED "Generated project file ${tgt_project} doesn't exist.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
file(STRINGS ${tgt_project} tgt_projects_strings)
|
||||
|
||||
foreach(line IN LISTS tgt_projects_strings)
|
||||
if (line MATCHES "<ClCompile Include=.*/>")
|
||||
set(unity_source_line ${line})
|
||||
endif()
|
||||
|
||||
if (line MATCHES "<ClCompile Include=\"[^\"]*\">")
|
||||
string(REGEX MATCH "<ClCompile Include=\"([^\"]*)\">" source_file ${line})
|
||||
list(APPEND sources_list ${source_file})
|
||||
endif()
|
||||
|
||||
if (line MATCHES "<ExcludedFromBuild.*</ExcludedFromBuild>")
|
||||
list(APPEND excluded_sources_list ${source_file})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
string(REPLACE "\\" "/" unity_source_line ${unity_source_line})
|
||||
string(FIND "${unity_source_line}" "CMakeFiles/tgt.dir/Unity/unity_poolA.c" unity_source_file_position)
|
||||
if (unity_source_file_position EQUAL "-1")
|
||||
set(RunCMake_TEST_FAILED "Generated project should include the generated unity source file.")
|
||||
return()
|
||||
endif()
|
||||
string(FIND "${unity_source_line}" "CMakeFiles/tgt.dir/Unity/unity_poolB.c" unity_source_file_position)
|
||||
if (unity_source_file_position EQUAL "-1")
|
||||
set(RunCMake_TEST_FAILED "Generated project should include the generated unity source file.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
list(LENGTH sources_list number_of_sources)
|
||||
if(NOT number_of_sources EQUAL 7)
|
||||
set(RunCMake_TEST_FAILED "Generated project doesn't include the expect number of files.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Exclusions for Debug|Release|MinSizeRel|RelWithDebInfo
|
||||
list(LENGTH excluded_sources_list number_of_excluded_sources)
|
||||
if(NOT number_of_excluded_sources EQUAL 28)
|
||||
set(RunCMake_TEST_FAILED "Generated project doesn't exclude the source files for all configurations.")
|
||||
return()
|
||||
endif()
|
||||
@@ -0,0 +1,20 @@
|
||||
project(unitybuild_c C)
|
||||
|
||||
set(srcs "")
|
||||
foreach(s RANGE 1 8)
|
||||
set(src "${CMAKE_CURRENT_BINARY_DIR}/s${s}.c")
|
||||
file(WRITE "${src}" "int s${s}(void) { return 0; }\n")
|
||||
list(APPEND srcs "${src}")
|
||||
endforeach()
|
||||
|
||||
add_library(tgt SHARED ${srcs})
|
||||
|
||||
set_target_properties(tgt PROPERTIES UNITY_BUILD ON UNITY_BUILD_MODE GROUP)
|
||||
|
||||
set_source_files_properties(s1.c s2.c s3.c s4.c
|
||||
PROPERTIES UNITY_GROUP "poolA"
|
||||
)
|
||||
|
||||
set_source_files_properties(s5.c s6.c s7.c
|
||||
PROPERTIES UNITY_GROUP "poolB"
|
||||
)
|
||||
Reference in New Issue
Block a user