Ninja: support short object directories

This commit is contained in:
John Parent
2025-05-21 23:11:31 +02:00
committed by Ben Boeckel
parent 050f891d81
commit 851e07fda3
24 changed files with 117 additions and 5 deletions

View File

@@ -4,4 +4,7 @@ short-object-names
* There is now the :variable:`CMAKE_INTERMEDIATE_DIR_STRATEGY` variable (and
associated environment variable :envvar:`CMAKE_INTERMEDIATE_DIR_STRATEGY`)
that may be used to change the strategy used to name intermediate
directories used for object files (and other associated target metadata).
directories used for object files (and other associated target metadata). It
is supported for the following generators:
- :ref:`Ninja Generators`

View File

@@ -1048,6 +1048,11 @@ bool cmGlobalNinjaGenerator::HasRule(std::string const& name)
// Private virtual overrides
bool cmGlobalNinjaGenerator::SupportsShortObjectNames() const
{
return true;
}
void cmGlobalNinjaGenerator::ComputeTargetObjectDirectory(
cmGeneratorTarget* gt) const
{
@@ -2276,7 +2281,7 @@ void cmGlobalNinjaGenerator::StripNinjaOutputPathPrefixAsSuffix(
/*
We use the following approach to support Fortran. Each target already
has a <target>.dir/ directory used to hold intermediate files for CMake.
has an intermediate directory used to hold intermediate files for CMake.
For each target, a FortranDependInfo.json file is generated by CMake with
information about include directories, module directories, and the locations
the per-target directories for target dependencies.

View File

@@ -391,6 +391,7 @@ public:
void AddTargetAlias(std::string const& alias, cmGeneratorTarget* target,
std::string const& config);
bool SupportsShortObjectNames() const override;
void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override;
// Ninja generator uses 'deps' and 'msvc_deps_prefix' introduced in 1.3

View File

@@ -163,6 +163,15 @@ void cmLocalNinjaGenerator::Generate()
}
}
std::string cmLocalNinjaGenerator::GetObjectOutputRoot() const
{
if (this->UseShortObjectNames()) {
return cmStrCat(this->GetBinaryDirectory(), '/',
this->GetGlobalGenerator()->GetShortBinaryOutputDir());
}
return cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles");
}
// Non-virtual public methods.
cmGlobalNinjaGenerator const* cmLocalNinjaGenerator::GetGlobalNinjaGenerator()

View File

@@ -62,6 +62,7 @@ public:
{
return this->HomeRelativeOutputPath;
}
std::string GetObjectOutputRoot() const override;
std::string BuildCommandLine(
std::vector<std::string> const& cmdLines, std::string const& outputConfig,

View File

@@ -1414,6 +1414,12 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
vars["DEFINES"] = this->ComputeDefines(source, language, config);
vars["INCLUDES"] = this->ComputeIncludes(source, language, config);
vars["CONFIG"] = config;
if (this->GetGeneratorTarget()->GetUseShortObjectNames()) {
vars.emplace(
"description",
cmStrCat("Compiling object ", objectFileName, " from source ",
this->GetLocalGenerator()->GetRelativeSourceFileName(*source)));
}
auto compilerLauncher = this->GetCompilerLauncher(language, config);

View File

@@ -1,3 +1,5 @@
set(CMAKE_INTERMEDIATE_DIR_STRATEGY FULL CACHE STRING "" FORCE)
enable_language(C)
add_custom_command(

View File

@@ -0,0 +1,27 @@
set(CMAKE_INTERMEDIATE_DIR_STRATEGY SHORT CACHE STRING "" FORCE)
enable_language(C)
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/command.h"
COMMAND "${CMAKE_COMMAND}" -E touch
"${CMAKE_CURRENT_BINARY_DIR}/command.h"
COMMENT "Creating command.h")
add_custom_target(create-command.h
DEPENDS
"${CMAKE_CURRENT_BINARY_DIR}/command.h")
add_custom_target(create-target.h
BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/target.h"
COMMAND "${CMAKE_COMMAND}" -E touch
"${CMAKE_CURRENT_BINARY_DIR}/target.h"
COMMENT "Creating target.h")
add_library(dep SHARED dep.c)
add_dependencies(dep create-command.h create-target.h)
target_include_directories(dep
PUBLIC
"${CMAKE_CURRENT_BINARY_DIR}")
add_library(top top.c)
target_link_libraries(top PRIVATE dep)

View File

@@ -83,6 +83,16 @@ function(run_VerboseBuild)
endfunction()
run_VerboseBuild()
function(run_VerboseBuildShort)
run_cmake(VerboseBuildShort)
set(RunCMake_TEST_NO_CLEAN 1)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/VerboseBuildShort-build)
set(RunCMake_TEST_OUTPUT_MERGE 1)
run_cmake_command(VerboseBuildShort-build ${CMAKE_COMMAND} --build . -v --clean-first)
run_cmake_command(VerboseBuildShort-nowork ${CMAKE_COMMAND} --build . --verbose)
endfunction()
run_VerboseBuildShort()
function(run_CMP0058 case)
# Use a single build tree for a few tests without cleaning.
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMP0058-${case}-build)
@@ -195,6 +205,23 @@ function (run_LooseObjectDepends)
endfunction ()
run_LooseObjectDepends()
function (run_LooseObjectDependsShort)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/LooseObjectDependsShort-build)
run_cmake(LooseObjectDependsShort)
run_ninja("${RunCMake_TEST_BINARY_DIR}" ".o/e86fd702/b1363cd8${CMAKE_C_OUTPUT_EXTENSION}")
if (EXISTS "${RunCMake_TEST_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}dep${CMAKE_SHARED_LIBRARY_SUFFIX}")
message(FATAL_ERROR
"The `dep` library was created when requesting an object file to be "
"built; this should no longer be necessary.")
endif ()
if (EXISTS "${RunCMake_TEST_BINARY_DIR}/.o/600bd702/d56215${CMAKE_C_OUTPUT_EXTENSION}")
message(FATAL_ERROR
"The `dep.c` object file was created when requesting an object file to "
"be built; this should no longer be necessary.")
endif ()
endfunction ()
run_LooseObjectDependsShort()
function (run_CustomCommandExplictDepends)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CustomCommandExplicitDepends-build)
run_cmake(CustomCommandExplicitDepends)
@@ -425,3 +452,5 @@ if(CMake_TEST_Qt_version)
endif()
run_cmake(LINK_OPTIONSWithNewlines)
run_cmake(StaticLibShort)

View File

@@ -0,0 +1 @@
.*.o.75d5d702.cf59cf\.o.*

View File

@@ -0,0 +1,7 @@
set(CMAKE_INTERMEDIATE_DIR_STRATEGY SHORT CACHE STRING "" FORCE)
enable_language(C)
add_library(greeting STATIC greeting.c)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_executable(hello hello_with_greeting.c)
target_link_libraries(hello greeting)

View File

@@ -1,3 +1,5 @@
set(CMAKE_INTERMEDIATE_DIR_STRATEGY FULL CACHE STRING "" FORCE)
enable_language(C)
add_executable(hello hello.c)
target_compile_definitions(hello PRIVATE "DEFINE_FOR_VERBOSE_DETECTION")

View File

@@ -0,0 +1 @@
DEFINE_FOR_VERBOSE_DETECTION.*75d5d702.4efa03e1.o

View File

@@ -0,0 +1 @@
ninja: no work to do

View File

@@ -0,0 +1,5 @@
set(CMAKE_INTERMEDIATE_DIR_STRATEGY SHORT CACHE STRING "" FORCE)
enable_language(C)
add_executable(hello hello.c)
target_compile_definitions(hello PRIVATE "DEFINE_FOR_VERBOSE_DETECTION")

View File

@@ -1,3 +1,5 @@
set(CMAKE_INTERMEDIATE_DIR_STRATEGY FULL CACHE STRING "" FORCE)
enable_language(C)
add_executable(exe main.c)

View File

@@ -1,3 +1,5 @@
set(CMAKE_INTERMEDIATE_DIR_STRATEGY FULL CACHE STRING "" FORCE)
enable_language(C)
add_executable(echo echo.c)

View File

@@ -1,3 +1,5 @@
set(CMAKE_INTERMEDIATE_DIR_STRATEGY FULL CACHE STRING "" FORCE)
enable_language(C)
file(REMOVE "${CMAKE_BINARY_DIR}/target_files_custom.cmake")

View File

@@ -1,3 +1,5 @@
set(CMAKE_INTERMEDIATE_DIR_STRATEGY FULL CACHE STRING "" FORCE)
enable_language(C)
set(CMAKE_CONFIGURATION_TYPES "Release;Debug" CACHE STRING "")

View File

@@ -1,3 +1,5 @@
set(CMAKE_INTERMEDIATE_DIR_STRATEGY FULL CACHE STRING "" FORCE)
enable_language(C)
set(CMAKE_DEBUG_POSTFIX "_debug")

View File

@@ -1,3 +1,5 @@
set(CMAKE_INTERMEDIATE_DIR_STRATEGY FULL CACHE STRING "" FORCE)
enable_language(CXX)
function(copy_file file dest)

View File

@@ -91,6 +91,6 @@ function(run_Dependencies suffix)
endfunction()
run_Dependencies("")
if (CMAKE_GENERATOR MATCHES "NONE")
if (CMAKE_GENERATOR MATCHES "Ninja")
run_Dependencies(Short)
endif ()

View File

@@ -18,7 +18,7 @@ endfunction()
run_cmake(DisabledPch)
run_cmake(PchDebugGenex)
run_test(PchInterface)
if (CMAKE_GENERATOR MATCHES "NONE")
if (CMAKE_GENERATOR MATCHES "Ninja")
run_test(PchInterfaceShort)
endif ()
run_test(PchInterfaceUnity)

View File

@@ -72,6 +72,6 @@ endfunction()
run_test(unitybuild_runtest)
run_test(unitybuild_object_library)
if (CMAKE_GENERATOR MATCHES "NONE")
if (CMAKE_GENERATOR MATCHES "Ninja")
run_build(unitybuild_cxx_short)
endif ()