diff --git a/ffs/main.cc b/ffs/main.cc index 60e96ea..1db4058 100644 --- a/ffs/main.cc +++ b/ffs/main.cc @@ -2,6 +2,7 @@ // // SPDX-License-Identifier: BSD-2-Clause +#include "starlark/interpreter.h" #include "starlark/parser.h" #include "starlark/token.h" #include "starlark/tokenizer.h" @@ -54,22 +55,65 @@ build_files_from_pattern(std::filesystem::path const &from, std::string_view pat return std::nullopt; } - auto root_path = project_root(from); - if (!root_path) { - std::cerr << "Unable to find ffs project root for folder '" << from << "'.\n"; - return std::nullopt; - } - std::vector found; for (auto const &dir : std::filesystem::recursive_directory_iterator{from}) { - if (std::filesystem::exists(dir.path() / "BUILD.bazel")) { - found.push_back(dir.path() / "BUILD.bazel"); + if (dir.path().filename() == "BUILD.bazel") { + found.push_back(dir); } } return found; } +struct Target { + std::string name; +}; + +// TODO(robinlinden): This should be less silly. +std::optional> targets_from_build_file(std::filesystem::path bf) { + std::ifstream input{bf}; + if (!input) { + return std::nullopt; + } + + std::string content{std::istreambuf_iterator(input), std::istreambuf_iterator()}; + auto program = starlark::parse(content); + if (!program) { + return std::nullopt; + } + + std::vector targets; + + starlark::Interpreter interpreter; + + static constexpr auto kIgnore = [](auto const &) { return starlark::Value{}; }; + auto store_target_name = [&](std::vector args) { + auto it = std::ranges::find_if( + args, [](auto &name) { return name == "name"; }, &starlark::NativeArgument::name); + if (it != std::ranges::end(args) && std::holds_alternative(it->value.v)) { + targets.emplace_back(std::move(std::get(it->value.v))); + } + + return starlark::Value{0}; + }; + + interpreter.variables["cc_binary"] = + starlark::Value{std::make_shared(store_target_name)}; + interpreter.variables["cc_library"] = + starlark::Value{std::make_shared(store_target_name)}; + interpreter.variables["cc_test"] = + starlark::Value{std::make_shared(store_target_name)}; + interpreter.variables["glob"] = starlark::Value{std::make_shared(kIgnore)}; + + auto res = interpreter.run(*program); + if (!res) { + std::cerr << "Query failed. :(\n"; + return std::nullopt; + } + + return targets; +} + int run_debug(int argc, char **argv) { assert(argc == 2); @@ -104,18 +148,34 @@ int run_query(int argc, char **argv) { assert(argc == 3); auto cwd = std::filesystem::current_path(); + auto root_path = project_root(cwd); + if (!root_path) { + std::cerr << "Unable to find ffs project root for folder '" << cwd << "'.\n"; + return 1; + } + auto build_files = build_files_from_pattern(cwd, argv[2]); if (!build_files) { std::cerr << "Failed to find build files.\n"; return 1; } - // TODO(robinlinden): Get targets from build files. + bool failure = false; for (auto const &build_file : *build_files) { - std::cout << build_file << '\n'; + auto targets = targets_from_build_file(build_file); + if (!targets) { + std::cerr << "Resolving targets for build file " << build_file << " failed.\n"; + failure = true; + continue; + } + + auto package = build_file.parent_path().lexically_relative(*root_path).string(); + for (auto const &target : *targets) { + std::cout << "//" << package << ":" << target.name << '\n'; + } } - return 0; + return failure ? 1 : 0; } } // namespace diff --git a/starlark/interpreter.h b/starlark/interpreter.h index 34e3e67..9b5fbcf 100644 --- a/starlark/interpreter.h +++ b/starlark/interpreter.h @@ -50,15 +50,6 @@ class Interpreter { return result; } - std::optional run(auto const &) { - // TODO(robinlinden): Delete this. - return std::nullopt; - } - - std::optional run(Statement const &stmt) { - return std::visit([this](auto const &s) { return run(s); }, stmt); - } - std::optional run(AssignStmt const &stmt) { auto value = run(stmt.value); if (!value) { @@ -180,6 +171,11 @@ class Interpreter { return (**target)(std::move(native_args)); } + + std::optional run(LoadStmt const &load) { + std::ignore = load; // TODO(robinlinden): Implement. + return Value{}; + } }; } // namespace starlark