CMAKE_EXPORT_COMPILE_COMMANDS: allow configuration per target

The new target property `EXPORT_COMPILE_COMMANDS` associated with the
existing global variable can be used to optionally configure targets for
their compile commands to be exported.

Fixes: #19462
This commit is contained in:
Shannon Booth 2020-12-24 07:16:34 +13:00
parent ce8bb12f72
commit a742b5d137
12 changed files with 90 additions and 3 deletions

View File

@ -196,6 +196,7 @@ Properties on Targets
/prop_tgt/EXCLUDE_FROM_ALL
/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD
/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD_CONFIG
/prop_tgt/EXPORT_COMPILE_COMMANDS
/prop_tgt/EXPORT_NAME
/prop_tgt/EXPORT_PROPERTIES
/prop_tgt/FOLDER

View File

@ -0,0 +1,9 @@
EXPORT_COMPILE_COMMANDS
-----------------------
.. versionadded:: 3.20
Enable/Disable output of compile commands during generation for a target.
This property is initialized by the value of the variable
:variable:`CMAKE_EXPORT_COMPILE_COMMANDS` if it is set when a target is created.

View File

@ -0,0 +1,6 @@
export-compile-commands-per-target
----------------------------------
* The :prop_tgt:`EXPORT_COMPILE_COMMANDS` target property was added
for the associated :variable:`CMAKE_EXPORT_COMPILE_COMMANDS` variable
to allow for configuration of exporting compile commands per target.

View File

@ -28,7 +28,8 @@ form. The format of the JSON file looks like:
]
This is initialized by the :envvar:`CMAKE_EXPORT_COMPILE_COMMANDS` environment
variable.
variable, and initializes the :prop_tgt:`EXPORT_COMPILE_COMMANDS` target
property for all targets.
.. note::
This option is implemented only by :ref:`Makefile Generators`

View File

@ -897,7 +897,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
cmExpandList(compileRule, compileCommands);
}
if (this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS") &&
if (this->GeneratorTarget->GetPropertyAsBool("EXPORT_COMPILE_COMMANDS") &&
lang_can_export_cmds && compileCommands.size() == 1) {
std::string compileCommand = compileCommands[0];

View File

@ -1532,7 +1532,7 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
std::string const& objectFileDir, std::string const& flags,
std::string const& defines, std::string const& includes)
{
if (!this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS")) {
if (!this->GeneratorTarget->GetPropertyAsBool("EXPORT_COMPILE_COMMANDS")) {
return;
}

View File

@ -382,6 +382,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp("UNITY_BUILD");
initProp("UNITY_BUILD_UNIQUE_ID");
initProp("OPTIMIZE_DEPENDENCIES");
initProp("EXPORT_COMPILE_COMMANDS");
initPropValue("UNITY_BUILD_BATCH_SIZE", "8");
initPropValue("UNITY_BUILD_MODE", "BATCH");
initPropValue("PCH_WARN_INVALID", "ON");

View File

@ -0,0 +1,22 @@
enable_language(C)
add_library(Unset STATIC empty.c)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(SetOn STATIC empty.c)
set(CMAKE_EXPORT_COMPILE_COMMANDS OFF)
add_library(SetOff STATIC empty.c)
get_property(_set TARGET Unset PROPERTY EXPORT_COMPILE_COMMANDS)
if(_set)
message(SEND_ERROR "EXPORT_COMPILE_COMMANDS property should be unset for Unset target (got \"${_set}\")")
endif()
get_property(_on TARGET SetOn PROPERTY EXPORT_COMPILE_COMMANDS)
if(NOT _on STREQUAL "ON")
message(SEND_ERROR "EXPORT_COMPILE_COMMANDS property should be \"ON\" for SetOn target (got \"${_on}\")")
endif()
get_property(_off TARGET SetOff PROPERTY EXPORT_COMPILE_COMMANDS)
if(NOT _off STREQUAL "OFF")
message(SEND_ERROR "EXPORT_COMPILE_COMMANDS property should be \"OFF\" for SetOff target (got \"${_off}\")")
endif()

View File

@ -0,0 +1,32 @@
if(NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/compile_commands.json")
set(RunCMake_TEST_FAILED "compile_commands.json not generated")
return()
endif()
file(READ "${RunCMake_TEST_BINARY_DIR}/compile_commands.json" compile_commands)
macro(check_error)
if(error)
message(SEND_ERROR "Unexpected error \"${error}\"\nFor: ${compile_commands}")
endif()
endmacro()
string(JSON num_commands ERROR_VARIABLE error LENGTH "${compile_commands}")
check_error()
# Only one of the targets has the EXPORT_COMPILE_COMMANDS property enabled.
if(NOT num_commands STREQUAL 1)
message(SEND_ERROR "Expected 1 compile command, got ${num_commands} for ${compile_commands}")
endif()
# Get the compile command generated.
string(JSON result ERROR_VARIABLE error GET "${compile_commands}" 0)
check_error()
string(JSON result ERROR_VARIABLE error GET "${result}" file)
check_error()
# And ensure the correct target is in that compile command.
cmake_path(COMPARE "${result}" EQUAL "${RunCMake_TEST_SOURCE_DIR}/expected_file.c" good)
if(NOT good)
message(SEND_ERROR "Expected \"${result}\" in \"${RunCMake_TEST_SOURCE_DIR}/expected_file.c\"")
endif()

View File

@ -0,0 +1,7 @@
enable_language(C)
add_library(Unset STATIC empty.c)
add_library(ToBeSet STATIC expected_file.c)
# Only one target with EXPORT_COMPILE_COMMANDS property.
set_property(TARGET ToBeSet PROPERTY EXPORT_COMPILE_COMMANDS TRUE)

View File

@ -1,4 +1,12 @@
include(RunCMake)
if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
set(RunCMake_TEST_OPTIONS -DCMAKE_CONFIGURATION_TYPES=Debug)
else()
set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
endif()
run_cmake_with_options(BeforeProject -DCMAKE_PROJECT_INCLUDE_BEFORE=BeforeProjectBEFORE.cmake)
run_cmake(CustomCompileRule)
run_cmake(Properties)
run_cmake(PropertiesGenerateCommand)