mirror of
https://github.com/Kitware/CMake.git
synced 2025-05-08 22:37:04 +08:00
Precompile headers: Treat headers as relative to current source directory
Teach `target_precompile_headers` to treat relative paths the same way as `target_sources`. Fixes: #19733
This commit is contained in:
parent
ebb9346490
commit
acb9511044
@ -48,17 +48,32 @@ See the :manual:`cmake-generator-expressions(7)` manual for available
|
||||
expressions. See the :manual:`cmake-compile-features(7)` manual for
|
||||
information on compile features and a list of supported compilers.
|
||||
|
||||
Usage
|
||||
^^^^^
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
target_precompile_headers(<target>
|
||||
PUBLIC
|
||||
"project_header.h"
|
||||
project_header.h
|
||||
PRIVATE
|
||||
[["other_header.h"]]
|
||||
<unordered_map>
|
||||
)
|
||||
|
||||
Header files will be double quoted if they are not specified with double
|
||||
quotes or angle brackets.
|
||||
The list of header files is used to generate a header file named
|
||||
``cmake_pch.h|xx`` which is used to generate the precompiled header file
|
||||
(``.pch``, ``.gch``, ``.pchi``) artifact. The ``cmake_pch.h|xx`` header
|
||||
file will be force included (``-include`` for GCC, ``/FI`` for MSVC) to
|
||||
all source files, so sources do not need to have ``#include "pch.h"``.
|
||||
|
||||
Header file names specified with angle brackets (e.g. ``<unordered_map>``) or
|
||||
explicit double quotes (escaped for the :manual:`cmake-language(7)`,
|
||||
e.g. ``[["other_header.h"]]``) will be treated as is, and include directories
|
||||
must be available for the compiler to find them. Other header file names
|
||||
(e.g. ``project_header.h``) are interpreted as being relative to the current
|
||||
source directory (e.g. :variable:`CMAKE_CURRENT_SOURCE_DIR`) and will be
|
||||
included by absolute path.
|
||||
|
||||
See Also
|
||||
^^^^^^^^
|
||||
|
@ -2,17 +2,29 @@
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmTargetPrecompileHeadersCommand.h"
|
||||
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmMessageType.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTarget.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
bool cmTargetPrecompileHeadersCommand::InitialPass(
|
||||
std::vector<std::string> const& args, cmExecutionStatus&)
|
||||
{
|
||||
return this->HandleArguments(args, "PRECOMPILE_HEADERS", PROCESS_REUSE_FROM);
|
||||
}
|
||||
|
||||
void cmTargetPrecompileHeadersCommand::HandleInterfaceContent(
|
||||
cmTarget* tgt, const std::vector<std::string>& content, bool prepend,
|
||||
bool system)
|
||||
{
|
||||
cmTargetPropCommandBase::HandleInterfaceContent(
|
||||
tgt, ConvertToAbsoluteContent(tgt, content, true), prepend, system);
|
||||
}
|
||||
|
||||
void cmTargetPrecompileHeadersCommand::HandleMissingTarget(
|
||||
const std::string& name)
|
||||
{
|
||||
@ -31,6 +43,33 @@ std::string cmTargetPrecompileHeadersCommand::Join(
|
||||
bool cmTargetPrecompileHeadersCommand::HandleDirectContent(
|
||||
cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
|
||||
{
|
||||
tgt->AppendProperty("PRECOMPILE_HEADERS", this->Join(content).c_str());
|
||||
tgt->AppendProperty(
|
||||
"PRECOMPILE_HEADERS",
|
||||
this->Join(ConvertToAbsoluteContent(tgt, content, false)).c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
cmTargetPrecompileHeadersCommand::ConvertToAbsoluteContent(
|
||||
cmTarget* /*tgt*/, const std::vector<std::string>& content,
|
||||
bool /*isInterfaceContent*/)
|
||||
{
|
||||
std::vector<std::string> absoluteContent;
|
||||
absoluteContent.reserve(content.size());
|
||||
for (std::string const& src : content) {
|
||||
std::string absoluteSrc;
|
||||
// Use '<foo.h>' and '"foo.h"' includes and absolute paths as-is.
|
||||
// Interpret relative paths with respect to the source directory.
|
||||
// If the path starts in a generator expression, assume it is absolute.
|
||||
if (cmHasLiteralPrefix(src, "<") || cmHasLiteralPrefix(src, "\"") ||
|
||||
cmSystemTools::FileIsFullPath(src) ||
|
||||
cmGeneratorExpression::Find(src) == 0) {
|
||||
absoluteSrc = src;
|
||||
} else {
|
||||
absoluteSrc =
|
||||
cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', src);
|
||||
}
|
||||
absoluteContent.emplace_back(std::move(absoluteSrc));
|
||||
}
|
||||
return absoluteContent;
|
||||
}
|
||||
|
@ -28,6 +28,11 @@ public:
|
||||
bool InitialPass(std::vector<std::string> const& args,
|
||||
cmExecutionStatus& status) override;
|
||||
|
||||
protected:
|
||||
void HandleInterfaceContent(cmTarget* tgt,
|
||||
const std::vector<std::string>& content,
|
||||
bool prepend, bool system) override;
|
||||
|
||||
private:
|
||||
void HandleMissingTarget(const std::string& name) override;
|
||||
|
||||
@ -36,6 +41,10 @@ private:
|
||||
bool prepend, bool system) override;
|
||||
|
||||
std::string Join(const std::vector<std::string>& content) override;
|
||||
|
||||
std::vector<std::string> ConvertToAbsoluteContent(
|
||||
cmTarget* tgt, const std::vector<std::string>& content,
|
||||
bool isInterfaceContent);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -4,7 +4,7 @@ project(DisabledPch C)
|
||||
add_library(foo foo.c)
|
||||
target_include_directories(foo PUBLIC include)
|
||||
target_precompile_headers(foo PUBLIC
|
||||
foo.h
|
||||
include/foo.h
|
||||
<stdio.h>
|
||||
\"string.h\"
|
||||
)
|
||||
|
@ -18,19 +18,14 @@ endif()
|
||||
|
||||
file(STRINGS ${foo_pch_header} foo_pch_header_strings)
|
||||
|
||||
if (NOT "#include \"foo.h\"" IN_LIST foo_pch_header_strings OR
|
||||
NOT "#include <stdio.h>" IN_LIST foo_pch_header_strings OR
|
||||
NOT "#include \"string.h\"" IN_LIST foo_pch_header_strings)
|
||||
set(RunCMake_TEST_FAILED "Generated foo pch header ${foo_pch_header} has bad content")
|
||||
if (NOT foo_pch_header_strings MATCHES ";#include \"[^\"]*PrecompileHeaders/include/foo.h\";#include \"foo2.h\";#include <stdio.h>;#include \"string.h\"(;|$)")
|
||||
set(RunCMake_TEST_FAILED "Generated foo pch header\n ${foo_pch_header}\nhas bad content:\n ${foo_pch_header_strings}")
|
||||
return()
|
||||
endif()
|
||||
|
||||
file(STRINGS ${foobar_pch_header} foobar_pch_header_strings)
|
||||
|
||||
if (NOT "#include \"foo.h\"" IN_LIST foobar_pch_header_strings OR
|
||||
NOT "#include <stdio.h>" IN_LIST foobar_pch_header_strings OR
|
||||
NOT "#include \"string.h\"" IN_LIST foobar_pch_header_strings OR
|
||||
NOT "#include \"bar.h\"" IN_LIST foobar_pch_header_strings)
|
||||
set(RunCMake_TEST_FAILED "Generated foobar pch header ${foobar_pch_header} has bad content")
|
||||
if (NOT foobar_pch_header_strings MATCHES ";#include \"[^\"]*PrecompileHeaders/include/foo.h\";#include \"foo2.h\";#include <stdio.h>;#include \"string.h\";#include \"[^\"]*PrecompileHeaders/include/bar.h\"(;|$)")
|
||||
set(RunCMake_TEST_FAILED "Generated foobar pch header\n ${foobar_pch_header}\nhas bad content:\n ${foobar_pch_header_strings}")
|
||||
return()
|
||||
endif()
|
||||
|
@ -4,14 +4,15 @@ project(PchInterface C)
|
||||
add_library(foo foo.c)
|
||||
target_include_directories(foo PUBLIC include)
|
||||
target_precompile_headers(foo PUBLIC
|
||||
foo.h
|
||||
include/foo.h
|
||||
\"foo2.h\"
|
||||
<stdio.h>
|
||||
\"string.h\"
|
||||
)
|
||||
|
||||
add_library(bar INTERFACE)
|
||||
target_include_directories(bar INTERFACE include)
|
||||
target_precompile_headers(bar INTERFACE bar.h)
|
||||
target_precompile_headers(bar INTERFACE include/bar.h)
|
||||
|
||||
add_executable(foobar foobar.c)
|
||||
target_link_libraries(foobar foo bar)
|
||||
|
@ -1,6 +1,12 @@
|
||||
#include "foo.h"
|
||||
#include "foo2.h"
|
||||
|
||||
int foo()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int foo2()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
#include "bar.h"
|
||||
#include "foo.h"
|
||||
#include "foo2.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
return foo() + bar();
|
||||
return foo() + foo2() + bar();
|
||||
}
|
||||
|
6
Tests/RunCMake/PrecompileHeaders/include/foo2.h
Normal file
6
Tests/RunCMake/PrecompileHeaders/include/foo2.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef foo2_h
|
||||
#define foo2_h
|
||||
|
||||
int foo2(void);
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user