16d528ed9Sopenharmony_ci// Copyright 2020 The Chromium Authors. All rights reserved.
26d528ed9Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
36d528ed9Sopenharmony_ci// found in the LICENSE file.
46d528ed9Sopenharmony_ci
56d528ed9Sopenharmony_ci#ifndef TOOLS_GN_RUST_PROJECT_WRITER_HELPERS_H_
66d528ed9Sopenharmony_ci#define TOOLS_GN_RUST_PROJECT_WRITER_HELPERS_H_
76d528ed9Sopenharmony_ci
86d528ed9Sopenharmony_ci#include <fstream>
96d528ed9Sopenharmony_ci#include <optional>
106d528ed9Sopenharmony_ci#include <sstream>
116d528ed9Sopenharmony_ci#include <string>
126d528ed9Sopenharmony_ci#include <string_view>
136d528ed9Sopenharmony_ci#include <tuple>
146d528ed9Sopenharmony_ci#include <unordered_map>
156d528ed9Sopenharmony_ci#include <vector>
166d528ed9Sopenharmony_ci
176d528ed9Sopenharmony_ci#include "base/containers/flat_map.h"
186d528ed9Sopenharmony_ci#include "build_settings.h"
196d528ed9Sopenharmony_ci#include "gn/source_file.h"
206d528ed9Sopenharmony_ci#include "gn/target.h"
216d528ed9Sopenharmony_ci
226d528ed9Sopenharmony_ci// These are internal types and helper functions for RustProjectWriter that have
236d528ed9Sopenharmony_ci// been extracted for easier testability.
246d528ed9Sopenharmony_ci
256d528ed9Sopenharmony_ci// Crate Index in the generated file
266d528ed9Sopenharmony_ciusing CrateIndex = size_t;
276d528ed9Sopenharmony_ci
286d528ed9Sopenharmony_ciusing ConfigList = std::vector<std::string>;
296d528ed9Sopenharmony_ciusing Dependency = std::pair<CrateIndex, std::string>;
306d528ed9Sopenharmony_ciusing DependencyList = std::vector<Dependency>;
316d528ed9Sopenharmony_ci
326d528ed9Sopenharmony_ci// This class represents a crate to be serialized out as part of the
336d528ed9Sopenharmony_ci// rust-project.json file.  This is used to separate the generating
346d528ed9Sopenharmony_ci// of the data that needs to be in the file, from the file itself.
356d528ed9Sopenharmony_ciclass Crate {
366d528ed9Sopenharmony_ci public:
376d528ed9Sopenharmony_ci  Crate(SourceFile root,
386d528ed9Sopenharmony_ci        std::optional<OutputFile> gen_dir,
396d528ed9Sopenharmony_ci        CrateIndex index,
406d528ed9Sopenharmony_ci        std::string label,
416d528ed9Sopenharmony_ci        std::string edition)
426d528ed9Sopenharmony_ci      : root_(root),
436d528ed9Sopenharmony_ci        gen_dir_(gen_dir),
446d528ed9Sopenharmony_ci        index_(index),
456d528ed9Sopenharmony_ci        label_(label),
466d528ed9Sopenharmony_ci        edition_(edition) {}
476d528ed9Sopenharmony_ci
486d528ed9Sopenharmony_ci  ~Crate() = default;
496d528ed9Sopenharmony_ci
506d528ed9Sopenharmony_ci  // Add a config item to the crate.
516d528ed9Sopenharmony_ci  void AddConfigItem(std::string cfg_item) { configs_.push_back(cfg_item); }
526d528ed9Sopenharmony_ci
536d528ed9Sopenharmony_ci  // Add a key-value environment variable pair used when building this crate.
546d528ed9Sopenharmony_ci  void AddRustenv(std::string key, std::string value) {
556d528ed9Sopenharmony_ci    rustenv_.emplace(key, value);
566d528ed9Sopenharmony_ci  }
576d528ed9Sopenharmony_ci
586d528ed9Sopenharmony_ci  // Add another crate as a dependency of this one.
596d528ed9Sopenharmony_ci  void AddDependency(CrateIndex index, std::string name) {
606d528ed9Sopenharmony_ci    deps_.push_back(std::make_pair(index, name));
616d528ed9Sopenharmony_ci  }
626d528ed9Sopenharmony_ci
636d528ed9Sopenharmony_ci  // Set the compiler arguments used to invoke the compilation of this crate
646d528ed9Sopenharmony_ci  void SetCompilerArgs(std::vector<std::string> args) { compiler_args_ = args; }
656d528ed9Sopenharmony_ci
666d528ed9Sopenharmony_ci  // Set the compiler target ("e.g. x86_64-linux-kernel")
676d528ed9Sopenharmony_ci  void SetCompilerTarget(std::string target) { compiler_target_ = target; }
686d528ed9Sopenharmony_ci
696d528ed9Sopenharmony_ci  // Set that this is a proc macro with the path to the output .so/dylib/dll
706d528ed9Sopenharmony_ci  void SetIsProcMacro(OutputFile proc_macro_dynamic_library) {
716d528ed9Sopenharmony_ci    proc_macro_dynamic_library_ = proc_macro_dynamic_library;
726d528ed9Sopenharmony_ci  }
736d528ed9Sopenharmony_ci
746d528ed9Sopenharmony_ci  // Returns the root file for the crate.
756d528ed9Sopenharmony_ci  SourceFile& root() { return root_; }
766d528ed9Sopenharmony_ci
776d528ed9Sopenharmony_ci  // Returns the root file for the crate.
786d528ed9Sopenharmony_ci  std::optional<OutputFile>& gen_dir() { return gen_dir_; }
796d528ed9Sopenharmony_ci
806d528ed9Sopenharmony_ci  // Returns the crate index.
816d528ed9Sopenharmony_ci  CrateIndex index() { return index_; }
826d528ed9Sopenharmony_ci
836d528ed9Sopenharmony_ci  // Returns the displayable crate label.
846d528ed9Sopenharmony_ci  const std::string& label() { return label_; }
856d528ed9Sopenharmony_ci
866d528ed9Sopenharmony_ci  // Returns the Rust Edition this crate uses.
876d528ed9Sopenharmony_ci  const std::string& edition() { return edition_; }
886d528ed9Sopenharmony_ci
896d528ed9Sopenharmony_ci  // Return the set of config items for this crate.
906d528ed9Sopenharmony_ci  ConfigList& configs() { return configs_; }
916d528ed9Sopenharmony_ci
926d528ed9Sopenharmony_ci  // Return the set of dependencies for this crate.
936d528ed9Sopenharmony_ci  DependencyList& dependencies() { return deps_; }
946d528ed9Sopenharmony_ci
956d528ed9Sopenharmony_ci  // Return the compiler arguments used to invoke the compilation of this crate
966d528ed9Sopenharmony_ci  const std::vector<std::string>& CompilerArgs() { return compiler_args_; }
976d528ed9Sopenharmony_ci
986d528ed9Sopenharmony_ci  // Return the compiler target "triple" from the compiler args
996d528ed9Sopenharmony_ci  const std::optional<std::string>& CompilerTarget() {
1006d528ed9Sopenharmony_ci    return compiler_target_;
1016d528ed9Sopenharmony_ci  }
1026d528ed9Sopenharmony_ci
1036d528ed9Sopenharmony_ci  // Returns whether this crate builds a proc macro .so
1046d528ed9Sopenharmony_ci  const std::optional<OutputFile>& proc_macro_path() {
1056d528ed9Sopenharmony_ci    return proc_macro_dynamic_library_;
1066d528ed9Sopenharmony_ci  }
1076d528ed9Sopenharmony_ci
1086d528ed9Sopenharmony_ci  // Returns environment variables applied to this, which may be necessary
1096d528ed9Sopenharmony_ci  // for correct functioning of environment variables
1106d528ed9Sopenharmony_ci  const base::flat_map<std::string, std::string>& rustenv() { return rustenv_; }
1116d528ed9Sopenharmony_ci
1126d528ed9Sopenharmony_ci private:
1136d528ed9Sopenharmony_ci  SourceFile root_;
1146d528ed9Sopenharmony_ci  std::optional<OutputFile> gen_dir_;
1156d528ed9Sopenharmony_ci  CrateIndex index_;
1166d528ed9Sopenharmony_ci  std::string label_;
1176d528ed9Sopenharmony_ci  std::string edition_;
1186d528ed9Sopenharmony_ci  ConfigList configs_;
1196d528ed9Sopenharmony_ci  DependencyList deps_;
1206d528ed9Sopenharmony_ci  std::optional<std::string> compiler_target_;
1216d528ed9Sopenharmony_ci  std::vector<std::string> compiler_args_;
1226d528ed9Sopenharmony_ci  std::optional<OutputFile> proc_macro_dynamic_library_;
1236d528ed9Sopenharmony_ci  base::flat_map<std::string, std::string> rustenv_;
1246d528ed9Sopenharmony_ci};
1256d528ed9Sopenharmony_ci
1266d528ed9Sopenharmony_ciusing CrateList = std::vector<Crate>;
1276d528ed9Sopenharmony_ci
1286d528ed9Sopenharmony_ci// Write the entire rust-project.json file contents into the given stream, based
1296d528ed9Sopenharmony_ci// on the the given crates list.
1306d528ed9Sopenharmony_civoid WriteCrates(const BuildSettings* build_settings,
1316d528ed9Sopenharmony_ci                 CrateList& crate_list,
1326d528ed9Sopenharmony_ci                 std::optional<std::string>& sysroot,
1336d528ed9Sopenharmony_ci                 std::ostream& rust_project);
1346d528ed9Sopenharmony_ci
1356d528ed9Sopenharmony_ci// Assemble the compiler arguments for the given GN Target.
1366d528ed9Sopenharmony_cistd::vector<std::string> ExtractCompilerArgs(const Target* target);
1376d528ed9Sopenharmony_ci
1386d528ed9Sopenharmony_ci// Find the value of an argument that's passed to the compiler as two
1396d528ed9Sopenharmony_ci// consecutive strings in the list of arguments:  ["arg", "value"]
1406d528ed9Sopenharmony_cistd::optional<std::string> FindArgValue(const char* arg,
1416d528ed9Sopenharmony_ci                                        const std::vector<std::string>& args);
1426d528ed9Sopenharmony_ci
1436d528ed9Sopenharmony_ci// Find the first argument that matches the prefix, returning the value after
1446d528ed9Sopenharmony_ci// the prefix.  e.g. ˝--arg=value", is returned as "value" if the prefix
1456d528ed9Sopenharmony_ci// "--arg=" is used.
1466d528ed9Sopenharmony_cistd::optional<std::string> FindArgValueAfterPrefix(
1476d528ed9Sopenharmony_ci    const std::string& prefix,
1486d528ed9Sopenharmony_ci    const std::vector<std::string>& args);
1496d528ed9Sopenharmony_ci
1506d528ed9Sopenharmony_ci// Find all arguments that match the given prefix, returning the value after
1516d528ed9Sopenharmony_ci// the prefix for each one.  e.g. "--cfg=value" is returned as "value" if the
1526d528ed9Sopenharmony_ci// prefix "--cfg=" is used.
1536d528ed9Sopenharmony_cistd::vector<std::string> FindAllArgValuesAfterPrefix(
1546d528ed9Sopenharmony_ci    const std::string& prefix,
1556d528ed9Sopenharmony_ci    const std::vector<std::string>& args);
1566d528ed9Sopenharmony_ci
1576d528ed9Sopenharmony_ci#endif  // TOOLS_GN_RUST_PROJECT_WRITER_HELPERS_H_
158