Commit ae62ba99 authored by Peter Collingbourne's avatar Peter Collingbourne Committed by Commit Bot

GN: Make the linker output file depend on the inputs.

This is useful for files that are only read by the linker, such as
orderfiles. We were normally getting this right in the case where
the target contained at least one source file, as the output file
would transitively depend on the inputs via the source files, but if
the target only contained dependencies on other targets, the inputs
wouldn't be depended on at all.

Bug: 835622
Change-Id: Ic7fb39caeacd4698b7ec6cfb0cb583a429a117dd
Reviewed-on: https://chromium-review.googlesource.com/1041274Reviewed-by: default avatarDirk Pranke <dpranke@chromium.org>
Commit-Queue: Peter Collingbourne <pcc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#555931}
parent 2380d0bf
...@@ -4696,10 +4696,10 @@ ...@@ -4696,10 +4696,10 @@
#### **Inputs for binary targets** #### **Inputs for binary targets**
``` ```
Any input dependencies will be resolved before compiling any sources. Any input dependencies will be resolved before compiling any sources or
Normally, all actions that a target depends on will be run before any files linking the target. Normally, all actions that a target depends on will be run
in a target are compiled. So if you depend on generated headers, you do not before any files in a target are compiled. So if you depend on generated
typically need to list them in the inputs section. headers, you do not typically need to list them in the inputs section.
Inputs for binary targets will be treated as implicit dependencies, meaning Inputs for binary targets will be treated as implicit dependencies, meaning
that changes in any of the inputs will force all sources in the target to be that changes in any of the inputs will force all sources in the target to be
......
...@@ -348,7 +348,7 @@ void NinjaBinaryTargetWriter::Run() { ...@@ -348,7 +348,7 @@ void NinjaBinaryTargetWriter::Run() {
DCHECK_NE(static_cast<size_t>(-1), computed_obj.IndexOf(obj)); DCHECK_NE(static_cast<size_t>(-1), computed_obj.IndexOf(obj));
#endif #endif
} else { } else {
WriteLinkerStuff(obj_files, other_files); WriteLinkerStuff(obj_files, other_files, input_dep);
} }
} }
...@@ -752,7 +752,8 @@ void NinjaBinaryTargetWriter::WriteCompilerBuildLine( ...@@ -752,7 +752,8 @@ void NinjaBinaryTargetWriter::WriteCompilerBuildLine(
void NinjaBinaryTargetWriter::WriteLinkerStuff( void NinjaBinaryTargetWriter::WriteLinkerStuff(
const std::vector<OutputFile>& object_files, const std::vector<OutputFile>& object_files,
const std::vector<SourceFile>& other_files) { const std::vector<SourceFile>& other_files,
const OutputFile& input_dep) {
std::vector<OutputFile> output_files; std::vector<OutputFile> output_files;
SubstitutionWriter::ApplyListToLinkerAsOutputFile( SubstitutionWriter::ApplyListToLinkerAsOutputFile(
target_, tool_, tool_->outputs(), &output_files); target_, tool_, tool_->outputs(), &output_files);
...@@ -816,6 +817,11 @@ void NinjaBinaryTargetWriter::WriteLinkerStuff( ...@@ -816,6 +817,11 @@ void NinjaBinaryTargetWriter::WriteLinkerStuff(
} }
} }
// The input dependency is only needed if there are no object files, as the
// dependency is normally provided transitively by the source files.
if (!input_dep.value().empty() && object_files.empty())
implicit_deps.push_back(input_dep);
// Append implicit dependencies collected above. // Append implicit dependencies collected above.
if (!implicit_deps.empty()) { if (!implicit_deps.empty()) {
out_ << " |"; out_ << " |";
......
...@@ -107,7 +107,8 @@ class NinjaBinaryTargetWriter : public NinjaTargetWriter { ...@@ -107,7 +107,8 @@ class NinjaBinaryTargetWriter : public NinjaTargetWriter {
const std::vector<OutputFile>& outputs); const std::vector<OutputFile>& outputs);
void WriteLinkerStuff(const std::vector<OutputFile>& object_files, void WriteLinkerStuff(const std::vector<OutputFile>& object_files,
const std::vector<SourceFile>& other_files); const std::vector<SourceFile>& other_files,
const OutputFile& input_dep);
void WriteLinkerFlags(const SourceFile* optional_def_file); void WriteLinkerFlags(const SourceFile* optional_def_file);
void WriteLibs(); void WriteLibs();
void WriteOutputSubstitutions(); void WriteOutputSubstitutions();
......
...@@ -1007,6 +1007,36 @@ TEST_F(NinjaBinaryTargetWriterTest, InputFiles) { ...@@ -1007,6 +1007,36 @@ TEST_F(NinjaBinaryTargetWriterTest, InputFiles) {
EXPECT_EQ(expected, out.str()); EXPECT_EQ(expected, out.str());
} }
// This target has one input but no source files.
{
Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
target.set_output_type(Target::SHARED_LIBRARY);
target.visibility().SetPublic();
target.config_values().inputs().push_back(SourceFile("//foo/input.data"));
target.SetToolchain(setup.toolchain());
ASSERT_TRUE(target.OnResolved(&err));
std::ostringstream out;
NinjaBinaryTargetWriter writer(&target, out);
writer.Run();
const char expected[] =
"defines =\n"
"include_dirs =\n"
"root_out_dir = .\n"
"target_out_dir = obj/foo\n"
"target_output_name = libbar\n"
"\n"
"\n"
"build ./libbar.so: solink | ../../foo/input.data\n"
" ldflags =\n"
" libs =\n"
" output_extension = .so\n"
" output_dir = \n";
EXPECT_EQ(expected, out.str());
}
// This target has multiple inputs. // This target has multiple inputs.
{ {
Target target(setup.settings(), Label(SourceDir("//foo/"), "bar")); Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
......
...@@ -1229,10 +1229,10 @@ Script input gotchas ...@@ -1229,10 +1229,10 @@ Script input gotchas
Inputs for binary targets Inputs for binary targets
Any input dependencies will be resolved before compiling any sources. Any input dependencies will be resolved before compiling any sources or
Normally, all actions that a target depends on will be run before any files linking the target. Normally, all actions that a target depends on will be run
in a target are compiled. So if you depend on generated headers, you do not before any files in a target are compiled. So if you depend on generated
typically need to list them in the inputs section. headers, you do not typically need to list them in the inputs section.
Inputs for binary targets will be treated as implicit dependencies, meaning Inputs for binary targets will be treated as implicit dependencies, meaning
that changes in any of the inputs will force all sources in the target to be that changes in any of the inputs will force all sources in the target to be
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment