in src/tool/abi/main.cpp [77:280]
int main(int const argc, char** argv)
{
int exitCode = 0;
basic_writer w;
try
{
auto const start = high_resolution_clock::now();
reader args{ argc, argv, options };
if (!args || args.exists("help"))
{
throw usage_exception{};
}
abi_configuration config;
config.verbose = args.exists("verbose");
config.output_directory = output_directory(args);
config.enum_class = args.exists("enum-class");
config.lowercase_include_guard = args.exists("lowercase-include-guard");
config.enable_header_deprecation = args.exists("enable-header-deprecation");
if (args.exists("ns-prefix"))
{
auto const& values = args.values("ns-prefix");
if (values.empty())
{
config.ns_prefix_state = ns_prefix::always;
}
else
{
auto const& value = values[0];
if (value == "always")
{
config.ns_prefix_state = ns_prefix::always;
}
else if (value == "never")
{
config.ns_prefix_state = ns_prefix::never;
}
else if (value == "optional")
{
config.ns_prefix_state = ns_prefix::optional;
}
else
{
throw_invalid("'" + value + "' is not a valid argument for 'ns-prefix'");
}
}
}
else
{
config.ns_prefix_state = ns_prefix::never;
}
auto inputFiles = args.files("input");
auto referenceFiles = args.files("reference");
if (config.verbose)
{
for (auto const& in : inputFiles)
{
w.write("in: %\n", in);
}
for (auto const& ref : referenceFiles)
{
w.write("ref: %\n", ref);
}
w.write("out: %\n", config.output_directory);
}
w.flush_to_console();
std::vector<std::string> filesToRead;
filesToRead.reserve(inputFiles.size() + referenceFiles.size());
filesToRead.insert(filesToRead.end(), inputFiles.begin(), inputFiles.end());
filesToRead.insert(filesToRead.end(), referenceFiles.begin(), referenceFiles.end());
cache c{ filesToRead };
metadata_cache mdCache{ c };
auto include = args.values("include");
if (include.empty() && !referenceFiles.empty())
{
for (auto const& db : c.databases())
{
if (std::find_if(inputFiles.begin(), inputFiles.end(), [&](auto const& file)
{
return db.path() == file;
}) != inputFiles.end())
{
for (auto const& type : db.TypeDef)
{
if (!type.Flags().WindowsRuntime())
{
continue;
}
include.push_back(std::string{ type.TypeNamespace() });
}
}
}
}
filter f{ include, args.values("exclude") };
task_group group;
auto filter_includes = [&](namespace_cache const& types)
{
auto includes = [&](auto const& vector)
{
return std::find_if(vector.begin(), vector.end(), [&](auto const& t)
{
return f.includes(t.type());
}) != vector.end();
};
if (includes(types.enums) || includes(types.structs) || includes(types.delegates) ||
includes(types.interfaces) || includes(types.classes))
{
return true;
}
for (auto const& contract : types.contracts)
{
if (f.includes(contract.type))
{
return true;
}
}
return false;
};
bool foundationDependency = false;
for (auto const& [ns, nsTypes] : mdCache.namespaces)
{
// Headers are all or nothing. If the consumer is wanting one type in a namespace, they get everything
if (filter_includes(nsTypes))
{
if ((ns == foundation_namespace) || (ns == collections_namespace))
{
foundationDependency = true;
}
else
{
group.add([&, ns = ns]()
{
write_abi_header(ns, config, mdCache.compile_namespaces({ ns }));
});
}
}
}
if (foundationDependency)
{
group.add([&]()
{
// Write the 'Windows.Foundation.h' header. This is a merge of the 'Windows.Foundation' and the
// 'Windows.Foundation.Collections' namespacess
auto foundationItr = mdCache.namespaces.find(foundation_namespace);
auto collectionsItr = mdCache.namespaces.find(collections_namespace);
if (foundationItr == mdCache.namespaces.end())
{
XLANG_ASSERT(false);
w.write("WARNING: Dependency on the 'Windows.Foundation.Collections' identified, but the "
"'Windows.Foundation' namespace could not be found. Skipping...");
w.flush_to_console();
}
else if (collectionsItr == mdCache.namespaces.end())
{
XLANG_ASSERT(false);
w.write("WARNING: Dependency on the 'Windows.Foundation' identified, but the "
"'Windows.Foundation.Collections' namespace could not be found. Skipping...");
w.flush_to_console();
}
else
{
auto types = mdCache.compile_namespaces({ foundation_namespace, collections_namespace });
write_abi_header(foundation_namespace, config, types);
}
});
}
group.get();
if (config.verbose)
{
w.write("time: %ms\n", static_cast<std::int64_t>(duration_cast<milliseconds>((high_resolution_clock::now() - start)).count()));
}
}
catch (usage_exception const&)
{
print_usage(w);
exitCode = 1;
}
catch (std::exception const& e)
{
exitCode = 1;
w.write("%\n", e.what());
}
w.flush_to_console();
return exitCode;
}