blob: eb4d2b9dc9c22c7ccec9f1bca3a9321693ce03b7 [file] [log] [blame]
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// Parses C++ headers and generates:
// * a Rust source file with bindings for the C++ API
// * a C++ source file with the implementation of the bindings
#include <string>
#include <utility>
#include <vector>
#include "base/init_google.h"
#include "base/logging.h"
#include "rs_bindings_from_cc/bazel_types.h"
#include "rs_bindings_from_cc/cmdline.h"
#include "rs_bindings_from_cc/ir.h"
#include "rs_bindings_from_cc/ir_from_cc.h"
#include "rs_bindings_from_cc/src_code_gen.h"
#include "third_party/absl/container/flat_hash_map.h"
#include "third_party/absl/status/status.h"
#include "third_party/absl/status/statusor.h"
#include "third_party/absl/strings/string_view.h"
#include "third_party/json/src/json.hpp"
#include "third_party/llvm/llvm-project/llvm/include/llvm/Support/raw_ostream.h"
#include "util/task/status.h"
#include "util/task/status_macros.h"
namespace {
absl::Status SetFileContents(absl::string_view path,
absl::string_view contents) {
std::error_code error_code;
llvm::raw_fd_ostream stream(path, error_code);
if (error_code) {
return absl::Status(absl::StatusCode::kInternal, error_code.message());
}
stream << contents;
stream.close();
if (stream.has_error()) {
return absl::Status(absl::StatusCode::kInternal, stream.error().message());
}
return absl::OkStatus();
}
absl::Status Main(int argc, char* argv[]) {
using rs_bindings_from_cc::Cmdline;
using rs_bindings_from_cc::IR;
ASSIGN_OR_RETURN(Cmdline cmdline, Cmdline::Create());
if (cmdline.do_nothing()) {
RETURN_IF_ERROR(SetFileContents(
cmdline.rs_out(),
"// intentionally left empty because --do_nothing was passed."));
RETURN_IF_ERROR(SetFileContents(
cmdline.cc_out(),
"// intentionally left empty because --do_nothing was passed."));
return absl::OkStatus();
}
ASSIGN_OR_RETURN(
IR ir,
rs_bindings_from_cc::IrFromCc(
/* extra_source_code= */ "", cmdline.current_target(),
cmdline.public_headers(),
/* virtual_headers_contents= */ {}, cmdline.headers_to_targets(),
std::vector<absl::string_view>(argv, argv + argc)));
if (!cmdline.ir_out().empty()) {
RETURN_IF_ERROR(
SetFileContents(cmdline.ir_out(), ir.ToJson().dump(/*indent=*/2)));
}
rs_bindings_from_cc::Bindings bindings =
rs_bindings_from_cc::GenerateBindings(ir);
RETURN_IF_ERROR(SetFileContents(cmdline.rs_out(), bindings.rs_api));
RETURN_IF_ERROR(SetFileContents(cmdline.cc_out(), bindings.rs_api_impl));
return absl::OkStatus();
}
} // namespace
int main(int argc, char* argv[]) {
InitGoogle(argv[0], &argc, &argv, true);
QCHECK_OK(Main(argc, argv));
return 0;
}