diff --git a/3party/protobuf-3.21.12/CMakeLists.txt b/3party/protobuf-3.21.12/CMakeLists.txt index 74d19e5..4bbdbcb 100644 --- a/3party/protobuf-3.21.12/CMakeLists.txt +++ b/3party/protobuf-3.21.12/CMakeLists.txt @@ -59,7 +59,7 @@ endif() option(protobuf_BUILD_TESTS "Build tests" OFF) option(protobuf_BUILD_CONFORMANCE "Build conformance tests" OFF) option(protobuf_BUILD_EXAMPLES "Build examples" OFF) -option(protobuf_BUILD_PROTOC_BINARIES "Build libprotoc and protoc compiler" OFF) +option(protobuf_BUILD_PROTOC_BINARIES "Build libprotoc and protoc compiler" ON) option(protobuf_BUILD_LIBPROTOC "Build libprotoc" OFF) option(protobuf_DISABLE_RTTI "Remove runtime type information in the binaries" OFF) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73dcf5b..b8298d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ option(SLED_BUILD_BENCHMARK "Build benchmark" OFF) option(SLED_BUILD_TESTS "Build tests" OFF) option(SLED_BUILD_FUZZ "Build fuzzer test" OFF) option(SLED_LOCATION_PATH "" "sled/src/sled/system/location.cc") +option(SLED_BUILD_PROTOC_PLUGIN "Build protoc plugin" OFF) set(BUILD_STATIC ON) set(BUILD_RTTR_DYNAMIC OFF) @@ -97,6 +98,7 @@ target_sources( target_link_libraries( sled PUBLIC rpc_core fmt marl Async++ minilua protobuf::libprotobuf + # protobuf::libprotoc PRIVATE dl # protobuf::libprotobuf ${WHOLE_ARCHIVE_WRAPPER_START} # tcmalloc_and_profiler_static ${WHOLE_ARCHIVE_WRAPPER_END} @@ -105,6 +107,10 @@ target_link_libraries( # set fPIC set_target_properties(sled PROPERTIES POSITION_INDEPENDENT_CODE ON) +if(SLED_BUILD_PROTOC_PLUGIN) + add_subdirectory(src/protoc_gen_sled) +endif() + if(SLED_BUILD_BENCHMARK) # if(NOT TARGET benchmark) find_package(mbenchmark REQUIRED) endif() diff --git a/src/protoc_gen_sled/CMakeLists.txt b/src/protoc_gen_sled/CMakeLists.txt new file mode 100644 index 0000000..7ec5718 --- /dev/null +++ b/src/protoc_gen_sled/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.10) + +project(protoc-gen-sled LANGUAGES C CXX) +add_executable(${PROJECT_NAME} main.cc sled_generator.cc) +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(${PROJECT_NAME} PRIVATE libprotoc sled) +install(TARGETS ${PROJECT_NAME} DESTINATION bin) diff --git a/src/protoc_gen_sled/main.cc b/src/protoc_gen_sled/main.cc new file mode 100644 index 0000000..daa0350 --- /dev/null +++ b/src/protoc_gen_sled/main.cc @@ -0,0 +1,17 @@ +#include "sled_generator.h" +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + google::protobuf::compiler::CommandLineInterface cli; + // google::protobuf::compiler::cpp::CppGenerator cpp_generator; + // cli.RegisterGenerator("--cpp_out", &cpp_generator, "Generate C++ source code."); + + sled::SledGenerator sled_generator; + cli.RegisterGenerator("--sled_out", &sled_generator, "sled cpp rpc generator"); + + return google::protobuf::compiler::PluginMain(argc, argv, &sled_generator); +} diff --git a/src/protoc_gen_sled/sled_generator.cc b/src/protoc_gen_sled/sled_generator.cc new file mode 100644 index 0000000..52646df --- /dev/null +++ b/src/protoc_gen_sled/sled_generator.cc @@ -0,0 +1,54 @@ +#include "sled_generator.h" +#include +#include +#include +#include +using namespace google::protobuf; +using namespace google::protobuf::compiler; +using namespace google::protobuf::io; + +namespace sled { + +void +PrintMessage(Printer &printer, const Descriptor *msg) +{ + printer.Print("- $name$\n", "name", msg->name()); + printer.Indent(); + for (int i = 0; i < msg->nested_type_count(); ++i) { PrintMessage(printer, msg->nested_type(i)); } + printer.Outdent(); +} + +void +PrintService(Printer &printer, const ServiceDescriptor *service) +{ + inja::json data; + data["classname"] = service->name(); + data["full_name"] = service->full_name(); + + printer.Print("- $name$\n", "name", service->full_name()); + printer.Indent(); + for (int i = 0; i < service->method_count(); i++) { + const MethodDescriptor *method = service->method(i); + printer.Print("- $name$\n", "name", method->name()); + printer.Indent(); + printer.Print("request: $name$ $file$\n", "name", method->input_type()->name(), "file", method->file()->name()); + printer + .Print("response: $name$ $file$\n", "name", method->output_type()->name(), "file", method->file()->name()); + printer.Outdent(); + } + printer.Outdent(); +} + +bool +SledGenerator::Generate(const FileDescriptor *file, + const std::string ¶meter, + GeneratorContext *generator_context, + std::string *error) const +{ + auto *out_stream = generator_context->Open(file->name() + ".txt"); + Printer printer(out_stream, '$'); + for (int i = 0; i < file->message_type_count(); i++) { PrintMessage(printer, file->message_type(i)); } + for (int i = 0; i < file->service_count(); i++) { PrintService(printer, file->service(i)); } + return true; +} +}// namespace sled diff --git a/src/protoc_gen_sled/sled_generator.h b/src/protoc_gen_sled/sled_generator.h new file mode 100644 index 0000000..aec8236 --- /dev/null +++ b/src/protoc_gen_sled/sled_generator.h @@ -0,0 +1,22 @@ +#ifndef SLED_SLED_GENERATOR_SLED_GENERATOR_H +#define SLED_SLED_GENERATOR_SLED_GENERATOR_H + +#pragma once +#include +#include + +using namespace google::protobuf; +using namespace google::protobuf::compiler; + +namespace sled { +class SledGenerator : public google::protobuf::compiler::CodeGenerator { +public: + ~SledGenerator() override = default; + bool Generate(const FileDescriptor *file, + const std::string ¶meter, + GeneratorContext *generator_context, + std::string *error) const override; +}; +}// namespace sled + +#endif// SLED_SLED_GENERATOR_SLED_GENERATOR_H diff --git a/src/sled/system/pid.cc b/src/sled/system/pid.cc index a2ea5e8..7d42829 100644 --- a/src/sled/system/pid.cc +++ b/src/sled/system/pid.cc @@ -1,7 +1,7 @@ #include "sled/system/pid.h" namespace sled { -pid_t +ProcessId GetCachedPID() { static pid_t cached_pid = getpid(); diff --git a/src/sled/system/pid.h b/src/sled/system/pid.h index 9d56be4..5a20c52 100644 --- a/src/sled/system/pid.h +++ b/src/sled/system/pid.h @@ -11,6 +11,12 @@ typedef unsigned long pid_t; #endif namespace sled { -pid_t GetCachedPID(); +#ifdef _WIN32 +typedef unsigned long ProcessId; +#else +typedef pid_t ProcessId; +#endif + +ProcessId GetCachedPID(); }// namespace sled #endif// SLED_SYSTEM_PID_H diff --git a/src/sled/system/process.cc b/src/sled/system/process.cc new file mode 100644 index 0000000..a012403 --- /dev/null +++ b/src/sled/system/process.cc @@ -0,0 +1,8 @@ +#include "sled/system/process.h" + +namespace sled { +Process::Process(const Option &option) : option(option) {} + +Process::~Process() noexcept { CloseAllFileDescriptors(); } + +}// namespace sled diff --git a/src/sled/system/process.h b/src/sled/system/process.h new file mode 100644 index 0000000..e611dde --- /dev/null +++ b/src/sled/system/process.h @@ -0,0 +1,79 @@ +#ifndef SLED_SLED_SYSTEM_PROCESS_H +#define SLED_SLED_SYSTEM_PROCESS_H + +#pragma once +#include "sled/optional.h" +#include "sled/synchronization/mutex.h" +#include "sled/system/pid.h" +#include +#include +#include +#include + +namespace sled { +class Process { +public: + using ByteReader = std::function; + + struct Option { + std::vector cmd_args; + std::string working_dir; + std::map envs; + ByteReader stdout_reader = nullptr; + ByteReader stderr_reader = nullptr; + bool open_stdin = false; + std::size_t stout_buffer_size = 128 * 1024; + std::size_t stderr_buffer_size = 128 * 1024; + bool inherit_file_descriptors = false; + }; + + struct Builder { + Builder &SetCmdArgs(const std::vector &args); + Builder &AppendCmdArg(const std::string &arg); + Builder &SetEnvs(const std::map &env); + Builder &AppendEnv(const std::string &key, const std::string &value); + + Builder &SetWorkingDir(const std::string &dir); + Builder &SetStdoutReader(ByteReader reader); + Builder &SetStderrReader(ByteReader reader); + Builder &SetOpenStdin(bool open); + Builder &SetStdoutBufferSize(std::size_t size); + Builder &SetStderrBufferSize(std::size_t size); + Builder &SetInheritFileDescriptors(bool inherit); + Process Build(); + + private: + Option option; + }; + +public: + Process(const Option &option); + ~Process() noexcept; + + ProcessId id() const noexcept { return id_; } + + sled::optional exit_status() noexcept; + void CloseStdin() noexcept; + void Kill(bool force = false) noexcept; + void Signal(int signal) noexcept; + std::size_t Write(const char *data, std::size_t size); + std::size_t Write(const std::string &data); + +public: + static void Kill(ProcessId id, bool force = false) noexcept; + static void Signal(ProcessId id, int signal) noexcept; + +private: + void CloseAllFileDescriptors() noexcept; + + const Option option; + ProcessId id_; + + std::unique_ptr stdout_fd_; + std::unique_ptr stderr_fd_; + std::unique_ptr stdin_fd_; + Option option_; +}; +}// namespace sled + +#endif// SLED_SLED_SYSTEM_PROCESS_H diff --git a/src/sled/system/process_unix.cc b/src/sled/system/process_unix.cc new file mode 100644 index 0000000..e69de29