mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
FASTBuild: Allow files in different subdirs to be in the same unity bucket
The FASTBuild generator puts source files from different subdirectories into different `FastbuildObjectListNode` instances. This ensures that files with the same name will not write to the same object file. A unity bucket can only contain files from a single `FastbuildObjectListNode` instance, so a side effect of this logic is that unity buckets can only contain files in the same subdirectory. This change fixes the problem by skipping the subdirectory check logic for files with unity enabled. Fixes: #27457
This commit is contained in:
@@ -1393,9 +1393,11 @@ void cmFastbuildNormalTargetGenerator::GenerateObjects(FastbuildTarget& target)
|
||||
|
||||
cmSourceFile const& srcFile = *source;
|
||||
std::string const pathToFile = srcFile.GetFullPath();
|
||||
bool fileUsesUnity = useUnity;
|
||||
if (useUnity) {
|
||||
// Check if the source should be added to "UnityInputIsolatedFiles".
|
||||
if (srcFile.GetPropertyAsBool(SKIP_UNITY_BUILD_INCLUSION)) {
|
||||
fileUsesUnity = false;
|
||||
isolatedFromUnity.emplace(pathToFile);
|
||||
}
|
||||
std::string const perFileUnityGroup =
|
||||
@@ -1435,11 +1437,17 @@ void cmFastbuildNormalTargetGenerator::GenerateObjects(FastbuildTarget& target)
|
||||
|
||||
// If object should be placed in some subdir in the output
|
||||
// path. Tested in "SourceGroups" test.
|
||||
auto const subdir = cmSystemTools::GetFilenamePath(
|
||||
this->GeneratorTarget->GetObjectName(source));
|
||||
if (!subdir.empty()) {
|
||||
objOutDirWithPossibleSubdir += "/";
|
||||
objOutDirWithPossibleSubdir += subdir;
|
||||
// Not necessary for files in unity buckets because they are
|
||||
// built into a single unity object file. Executing this logic
|
||||
// for unity bucketed files prevents buckets from containing
|
||||
// source files in different subdirectories.
|
||||
if (!fileUsesUnity) {
|
||||
auto const subdir = cmSystemTools::GetFilenamePath(
|
||||
this->GeneratorTarget->GetObjectName(source));
|
||||
if (!subdir.empty()) {
|
||||
objOutDirWithPossibleSubdir += "/";
|
||||
objOutDirWithPossibleSubdir += subdir;
|
||||
}
|
||||
}
|
||||
|
||||
std::string const objectListHash = hash.HashString(cmStrCat(
|
||||
|
||||
@@ -6,6 +6,8 @@ run_cmake(Unity2)
|
||||
run_cmake(UnityBatchSize)
|
||||
run_cmake(UnityGroup)
|
||||
run_cmake(UnityIsolate)
|
||||
run_cmake(UnitySubdirs)
|
||||
run_cmake(UnitySubdirsIsolate)
|
||||
run_cmake(DisableCaching)
|
||||
run_cmake(DisableDistribution)
|
||||
run_cmake(SetCompilerProps)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Verify that files from different subdirectories are combined into a single Unity node.
|
||||
|
||||
set(REGEX_TO_MATCH "
|
||||
Unity\\('main_Unity_1'\\)
|
||||
{
|
||||
\\.UnityOutputPath = 'CMakeFiles/main.dir'
|
||||
\\.UnityOutputPattern = 'main_Unity_1.cpp'
|
||||
\\.UnityInputFiles =
|
||||
{
|
||||
.*main.cpp',
|
||||
.*subdir1/file1.cpp',
|
||||
.*subdir2/file2.cpp'
|
||||
}
|
||||
}
|
||||
.*ObjectList.*
|
||||
.*
|
||||
.CompilerInputUnity =
|
||||
{
|
||||
'main_Unity_1'
|
||||
}
|
||||
")
|
||||
|
||||
include(${RunCMake_SOURCE_DIR}/check.cmake)
|
||||
@@ -0,0 +1,16 @@
|
||||
# Test that unity build combines files from different subdirectories into the same unity bucket.
|
||||
|
||||
set(CMAKE_UNITY_BUILD ON)
|
||||
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/subdir1)
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/subdir2)
|
||||
|
||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/main.cpp "int main() { return 0; }\n")
|
||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/subdir1/file1.cpp "int file1() { return 1; }\n")
|
||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/subdir2/file2.cpp "int file2() { return 2; }\n")
|
||||
|
||||
add_executable(main
|
||||
${CMAKE_CURRENT_BINARY_DIR}/main.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/subdir1/file1.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/subdir2/file2.cpp
|
||||
)
|
||||
@@ -0,0 +1,26 @@
|
||||
# Verify that:
|
||||
# 1. Non-isolated files from different subdirs are combined in one Unity node
|
||||
# 2. Isolated files from subdirs are in separate ObjectLists with proper subdir paths
|
||||
|
||||
# Check that Unity node contains the non-isolated files (main.cpp and unity_file.cpp)
|
||||
# but not the isolated file. The isolated file should be compiled separately with
|
||||
# its subdirectory in the output path.
|
||||
set(REGEX_TO_MATCH "
|
||||
Unity\\('main_Unity_1'\\)
|
||||
{
|
||||
\\.UnityOutputPath = 'CMakeFiles/main.dir'
|
||||
\\.UnityOutputPattern = 'main_Unity_1.cpp'
|
||||
\\.UnityInputFiles =
|
||||
{
|
||||
.*main.cpp',
|
||||
.*subdir1/unity_file.cpp'
|
||||
}
|
||||
}
|
||||
.*ObjectList.*
|
||||
.*
|
||||
\\.CompilerOutputPath = 'CMakeFiles/main.dir/subdir2'
|
||||
.*
|
||||
.*isolated_file.cpp'
|
||||
")
|
||||
|
||||
include(${RunCMake_SOURCE_DIR}/check.cmake)
|
||||
@@ -0,0 +1,23 @@
|
||||
# Test that isolated files from subdirectories get proper subdirectory-based object paths,
|
||||
# while non-isolated files are combined in unity buckets regardless of subdirectory.
|
||||
|
||||
set(CMAKE_UNITY_BUILD ON)
|
||||
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/subdir1)
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/subdir2)
|
||||
|
||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/main.cpp "int main() { return 0; }\n")
|
||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/subdir1/unity_file.cpp "int unity_file() { return 1; }\n")
|
||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/subdir2/isolated_file.cpp "int isolated_file() { return 2; }\n")
|
||||
|
||||
add_executable(main
|
||||
${CMAKE_CURRENT_BINARY_DIR}/main.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/subdir1/unity_file.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/subdir2/isolated_file.cpp
|
||||
)
|
||||
|
||||
set_source_files_properties(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/subdir2/isolated_file.cpp
|
||||
TARGET_DIRECTORY main
|
||||
PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON
|
||||
)
|
||||
Reference in New Issue
Block a user