Chromium Code Reviews| Index: tools/gn/substitution_writer.cc |
| diff --git a/tools/gn/substitution_writer.cc b/tools/gn/substitution_writer.cc |
| index 3a41b380173a62c2b30d5fe0c514eb904cfbffeb..5bb2e3d8c83cf24f00c144c9161372e3661f4b4f 100644 |
| --- a/tools/gn/substitution_writer.cc |
| +++ b/tools/gn/substitution_writer.cc |
| @@ -17,65 +17,17 @@ |
| namespace { |
| -// This happens when the output of a substitution looks like |
| -// <some_output_dir>/<other_stuff>. and we're computing a file in the output |
| -// directory. If <some_output_dir> resolves to the empty string because it |
| -// refers to the root build directory, the result will start with a slash which |
| -// is wrong. |
| -// |
| -// There are several possible solutions: |
| -// |
| -// - Could convert empty directories to a ".". However, this looks weird in the |
| -// Ninja file and Ninja doesn't canonicalize this away. |
| -// |
| -// - Make all substitutions compute SourceFiles and then convert to |
| -// OutputFiles. The root_build_dir will never be empty in this case, and the |
| -// Rebase function will properly strip the slash away when it is rebased to |
| -// be relative to the output directory. However, we never need compiler and |
| -// linker outputs as SourceFiles, and we do a lot of these conversions which |
| -// requires a lot of unnecessary path rebasing. |
| -// |
| -// - Detect this as a special case and delete the slash. |
| -// |
| -// This function implements the special case solution. This problem only arises |
| -// in the very specific case where we're appending a literal beginning in a |
| -// slash, the result string is empty, and the preceeding pattern identifies |
| -// an output directory. |
| -// |
| -// If we find too many problems with this implementation, it would probably be |
| -// cleanest to implement the "round trip through SourceFile" solution for |
| -// simplicity and guaranteed correctness, rather than adding even more special |
| -// cases. |
| -// |
| -// This function only needs to be called when computing substitutions as |
| -// OutputFiles (which are relative to the build dir) and not round-tripping |
| -// through SourceFiles. |
| -void AppendLiteralWithPossibleSlashEliding( |
| - const std::vector<SubstitutionPattern::Subrange>& ranges, |
| - size_t literal_index, |
| - std::string* result) { |
| - const std::string& literal = ranges[literal_index].literal; |
| - |
| - if (// When the literal's index is 0 and it begins with a slash the user |
| - // must have wanted it to start with a slash. Likewise, if it's 2 or |
| - // more, it's impossible to have a length > 1 sequence of substitutions |
| - // that both make sense as a path and resolve to the build directory. |
| - literal_index != 1 || |
| - // When the result is nonempty, appending the slash as a separator is |
| - // always OK. |
| - !result->empty() || |
| - // If the literal doesn't begin in a slash, appending directly is fine. |
| - literal.empty() || literal[0] != '/') { |
| - result->append(literal); |
| - return; |
| - } |
| +// Sets the given directory string to the destination, trimming any trailing |
| +// slash from the directory (SourceDirs and OutputFiles representing |
| +// directories will end in a trailing slash). If the directory is empty |
|
jamesr
2014/08/22 19:04:51
"If the directory is empty ...." what happens?
|
| +void SetDirOrDotWithNoSlash(const std::string& dir, std::string* dest) { |
| + if (!dir.empty() && dir[dir.size() - 1] == '/') |
| + dest->assign(dir.data(), dir.size() - 1); |
| + else |
| + dest->assign(dir); |
| - // If we get here, we need to collapse the slash. Assert that the first |
| - // substitution should have ended up in the output directory. This should |
| - // have already been checked since linker and compiler outputs (which is |
| - // what this is used for) should always bein the output directory. |
| - DCHECK(SubstitutionIsInOutputDir(ranges[0].type)); |
| - result->append(&literal[1], literal.size() - 1); |
| + if (dest->empty()) |
| + dest->push_back('.'); |
| } |
| } // namespace |
| @@ -486,20 +438,24 @@ bool SubstitutionWriter::GetTargetSubstitution( |
| !target->settings()->is_default()); |
| break; |
| case SUBSTITUTION_ROOT_GEN_DIR: |
| - *result = GetToolchainGenDirAsOutputFile(target->settings()).value(); |
| - TrimTrailingSlash(result); |
| + SetDirOrDotWithNoSlash( |
| + GetToolchainGenDirAsOutputFile(target->settings()).value(), |
| + result); |
| break; |
| case SUBSTITUTION_ROOT_OUT_DIR: |
| - *result = target->settings()->toolchain_output_subdir().value(); |
| - TrimTrailingSlash(result); |
| + SetDirOrDotWithNoSlash( |
| + target->settings()->toolchain_output_subdir().value(), |
| + result); |
| break; |
| case SUBSTITUTION_TARGET_GEN_DIR: |
| - *result = GetTargetGenDirAsOutputFile(target).value(); |
| - TrimTrailingSlash(result); |
| + SetDirOrDotWithNoSlash( |
| + GetTargetGenDirAsOutputFile(target).value(), |
| + result); |
| break; |
| case SUBSTITUTION_TARGET_OUT_DIR: |
| - *result = GetTargetOutputDirAsOutputFile(target).value(); |
| - TrimTrailingSlash(result); |
| + SetDirOrDotWithNoSlash( |
| + GetTargetOutputDirAsOutputFile(target).value(), |
| + result); |
| break; |
| case SUBSTITUTION_TARGET_OUTPUT_NAME: |
| *result = target->GetComputedOutputName(true); |
| @@ -528,8 +484,7 @@ OutputFile SubstitutionWriter::ApplyPatternToCompilerAsOutputFile( |
| for (size_t i = 0; i < pattern.ranges().size(); i++) { |
| const SubstitutionPattern::Subrange& subrange = pattern.ranges()[i]; |
| if (subrange.type == SUBSTITUTION_LITERAL) { |
| - AppendLiteralWithPossibleSlashEliding( |
| - pattern.ranges(), i, &result.value()); |
| + result.value().append(subrange.literal); |
| } else { |
| result.value().append( |
| GetCompilerSubstitution(target, source, subrange.type)); |
| @@ -575,8 +530,7 @@ OutputFile SubstitutionWriter::ApplyPatternToLinkerAsOutputFile( |
| for (size_t i = 0; i < pattern.ranges().size(); i++) { |
| const SubstitutionPattern::Subrange& subrange = pattern.ranges()[i]; |
| if (subrange.type == SUBSTITUTION_LITERAL) { |
| - AppendLiteralWithPossibleSlashEliding( |
| - pattern.ranges(), i, &result.value()); |
| + result.value().append(subrange.literal); |
| } else { |
| result.value().append(GetLinkerSubstitution(target, tool, subrange.type)); |
| } |