168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// found in the LICENSE file. 468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "tools/gn/build_settings.h" 668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "tools/gn/filesystem_utils.h" 768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "tools/gn/functions.h" 868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "tools/gn/parse_tree.h" 968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "tools/gn/scope.h" 1068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "tools/gn/settings.h" 1168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "tools/gn/source_dir.h" 1268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "tools/gn/source_file.h" 1368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "tools/gn/value.h" 1468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 1568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace functions { 1668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 1768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace { 1868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 1968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// We want the output to match the input in terms of ending in a slash or not. 2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Through all the transformations, these can get added or removed in various 2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// cases. 2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void MakeSlashEndingMatchInput(const std::string& input, std::string* output) { 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (EndsWithSlash(input)) { 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!EndsWithSlash(*output)) // Preserve same slash type as input. 2568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) output->push_back(input[input.size() - 1]); 2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else { 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (EndsWithSlash(*output)) 2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) output->resize(output->size() - 1); 2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Returns true if the given value looks like a directory, otherwise we'll 3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// assume it's a file. 3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool ValueLooksLikeDir(const std::string& value) { 3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (value.empty()) 3668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return true; 3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) size_t value_size = value.size(); 3868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Count the number of dots at the end of the string. 4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) size_t num_dots = 0; 4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) while (num_dots < value_size && value[value_size - num_dots - 1] == '.') 4268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) num_dots++; 4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (num_dots == value.size()) 4568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return true; // String is all dots. 4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (IsSlash(value[value_size - num_dots - 1])) 4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return true; // String is a [back]slash followed by 0 or more dots. 4968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 5068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Anything else. 5168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return false; 5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)Value ConvertOnePath(const Scope* scope, 5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const FunctionCallNode* function, 5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const Value& value, 5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const SourceDir& from_dir, 5868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const SourceDir& to_dir, 5968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool convert_to_system_absolute, 6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Err* err) { 6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Value result; // Ensure return value optimization. 6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!value.VerifyTypeIs(Value::STRING, err)) 6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return result; 6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& string_value = value.string_value(); 6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool looks_like_dir = ValueLooksLikeDir(string_value); 6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // System-absolute output special case. 7068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (convert_to_system_absolute) { 7168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::FilePath system_path; 7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (looks_like_dir) { 7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) system_path = scope->settings()->build_settings()->GetFullPath( 7468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) from_dir.ResolveRelativeDir(string_value)); 7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else { 7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) system_path = scope->settings()->build_settings()->GetFullPath( 7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) from_dir.ResolveRelativeFile(string_value)); 7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) result = Value(function, FilePathToUTF8(system_path)); 8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (looks_like_dir) 8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) MakeSlashEndingMatchInput(string_value, &result.string_value()); 8268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return result; 8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 8568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (from_dir.is_system_absolute() || to_dir.is_system_absolute()) { 8668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) *err = Err(function, "System-absolute directories are not supported for " 8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "the source or dest dir for rebase_path. It would be nice to add this " 8868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "if you're so inclined!"); 8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return result; 9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 9168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 9268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) result = Value(function, Value::STRING); 9368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (looks_like_dir) { 9468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) result.string_value() = RebaseSourceAbsolutePath( 9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) from_dir.ResolveRelativeDir(string_value).value(), 9668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) to_dir); 9768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) MakeSlashEndingMatchInput(string_value, &result.string_value()); 9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else { 9968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) result.string_value() = RebaseSourceAbsolutePath( 10068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) from_dir.ResolveRelativeFile(string_value).value(), 10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) to_dir); 10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 10468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return result; 10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} // namespace 10868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kRebasePath[] = "rebase_path"; 110e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char kRebasePath_HelpShort[] = 111e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch "rebase_path: Rebase a file or directory to another location."; 11268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kRebasePath_Help[] = 11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "rebase_path: Rebase a file or directory to another location.\n" 11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "\n" 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " converted = rebase_path(input,\n" 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " new_base = \"\",\n" 117c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch " current_base = \".\")\n" 11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "\n" 11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " Takes a string argument representing a file name, or a list of such\n" 12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " strings and converts it/them to be relative to a different base\n" 12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " directory.\n" 12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "\n" 12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " When invoking the compiler or scripts, GN will automatically convert\n" 12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " sources and include directories to be relative to the build directory.\n" 12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " However, if you're passing files directly in the \"args\" array or\n" 12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " doing other manual manipulations where GN doesn't know something is\n" 12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " a file name, you will need to convert paths to be relative to what\n" 12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " your tool is expecting.\n" 12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "\n" 13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " The common case is to use this to convert paths relative to the\n" 13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " current directory to be relative to the build directory (which will\n" 13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " be the current directory when executing scripts).\n" 13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "\n" 13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) " If you want to convert a file path to be source-absolute (that is,\n" 13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) " beginning with a double slash like \"//foo/bar\"), you should use\n" 13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) " the get_path_info() function. This function won't work because it will\n" 13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) " always make relative paths, and it needs to support making paths\n" 13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) " relative to the source root, so can't also generate source-absolute\n" 13946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) " paths without more special-cases.\n" 14046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "\n" 141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "Arguments:\n" 14268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "\n" 14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " input\n" 14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " A string or list of strings representing file or directory names\n" 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " These can be relative paths (\"foo/bar.txt\"), system absolute\n" 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " paths (\"/foo/bar.txt\"), or source absolute paths\n" 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " (\"//foo/bar.txt\").\n" 14868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "\n" 14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " new_base\n" 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " The directory to convert the paths to be relative to. This can be\n" 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " an absolute path or a relative path (which will be treated\n" 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " as being relative to the current BUILD-file's directory).\n" 15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "\n" 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " As a special case, if new_base is the empty string (the default),\n" 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " all paths will be converted to system-absolute native style paths\n" 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " with system path separators. This is useful for invoking external\n" 15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " programs.\n" 15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "\n" 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " current_base\n" 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " Directory representing the base for relative paths in the input.\n" 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " If this is not an absolute path, it will be treated as being\n" 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " relative to the current build file. Use \".\" (the default) to\n" 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " convert paths from the current BUILD-file's directory.\n" 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "\n" 16568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " On Posix systems there are no path separator transformations\n" 16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " applied. If the new_base is empty (specifying absolute output)\n" 16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " this parameter should not be supplied since paths will always be\n" 16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " converted,\n" 16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "\n" 17068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "Return value\n" 17168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "\n" 17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " The return value will be the same type as the input value (either a\n" 17368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " string or a list of strings). All relative and source-absolute file\n" 17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " names will be converted to be relative to the requested output\n" 17568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " System-absolute paths will be unchanged.\n" 17668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "\n" 17768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "Example\n" 17868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "\n" 17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " # Convert a file in the current directory to be relative to the build\n" 18068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " # directory (the current dir when executing compilers and scripts).\n" 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " foo = rebase_path(\"myfile.txt\", root_build_dir)\n" 18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " # might produce \"../../project/myfile.txt\".\n" 18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "\n" 18468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " # Convert a file to be system absolute:\n" 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " foo = rebase_path(\"myfile.txt\")\n" 18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " # Might produce \"D:\\source\\project\\myfile.txt\" on Windows or\n" 18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " # \"/home/you/source/project/myfile.txt\" on Linux.\n" 18868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "\n" 18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " # Convert a file's path separators from forward slashes to system\n" 19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " # slashes.\n" 19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " foo = rebase_path(\"source/myfile.txt\", \".\", \".\", \"to_system\")\n" 19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "\n" 19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " # Typical usage for converting to the build directory for a script.\n" 19423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) " action(\"myscript\") {\n" 19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " # Don't convert sources, GN will automatically convert these to be\n" 19668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " # relative to the build directory when it contructs the command\n" 19768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " # line for your script.\n" 19868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " sources = [ \"foo.txt\", \"bar.txt\" ]\n" 19968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "\n" 20068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " # Extra file args passed manually need to be explicitly converted\n" 20168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " # to be relative to the build directory:\n" 20268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " args = [\n" 20368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " \"--data\",\n" 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " rebase_path(\"//mything/data/input.dat\", root_build_dir),\n" 20568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " \"--rel\",\n" 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " rebase_path(\"relative_path.txt\", root_build_dir)\n" 20723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) " ] + sources\n" 20868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) " }\n"; 20968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 21068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)Value RunRebasePath(Scope* scope, 21168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const FunctionCallNode* function, 21268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::vector<Value>& args, 21368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Err* err) { 21468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Value result; 21568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Argument indices. 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const size_t kArgIndexInputs = 0; 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const size_t kArgIndexDest = 1; 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const size_t kArgIndexFrom = 2; 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 22168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Inputs. 222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (args.size() < 1 || args.size() > 3) { 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *err = Err(function->function(), "Wrong # of arguments for rebase_path."); 22468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return result; 22568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Value& inputs = args[kArgIndexInputs]; 22768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 22868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // To path. 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool convert_to_system_absolute = true; 23068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) SourceDir to_dir; 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const SourceDir& current_dir = scope->GetSourceDir(); 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (args.size() > kArgIndexDest) { 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!args[kArgIndexDest].VerifyTypeIs(Value::STRING, err)) 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return result; 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!args[kArgIndexDest].string_value().empty()) { 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) to_dir = 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) current_dir.ResolveRelativeDir(args[kArgIndexDest].string_value()); 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) convert_to_system_absolute = false; 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // From path. 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SourceDir from_dir; 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (args.size() > kArgIndexFrom) { 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!args[kArgIndexFrom].VerifyTypeIs(Value::STRING, err)) 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return result; 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) from_dir = 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) current_dir.ResolveRelativeDir(args[kArgIndexFrom].string_value()); 24968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else { 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Default to current directory if unspecified. 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) from_dir = current_dir; 25268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 25368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 25468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Path conversion. 25568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (inputs.type() == Value::STRING) { 25668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return ConvertOnePath(scope, function, inputs, 257c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch from_dir, to_dir, convert_to_system_absolute, err); 25868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 25968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else if (inputs.type() == Value::LIST) { 26068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) result = Value(function, Value::LIST); 26168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) result.list_value().reserve(inputs.list_value().size()); 26268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 26368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (size_t i = 0; i < inputs.list_value().size(); i++) { 26468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) result.list_value().push_back( 26568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ConvertOnePath(scope, function, inputs.list_value()[i], 266c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch from_dir, to_dir, convert_to_system_absolute, err)); 26768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (err->has_error()) { 26868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) result = Value(); 26968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return result; 27068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 27168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 27268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return result; 27368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 27468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 27568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) *err = Err(function->function(), 27668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "rebase_path requires a list or a string."); 27768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return result; 27868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 27968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 28068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} // namespace functions 281