diff --git a/clang-tools-extra/clangd/CMakeLists.txt b/clang-tools-extra/clangd/CMakeLists.txt --- a/clang-tools-extra/clangd/CMakeLists.txt +++ b/clang-tools-extra/clangd/CMakeLists.txt @@ -140,7 +140,6 @@ endif() add_subdirectory(tool) add_subdirectory(indexer) -add_subdirectory(index/dex/dexp) if (LLVM_INCLUDE_BENCHMARKS) add_subdirectory(benchmarks) @@ -159,6 +158,10 @@ set(GRPC_INSTALL_PATH "" CACHE PATH "Path to gRPC library manual installation.") if (CLANGD_ENABLE_REMOTE) + add_definitions(-DCLANGD_REMOTE) include(FindGRPC) + # FIXME(kirillbobyrev): Move this tto index/remote/CMakeLists.txt and make RemoteProtosLocation global via... CACHE? + generate_grpc_protos(RemoteIndexProtos "index/remote/Index.proto" RemoteProtosLocation) add_subdirectory(index/remote) endif() +add_subdirectory(index/dex/dexp) diff --git a/clang-tools-extra/clangd/index/Serialization.h b/clang-tools-extra/clangd/index/Serialization.h --- a/clang-tools-extra/clangd/index/Serialization.h +++ b/clang-tools-extra/clangd/index/Serialization.h @@ -77,6 +77,11 @@ std::string toYAML(const Symbol &); std::string toYAML(const std::pair> &); std::string toYAML(const Relation &); +std::string toYAML(const Ref &); + +// Deserialize a single symbol from YAML. +clangd::Symbol symbolFromYAML(StringRef YAML, llvm::UniqueStringSaver *Strings); +clangd::Ref refFromYAML(StringRef YAML, llvm::UniqueStringSaver *Strings); // Build an in-memory static index from an index file. // The size should be relatively small, so data can be managed in memory. diff --git a/clang-tools-extra/clangd/index/YAMLSerialization.cpp b/clang-tools-extra/clangd/index/YAMLSerialization.cpp --- a/clang-tools-extra/clangd/index/YAMLSerialization.cpp +++ b/clang-tools-extra/clangd/index/YAMLSerialization.cpp @@ -418,5 +418,31 @@ return Buf; } +std::string toYAML(const Ref &R) { + std::string Buf; + { + llvm::raw_string_ostream OS(Buf); + llvm::yaml::Output Yout(OS); + Ref Reference = R; // copy: Yout<< requires mutability. + Yout << Reference; + } + return Buf; +} + +clangd::Symbol symbolFromYAML(StringRef YAML, + llvm::UniqueStringSaver *Strings) { + clangd::Symbol Deserialized; + llvm::yaml::Input YAMLInput(YAML, Strings); + YAMLInput >> Deserialized; + return Deserialized; +} + +clangd::Ref refFromYAML(StringRef YAML, llvm::UniqueStringSaver *Strings) { + clangd::Ref Deserialized; + llvm::yaml::Input YAMLInput(YAML, Strings); + YAMLInput >> Deserialized; + return Deserialized; +} + } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/index/dex/dexp/CMakeLists.txt b/clang-tools-extra/clangd/index/dex/dexp/CMakeLists.txt --- a/clang-tools-extra/clangd/index/dex/dexp/CMakeLists.txt +++ b/clang-tools-extra/clangd/index/dex/dexp/CMakeLists.txt @@ -1,5 +1,9 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../) +include_directories(${RemoteProtosLocation}) +# FIXME(kirillbobyrev): This should be target-local, but it's not working with +# add_clang_library. +add_definitions(-DGOOGLE_PROTOBUF_NO_RTTI=1) set(LLVM_LINK_COMPONENTS LineEditor Support @@ -16,4 +20,8 @@ target_link_libraries(dexp PRIVATE clangDaemon + clangRemoteIndex + + RemoteIndexProtos + grpc++ ) diff --git a/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp b/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp --- a/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp +++ b/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp @@ -14,6 +14,7 @@ #include "SourceCode.h" #include "index/Serialization.h" #include "index/dex/Dex.h" +#include "index/remote/Index.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -22,16 +23,27 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Signals.h" +#ifdef CLANGD_ENABLE_REMOTE +#include "Index.grpc.pb.h" +#endif + namespace clang { namespace clangd { namespace { -llvm::cl::opt IndexPath(llvm::cl::desc(""), - llvm::cl::Positional, llvm::cl::Required); +llvm::cl::opt IndexLocation(llvm::cl::desc(""), + llvm::cl::Positional); llvm::cl::opt ExecCommand("c", llvm::cl::desc("Command to execute and then exit")); +#ifdef CLANGD_REMOTE +// FIXME(kirillbobyrev): This is not working properly for some reason. +llvm::cl::opt + RemoteMode("remote", + llvm::cl::desc("Connect to remote index")); +#endif + static const std::string Overview = R"( This is an **experimental** interactive tool to process user-provided search queries over given symbol collection obtained via clangd-indexer. The @@ -150,7 +162,7 @@ } Request.AnyScope = Request.Scopes.empty(); // FIXME(kbobyrev): Print symbol final scores to see the distribution. - static const auto OutputFormat = "{0,-4} | {1,-40} | {2,-25}\n"; + static const auto *OutputFormat = "{0,-4} | {1,-40} | {2,-25}\n"; llvm::outs() << llvm::formatv(OutputFormat, "Rank", "Symbol ID", "Symbol Name"); size_t Rank = 0; @@ -266,12 +278,17 @@ {"find", "Search for symbols with fuzzyFind", std::make_unique}, {"lookup", "Dump symbol details by ID or qualified name", std::make_unique}, - {"refs", "Find references by ID or qualified name", - std::make_unique}, + {"refs", "Find references by ID or qualified name", std::make_unique}, }; std::unique_ptr openIndex(llvm::StringRef Index) { +#ifdef CLANGD_REMOTE + return RemoteMode + ? std::unique_ptr(new remote::IndexClient(Index)) + : loadIndex(Index, /*UseDex=*/true); +#else return loadIndex(Index, /*UseDex=*/true); +#endif } bool runCommand(std::string Request, const SymbolIndex &Index) { @@ -314,9 +331,7 @@ llvm::sys::PrintStackTraceOnErrorSignal(argv[0]); std::unique_ptr Index; - reportTime("Dex build", [&]() { - Index = openIndex(IndexPath); - }); + reportTime("Dex build", [&]() { Index = openIndex(IndexLocation); }); if (!Index) { llvm::outs() << "Failed to open the index.\n"; diff --git a/clang-tools-extra/clangd/index/remote/CMakeLists.txt b/clang-tools-extra/clangd/index/remote/CMakeLists.txt --- a/clang-tools-extra/clangd/index/remote/CMakeLists.txt +++ b/clang-tools-extra/clangd/index/remote/CMakeLists.txt @@ -1,7 +1,18 @@ -generate_grpc_protos(RemoteIndexProtos "Index.proto") - -include_directories("${CMAKE_CURRENT_BINARY_DIR}") +include_directories(${RemoteProtosLocation}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../) -add_subdirectory(client) +# FIXME(kirillbobyrev): This should be target-local, but it's not working with +# add_clang_library. +add_definitions(-DGOOGLE_PROTOBUF_NO_RTTI=1) +add_clang_library(clangRemoteIndex + Index.cpp + + LINK_LIBS + RemoteIndexProtos + + protobuf + grpc++ + clangDaemon + ) + add_subdirectory(server) diff --git a/clang-tools-extra/clangd/index/remote/Index.h b/clang-tools-extra/clangd/index/remote/Index.h new file mode 100644 --- /dev/null +++ b/clang-tools-extra/clangd/index/remote/Index.h @@ -0,0 +1,50 @@ +//===--- Index.h -------------------------------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_INDEX_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_INDEX_H + +#include "grpcpp/grpcpp.h" + +#include "Index.grpc.pb.h" +#include "index/Index.h" + +namespace clang { +namespace clangd { +namespace remote { + +class IndexClient : public SymbolIndex { +public: + IndexClient(llvm::StringRef Address) + : Stub(remote::Index::NewStub(grpc::CreateChannel( + Address.str(), grpc::InsecureChannelCredentials()))) {} + + void lookup(const clangd::LookupRequest &, + llvm::function_ref) const override; + + bool + fuzzyFind(const clangd::FuzzyFindRequest &, + llvm::function_ref) const override; + bool refs(const clangd::RefsRequest &, + llvm::function_ref) const override; + void + relations(const RelationsRequest &, + llvm::function_ref) const override; + + size_t estimateMemoryUsage() const override; + +private: + std::unique_ptr Stub; +}; + +} // namespace remote +} // namespace clangd +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_INDEX_H diff --git a/clang-tools-extra/clangd/index/remote/Index.cpp b/clang-tools-extra/clangd/index/remote/Index.cpp new file mode 100644 --- /dev/null +++ b/clang-tools-extra/clangd/index/remote/Index.cpp @@ -0,0 +1,96 @@ +//===--- Index.cpp -----------------------------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Index.h" +#include "Index.grpc.pb.h" +#include "index/Serialization.h" +#include "llvm/Support/YAMLTraits.h" + +namespace clang { +namespace clangd { +namespace remote { + +// IndexClient does not take any space since the data is stored on the server. +size_t IndexClient::estimateMemoryUsage() const { return 0; } + +void IndexClient::lookup( + const clangd::LookupRequest &Request, + llvm::function_ref Callback) const { + LookupRequest RPCRequest; + for (const auto &SymbolID : Request.IDs) + RPCRequest.add_ids(SymbolID.str()); + + grpc::ClientContext Context; + remote::Symbol Reply; + std::unique_ptr> Reader( + Stub->Lookup(&Context, RPCRequest)); + llvm::BumpPtrAllocator Arena; + llvm::UniqueStringSaver Strings(Arena); + while (Reader->Read(&Reply)) + Callback(symbolFromYAML(Reply.yaml_serializatiton(), &Strings)); + grpc::Status Status = Reader->Finish(); + llvm::outs() << "lookup rpc " << (Status.ok() ? "succeeded" : "failed") + << '\n'; +} + +bool IndexClient::fuzzyFind( + const clangd::FuzzyFindRequest &Request, + llvm::function_ref Callback) const { + FuzzyFindRequest RPCRequest; + RPCRequest.set_query(Request.Query); + for (const auto &Scope : Request.Scopes) + RPCRequest.add_scopes(Scope); + RPCRequest.set_any_scope(Request.AnyScope); + if (Request.Limit) + RPCRequest.set_limit(*Request.Limit); + RPCRequest.set_resricted_for_code_completion( + Request.RestrictForCodeCompletion); + for (const auto &Path : Request.ProximityPaths) + RPCRequest.add_proximity_paths(Path); + for (const auto &Type : Request.PreferredTypes) + RPCRequest.add_preferred_types(Type); + + grpc::ClientContext Context; + FuzzyFindReply Reply; + grpc::Status Status = Stub->FuzzyFind(&Context, RPCRequest, &Reply); + llvm::BumpPtrAllocator Arena; + llvm::UniqueStringSaver Strings(Arena); + for (const auto &SymbolObject : Reply.symbols()) + Callback(symbolFromYAML(SymbolObject.yaml_serializatiton(), &Strings)); + llvm::outs() << "FuzzyFind rpc " << (Status.ok() ? "succeeded" : "failed") + << '\n'; + return Reply.has_more(); +} + +bool IndexClient::refs(const clangd::RefsRequest &Request, + llvm::function_ref Callback) const { + RefsRequest RPCRequest; + for (const auto &ID : Request.IDs) + RPCRequest.add_ids(ID.str()); + RPCRequest.set_filter(static_cast(Request.Filter)); + if (Request.Limit) + RPCRequest.set_limit(*Request.Limit); + + grpc::ClientContext Context; + RefsReply Reply; + grpc::Status Status = Stub->Refs(&Context, RPCRequest, &Reply); + llvm::BumpPtrAllocator Arena; + llvm::UniqueStringSaver Strings(Arena); + for (const auto &RefYAML : Reply.refs()) + Callback(refFromYAML(RefYAML, &Strings)); + llvm::outs() << "Refs rpc " << (Status.ok() ? "succeeded" : "failed") << '\n'; + return Reply.has_more(); +} +void IndexClient::relations( + const RelationsRequest &, + llvm::function_ref) + const {} + +} // namespace remote +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/index/remote/Index.proto b/clang-tools-extra/clangd/index/remote/Index.proto --- a/clang-tools-extra/clangd/index/remote/Index.proto +++ b/clang-tools-extra/clangd/index/remote/Index.proto @@ -11,9 +11,40 @@ package clang.clangd.remote; service Index { - rpc Lookup(LookupRequest) returns (stream LookupReply) {} + rpc Lookup(LookupRequest) returns (stream Symbol) {} + + rpc FuzzyFind(FuzzyFindRequest) returns (FuzzyFindReply) {} + + rpc Refs(RefsRequest) returns (RefsReply) {} +} + +message LookupRequest { repeated string ids = 1; } + +// FIXME(kirillbobyrev): Properly serialize symbol instead of passing YAML. +message Symbol { string yaml_serializatiton = 1; } + +message FuzzyFindRequest { + string query = 1; + repeated string scopes = 2; + bool any_scope = 3; + uint32 limit = 4; + bool resricted_for_code_completion = 5; + repeated string proximity_paths = 6; + repeated string preferred_types = 7; } -message LookupRequest { string id = 1; } +message FuzzyFindReply { + repeated Symbol symbols = 1; + bool has_more = 2; +} -message LookupReply { string symbol_yaml = 1; } +message RefsRequest { + repeated string ids = 1; + uint32 filter = 2; + uint32 limit = 3; +} + +message RefsReply { + repeated string refs = 1; + bool has_more = 2; +} diff --git a/clang-tools-extra/clangd/index/remote/client/CMakeLists.txt b/clang-tools-extra/clangd/index/remote/client/CMakeLists.txt deleted file mode 100644 --- a/clang-tools-extra/clangd/index/remote/client/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -set(LLVM_LINK_COMPONENTS - LineEditor - Support - ) -add_clang_executable(clangd-index-client - Client.cpp - ) -target_compile_definitions(clangd-index-client PRIVATE -DGOOGLE_PROTOBUF_NO_RTTI=1) -clang_target_link_libraries(clangd-index-client - PRIVATE - clangDaemon - ) -target_link_libraries(clangd-index-client - PRIVATE - RemoteIndexProtos - - protobuf - grpc++ - ) diff --git a/clang-tools-extra/clangd/index/remote/client/Client.cpp b/clang-tools-extra/clangd/index/remote/client/Client.cpp deleted file mode 100644 --- a/clang-tools-extra/clangd/index/remote/client/Client.cpp +++ /dev/null @@ -1,91 +0,0 @@ -//===--- Client.cpp - Remote Index Client -----------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements a simple interactive tool which can be used to manually -// evaluate symbol search quality of Clangd index. -// -//===----------------------------------------------------------------------===// - -#include "SourceCode.h" -#include "index/Serialization.h" -#include "index/dex/Dex.h" -#include "llvm/ADT/ScopeExit.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/LineEditor/LineEditor.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Signals.h" - -#include "grpcpp/grpcpp.h" - -#include "Index.grpc.pb.h" - -namespace clang { -namespace clangd { -namespace { - -llvm::cl::opt - ServerAddress("server-address", - llvm::cl::desc("Address of remote index server to use."), - llvm::cl::init("0.0.0.0:50051")); - -static const std::string Overview = R"( -This is an **experimental** interactive tool to process user-provided search -queries over given symbol collection obtained via clangd-indexer with the help -of remote index server. The client will connect to remote index server and pass -it lookup queries. -)"; - -class RemoteIndexClient { -public: - RemoteIndexClient(std::shared_ptr Channel) - : Stub(remote::Index::NewStub(Channel)) {} - - void lookup(llvm::StringRef ID) { - llvm::outs() << "Lookup of symbol with ID " << ID << '\n'; - remote::LookupRequest Proto; - Proto.set_id(ID.str()); - - grpc::ClientContext Context; - remote::LookupReply Reply; - std::unique_ptr> Reader( - Stub->Lookup(&Context, Proto)); - while (Reader->Read(&Reply)) { - llvm::outs() << Reply.symbol_yaml(); - } - grpc::Status Status = Reader->Finish(); - if (Status.ok()) { - llvm::outs() << "lookupRequest rpc succeeded.\n"; - } else { - llvm::outs() << "lookupRequest rpc failed.\n"; - } - } - -private: - std::unique_ptr Stub; -}; - -} // namespace -} // namespace clangd -} // namespace clang - -int main(int argc, const char *argv[]) { - using namespace clang::clangd; - - llvm::cl::ParseCommandLineOptions(argc, argv, Overview); - llvm::cl::ResetCommandLineParser(); // We reuse it for REPL commands. - llvm::sys::PrintStackTraceOnErrorSignal(argv[0]); - - RemoteIndexClient IndexClient( - grpc::CreateChannel(ServerAddress, grpc::InsecureChannelCredentials())); - - llvm::LineEditor LE("remote-index-client"); - while (llvm::Optional Request = LE.readLine()) - IndexClient.lookup(std::move(*Request)); -} diff --git a/clang-tools-extra/clangd/index/remote/server/Server.cpp b/clang-tools-extra/clangd/index/remote/server/Server.cpp --- a/clang-tools-extra/clangd/index/remote/server/Server.cpp +++ b/clang-tools-extra/clangd/index/remote/server/Server.cpp @@ -23,6 +23,7 @@ namespace clang { namespace clangd { +namespace remote { namespace { static const std::string Overview = R"( @@ -40,6 +41,22 @@ return loadIndex(Index, /*UseIndex=*/true); } +clangd::FuzzyFindRequest deserialize(const FuzzyFindRequest *Request) { + clangd::FuzzyFindRequest Result; + Result.Query = Request->query(); + for (const auto &Scope : Request->scopes()) + Result.Scopes.push_back(Scope); + Result.AnyScope = Request->any_scope(); + if (Request->limit()) + Result.Limit = Request->limit(); + Result.RestrictForCodeCompletion = Request->resricted_for_code_completion(); + for (const auto &Path : Request->proximity_paths()) + Result.ProximityPaths.push_back(Path); + for (const auto &Type : Request->preferred_types()) + Result.ProximityPaths.push_back(Type); + return Result; +} + class RemoteIndexServer final : public remote::Index::Service { public: RemoteIndexServer(std::unique_ptr Index) @@ -47,24 +64,51 @@ private: grpc::Status Lookup(grpc::ServerContext *Context, - const remote::LookupRequest *Request, - grpc::ServerWriter *Reply) override { - llvm::outs() << "Lookup of symbol with ID " << Request->id() << '\n'; - LookupRequest Req; - auto SID = SymbolID::fromStr(Request->id()); - if (!SID) { - llvm::outs() << llvm::toString(SID.takeError()) << "\n"; - return grpc::Status::CANCELLED; + const LookupRequest *Request, + grpc::ServerWriter *Reply) override { + clangd::LookupRequest Req; + for (const auto &ID : Request->ids()) { + auto SID = SymbolID::fromStr(StringRef(ID)); + if (!SID) + return grpc::Status::CANCELLED; + Req.IDs.insert(*SID); } - Req.IDs.insert(*SID); - Index->lookup(Req, [&](const Symbol &Sym) { - remote::LookupReply NextSymbol; - NextSymbol.set_symbol_yaml(toYAML(Sym)); + Index->lookup(Req, [&](const clangd::Symbol &Sym) { + remote::Symbol NextSymbol; + NextSymbol.set_yaml_serializatiton(toYAML(Sym)); Reply->Write(NextSymbol); }); return grpc::Status::OK; } + grpc::Status FuzzyFind(grpc::ServerContext *Context, + const FuzzyFindRequest *Request, + FuzzyFindReply *Reply) override { + const auto Req = deserialize(Request); + bool HasMore = Index->fuzzyFind(Req, [&](const clangd::Symbol &Sym) { + auto *NextSymbol = Reply->add_symbols(); + NextSymbol->set_yaml_serializatiton(toYAML(Sym)); + }); + Reply->set_has_more(HasMore); + return grpc::Status::OK; + } + + grpc::Status Refs(grpc::ServerContext *Context, const RefsRequest *Request, + RefsReply *Reply) override { + clangd::RefsRequest Req; + for (const auto &ID : Request->ids()) { + auto SID = SymbolID::fromStr(StringRef(ID)); + if (!SID) + return grpc::Status::CANCELLED; + Req.IDs.insert(*SID); + } + bool HasMore = Index->refs(Req, [&](const clangd::Ref &Reference) { + Reply->add_refs(toYAML(Reference)); + }); + Reply->set_has_more(HasMore); + return grpc::Status::OK; + } + std::unique_ptr Index; }; @@ -83,15 +127,16 @@ } } // namespace +} // namespace remote } // namespace clangd } // namespace clang int main(int argc, char *argv[]) { - using namespace clang::clangd; - llvm::cl::ParseCommandLineOptions(argc, argv, clang::clangd::Overview); + using namespace clang::clangd::remote; + llvm::cl::ParseCommandLineOptions(argc, argv, Overview); llvm::sys::PrintStackTraceOnErrorSignal(argv[0]); - std::unique_ptr Index = openIndex(IndexPath); + std::unique_ptr Index = openIndex(IndexPath); if (!Index) { llvm::outs() << "Failed to open the index.\n"; diff --git a/llvm/cmake/modules/FindGRPC.cmake b/llvm/cmake/modules/FindGRPC.cmake --- a/llvm/cmake/modules/FindGRPC.cmake +++ b/llvm/cmake/modules/FindGRPC.cmake @@ -23,11 +23,11 @@ find_program(PROTOC protoc) endif() -# Proto headers are generated in ${CMAKE_CURRENT_BINARY_DIR}. +# Proto headers are generated in ${GeneratedFilesLocation}. # Libraries that use these headers should adjust the include path. # FIXME(kirillbobyrev): Allow optional generation of gRPC code and give callers # control over it via additional parameters. -function(generate_grpc_protos LibraryName ProtoFile) +function(generate_grpc_protos LibraryName ProtoFile GeneratedFilesLocation) get_filename_component(ProtoSourceAbsolutePath "${CMAKE_CURRENT_SOURCE_DIR}/${ProtoFile}" ABSOLUTE) get_filename_component(ProtoSourcePath ${ProtoSourceAbsolutePath} PATH) @@ -35,6 +35,7 @@ set(GeneratedProtoHeader "${CMAKE_CURRENT_BINARY_DIR}/Index.pb.h") set(GeneratedGRPCSource "${CMAKE_CURRENT_BINARY_DIR}/Index.grpc.pb.cc") set(GeneratedGRPCHeader "${CMAKE_CURRENT_BINARY_DIR}/Index.grpc.pb.h") + set(${GeneratedFilesLocation} ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE) add_custom_command( OUTPUT "${GeneratedProtoSource}" "${GeneratedProtoHeader}" "${GeneratedGRPCSource}" "${GeneratedGRPCHeader}" COMMAND ${PROTOC}