diff --git a/bootstrap/include/bootstrap/build_buildcc.h b/bootstrap/include/bootstrap/build_buildcc.h index e8fb8110..da4cc9f1 100644 --- a/bootstrap/include/bootstrap/build_buildcc.h +++ b/bootstrap/include/bootstrap/build_buildcc.h @@ -30,10 +30,7 @@ namespace buildcc { -void schema_gen_cb(FileGenerator &generator, const BaseTarget &flatc_exe); - -void buildcc_cb(BaseTarget &target, const FileGenerator &schema_gen, - const TargetInfo &flatbuffers_ho, +void buildcc_cb(BaseTarget &target, const TargetInfo &flatbuffers_ho, const TargetInfo &nlohmann_json_ho, const TargetInfo &fmt_ho, const TargetInfo &spdlog_ho, const TargetInfo &cli11_ho, const TargetInfo &taskflow_ho, const TargetInfo &tl_optional_ho, @@ -57,9 +54,6 @@ class BuildBuildCC { // Executable static constexpr const char *const kFlatcExeName = "flatc"; - // Generator - static constexpr const char *const kSchemaGenName = "schema_gen"; - // Libraries static constexpr const char *const kTplLibName = "libtpl"; static constexpr const char *const kBuildccLibName = "libbuildcc"; @@ -86,9 +80,6 @@ class BuildBuildCC { ExecutableTarget_generic &GetFlatc() { return storage_.Ref(kFlatcExeName); } - FileGenerator &GetSchemaGen() { - return storage_.Ref(kSchemaGenName); - } TargetInfo &GetFlatbuffersHo() { return storage_.Ref(kFlatbuffersHoName); } diff --git a/bootstrap/src/build_buildcc.cpp b/bootstrap/src/build_buildcc.cpp index 8e72841d..662e0728 100644 --- a/bootstrap/src/build_buildcc.cpp +++ b/bootstrap/src/build_buildcc.cpp @@ -18,37 +18,13 @@ namespace buildcc { -void schema_gen_cb(FileGenerator &generator, const BaseTarget &flatc_exe) { - generator.AddPattern("path_fbs", "{current_root_dir}/path.fbs"); - generator.AddPattern("target_fbs", "{current_root_dir}/target.fbs"); - - generator.AddInput("{path_fbs}"); - generator.AddInput("{target_fbs}"); - - generator.AddOutput("{current_build_dir}/path_generated.h"); - generator.AddOutput("{current_build_dir}/target_generated.h"); - - generator.AddPatterns({ - {"flatc_compiler", fmt::format("{}", flatc_exe.GetTargetPath())}, - }); - // generator.AddCommand("{flatc_compiler} --help"); - generator.AddCommand("{flatc_compiler} -o {current_build_dir} -I " - "{current_root_dir} --gen-object-api " - "--cpp {path_fbs} {target_fbs}"); - - generator.Build(); -} - -void buildcc_cb(BaseTarget &target, const FileGenerator &schema_gen, - const TargetInfo &flatbuffers_ho, +void buildcc_cb(BaseTarget &target, const TargetInfo &flatbuffers_ho, const TargetInfo &nlohmann_json_ho, const TargetInfo &fmt_ho, const TargetInfo &spdlog_ho, const TargetInfo &cli11_ho, const TargetInfo &taskflow_ho, const TargetInfo &tl_optional_ho, const BaseTarget &tpl) { // NOTE, Build as single lib target.AddIncludeDir("", true); - const std::string &schema_build_dir = schema_gen.Get("current_build_dir"); - target.AddIncludeDirAbsolute(schema_build_dir, true); // ENV target.GlobSources("lib/env/src"); @@ -60,7 +36,6 @@ void buildcc_cb(BaseTarget &target, const FileGenerator &schema_gen, target.AddIncludeDir("schema/include"); target.GlobHeaders("schema/include/schema"); target.GlobHeaders("schema/include/schema/interface"); - target.GlobHeaders("schema/include/schema/private"); // TOOLCHAIN target.GlobSources("lib/toolchain/src/api"); @@ -205,12 +180,6 @@ void BuildBuildCC::Initialize() { TargetEnv(env_.GetTargetRootDir() / "third_party" / "flatbuffers", env_.GetTargetBuildDir())); - // Schema - (void)storage_.Add( - kSchemaGenName, kSchemaGenName, - TargetEnv(env_.GetTargetRootDir() / "buildcc" / "schema", - env_.GetTargetBuildDir() / toolchain_.GetName())); - // Flatbuffers HO lib (void)storage_.Add( kFlatbuffersHoName, toolchain_, @@ -271,8 +240,6 @@ void BuildBuildCC::Initialize() { } void BuildBuildCC::Setup(const ArgToolchainState &state) { - auto &flatc_exe = GetFlatc(); - auto &schema_gen = GetSchemaGen(); auto &flatbuffers_ho_lib = GetFlatbuffersHo(); auto &nlohmann_json_ho_lib = GetNlohmannJsonHo(); auto &cli11_ho_lib = GetCli11Ho(); @@ -283,10 +250,6 @@ void BuildBuildCC::Setup(const ArgToolchainState &state) { auto &tpl_lib = GetTpl(); auto &buildcc_lib = GetBuildcc(); Reg::Toolchain(state) - .Func(global_flags_cb, flatc_exe, toolchain_) - .Build(build_flatc_exe_cb, flatc_exe) - .Build(schema_gen_cb, schema_gen, flatc_exe) - .Dep(schema_gen, flatc_exe) .Func(flatbuffers_ho_cb, flatbuffers_ho_lib) .Func(nlohmann_json_ho_cb, nlohmann_json_ho_lib) .Func(cli11_ho_cb, cli11_ho_lib) @@ -297,10 +260,9 @@ void BuildBuildCC::Setup(const ArgToolchainState &state) { .Func(global_flags_cb, tpl_lib, toolchain_) .Build(tpl_cb, tpl_lib) .Func(global_flags_cb, buildcc_lib, toolchain_) - .Build(buildcc_cb, buildcc_lib, schema_gen, flatbuffers_ho_lib, - nlohmann_json_ho_lib, fmt_ho_lib, spdlog_ho_lib, cli11_ho_lib, - taskflow_ho_lib, tl_optional_ho_lib, tpl_lib) - .Dep(buildcc_lib, schema_gen) + .Build(buildcc_cb, buildcc_lib, flatbuffers_ho_lib, nlohmann_json_ho_lib, + fmt_ho_lib, spdlog_ho_lib, cli11_ho_lib, taskflow_ho_lib, + tl_optional_ho_lib, tpl_lib) .Dep(buildcc_lib, tpl_lib); } diff --git a/buildcc/schema/CMakeLists.txt b/buildcc/schema/CMakeLists.txt index 6883e1a5..2f953e53 100644 --- a/buildcc/schema/CMakeLists.txt +++ b/buildcc/schema/CMakeLists.txt @@ -1,2 +1 @@ -include(cmake/schema_generate.cmake) include(cmake/schema.cmake) diff --git a/buildcc/schema/cmake/schema.cmake b/buildcc/schema/cmake/schema.cmake index aa48d13f..20ba85cf 100644 --- a/buildcc/schema/cmake/schema.cmake +++ b/buildcc/schema/cmake/schema.cmake @@ -1,7 +1,6 @@ # schema test if (${TESTING}) add_library(mock_schema STATIC - include/schema/private/schema_util.h include/schema/interface/serialization_interface.h include/schema/path.h @@ -11,6 +10,7 @@ if (${TESTING}) include/schema/custom_generator_serialization.h src/target_serialization.cpp + include/schema/target_schema.h include/schema/target_serialization.h ) target_include_directories(mock_schema PUBLIC @@ -27,7 +27,6 @@ if (${TESTING}) CppUTestExt ${TEST_LINK_LIBS} ) - add_dependencies(mock_schema fbs_to_header) target_compile_options(mock_schema PUBLIC ${TEST_COMPILE_FLAGS} ${BUILD_COMPILE_FLAGS}) target_link_options(mock_schema PUBLIC ${TEST_LINK_FLAGS} ${BUILD_LINK_FLAGS}) @@ -38,21 +37,30 @@ if (${TESTING}) ) target_link_libraries(test_custom_generator_serialization PRIVATE mock_schema) + add_executable(test_target_serialization + test/test_target_serialization.cpp + ) + target_link_libraries(test_target_serialization PRIVATE mock_schema) + add_test(NAME test_custom_generator_serialization COMMAND test_custom_generator_serialization WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test ) + add_test(NAME test_target_serialization COMMAND test_target_serialization + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test + ) endif() set(SCHEMA_SRCS - include/schema/private/schema_util.h include/schema/interface/serialization_interface.h include/schema/path.h src/custom_generator_serialization.cpp + include/schema/custom_generator_schema.h include/schema/custom_generator_serialization.h src/target_serialization.cpp + include/schema/target_schema.h include/schema/target_serialization.h ) @@ -67,7 +75,6 @@ if(${BUILDCC_BUILD_AS_SINGLE_LIB}) target_include_directories(buildcc PRIVATE ${SCHEMA_BUILD_DIR} ) - add_dependencies(buildcc fbs_to_header) endif() if(${BUILDCC_BUILD_AS_INTERFACE}) @@ -89,7 +96,6 @@ if(${BUILDCC_BUILD_AS_INTERFACE}) ) target_compile_options(schema PRIVATE ${BUILD_COMPILE_FLAGS}) target_link_options(schema PRIVATE ${BUILD_LINK_FLAGS}) - add_dependencies(schema fbs_to_header) endif() if (${BUILDCC_INSTALL}) diff --git a/buildcc/schema/cmake/schema_generate.cmake b/buildcc/schema/cmake/schema_generate.cmake deleted file mode 100644 index c1a6b604..00000000 --- a/buildcc/schema/cmake/schema_generate.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# Generate files -set(SCHEMA_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated CACHE PATH "Generate path of flatbuffer schema") - -set(FBS_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/path.fbs - ${CMAKE_CURRENT_SOURCE_DIR}/target.fbs -) -set(FBS_GEN_FILES - ${SCHEMA_BUILD_DIR}/path_generated.h - ${SCHEMA_BUILD_DIR}/target_generated.h -) -set(FBS_GEN_OPTIONS - -I ${CMAKE_CURRENT_SOURCE_DIR} - --gen-object-api -) - -add_custom_command(OUTPUT ${FBS_GEN_FILES} - COMMAND flatc -o ${SCHEMA_BUILD_DIR} ${FBS_GEN_OPTIONS} --cpp ${FBS_FILES} - DEPENDS flatc ${FBS_FILES} -) - -add_custom_target(fbs_to_header - DEPENDS ${FBS_GEN_FILES} -) diff --git a/buildcc/schema/include/schema/custom_generator_schema.h b/buildcc/schema/include/schema/custom_generator_schema.h index a7058e3e..0a171f2c 100644 --- a/buildcc/schema/include/schema/custom_generator_schema.h +++ b/buildcc/schema/include/schema/custom_generator_schema.h @@ -25,18 +25,18 @@ namespace buildcc::internal { struct CustomGeneratorSchema { private: - static constexpr const char *const kSchemaName = "name"; - static constexpr const char *const kIdsName = "ids"; - static constexpr const char *const kGroupsName = "groups"; + static constexpr const char *const kName = "name"; + static constexpr const char *const kIds = "ids"; + static constexpr const char *const kGroups = "groups"; public: using IdKey = std::string; using GroupKey = std::string; struct IdInfo { private: - static constexpr const char *const kInputsName = "inputs"; - static constexpr const char *const kOutputsName = "outputs"; - static constexpr const char *const kUserblobName = "userblob"; + static constexpr const char *const kInputs = "inputs"; + static constexpr const char *const kOutputs = "outputs"; + static constexpr const char *const kUserblob = "userblob"; public: path_unordered_set internal_inputs; @@ -44,15 +44,15 @@ struct CustomGeneratorSchema { std::vector userblob; friend void to_json(json &j, const IdInfo &info) { - j[kInputsName] = info.internal_inputs; - j[kOutputsName] = info.outputs; - j[kUserblobName] = info.userblob; + j[kInputs] = info.internal_inputs; + j[kOutputs] = info.outputs; + j[kUserblob] = info.userblob; } friend void from_json(const json &j, IdInfo &info) { - j.at(kInputsName).get_to(info.internal_inputs); - j.at(kOutputsName).get_to(info.outputs); - j.at(kUserblobName).get_to(info.userblob); + j.at(kInputs).get_to(info.internal_inputs); + j.at(kOutputs).get_to(info.outputs); + j.at(kUserblob).get_to(info.userblob); } }; @@ -65,15 +65,15 @@ struct CustomGeneratorSchema { std::unordered_map internal_groups; friend void to_json(json &j, const CustomGeneratorSchema &schema) { - j[kSchemaName] = schema.name; - j[kIdsName] = schema.internal_ids; - j[kGroupsName] = schema.internal_groups; + j[kName] = schema.name; + j[kIds] = schema.internal_ids; + j[kGroups] = schema.internal_groups; } friend void from_json(const json &j, CustomGeneratorSchema &schema) { - j.at(kSchemaName).get_to(schema.name); - j.at(kIdsName).get_to(schema.internal_ids); - j.at(kGroupsName).get_to(schema.internal_groups); + j.at(kName).get_to(schema.name); + j.at(kIds).get_to(schema.internal_ids); + j.at(kGroups).get_to(schema.internal_groups); } }; diff --git a/buildcc/schema/include/schema/private/schema_util.h b/buildcc/schema/include/schema/private/schema_util.h deleted file mode 100644 index 3a826016..00000000 --- a/buildcc/schema/include/schema/private/schema_util.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2021-2022 Niket Naidu. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SCHEMA_PRIVATE_SCHEMA_UTIL_H_ -#define SCHEMA_PRIVATE_SCHEMA_UTIL_H_ - -#include "path_generated.h" - -#include - -#include "schema/path.h" - -namespace fbs = schema::internal; - -namespace buildcc::internal { - -// extract APIs for LOAD - -inline void extract_path( - const flatbuffers::Vector> - *fbs_paths, - path_unordered_set &out) { - if (fbs_paths == nullptr) { - return; - } - - for (auto iter = fbs_paths->begin(); iter != fbs_paths->end(); iter++) { - out.insert(Path(iter->pathname()->c_str(), iter->last_write_timestamp())); - } -} - -inline void extract_path( - const flatbuffers::Vector> - *fbs_paths, - std::vector &out) { - if (fbs_paths == nullptr) { - return; - } - - for (auto iter = fbs_paths->begin(); iter != fbs_paths->end(); iter++) { - out.push_back( - Path(iter->pathname()->c_str(), iter->last_write_timestamp())); - } -} - -inline void extract(const flatbuffers::Vector *fbs_data, - std::vector &out) { - if (fbs_data == nullptr) { - return; - } - - for (auto iter = fbs_data->begin(); iter != fbs_data->end(); iter++) { - out.push_back(*iter); - } -} - -inline void -extract(const flatbuffers::Vector> - *fbs_paths, - fs_unordered_set &out) { - if (fbs_paths == nullptr) { - return; - } - - for (auto iter = fbs_paths->begin(); iter != fbs_paths->end(); iter++) { - out.insert(iter->str()); - } -} - -template -inline void -extract(const flatbuffers::Vector> - *fbs_paths, - std::unordered_set &out) { - if (fbs_paths == nullptr) { - return; - } - - for (auto iter = fbs_paths->begin(); iter != fbs_paths->end(); iter++) { - out.insert(iter->str()); - } -} - -template -inline void -extract(const flatbuffers::Vector> - *fbs_paths, - std::vector &out) { - if (fbs_paths == nullptr) { - return; - } - - for (auto iter = fbs_paths->begin(); iter != fbs_paths->end(); iter++) { - out.push_back(iter->str()); - } -} - -// Create APIs for STORE - -template -inline std::vector> -create_fbs_vector_path(flatbuffers::FlatBufferBuilder &builder, - const T &pathlist) { - std::vector> paths; - for (const auto &p : pathlist) { - auto fbs_file = fbs::CreatePathDirect(builder, p.GetPathAsString().c_str(), - p.last_write_timestamp); - paths.push_back(fbs_file); - } - return paths; -} - -template -inline std::vector> -create_fbs_vector_string(flatbuffers::FlatBufferBuilder &builder, - const T &strlist) { - std::vector> strs; - std::transform( - strlist.begin(), strlist.end(), std::back_inserter(strs), - [&](const std::string &str) -> flatbuffers::Offset { - return builder.CreateString(str); - }); - return strs; -} - -inline std::vector> -create_fbs_vector_string(flatbuffers::FlatBufferBuilder &builder, - const buildcc::fs_unordered_set &fslist) { - std::vector> strs; - std::transform( - fslist.begin(), fslist.end(), std::back_inserter(strs), - [&](const fs::path &p) -> flatbuffers::Offset { - return builder.CreateString(path_as_string(p)); - }); - return strs; -} - -} // namespace buildcc::internal - -#endif diff --git a/buildcc/schema/include/schema/target_schema.h b/buildcc/schema/include/schema/target_schema.h new file mode 100644 index 00000000..f1cae3f0 --- /dev/null +++ b/buildcc/schema/include/schema/target_schema.h @@ -0,0 +1,142 @@ +/* + * Copyright 2021-2022 Niket Naidu. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SCHEMA_TARGET_SCHEMA_H_ +#define SCHEMA_TARGET_SCHEMA_H_ + +#include +#include + +#include "schema/path.h" +#include "schema/target_type.h" + +namespace buildcc::internal { + +struct TargetSchema { + std::string name; + TargetType type{TargetType::Undefined}; + + path_unordered_set internal_sources; + path_unordered_set internal_headers; + path_unordered_set internal_pchs; + std::vector internal_libs; + std::vector external_libs; + + fs_unordered_set include_dirs; + fs_unordered_set lib_dirs; + + std::unordered_set preprocessor_flags; + std::unordered_set common_compile_flags; + std::unordered_set pch_compile_flags; + std::unordered_set pch_object_flags; + std::unordered_set asm_compile_flags; + std::unordered_set c_compile_flags; + std::unordered_set cpp_compile_flags; + std::unordered_set link_flags; + + path_unordered_set internal_compile_dependencies; + path_unordered_set internal_link_dependencies; + + bool pch_compiled{false}; + bool target_linked{false}; + +private: + static constexpr const char *const kName = "name"; + static constexpr const char *const kType = "type"; + + static constexpr const char *const kSources = "sources"; + static constexpr const char *const kHeaders = "headers"; + static constexpr const char *const kPchs = "pchs"; + static constexpr const char *const kLibs = "libs"; + static constexpr const char *const kExternalLibs = "external_libs"; + + static constexpr const char *const kIncludeDirs = "include_dirs"; + static constexpr const char *const kLibDirs = "lib_dirs"; + + static constexpr const char *const kPreprocessorFlags = "preprocessor_flags"; + static constexpr const char *const kCommonCompileFlags = + "common_compile_flags"; + static constexpr const char *const kPchCompileFlags = "pch_compile_flags"; + static constexpr const char *const kPchObjectFlags = "pch_object_flags"; + static constexpr const char *const kAsmCompileFlags = "asm_compile_flags"; + static constexpr const char *const kCCompileFlags = "c_compile_flags"; + static constexpr const char *const kCppCompileFlags = "cpp_compile_flags"; + static constexpr const char *const kLinkFlags = "link_flags"; + + static constexpr const char *const kCompileDependencies = + "compile_dependencies"; + static constexpr const char *const kLinkDependencies = "link_dependencies"; + + static constexpr const char *const kPchCompiled = "pch_compiled"; + static constexpr const char *const kTargetLinked = "target_linked"; + +public: + friend void to_json(json &j, const TargetSchema &schema) { + j[kName] = schema.name; + j[kType] = schema.type; + j[kSources] = schema.internal_sources; + j[kHeaders] = schema.internal_headers; + j[kPchs] = schema.internal_pchs; + j[kLibs] = schema.internal_libs; + j[kExternalLibs] = schema.external_libs; + j[kIncludeDirs] = schema.include_dirs; + j[kLibDirs] = schema.lib_dirs; + + j[kPreprocessorFlags] = schema.preprocessor_flags; + j[kCommonCompileFlags] = schema.common_compile_flags; + j[kPchCompileFlags] = schema.pch_compile_flags; + j[kPchObjectFlags] = schema.pch_object_flags; + j[kAsmCompileFlags] = schema.asm_compile_flags; + j[kCCompileFlags] = schema.c_compile_flags; + j[kCppCompileFlags] = schema.cpp_compile_flags; + j[kLinkFlags] = schema.link_flags; + + j[kCompileDependencies] = schema.internal_compile_dependencies; + j[kLinkDependencies] = schema.internal_link_dependencies; + j[kPchCompiled] = schema.pch_compiled; + j[kTargetLinked] = schema.target_linked; + } + + friend void from_json(const json &j, TargetSchema &schema) { + j.at(kName).get_to(schema.name); + j.at(kType).get_to(schema.type); + j.at(kSources).get_to(schema.internal_sources); + j.at(kHeaders).get_to(schema.internal_headers); + j.at(kPchs).get_to(schema.internal_pchs); + j.at(kLibs).get_to(schema.internal_libs); + j.at(kExternalLibs).get_to(schema.external_libs); + j.at(kIncludeDirs).get_to(schema.include_dirs); + j.at(kLibDirs).get_to(schema.lib_dirs); + + j.at(kPreprocessorFlags).get_to(schema.preprocessor_flags); + j.at(kCommonCompileFlags).get_to(schema.common_compile_flags); + j.at(kPchCompileFlags).get_to(schema.pch_compile_flags); + j.at(kPchObjectFlags).get_to(schema.pch_object_flags); + j.at(kAsmCompileFlags).get_to(schema.asm_compile_flags); + j.at(kCCompileFlags).get_to(schema.c_compile_flags); + j.at(kCppCompileFlags).get_to(schema.cpp_compile_flags); + j.at(kLinkFlags).get_to(schema.link_flags); + + j.at(kCompileDependencies).get_to(schema.internal_compile_dependencies); + j.at(kLinkDependencies).get_to(schema.internal_link_dependencies); + j.at(kPchCompiled).get_to(schema.pch_compiled); + j.at(kTargetLinked).get_to(schema.target_linked); + } +}; + +} // namespace buildcc::internal + +#endif diff --git a/buildcc/schema/include/schema/target_serialization.h b/buildcc/schema/include/schema/target_serialization.h index e4869f3b..bc5116a3 100644 --- a/buildcc/schema/include/schema/target_serialization.h +++ b/buildcc/schema/include/schema/target_serialization.h @@ -20,41 +20,12 @@ #include #include "schema/path.h" -#include "schema/target_type.h" +#include "schema/target_schema.h" #include "schema/interface/serialization_interface.h" namespace buildcc::internal { -struct TargetSchema { - std::string name; - TargetType type{TargetType::Undefined}; - - path_unordered_set internal_sources; - path_unordered_set internal_headers; - path_unordered_set internal_pchs; - std::vector internal_libs; - std::vector external_libs; - - fs_unordered_set include_dirs; - fs_unordered_set lib_dirs; - - std::unordered_set preprocessor_flags; - std::unordered_set common_compile_flags; - std::unordered_set pch_compile_flags; - std::unordered_set pch_object_flags; - std::unordered_set asm_compile_flags; - std::unordered_set c_compile_flags; - std::unordered_set cpp_compile_flags; - std::unordered_set link_flags; - - path_unordered_set internal_compile_dependencies; - path_unordered_set internal_link_dependencies; - - bool pch_compiled{false}; - bool target_linked{false}; -}; - class TargetSerialization : public SerializationInterface { public: TargetSerialization(const fs::path &serialized_file) diff --git a/buildcc/schema/include/schema/target_type.h b/buildcc/schema/include/schema/target_type.h index 866b030b..2871551a 100644 --- a/buildcc/schema/include/schema/target_type.h +++ b/buildcc/schema/include/schema/target_type.h @@ -17,6 +17,10 @@ #ifndef SCHEMA_TARGET_TYPE_H_ #define SCHEMA_TARGET_TYPE_H_ +#include +#include +#include + namespace buildcc { enum class TargetType { @@ -26,6 +30,37 @@ enum class TargetType { Undefined, ///< Undefined target type }; +constexpr std::array, 3> + kTargetTypeInfo{ + std::make_pair("executable", TargetType::Executable), + std::make_pair("static_library", TargetType::StaticLibrary), + std::make_pair("dynamic_library", TargetType::DynamicLibrary), + }; + +template void to_json(JsonType &j, TargetType type) { + j = nullptr; + auto iter = std::find_if(kTargetTypeInfo.cbegin(), kTargetTypeInfo.cend(), + [type](const auto &p) { return p.second == type; }); + if (iter != kTargetTypeInfo.cend()) { + j = iter->first; + } } +template +void from_json(const JsonType &j, TargetType &type) { + type = TargetType::Undefined; + if (j.is_string()) { + std::string name; + j.get_to(name); + auto iter = + std::find_if(kTargetTypeInfo.cbegin(), kTargetTypeInfo.cend(), + [&name](const auto &p) { return p.first == name; }); + if (iter != kTargetTypeInfo.cend()) { + type = iter->second; + } + } +} + +} // namespace buildcc + #endif diff --git a/buildcc/schema/path.fbs b/buildcc/schema/path.fbs deleted file mode 100644 index 3407649e..00000000 --- a/buildcc/schema/path.fbs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2021-2022 Niket Naidu. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace schema.internal; - -table Path { - pathname:string (key); - last_write_timestamp:uint64; -} diff --git a/buildcc/schema/src/target_serialization.cpp b/buildcc/schema/src/target_serialization.cpp index 68fdaa24..9e447893 100644 --- a/buildcc/schema/src/target_serialization.cpp +++ b/buildcc/schema/src/target_serialization.cpp @@ -16,15 +16,6 @@ #include "schema/target_serialization.h" -// Third party -#include "flatbuffers/flatbuffers.h" - -// Private -#include "schema/private/schema_util.h" - -// Schema generated -#include "target_generated.h" - namespace buildcc::internal { // PUBLIC @@ -32,8 +23,9 @@ void TargetSerialization::UpdatePchCompiled(const TargetSchema &store) { store_.internal_pchs = store.internal_pchs; store_.pch_compiled = true; } + void TargetSerialization::AddSource(const internal::Path &source) { - std::lock_guard guard(add_source_mutex); + std::scoped_lock guard(add_source_mutex); store_.internal_sources.insert(source); } @@ -52,102 +44,30 @@ void TargetSerialization::UpdateStore(const TargetSchema &store) { // PRIVATE bool TargetSerialization::Verify(const std::string &serialized_data) { - flatbuffers::Verifier verifier((const uint8_t *)serialized_data.c_str(), - serialized_data.length()); - return fbs::VerifyTargetBuffer(verifier); + (void)serialized_data; + return true; } bool TargetSerialization::Load(const std::string &serialized_data) { - const auto *target = fbs::GetTarget((const void *)serialized_data.c_str()); - if (target == nullptr) { - return false; + json j = json::parse(serialized_data, nullptr, false); + bool loaded = !j.is_discarded(); + + if (loaded) { + try { + load_ = j.get(); + } catch (const std::exception &e) { + env::log_critical(__FUNCTION__, e.what()); + loaded = false; + } } - - extract_path(target->source_files(), load_.internal_sources); - extract_path(target->header_files(), load_.internal_headers); - extract_path(target->pch_files(), load_.internal_pchs); - extract_path(target->lib_deps(), load_.internal_libs); - - extract(target->external_lib_deps(), load_.external_libs); - - extract(target->include_dirs(), load_.include_dirs); - extract(target->lib_dirs(), load_.lib_dirs); - - extract(target->preprocessor_flags(), load_.preprocessor_flags); - extract(target->common_compile_flags(), load_.common_compile_flags); - extract(target->pch_compile_flags(), load_.pch_compile_flags); - extract(target->pch_object_flags(), load_.pch_object_flags); - extract(target->asm_compile_flags(), load_.asm_compile_flags); - extract(target->c_compile_flags(), load_.c_compile_flags); - extract(target->cpp_compile_flags(), load_.cpp_compile_flags); - extract(target->link_flags(), load_.link_flags); - - extract_path(target->compile_dependencies(), - load_.internal_compile_dependencies); - extract_path(target->link_dependencies(), load_.internal_link_dependencies); - - load_.pch_compiled = target->pch_compiled(); - load_.target_linked = target->target_linked(); - return true; + return loaded; } bool TargetSerialization::Store(const fs::path &absolute_serialized_file) { - flatbuffers::FlatBufferBuilder builder; - - auto fbs_target_type = (fbs::TargetType)store_.type; - - auto fbs_source_files = - internal::create_fbs_vector_path(builder, store_.internal_sources); - auto fbs_header_files = - internal::create_fbs_vector_path(builder, store_.internal_headers); - auto fbs_pch_files = - internal::create_fbs_vector_path(builder, store_.internal_pchs); - - auto fbs_lib_deps = - internal::create_fbs_vector_path(builder, store_.internal_libs); - auto fbs_external_lib_deps = - internal::create_fbs_vector_string(builder, store_.external_libs); - - auto fbs_include_dirs = - internal::create_fbs_vector_string(builder, store_.include_dirs); - auto fbs_lib_dirs = - internal::create_fbs_vector_string(builder, store_.lib_dirs); - - auto fbs_preprocessor_flags = - internal::create_fbs_vector_string(builder, store_.preprocessor_flags); - auto fbs_common_compile_flags = - internal::create_fbs_vector_string(builder, store_.common_compile_flags); - auto fbs_pch_compile_flags = - internal::create_fbs_vector_string(builder, store_.pch_compile_flags); - auto fbs_pch_object_flags = - internal::create_fbs_vector_string(builder, store_.pch_object_flags); - auto fbs_asm_compile_flags = - internal::create_fbs_vector_string(builder, store_.asm_compile_flags); - auto fbs_c_compile_flags = - internal::create_fbs_vector_string(builder, store_.c_compile_flags); - auto fbs_cpp_compile_flags = - internal::create_fbs_vector_string(builder, store_.cpp_compile_flags); - auto fbs_link_flags = - internal::create_fbs_vector_string(builder, store_.link_flags); - - auto fbs_compile_dependencies = internal::create_fbs_vector_path( - builder, store_.internal_compile_dependencies); - auto fbs_link_dependencies = internal::create_fbs_vector_path( - builder, store_.internal_link_dependencies); - - auto fbs_target = fbs::CreateTargetDirect( - builder, store_.name.c_str(), fbs_target_type, &fbs_source_files, - &fbs_header_files, &fbs_pch_files, &fbs_lib_deps, &fbs_external_lib_deps, - &fbs_include_dirs, &fbs_lib_dirs, &fbs_preprocessor_flags, - &fbs_common_compile_flags, &fbs_pch_compile_flags, &fbs_pch_object_flags, - &fbs_asm_compile_flags, &fbs_c_compile_flags, &fbs_cpp_compile_flags, - &fbs_link_flags, &fbs_compile_dependencies, &fbs_link_dependencies, - store_.pch_compiled, store_.target_linked); - fbs::FinishTargetBuffer(builder, fbs_target); - - return env::save_file(path_as_string(absolute_serialized_file).c_str(), - (const char *)builder.GetBufferPointer(), - builder.GetSize(), true); + json j = store_; + auto data = j.dump(4); + return env::save_file(path_as_string(absolute_serialized_file).c_str(), data, + false); } } // namespace buildcc::internal diff --git a/buildcc/schema/target.fbs b/buildcc/schema/target.fbs deleted file mode 100644 index 0eff9a0e..00000000 --- a/buildcc/schema/target.fbs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2021-2022 Niket Naidu. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -include "path.fbs"; - -namespace schema.internal; - -enum TargetType : byte { - Executable, - StaticLibrary, - DynamicLibrary -} - -// TODO, Check if Toolchain needs to be added to Target -table Target { - // Metadata - name:string (key); - type:TargetType; - - // Input - // Files - source_files:[Path]; - header_files:[Path]; - pch_files:[Path]; - lib_deps:[Path]; - - // Links - external_lib_deps:[string]; - - // Directories - include_dirs:[string]; - lib_dirs:[string]; - - // Flags - preprocessor_flags:[string]; - common_compile_flags:[string]; - pch_compile_flags:[string]; - pch_object_flags:[string]; - asm_compile_flags:[string]; - c_compile_flags:[string]; - cpp_compile_flags:[string]; - link_flags:[string]; - - // Additional dependencies - compile_dependencies:[Path]; - link_dependencies:[Path]; - - // Output - // Does not need to be stored - - // State - pch_compiled:bool; - target_linked:bool; -} - -root_type Target; diff --git a/buildcc/schema/test/test_custom_generator_serialization.cpp b/buildcc/schema/test/test_custom_generator_serialization.cpp index 3c215257..e7411470 100644 --- a/buildcc/schema/test/test_custom_generator_serialization.cpp +++ b/buildcc/schema/test/test_custom_generator_serialization.cpp @@ -1,9 +1,5 @@ #include "schema/custom_generator_serialization.h" -#include "schema/private/schema_util.h" - -#include "flatbuffers/flatbuffers.h" - // NOTE, Make sure all these includes are AFTER the system and header includes #include "CppUTest/CommandLineTestRunner.h" #include "CppUTest/MemoryLeakDetectorNewMacros.h" @@ -24,7 +20,7 @@ TEST(CustomGeneratorSerializationTestGroup, JsonParse_Failure) { { // JSON Parse fails buildcc::internal::CustomGeneratorSerialization serialization( - "dump/JsonParseFailure.json"); + "dump/CustomGeneratorJsonParseFailure.json"); buildcc::env::save_file(serialization.GetSerializedFile().string().c_str(), std::string(""), false); @@ -35,7 +31,7 @@ TEST(CustomGeneratorSerializationTestGroup, JsonParse_Failure) { { // Custom Generator Schema conversion fails buildcc::internal::CustomGeneratorSerialization serialization( - "dump/JsonParseFailure.json"); + "dump/CustomGeneratorJsonParseFailure.json"); auto data = R"({"name": ""})"; buildcc::env::save_file(serialization.GetSerializedFile().string().c_str(), @@ -47,7 +43,7 @@ TEST(CustomGeneratorSerializationTestGroup, JsonParse_Failure) { TEST(CustomGeneratorSerializationTestGroup, FormatEmptyCheck) { buildcc::internal::CustomGeneratorSerialization serialization( - "dump/FormatEmptyCheck.json"); + "dump/CustomGeneratorFormatEmptyCheck.json"); bool stored = serialization.StoreToFile(); CHECK_TRUE(stored); @@ -56,13 +52,13 @@ TEST(CustomGeneratorSerializationTestGroup, FormatEmptyCheck) { TEST(CustomGeneratorSerializationTestGroup, EmptyFile_Failure) { { buildcc::internal::CustomGeneratorSerialization serialization( - "dump/EmptyFile.json"); + "dump/CustomGeneratorEmptyFile.json"); CHECK_FALSE(serialization.LoadFromFile()); } { buildcc::internal::CustomGeneratorSerialization serialization( - "dump/EmptyFile.json"); + "dump/CustomGeneratorEmptyFile.json"); buildcc::env::save_file(serialization.GetSerializedFile().string().c_str(), "", false); CHECK_FALSE(serialization.LoadFromFile()); diff --git a/buildcc/schema/test/test_target_serialization.cpp b/buildcc/schema/test/test_target_serialization.cpp new file mode 100644 index 00000000..522a6b64 --- /dev/null +++ b/buildcc/schema/test/test_target_serialization.cpp @@ -0,0 +1,196 @@ +#include "schema/target_serialization.h" + +#include "nlohmann/json.hpp" + +using json = nlohmann::ordered_json; + +// NOTE, Make sure all these includes are AFTER the system and header includes +#include "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/MemoryLeakDetectorNewMacros.h" +#include "CppUTest/TestHarness.h" +#include "CppUTest/Utest.h" +#include "CppUTestExt/MockSupport.h" + +// clang-format off +TEST_GROUP(TargetSerializationTestGroup) +{ + void teardown() { + mock().clear(); + } +}; +// clang-format on + +TEST(TargetSerializationTestGroup, TargetType) { + buildcc::TargetType type; + json j; + + { + j = buildcc::kTargetTypeInfo[0].first; + from_json(j, type); + CHECK_TRUE(type == buildcc::kTargetTypeInfo[0].second); + } + + { + j = buildcc::kTargetTypeInfo[1].first; + from_json(j, type); + CHECK_TRUE(type == buildcc::kTargetTypeInfo[1].second); + } + + { + j = buildcc::kTargetTypeInfo[2].first; + from_json(j, type); + CHECK_TRUE(type == buildcc::kTargetTypeInfo[2].second); + } + + { + j = "should_not_exist"; + from_json(j, type); + CHECK_TRUE(type == buildcc::TargetType::Undefined); + } + + { + j = nullptr; + from_json(j, type); + CHECK_TRUE(type == buildcc::TargetType::Undefined); + } +} + +TEST(TargetSerializationTestGroup, TargetSerialization_TargetType) { + { + // Target Type executable + buildcc::internal::TargetSerialization serialization( + "dump/TargetTypeTest.json"); + + buildcc::internal::TargetSchema schema; + schema.type = buildcc::TargetType::Executable; + serialization.UpdateStore(schema); + bool store = serialization.StoreToFile(); + CHECK_TRUE(store); + + bool load = serialization.LoadFromFile(); + CHECK_TRUE(load); + CHECK_TRUE(serialization.GetLoad().type == buildcc::TargetType::Executable); + } + + { + // Target Type static library + buildcc::internal::TargetSerialization serialization( + "dump/TargetTypeTest.json"); + + buildcc::internal::TargetSchema schema; + schema.type = buildcc::TargetType::StaticLibrary; + serialization.UpdateStore(schema); + bool store = serialization.StoreToFile(); + CHECK_TRUE(store); + + bool load = serialization.LoadFromFile(); + CHECK_TRUE(load); + CHECK_TRUE(serialization.GetLoad().type == + buildcc::TargetType::StaticLibrary); + } + + { + // Target Type dynamic library + buildcc::internal::TargetSerialization serialization( + "dump/TargetTypeTest.json"); + + buildcc::internal::TargetSchema schema; + schema.type = buildcc::TargetType::DynamicLibrary; + serialization.UpdateStore(schema); + bool store = serialization.StoreToFile(); + CHECK_TRUE(store); + + bool load = serialization.LoadFromFile(); + CHECK_TRUE(load); + CHECK_TRUE(serialization.GetLoad().type == + buildcc::TargetType::DynamicLibrary); + } + + { + // Target Type undefined + buildcc::internal::TargetSerialization serialization( + "dump/TargetTypeTest.json"); + + buildcc::internal::TargetSchema schema; + schema.type = buildcc::TargetType::Undefined; + serialization.UpdateStore(schema); + bool store = serialization.StoreToFile(); + CHECK_TRUE(store); + + bool load = serialization.LoadFromFile(); + CHECK_TRUE(load); + CHECK_TRUE(serialization.GetLoad().type == buildcc::TargetType::Undefined); + } + + { + // Target Type random value + buildcc::internal::TargetSerialization serialization( + "dump/TargetTypeTest.json"); + + buildcc::internal::TargetSchema schema; + schema.type = (buildcc::TargetType)65535; + serialization.UpdateStore(schema); + bool store = serialization.StoreToFile(); + CHECK_TRUE(store); + + bool load = serialization.LoadFromFile(); + CHECK_TRUE(load); + CHECK_TRUE(serialization.GetLoad().type == buildcc::TargetType::Undefined); + } +} + +TEST(TargetSerializationTestGroup, JsonParse_Failure) { + { + // JSON Parse fails + buildcc::internal::TargetSerialization serialization( + "dump/TargetJsonParseFailure.json"); + + buildcc::env::save_file(serialization.GetSerializedFile().string().c_str(), + std::string(""), false); + bool loaded = serialization.LoadFromFile(); + CHECK_FALSE(loaded); + } + + { + // Custom Generator Schema conversion fails + buildcc::internal::TargetSerialization serialization( + "dump/TargetJsonParseFailure.json"); + + auto data = R"({"name": ""})"; + buildcc::env::save_file(serialization.GetSerializedFile().string().c_str(), + data, false); + bool loaded = serialization.LoadFromFile(); + CHECK_FALSE(loaded); + } +} + +TEST(TargetSerializationTestGroup, FormatEmptyCheck) { + buildcc::internal::TargetSerialization serialization( + "dump/TargetFormatEmptyCheck.json"); + + bool stored = serialization.StoreToFile(); + CHECK_TRUE(stored); + + bool loaded = serialization.LoadFromFile(); + CHECK_TRUE(loaded); +} + +TEST(TargetSerializationTestGroup, EmptyFile_Failure) { + { + buildcc::internal::TargetSerialization serialization( + "dump/TargetEmptyFile.json"); + CHECK_FALSE(serialization.LoadFromFile()); + } + + { + buildcc::internal::TargetSerialization serialization( + "dump/TargetEmptyFile.json"); + buildcc::env::save_file(serialization.GetSerializedFile().string().c_str(), + "", false); + CHECK_FALSE(serialization.LoadFromFile()); + } +} + +int main(int ac, char **av) { + return CommandLineTestRunner::RunAllTests(ac, av); +}