| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "tools/gn/label.h" | 5 #include "tools/gn/label.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "tools/gn/err.h" | 8 #include "tools/gn/err.h" |
| 9 #include "tools/gn/parse_tree.h" | 9 #include "tools/gn/parse_tree.h" |
| 10 #include "tools/gn/value.h" | 10 #include "tools/gn/value.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 } | 21 } |
| 22 | 22 |
| 23 // Given the separate-out input (everything before the colon) in the dep rule, | 23 // Given the separate-out input (everything before the colon) in the dep rule, |
| 24 // computes the final build rule. Sets err on failure. On success, | 24 // computes the final build rule. Sets err on failure. On success, |
| 25 // |*used_implicit| will be set to whether the implicit current directory was | 25 // |*used_implicit| will be set to whether the implicit current directory was |
| 26 // used. The value is used only for generating error messages. | 26 // used. The value is used only for generating error messages. |
| 27 bool ComputeBuildLocationFromDep(const Value& input_value, | 27 bool ComputeBuildLocationFromDep(const Value& input_value, |
| 28 const SourceDir& current_dir, | 28 const SourceDir& current_dir, |
| 29 const base::StringPiece& input, | 29 const base::StringPiece& input, |
| 30 SourceDir* result, | 30 SourceDir* result, |
| 31 const base::FilePath& source_root, |
| 31 Err* err) { | 32 Err* err) { |
| 32 // No rule, use the current locaton. | 33 // No rule, use the current locaton. |
| 33 if (input.empty()) { | 34 if (input.empty()) { |
| 34 *result = current_dir; | 35 *result = current_dir; |
| 35 return true; | 36 return true; |
| 36 } | 37 } |
| 37 | 38 |
| 38 // Don't allow directories to start with a single slash. All labels must be | 39 // Don't allow directories to start with a single slash. All labels must be |
| 39 // in the source root. | 40 // in the source root. |
| 40 if (input[0] == '/' && (input.size() == 1 || input[1] != '/')) { | 41 if (input[0] == '/' && (input.size() == 1 || input[1] != '/')) { |
| 41 *err = Err(input_value, "Label can't start with a single slash", | 42 *err = Err(input_value, "Label can't start with a single slash", |
| 42 "Labels must be either relative (no slash at the beginning) or be " | 43 "Labels must be either relative (no slash at the beginning) or be " |
| 43 "absolute\ninside the source root (two slashes at the beginning)."); | 44 "absolute\ninside the source root (two slashes at the beginning)."); |
| 44 return false; | 45 return false; |
| 45 } | 46 } |
| 46 | 47 |
| 47 *result = current_dir.ResolveRelativeDir(input); | 48 *result = current_dir.ResolveRelativeDir(input, source_root); |
| 48 return true; | 49 return true; |
| 49 } | 50 } |
| 50 | 51 |
| 51 // Given the separated-out target name (after the colon) computes the final | 52 // Given the separated-out target name (after the colon) computes the final |
| 52 // name, using the implicit name from the previously-generated | 53 // name, using the implicit name from the previously-generated |
| 53 // computed_location if necessary. The input_value is used only for generating | 54 // computed_location if necessary. The input_value is used only for generating |
| 54 // error messages. | 55 // error messages. |
| 55 bool ComputeTargetNameFromDep(const Value& input_value, | 56 bool ComputeTargetNameFromDep(const Value& input_value, |
| 56 const SourceDir& computed_location, | 57 const SourceDir& computed_location, |
| 57 const base::StringPiece& input, | 58 const base::StringPiece& input, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 // Returns true on success. On failure, the out* variables might be written to | 93 // Returns true on success. On failure, the out* variables might be written to |
| 93 // but shouldn't be used. | 94 // but shouldn't be used. |
| 94 bool Resolve(const SourceDir& current_dir, | 95 bool Resolve(const SourceDir& current_dir, |
| 95 const Label& current_toolchain, | 96 const Label& current_toolchain, |
| 96 const Value& original_value, | 97 const Value& original_value, |
| 97 const base::StringPiece& input, | 98 const base::StringPiece& input, |
| 98 SourceDir* out_dir, | 99 SourceDir* out_dir, |
| 99 std::string* out_name, | 100 std::string* out_name, |
| 100 SourceDir* out_toolchain_dir, | 101 SourceDir* out_toolchain_dir, |
| 101 std::string* out_toolchain_name, | 102 std::string* out_toolchain_name, |
| 103 const base::FilePath& source_root, |
| 102 Err* err) { | 104 Err* err) { |
| 103 // To workaround the problem that StringPiece operator[] doesn't return a ref. | 105 // To workaround the problem that StringPiece operator[] doesn't return a ref. |
| 104 const char* input_str = input.data(); | 106 const char* input_str = input.data(); |
| 105 | 107 |
| 106 size_t path_separator = input.find_first_of(":("); | 108 size_t path_separator = input.find_first_of(":("); |
| 107 base::StringPiece location_piece; | 109 base::StringPiece location_piece; |
| 108 base::StringPiece name_piece; | 110 base::StringPiece name_piece; |
| 109 base::StringPiece toolchain_piece; | 111 base::StringPiece toolchain_piece; |
| 110 if (path_separator == std::string::npos) { | 112 if (path_separator == std::string::npos) { |
| 111 location_piece = input; | 113 location_piece = input; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 // Absolute: "//foo:bar" -> /foo:bar | 155 // Absolute: "//foo:bar" -> /foo:bar |
| 154 // Target in current file: ":foo" -> <currentdir>:foo | 156 // Target in current file: ":foo" -> <currentdir>:foo |
| 155 // Path with implicit name: "/foo" -> /foo:foo | 157 // Path with implicit name: "/foo" -> /foo:foo |
| 156 if (location_piece.empty() && name_piece.empty()) { | 158 if (location_piece.empty() && name_piece.empty()) { |
| 157 // Can't use both implicit filename and name (":"). | 159 // Can't use both implicit filename and name (":"). |
| 158 *err = Err(original_value, "This doesn't specify a dependency."); | 160 *err = Err(original_value, "This doesn't specify a dependency."); |
| 159 return false; | 161 return false; |
| 160 } | 162 } |
| 161 | 163 |
| 162 if (!ComputeBuildLocationFromDep(original_value, current_dir, location_piece, | 164 if (!ComputeBuildLocationFromDep(original_value, current_dir, location_piece, |
| 163 out_dir, err)) | 165 out_dir, source_root, err)) |
| 164 return false; | 166 return false; |
| 165 | 167 |
| 166 if (!ComputeTargetNameFromDep(original_value, *out_dir, name_piece, | 168 if (!ComputeTargetNameFromDep(original_value, *out_dir, name_piece, |
| 167 out_name, err)) | 169 out_name, err)) |
| 168 return false; | 170 return false; |
| 169 | 171 |
| 170 // Last, do the toolchains. | 172 // Last, do the toolchains. |
| 171 if (out_toolchain_dir) { | 173 if (out_toolchain_dir) { |
| 172 // Handle empty toolchain strings. We don't allow normal labels to be | 174 // Handle empty toolchain strings. We don't allow normal labels to be |
| 173 // empty so we can't allow the recursive call of this function to do this | 175 // empty so we can't allow the recursive call of this function to do this |
| 174 // check. | 176 // check. |
| 175 if (toolchain_piece.empty()) { | 177 if (toolchain_piece.empty()) { |
| 176 *out_toolchain_dir = current_toolchain.dir(); | 178 *out_toolchain_dir = current_toolchain.dir(); |
| 177 *out_toolchain_name = current_toolchain.name(); | 179 *out_toolchain_name = current_toolchain.name(); |
| 178 return true; | 180 return true; |
| 179 } else { | 181 } else { |
| 180 return Resolve(current_dir, current_toolchain, | 182 return Resolve(current_dir, current_toolchain, |
| 181 original_value, toolchain_piece, | 183 original_value, toolchain_piece, |
| 182 out_toolchain_dir, out_toolchain_name, NULL, NULL, err); | 184 out_toolchain_dir, out_toolchain_name, NULL, NULL, |
| 185 source_root, err); |
| 183 } | 186 } |
| 184 } | 187 } |
| 185 return true; | 188 return true; |
| 186 } | 189 } |
| 187 | 190 |
| 188 } // namespace | 191 } // namespace |
| 189 | 192 |
| 190 Label::Label() { | 193 Label::Label() { |
| 191 } | 194 } |
| 192 | 195 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 205 name_.assign(name.data(), name.size()); | 208 name_.assign(name.data(), name.size()); |
| 206 } | 209 } |
| 207 | 210 |
| 208 Label::~Label() { | 211 Label::~Label() { |
| 209 } | 212 } |
| 210 | 213 |
| 211 // static | 214 // static |
| 212 Label Label::Resolve(const SourceDir& current_dir, | 215 Label Label::Resolve(const SourceDir& current_dir, |
| 213 const Label& current_toolchain, | 216 const Label& current_toolchain, |
| 214 const Value& input, | 217 const Value& input, |
| 218 const base::FilePath& source_root, |
| 215 Err* err) { | 219 Err* err) { |
| 216 Label ret; | 220 Label ret; |
| 217 if (input.type() != Value::STRING) { | 221 if (input.type() != Value::STRING) { |
| 218 *err = Err(input, "Dependency is not a string."); | 222 *err = Err(input, "Dependency is not a string."); |
| 219 return ret; | 223 return ret; |
| 220 } | 224 } |
| 221 const std::string& input_string = input.string_value(); | 225 const std::string& input_string = input.string_value(); |
| 222 if (input_string.empty()) { | 226 if (input_string.empty()) { |
| 223 *err = Err(input, "Dependency string is empty."); | 227 *err = Err(input, "Dependency string is empty."); |
| 224 return ret; | 228 return ret; |
| 225 } | 229 } |
| 226 | 230 |
| 227 if (!::Resolve(current_dir, current_toolchain, input, input_string, | 231 if (!::Resolve(current_dir, current_toolchain, input, input_string, |
| 228 &ret.dir_, &ret.name_, | 232 &ret.dir_, &ret.name_, |
| 229 &ret.toolchain_dir_, &ret.toolchain_name_, | 233 &ret.toolchain_dir_, &ret.toolchain_name_, |
| 230 err)) | 234 source_root, err)) |
| 231 return Label(); | 235 return Label(); |
| 232 return ret; | 236 return ret; |
| 233 } | 237 } |
| 234 | 238 |
| 235 Label Label::GetToolchainLabel() const { | 239 Label Label::GetToolchainLabel() const { |
| 236 return Label(toolchain_dir_, toolchain_name_); | 240 return Label(toolchain_dir_, toolchain_name_); |
| 237 } | 241 } |
| 238 | 242 |
| 239 Label Label::GetWithNoToolchain() const { | 243 Label Label::GetWithNoToolchain() const { |
| 240 return Label(dir_, name_); | 244 return Label(dir_, name_); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 262 } | 266 } |
| 263 return ret; | 267 return ret; |
| 264 } | 268 } |
| 265 | 269 |
| 266 std::string Label::GetUserVisibleName(const Label& default_toolchain) const { | 270 std::string Label::GetUserVisibleName(const Label& default_toolchain) const { |
| 267 bool include_toolchain = | 271 bool include_toolchain = |
| 268 default_toolchain.dir() != toolchain_dir_ || | 272 default_toolchain.dir() != toolchain_dir_ || |
| 269 default_toolchain.name() != toolchain_name_; | 273 default_toolchain.name() != toolchain_name_; |
| 270 return GetUserVisibleName(include_toolchain); | 274 return GetUserVisibleName(include_toolchain); |
| 271 } | 275 } |
| OLD | NEW |