1 // Copyright 2020 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef TOOLS_GN_RUST_PROJECT_WRITER_HELPERS_H_ 6 #define TOOLS_GN_RUST_PROJECT_WRITER_HELPERS_H_ 7 8 #include <fstream> 9 #include <optional> 10 #include <sstream> 11 #include <string> 12 #include <string_view> 13 #include <tuple> 14 #include <unordered_map> 15 #include <vector> 16 17 #include "base/containers/flat_map.h" 18 #include "build_settings.h" 19 #include "gn/source_file.h" 20 #include "gn/target.h" 21 22 // These are internal types and helper functions for RustProjectWriter that have 23 // been extracted for easier testability. 24 25 // Crate Index in the generated file 26 using CrateIndex = size_t; 27 28 using ConfigList = std::vector<std::string>; 29 using Dependency = std::pair<CrateIndex, std::string>; 30 using DependencyList = std::vector<Dependency>; 31 32 // This class represents a crate to be serialized out as part of the 33 // rust-project.json file. This is used to separate the generating 34 // of the data that needs to be in the file, from the file itself. 35 class Crate { 36 public: Crate(SourceFile root, std::optional<OutputFile> gen_dir, CrateIndex index, std::string label, std::string edition)37 Crate(SourceFile root, 38 std::optional<OutputFile> gen_dir, 39 CrateIndex index, 40 std::string label, 41 std::string edition) 42 : root_(root), 43 gen_dir_(gen_dir), 44 index_(index), 45 label_(label), 46 edition_(edition) {} 47 48 ~Crate() = default; 49 50 // Add a config item to the crate. AddConfigItem(std::string cfg_item)51 void AddConfigItem(std::string cfg_item) { configs_.push_back(cfg_item); } 52 53 // Add a key-value environment variable pair used when building this crate. AddRustenv(std::string key, std::string value)54 void AddRustenv(std::string key, std::string value) { 55 rustenv_.emplace(key, value); 56 } 57 58 // Add another crate as a dependency of this one. AddDependency(CrateIndex index, std::string name)59 void AddDependency(CrateIndex index, std::string name) { 60 deps_.push_back(std::make_pair(index, name)); 61 } 62 63 // Set the compiler arguments used to invoke the compilation of this crate SetCompilerArgs(std::vector<std::string> args)64 void SetCompilerArgs(std::vector<std::string> args) { compiler_args_ = args; } 65 66 // Set the compiler target ("e.g. x86_64-linux-kernel") SetCompilerTarget(std::string target)67 void SetCompilerTarget(std::string target) { compiler_target_ = target; } 68 69 // Set that this is a proc macro with the path to the output .so/dylib/dll SetIsProcMacro(OutputFile proc_macro_dynamic_library)70 void SetIsProcMacro(OutputFile proc_macro_dynamic_library) { 71 proc_macro_dynamic_library_ = proc_macro_dynamic_library; 72 } 73 74 // Returns the root file for the crate. root()75 SourceFile& root() { return root_; } 76 77 // Returns the root file for the crate. gen_dir()78 std::optional<OutputFile>& gen_dir() { return gen_dir_; } 79 80 // Returns the crate index. index()81 CrateIndex index() { return index_; } 82 83 // Returns the displayable crate label. label()84 const std::string& label() { return label_; } 85 86 // Returns the Rust Edition this crate uses. edition()87 const std::string& edition() { return edition_; } 88 89 // Return the set of config items for this crate. configs()90 ConfigList& configs() { return configs_; } 91 92 // Return the set of dependencies for this crate. dependencies()93 DependencyList& dependencies() { return deps_; } 94 95 // Return the compiler arguments used to invoke the compilation of this crate CompilerArgs()96 const std::vector<std::string>& CompilerArgs() { return compiler_args_; } 97 98 // Return the compiler target "triple" from the compiler args CompilerTarget()99 const std::optional<std::string>& CompilerTarget() { 100 return compiler_target_; 101 } 102 103 // Returns whether this crate builds a proc macro .so proc_macro_path()104 const std::optional<OutputFile>& proc_macro_path() { 105 return proc_macro_dynamic_library_; 106 } 107 108 // Returns environment variables applied to this, which may be necessary 109 // for correct functioning of environment variables rustenv()110 const base::flat_map<std::string, std::string>& rustenv() { return rustenv_; } 111 112 private: 113 SourceFile root_; 114 std::optional<OutputFile> gen_dir_; 115 CrateIndex index_; 116 std::string label_; 117 std::string edition_; 118 ConfigList configs_; 119 DependencyList deps_; 120 std::optional<std::string> compiler_target_; 121 std::vector<std::string> compiler_args_; 122 std::optional<OutputFile> proc_macro_dynamic_library_; 123 base::flat_map<std::string, std::string> rustenv_; 124 }; 125 126 using CrateList = std::vector<Crate>; 127 128 // Write the entire rust-project.json file contents into the given stream, based 129 // on the the given crates list. 130 void WriteCrates(const BuildSettings* build_settings, 131 CrateList& crate_list, 132 std::optional<std::string>& sysroot, 133 std::ostream& rust_project); 134 135 // Assemble the compiler arguments for the given GN Target. 136 std::vector<std::string> ExtractCompilerArgs(const Target* target); 137 138 // Find the value of an argument that's passed to the compiler as two 139 // consecutive strings in the list of arguments: ["arg", "value"] 140 std::optional<std::string> FindArgValue(const char* arg, 141 const std::vector<std::string>& args); 142 143 // Find the first argument that matches the prefix, returning the value after 144 // the prefix. e.g. ˝--arg=value", is returned as "value" if the prefix 145 // "--arg=" is used. 146 std::optional<std::string> FindArgValueAfterPrefix( 147 const std::string& prefix, 148 const std::vector<std::string>& args); 149 150 // Find all arguments that match the given prefix, returning the value after 151 // the prefix for each one. e.g. "--cfg=value" is returned as "value" if the 152 // prefix "--cfg=" is used. 153 std::vector<std::string> FindAllArgValuesAfterPrefix( 154 const std::string& prefix, 155 const std::vector<std::string>& args); 156 157 #endif // TOOLS_GN_RUST_PROJECT_WRITER_HELPERS_H_ 158