blob: af58a4cd72842a2b19e920599065efffaad892ee [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <cstdio>
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <string.h>
#include <utility>
#include "llcpp_codegen.h"
namespace fs = std::filesystem;
static void Usage(const char* exe_name) {
"Generate or validate the checked-in low-level C++ bindings in zircon.\n"
"Usage: %s (validate|update) ZIRCON_BUILDROOT FIDLGEN_LLCPP_PATH "
"ZIRCON_BUILDROOT is the root build directory of the Zircon GN build.\n"
"FIDLGEN_LLCPP_PATH is the path to the fidlgen_llcpp executable.\n"
"STAMP is the output path to a file indicating the success of the tool.\n"
"DEPFILE is the output path to a depfile describing the FIDL files\n"
"which when updated should trigger a re-run of this tool.\n"
"TMP_DIR is a temporary directory for the validator to store generated\n"
"bindings. It will be cleared on each run.\n"
"When validate is specified, it will validate that the generated\n"
"bindings are up-to-date, exiting with an error if not so.\n"
"Files in the source tree are not modified.\n"
"When update is specified, it will regenerate the bindings in\n"
"zircon/system/fidl from GN metadata.\n"
int main(int argc, char** argv) {
if (argc != 7) {
std::cerr << argv[0] << ": Invalid arguments" << "\n\n";
return -1;
// Since we're dealing with two builds, it's less ambiguous if we start with
// all absolute paths in the beginning, then convert to relative paths
// where required, similar to rebase_path in GN.
fs::path zircon_build_root = fs::absolute(argv[2]);
fs::path fidlgen_llcpp_path = fs::absolute(argv[3]);
fs::path stamp_path = fs::absolute(argv[4]);
fs::path depfile_path = fs::absolute(argv[5]);
fs::path tmp_dir = fs::absolute(argv[6]);
std::vector<fs::path> dependencies;
if (strcmp(argv[1], "validate") == 0) {
bool ok = DoValidate(zircon_build_root, fidlgen_llcpp_path, tmp_dir,
if (!ok) {
std::cerr << "========================================================\n"
<< "Out-of-date checked-in low-level C++ bindings in Zircon.\n"
"Re-run fx build -k 0 tools/fidlgen_llcpp_zircon:update\n"
<< "========================================================\n";
return -1;
} else if (strcmp(argv[1], "update") == 0) {
DoUpdate(zircon_build_root, fidlgen_llcpp_path, &dependencies);
} else {
std::cerr << argv[0] << ": Expected validate or update, not " << argv[1]
<< "\n\n";
return -1;
// Generate depfile
std::fstream depfile;, std::ios::out);
if (!depfile) {
std::cerr << "Failed to create depfile " << depfile_path << std::endl;
return -1;
depfile << fs::relative(stamp_path).string() << ":";
for (const auto& dep : dependencies) {
depfile << " " << fs::relative(dep).string();
depfile << " " << fs::relative(fidlgen_llcpp_path).string();
depfile << std::endl;
// Generate stamp file
std::fstream stamp;, std::ios::out);
if (!stamp) {
std::cerr << "Failed to stamp " << stamp_path << std::endl;
return -1;
return 0;