#ifndef TOOLS_GN_RESOLVED_TARGET_DATA_H_
#define TOOLS_GN_RESOLVED_TARGET_DATA_H_
#include <atomic>
#include <memory>
#include <mutex>
#include <shared_mutex>
#include <vector>
#include "base/containers/span.h"
#include "gn/lib_file.h"
#include "gn/resolved_target_deps.h"
#include "gn/source_dir.h"
#include "gn/target.h"
#include "gn/target_public_pair.h"
#include "gn/unique_vector.h"
class ResolvedTargetData {
public:
const ResolvedTargetDeps& GetTargetDeps(const Target* target) const {
return GetTargetInfo(target)->deps;
}
base::span<const Target*> GetDataDeps(const Target* target) const {
return GetTargetDeps(target).data_deps();
}
base::span<const Target*> GetLinkedDeps(const Target* target) const {
return GetTargetDeps(target).linked_deps();
}
const std::vector<SourceDir>& GetLinkedLibraryDirs(
const Target* target) const {
return GetTargetLibInfo(target)->lib_dirs;
}
const std::vector<LibFile>& GetLinkedLibraries(const Target* target) const {
return GetTargetLibInfo(target)->libs;
}
const std::vector<SourceDir>& GetLinkedFrameworkDirs(
const Target* target) const {
return GetTargetFrameworkInfo(target)->framework_dirs;
}
const std::vector<std::string>& GetLinkedFrameworks(
const Target* target) const {
return GetTargetFrameworkInfo(target)->frameworks;
}
const std::vector<std::string>& GetLinkedWeakFrameworks(
const Target* target) const {
return GetTargetFrameworkInfo(target)->weak_frameworks;
}
const std::vector<std::string>& GetLinkedWeakLibraries(
const Target* target) const {
return GetTargetFrameworkInfo(target)->weak_libraries;
}
const TargetSet& GetHardDeps(const Target* target) const {
return GetTargetHardDeps(target)->hard_deps;
}
const std::vector<TargetPublicPair>& GetInheritedLibraries(
const Target* target) const {
return GetTargetInheritedLibs(target)->inherited_libs;
}
const std::vector<TargetPublicPair>& GetModuleDepsInformation(
const Target* target) const {
return GetTargetModuleDepsInformation(target)->module_deps_information;
}
const std::vector<TargetPublicPair>& GetRustInheritedLibraries(
const Target* target) const {
return GetTargetRustLibs(target)->rust_inherited_libs;
}
base::span<const Target*> GetSwiftModuleDependencies(
const Target* target) const {
const TargetInfo* info = GetTargetSwiftValues(target);
if (!info->swift_values.get())
return {};
return info->swift_values->modules;
}
private:
struct TargetInfo {
TargetInfo() = default;
TargetInfo(const Target* target)
: target(target),
deps(target->public_deps(),
target->private_deps(),
target->data_deps()) {}
const Target* target = nullptr;
ResolvedTargetDeps deps;
mutable std::mutex mutex;
std::atomic<bool> has_lib_info = false;
std::atomic<bool> has_framework_info = false;
std::atomic<bool> has_hard_deps = false;
std::atomic<bool> has_inherited_libs = false;
std::atomic<bool> has_module_deps_information = false;
std::atomic<bool> has_rust_libs = false;
std::atomic<bool> has_swift_values = false;
std::vector<SourceDir> lib_dirs;
std::vector<LibFile> libs;
std::vector<SourceDir> framework_dirs;
std::vector<std::string> frameworks;
std::vector<std::string> weak_frameworks;
std::vector<std::string> weak_libraries;
TargetSet hard_deps;
std::vector<TargetPublicPair> inherited_libs;
std::vector<TargetPublicPair> module_deps_information;
std::vector<TargetPublicPair> rust_inherited_libs;
std::vector<TargetPublicPair> rust_inheritable_libs;
struct SwiftValues {
std::vector<const Target*> modules;
std::vector<const Target*> public_modules;
SwiftValues(std::vector<const Target*> modules,
std::vector<const Target*> public_modules)
: modules(std::move(modules)),
public_modules(std::move(public_modules)) {}
};
std::unique_ptr<SwiftValues> swift_values;
};
TargetInfo* GetTargetInfo(const Target* target) const;
const TargetInfo* GetTargetLibInfo(const Target* target) const {
TargetInfo* info = GetTargetInfo(target);
if (!info->has_lib_info.load(std::memory_order_acquire)) {
std::lock_guard<std::mutex> lock(info->mutex);
if (!info->has_lib_info.load(std::memory_order_relaxed)) {
ComputeLibInfo(info);
info->has_lib_info.store(true, std::memory_order_release);
}
}
return info;
}
const TargetInfo* GetTargetFrameworkInfo(const Target* target) const {
TargetInfo* info = GetTargetInfo(target);
if (!info->has_framework_info.load(std::memory_order_acquire)) {
std::lock_guard<std::mutex> lock(info->mutex);
if (!info->has_framework_info.load(std::memory_order_relaxed)) {
ComputeFrameworkInfo(info);
info->has_framework_info.store(true, std::memory_order_release);
}
}
return info;
}
const TargetInfo* GetTargetHardDeps(const Target* target) const {
TargetInfo* info = GetTargetInfo(target);
if (!info->has_hard_deps.load(std::memory_order_acquire)) {
std::lock_guard<std::mutex> lock(info->mutex);
if (!info->has_hard_deps.load(std::memory_order_relaxed)) {
ComputeHardDeps(info);
info->has_hard_deps.store(true, std::memory_order_release);
}
}
return info;
}
const TargetInfo* GetTargetInheritedLibs(const Target* target) const {
TargetInfo* info = GetTargetInfo(target);
if (!info->has_inherited_libs.load(std::memory_order_acquire)) {
std::lock_guard<std::mutex> lock(info->mutex);
if (!info->has_inherited_libs.load(std::memory_order_relaxed)) {
ComputeInheritedLibs(info);
info->has_inherited_libs.store(true, std::memory_order_release);
}
}
return info;
}
const TargetInfo* GetTargetModuleDepsInformation(const Target* target) const {
TargetInfo* info = GetTargetInfo(target);
if (!info->has_module_deps_information.load(std::memory_order_acquire)) {
std::lock_guard<std::mutex> lock(info->mutex);
if (!info->has_module_deps_information.load(std::memory_order_relaxed)) {
ComputeModuleDepsInformation(info);
info->has_module_deps_information.store(true,
std::memory_order_release);
}
}
return info;
}
const TargetInfo* GetTargetRustLibs(const Target* target) const {
TargetInfo* info = GetTargetInfo(target);
if (!info->has_rust_libs.load(std::memory_order_acquire)) {
std::lock_guard<std::mutex> lock(info->mutex);
if (!info->has_rust_libs.load(std::memory_order_relaxed)) {
ComputeRustLibs(info);
info->has_rust_libs.store(true, std::memory_order_release);
}
}
return info;
}
const TargetInfo* GetTargetSwiftValues(const Target* target) const {
TargetInfo* info = GetTargetInfo(target);
if (!info->has_swift_values.load(std::memory_order_acquire)) {
std::lock_guard<std::mutex> lock(info->mutex);
if (!info->has_swift_values.load(std::memory_order_relaxed)) {
ComputeSwiftValues(info);
info->has_swift_values.store(true, std::memory_order_release);
}
}
return info;
}
void ComputeLibInfo(TargetInfo* info) const;
void ComputeFrameworkInfo(TargetInfo* info) const;
void ComputeHardDeps(TargetInfo* info) const;
void ComputeInheritedLibs(TargetInfo* info) const;
void ComputeModuleDepsInformation(TargetInfo* info) const;
void ComputeRustLibs(TargetInfo* info) const;
void ComputeSwiftValues(TargetInfo* info) const;
void ComputeInheritedLibsFor(
base::span<const Target*> deps,
bool is_public,
TargetPublicPairListBuilder* inherited_libraries) const;
void ComputeModuleDepsInformationFor(
base::span<const Target*> deps,
bool is_public,
TargetPublicPairListBuilder* module_deps_information) const;
struct RustLibsBuilder {
TargetPublicPairListBuilder inherited;
TargetPublicPairListBuilder inheritable;
};
void ComputeRustLibsFor(base::span<const Target*> deps,
bool is_public,
RustLibsBuilder* rust_libs) const;
mutable std::shared_mutex map_mutex_;
mutable UniqueVector<const Target*> targets_;
mutable std::vector<std::unique_ptr<TargetInfo>> infos_;
};
#endif