• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Mapping of a sysroot crate (path) to it's index in the crates list.
129 using SysrootCrateIndexMap = std::unordered_map<std::string_view, CrateIndex>;
130 
131 // Mapping of a sysroot (path) to the mapping of each of the sysroot crates to
132 // their index in the crates list.
133 using SysrootIndexMap =
134     std::unordered_map<std::string_view, SysrootCrateIndexMap>;
135 
136 // Add all of the crates for a sysroot (path) to the rust_project ostream.
137 // Add the given sysroot to the project, if it hasn't already been added.
138 void AddSysroot(const BuildSettings* build_settings,
139                 std::string_view sysroot,
140                 SysrootIndexMap& sysroot_lookup,
141                 CrateList& crate_list);
142 
143 // Write the entire rust-project.json file contents into the given stream, based
144 // on the the given crates list.
145 void WriteCrates(const BuildSettings* build_settings,
146                  CrateList& crate_list,
147                  std::ostream& rust_project);
148 
149 // Assemble the compiler arguments for the given GN Target.
150 std::vector<std::string> ExtractCompilerArgs(const Target* target);
151 
152 // Find the value of an argument that's passed to the compiler as two
153 // consecutive strings in the list of arguments:  ["arg", "value"]
154 std::optional<std::string> FindArgValue(const char* arg,
155                                         const std::vector<std::string>& args);
156 
157 // Find the first argument that matches the prefix, returning the value after
158 // the prefix.  e.g. ˝--arg=value", is returned as "value" if the prefix
159 // "--arg=" is used.
160 std::optional<std::string> FindArgValueAfterPrefix(
161     const std::string& prefix,
162     const std::vector<std::string>& args);
163 
164 // Find all arguments that match the given prefix, returning the value after
165 // the prefix for each one.  e.g. "--cfg=value" is returned as "value" if the
166 // prefix "--cfg=" is used.
167 std::vector<std::string> FindAllArgValuesAfterPrefix(
168     const std::string& prefix,
169     const std::vector<std::string>& args);
170 
171 
172 #endif  // TOOLS_GN_RUST_PROJECT_WRITER_HELPERS_H_
173