1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-06-13 22:30:25 +08:00
CMake/Source/cmNinjaTypes.h
Brad King 2725ecff38 Ninja: Handle depfiles with absolute paths to generated files
Ninja treats every (normalized) path as its own node.  It does not
recognize `/abs/path/to/file` in a depfile as matching `path/to/file`
even when `build.ninja` and the working directory are in `/abs/`.
See Ninja Issue 1251.  In cases where we pass absolute paths to the
compiler, it will write a depfile containing absolute paths.  If those
files are generated in the build tree by custom commands, `build.ninja`
references them by relative path in build statement outputs, so Ninja
does not hook up the dependency and rebuild the project correctly.

Add infrastructure to work around this problem by adding implicit
outputs to custom command build statements that reference the main
outputs by absolute path.  Use a `${cmake_ninja_workdir}` placeholder
to avoid repeating the base path.  For example:

    build out.txt | ${cmake_ninja_workdir}out.txt: CUSTOM_COMMAND ...

Ninja will create two nodes for the output file, one with a relative
path and one with an absolute path.  A depfile may then mention either
form of the path and Ninja will hook up the dependency.  Unfortunately
Ninja will also stat the file twice.

Issue: #13894
Fixes: #21865
2021-05-19 13:28:14 -04:00

63 lines
1.2 KiB
C++

/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>
enum cmNinjaTargetDepends
{
DependOnTargetArtifact,
DependOnTargetOrdering
};
using cmNinjaDeps = std::vector<std::string>;
using cmNinjaOuts = std::set<std::string>;
using cmNinjaVars = std::map<std::string, std::string>;
class cmNinjaRule
{
public:
cmNinjaRule(std::string name)
: Name(std::move(name))
{
}
std::string Name;
std::string Command;
std::string Description;
std::string Comment;
std::string DepFile;
std::string DepType;
std::string RspFile;
std::string RspContent;
std::string Restat;
bool Generator = false;
};
class cmNinjaBuild
{
public:
cmNinjaBuild() = default;
cmNinjaBuild(std::string rule)
: Rule(std::move(rule))
{
}
std::string Comment;
std::string Rule;
cmNinjaDeps Outputs;
cmNinjaDeps ImplicitOuts;
cmNinjaDeps WorkDirOuts; // For cmake_ninja_workdir.
cmNinjaDeps ExplicitDeps;
cmNinjaDeps ImplicitDeps;
cmNinjaDeps OrderOnlyDeps;
cmNinjaVars Variables;
std::string RspFile;
};