diff --git a/bootstrap/main.buildcc.cpp b/bootstrap/main.buildcc.cpp index 4701d5d6..4e8738fd 100644 --- a/bootstrap/main.buildcc.cpp +++ b/bootstrap/main.buildcc.cpp @@ -49,7 +49,7 @@ int main(int argc, char **argv) { ExecutableTarget_generic buildcc_hybrid_simple_example( "buildcc_hybrid_simple_example", toolchain, "example/hybrid/simple"); Reg::Toolchain(custom_toolchain_arg.state) - // .Func([&]() { toolchain.Verify(); }) + .Func([&]() { toolchain.Verify(); }) .BuildPackage(buildcc) .Build(hybrid_simple_example_cb, buildcc_hybrid_simple_example, buildcc_lib) diff --git a/bootstrap/src/build_buildcc.cpp b/bootstrap/src/build_buildcc.cpp index a42ca748..8669dffc 100644 --- a/bootstrap/src/build_buildcc.cpp +++ b/bootstrap/src/build_buildcc.cpp @@ -28,7 +28,7 @@ void schema_gen_cb(FileGenerator &generator, const BaseTarget &flatc_exe) { generator.AddOutput("{gen_build_dir}/custom_generator_generated.h"); generator.AddOutput("{gen_build_dir}/target_generated.h"); - generator.AddDefaultArguments({ + generator.AddPatterns({ {"flatc_compiler", fmt::format("{}", flatc_exe.GetTargetPath())}, }); // generator.AddCommand("{flatc_compiler} --help"); @@ -45,8 +45,7 @@ void buildcc_cb(BaseTarget &target, const FileGenerator &schema_gen, const TargetInfo &taskflow_ho, const BaseTarget &tpl) { // NOTE, Build as single lib target.AddIncludeDir("", true); - const std::string &schema_build_dir = - schema_gen.GetValueByIdentifier("gen_build_dir"); + const std::string &schema_build_dir = schema_gen.Get("gen_build_dir"); target.AddIncludeDirAbsolute(schema_build_dir, true); // ENV diff --git a/buildcc/buildcc.h b/buildcc/buildcc.h index e73bbffe..a48551cb 100644 --- a/buildcc/buildcc.h +++ b/buildcc/buildcc.h @@ -32,7 +32,8 @@ // Base #include "toolchain/toolchain.h" #include "target/custom_generator.h" -#include "target/generator.h" +#include "target/file_generator.h" +#include "target/template_generator.h" #include "target/target_info.h" #include "target/target.h" diff --git a/buildcc/lib/args/include/args/register.h b/buildcc/lib/args/include/args/register.h index 26b5795c..62013db4 100644 --- a/buildcc/lib/args/include/args/register.h +++ b/buildcc/lib/args/include/args/register.h @@ -22,7 +22,8 @@ #include "args.h" -#include "target/generator.h" +#include "target/custom_generator.h" +#include "target/file_generator.h" #include "target/target.h" #include "args/register/test_info.h" diff --git a/buildcc/lib/target/cmake/common_target_src.cmake b/buildcc/lib/target/cmake/common_target_src.cmake index 31ab0a03..130bda3f 100644 --- a/buildcc/lib/target/cmake/common_target_src.cmake +++ b/buildcc/lib/target/cmake/common_target_src.cmake @@ -36,8 +36,10 @@ set(COMMON_TARGET_SRCS # Generator src/custom_generator/custom_generator.cpp include/target/custom_generator.h - src/generator/generator.cpp - include/target/generator.h + src/generator/file_generator.cpp + include/target/file_generator.h + src/generator/template_generator.cpp + include/target/template_generator.h # Target Info src/target_info/target_info.cpp diff --git a/buildcc/lib/target/include/target/custom_generator.h b/buildcc/lib/target/include/target/custom_generator.h index ddc01546..76e64576 100644 --- a/buildcc/lib/target/include/target/custom_generator.h +++ b/buildcc/lib/target/include/target/custom_generator.h @@ -115,17 +115,12 @@ class CustomGenerator : public internal::BuilderInterface { virtual ~CustomGenerator() = default; CustomGenerator(const CustomGenerator &) = delete; - // From env::Command module, forwarding here - // TODO, Create a Mixin - void AddDefaultArgument(const std::string &identifier, - const std::string &pattern); - void AddDefaultArguments( - const std::unordered_map &arguments); - std::string Construct( - const std::string &pattern, - const std::unordered_map &arguments = {}); - const std::string & - GetValueByIdentifier(const std::string &file_identifier) const; + // TODO, Doc + void AddPattern(const std::string &identifier, const std::string &pattern); + + // TODO, Doc + void + AddPatterns(const std::unordered_map &pattern_map); /** * @brief Single Generator task for inputs->generate_cb->outputs @@ -168,6 +163,7 @@ class CustomGenerator : public internal::BuilderInterface { const fs::path &GetRootDir() const { return env_.GetTargetRootDir(); } const fs::path &GetBuildDir() const { return env_.GetTargetBuildDir(); } tf::Taskflow &GetTaskflow() { return tf_; } + const std::string &Get(const std::string &file_identifier) const; private: void Initialize(); @@ -184,6 +180,9 @@ class CustomGenerator : public internal::BuilderInterface { void IdAdded(); void IdUpdated(); +protected: + env::Command command_; + private: std::string name_; TargetEnv env_; @@ -196,7 +195,6 @@ class CustomGenerator : public internal::BuilderInterface { std::unordered_map success_schema_; // Internal - env::Command command_; tf::Taskflow tf_; // Callbacks diff --git a/buildcc/lib/target/include/target/generator.h b/buildcc/lib/target/include/target/file_generator.h similarity index 97% rename from buildcc/lib/target/include/target/generator.h rename to buildcc/lib/target/include/target/file_generator.h index 3e1c0068..08eb1d99 100644 --- a/buildcc/lib/target/include/target/generator.h +++ b/buildcc/lib/target/include/target/file_generator.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TARGET_GENERATOR_H_ -#define TARGET_GENERATOR_H_ +#ifndef TARGET_FILE_GENERATOR_H_ +#define TARGET_FILE_GENERATOR_H_ #include "target/custom_generator.h" diff --git a/buildcc/lib/target/include/target/interface/builder_interface.h b/buildcc/lib/target/include/target/interface/builder_interface.h index 22fbb7ba..cfe40202 100644 --- a/buildcc/lib/target/include/target/interface/builder_interface.h +++ b/buildcc/lib/target/include/target/interface/builder_interface.h @@ -27,7 +27,7 @@ namespace buildcc::internal { -enum PathState { +enum class PathState { kNoChange, kRemoved, kAdded, @@ -69,14 +69,14 @@ inline PathState CheckPaths(const internal::path_unordered_set &previous_path, const bool added_cond = (find == previous_path.end()); if (added_cond) { dirty = true; - state = kAdded; + state = PathState::kAdded; } else { const bool updated_cond = (p.GetLastWriteTimestamp() > find->GetLastWriteTimestamp()); if (updated_cond) { dirty = true; - state = kUpdated; + state = PathState::kUpdated; } else { dirty = false; } @@ -110,7 +110,7 @@ class BuilderInterface { return; } - if (previous != current) { + if (CheckChanged(previous, current)) { callback(); dirty_ = true; } @@ -130,39 +130,25 @@ class BuilderInterface { return; } - // * Old path is removed - const bool removed = - std::any_of(previous_path.begin(), previous_path.end(), - [&](const internal::Path &p) { - return current_path.find(p) == current_path.end(); - }); - if (removed) { + auto path_state = CheckPaths(previous_path, current_path); + switch (path_state) { + case PathState::kRemoved: path_removed_cb(); dirty_ = true; - return; + break; + case PathState::kAdded: + path_added_cb(); + dirty_ = true; + break; + case PathState::kUpdated: + path_updated_cb(); + dirty_ = true; + break; + case PathState::kNoChange: + default: + dirty_ = false; + break; } - - dirty_ = std::any_of( - current_path.cbegin(), current_path.cend(), - [&](const internal::Path &p) -> bool { - bool dirty = false; - const auto find = previous_path.find(p); - const bool added_cond = (find == previous_path.end()); - if (added_cond) { - path_added_cb(); - dirty = true; - } else { - const bool updated_cond = - (p.GetLastWriteTimestamp() > find->GetLastWriteTimestamp()); - if (updated_cond) { - path_updated_cb(); - dirty = true; - } else { - dirty = false; - } - } - return dirty; - }); } protected: diff --git a/buildcc/lib/target/include/target/template_generator.h b/buildcc/lib/target/include/target/template_generator.h new file mode 100644 index 00000000..2d2061a5 --- /dev/null +++ b/buildcc/lib/target/include/target/template_generator.h @@ -0,0 +1,58 @@ +/* + * 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 TARGET_TEMPLATE_GENERATOR_H_ +#define TARGET_TEMPLATE_GENERATOR_H_ + +#include "target/custom_generator.h" + +namespace buildcc { + +class TemplateGenerator : public CustomGenerator { +public: + TemplateGenerator(const std::string &name, const TargetEnv &env) + : CustomGenerator(name, env) {} + + void AddTemplate(const fs::path &input_filename, + const fs::path &output_filename); + std::string Parse(const std::string &pattern); + + /** + * @brief Build FileGenerator Tasks + * + * Use `GetTaskflow` for the registered tasks + */ + void Build() override; + + // Restrict access to certain custom generator APIs +private: + using CustomGenerator::AddDependencyCb; + using CustomGenerator::AddGenInfo; + using CustomGenerator::Build; + +private: + struct TemplateInfo { + fs::path input; + fs::path output; + }; + +private: + std::vector template_infos_; +}; + +} // namespace buildcc + +#endif diff --git a/buildcc/lib/target/src/custom_generator/custom_generator.cpp b/buildcc/lib/target/src/custom_generator/custom_generator.cpp index fec70cab..466d43dd 100644 --- a/buildcc/lib/target/src/custom_generator/custom_generator.cpp +++ b/buildcc/lib/target/src/custom_generator/custom_generator.cpp @@ -27,26 +27,20 @@ constexpr const char *const kGenerateTaskName = "Generate"; namespace buildcc { -void CustomGenerator::AddDefaultArgument(const std::string &identifier, - const std::string &pattern) { +void CustomGenerator::AddPattern(const std::string &identifier, + const std::string &pattern) { command_.AddDefaultArgument(identifier, command_.Construct(pattern)); } -void CustomGenerator::AddDefaultArguments( - const std::unordered_map &arguments) { - for (const auto &arg_iter : arguments) { - AddDefaultArgument(arg_iter.first, arg_iter.second); +void CustomGenerator::AddPatterns( + const std::unordered_map &pattern_map) { + for (const auto &arg_iter : pattern_map) { + AddPattern(arg_iter.first, arg_iter.second); } } -std::string CustomGenerator::Construct( - const std::string &pattern, - const std::unordered_map &arguments) { - return command_.Construct(pattern, arguments); -} - -const std::string &CustomGenerator::GetValueByIdentifier( - const std::string &file_identifier) const { +const std::string & +CustomGenerator::Get(const std::string &file_identifier) const { return command_.GetDefaultValueByKey(file_identifier); } @@ -60,10 +54,16 @@ void CustomGenerator::AddGenInfo( UserGenInfo schema; for (const auto &i : inputs) { - schema.inputs.emplace(command_.Construct(path_as_string(i))); + fs::path input = + internal::Path::CreateNewPath(command_.Construct(path_as_string(i))) + .GetPathname(); + schema.inputs.emplace(std::move(input)); } for (const auto &o : outputs) { - schema.outputs.emplace(command_.Construct(path_as_string(o))); + fs::path output = + internal::Path::CreateNewPath(command_.Construct(path_as_string(o))) + .GetPathname(); + schema.outputs.emplace(std::move(output)); } schema.generate_cb = generate_cb; schema.blob_handler = std::move(blob_handler); @@ -90,6 +90,8 @@ void CustomGenerator::Initialize() { // fs::create_directories(env_.GetTargetBuildDir()); command_.AddDefaultArguments({ + {"project_root_dir", path_as_string(Project::GetRootDir())}, + {"project_build_dir", path_as_string(Project::GetBuildDir())}, {"gen_root_dir", path_as_string(env_.GetTargetRootDir())}, {"gen_build_dir", path_as_string(env_.GetTargetBuildDir())}, }); diff --git a/buildcc/lib/target/src/generator/generator.cpp b/buildcc/lib/target/src/generator/file_generator.cpp similarity index 89% rename from buildcc/lib/target/src/generator/generator.cpp rename to buildcc/lib/target/src/generator/file_generator.cpp index 3437d2f5..ca94d9e2 100644 --- a/buildcc/lib/target/src/generator/generator.cpp +++ b/buildcc/lib/target/src/generator/file_generator.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "target/generator.h" +#include "target/file_generator.h" #include @@ -80,32 +80,35 @@ namespace buildcc { void FileGenerator::AddInput(const std::string &absolute_input_pattern, const char *identifier) { - std::string absolute_input_string = Construct(absolute_input_pattern); + std::string absolute_input_string = + command_.Construct(absolute_input_pattern); const auto absolute_input_path = internal::Path::CreateNewPath(absolute_input_string); inputs_.insert(absolute_input_path.GetPathname()); if (identifier != nullptr) { - AddDefaultArgument(identifier, absolute_input_path.GetPathAsString()); + AddPattern(identifier, absolute_input_path.GetPathAsString()); } } void FileGenerator::AddOutput(const std::string &absolute_output_pattern, const char *identifier) { - std::string absolute_output_string = Construct(absolute_output_pattern); + std::string absolute_output_string = + command_.Construct(absolute_output_pattern); const auto absolute_output_path = internal::Path::CreateNewPath(absolute_output_string); outputs_.insert(absolute_output_path.GetPathname()); if (identifier != nullptr) { - AddDefaultArgument(identifier, absolute_output_path.GetPathAsString()); + AddPattern(identifier, absolute_output_path.GetPathAsString()); } } void FileGenerator::AddCommand( const std::string &command_pattern, const std::unordered_map &arguments) { - std::string constructed_command = Construct(command_pattern, arguments); + std::string constructed_command = + command_.Construct(command_pattern, arguments); commands_.emplace_back(std::move(constructed_command)); } diff --git a/buildcc/lib/target/src/generator/template_generator.cpp b/buildcc/lib/target/src/generator/template_generator.cpp new file mode 100644 index 00000000..c99fc541 --- /dev/null +++ b/buildcc/lib/target/src/generator/template_generator.cpp @@ -0,0 +1,77 @@ +/* + * 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 "target/template_generator.h" + +#include "env/env.h" + +namespace { + +bool template_generate_cb(const buildcc::CustomGeneratorContext &ctx) { + std::string pattern_data; + const fs::path &input = *ctx.inputs.begin(); + const fs::path &output = *ctx.outputs.begin(); + + bool success = + buildcc::env::load_file(input.string().c_str(), false, &pattern_data); + if (success) { + std::string parsed_data = ctx.command.Construct(pattern_data); + success = + buildcc::env::save_file(output.string().c_str(), parsed_data, false); + } + + if (!success) { + buildcc::env::log_critical( + __FUNCTION__, fmt::format("Failed to parse {} -> {}", input, output)); + } + return success; +} + +} // namespace + +namespace buildcc { + +void TemplateGenerator::AddTemplate(const fs::path &input_filename, + const fs::path &output_filename) { + TemplateInfo info; + info.input = internal::Path::CreateNewPath( + command_.Construct(path_as_string(input_filename))) + .GetPathname(); + info.output = internal::Path::CreateNewPath( + command_.Construct(path_as_string(output_filename))) + .GetPathname(); + template_infos_.emplace_back(std::move(info)); +} + +std::string TemplateGenerator::Parse(const std::string &pattern) { + return command_.Construct(pattern); +} + +/** + * @brief Build FileGenerator Tasks + * + * Use `GetTaskflow` for the registered tasks + */ +void TemplateGenerator::Build() { + for (const auto &info : template_infos_) { + std::string name = + info.input.lexically_relative(Project::GetRootDir()).string(); + AddGenInfo(name, {info.input}, {info.output}, template_generate_cb); + } + this->CustomGenerator::Build(); +} + +} // namespace buildcc diff --git a/buildcc/lib/target/test/target/CMakeLists.txt b/buildcc/lib/target/test/target/CMakeLists.txt index a77da279..1e7ef314 100644 --- a/buildcc/lib/target/test/target/CMakeLists.txt +++ b/buildcc/lib/target/test/target/CMakeLists.txt @@ -47,15 +47,23 @@ add_executable(test_custom_generator ) target_link_libraries(test_custom_generator PRIVATE target_interface) -add_executable(test_generator - test_generator.cpp +add_executable(test_file_generator + test_file_generator.cpp ) -target_link_libraries(test_generator PRIVATE target_interface) +target_link_libraries(test_file_generator PRIVATE target_interface) + +add_executable(test_template_generator + test_template_generator.cpp +) +target_link_libraries(test_template_generator PRIVATE target_interface) add_test(NAME test_custom_generator COMMAND test_custom_generator WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) -add_test(NAME test_generator COMMAND test_generator +add_test(NAME test_file_generator COMMAND test_file_generator + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) +add_test(NAME test_template_generator COMMAND test_template_generator WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) diff --git a/buildcc/lib/target/test/target/data/template/default_values.txt.in b/buildcc/lib/target/test/target/data/template/default_values.txt.in new file mode 100644 index 00000000..9ea1d25f --- /dev/null +++ b/buildcc/lib/target/test/target/data/template/default_values.txt.in @@ -0,0 +1,4 @@ +{gen_root_dir} +{gen_build_dir} +{project_root_dir} +{project_build_dir} diff --git a/buildcc/lib/target/test/target/data/template/hello_world.txt.in b/buildcc/lib/target/test/target/data/template/hello_world.txt.in new file mode 100644 index 00000000..cd2ccb82 --- /dev/null +++ b/buildcc/lib/target/test/target/data/template/hello_world.txt.in @@ -0,0 +1 @@ +{hello} {world} diff --git a/buildcc/lib/target/test/target/test_custom_generator.cpp b/buildcc/lib/target/test/target/test_custom_generator.cpp index a7c6ea71..5efa7e6f 100644 --- a/buildcc/lib/target/test/target/test_custom_generator.cpp +++ b/buildcc/lib/target/test/target/test_custom_generator.cpp @@ -87,7 +87,7 @@ TEST(CustomGeneratorTestGroup, Basic_Failure) { TEST(CustomGeneratorTestGroup, DefaultArgumentUsage) { buildcc::CustomGenerator cgen("default_argument_usage", ""); - cgen.AddDefaultArguments({ + cgen.AddPatterns({ {"dummy_main_c", "{gen_root_dir}/dummy_main.c"}, {"dummy_main_o", "{gen_build_dir}/dummy_main.o"}, {"dummy_main_cpp", "{gen_root_dir}/dummy_main.cpp"}, diff --git a/buildcc/lib/target/test/target/test_generator.cpp b/buildcc/lib/target/test/target/test_file_generator.cpp similarity index 91% rename from buildcc/lib/target/test/target/test_generator.cpp rename to buildcc/lib/target/test/target/test_file_generator.cpp index 62c8b722..f6fc257e 100644 --- a/buildcc/lib/target/test/target/test_generator.cpp +++ b/buildcc/lib/target/test/target/test_file_generator.cpp @@ -1,4 +1,4 @@ -#include "target/generator.h" +#include "target/file_generator.h" #include "expect_command.h" #include "expect_custom_generator.h" @@ -16,7 +16,7 @@ #include "CppUTestExt/MockSupport.h" // clang-format off -TEST_GROUP(GeneratorTestGroup) +TEST_GROUP(FileGeneratorTestGroup) { void teardown() { buildcc::env::set_task_state(buildcc::env::TaskState::SUCCESS); @@ -25,13 +25,13 @@ TEST_GROUP(GeneratorTestGroup) }; // clang-format on -fs::path BUILD_DIR = fs::current_path() / "intermediate" / "generator"; +fs::path BUILD_DIR = fs::current_path() / "intermediate" / "file_generator"; -TEST(GeneratorTestGroup, Generator_Build) { +TEST(FileGeneratorTestGroup, Generator_Build) { constexpr const char *const NAME = "Build"; buildcc::FileGenerator generator(NAME, ""); - generator.AddDefaultArguments({ + generator.AddPatterns({ {"compiler", "gcc"}, }); @@ -47,11 +47,11 @@ TEST(GeneratorTestGroup, Generator_Build) { mock().checkExpectations(); } -TEST(GeneratorTestGroup, Generator_Identifier) { +TEST(FileGeneratorTestGroup, Generator_Identifier) { constexpr const char *const NAME = "Identifier"; buildcc::FileGenerator generator(NAME, ""); - generator.AddDefaultArguments({ + generator.AddPatterns({ {"compiler", "gcc"}, }); @@ -66,7 +66,7 @@ TEST(GeneratorTestGroup, Generator_Identifier) { mock().checkExpectations(); } -TEST(GeneratorTestGroup, Generator_Rebuild) { +TEST(FileGeneratorTestGroup, Generator_Rebuild) { constexpr const char *const NAME = "Rebuild"; { buildcc::FileGenerator generator(NAME, ""); @@ -100,7 +100,7 @@ TEST(GeneratorTestGroup, Generator_Rebuild) { mock().checkExpectations(); } -TEST(GeneratorTestGroup, Generator_Rebuild_Inputs) { +TEST(FileGeneratorTestGroup, Generator_Rebuild_Inputs) { constexpr const char *const NAME = "Rebuild_Inputs"; { @@ -164,7 +164,7 @@ TEST(GeneratorTestGroup, Generator_Rebuild_Inputs) { mock().checkExpectations(); } -TEST(GeneratorTestGroup, Generator_Rebuild_Outputs) { +TEST(FileGeneratorTestGroup, Generator_Rebuild_Outputs) { constexpr const char *const NAME = "Rebuild_Outputs"; { buildcc::FileGenerator generator(NAME, ""); @@ -213,7 +213,7 @@ TEST(GeneratorTestGroup, Generator_Rebuild_Outputs) { mock().checkExpectations(); } -TEST(GeneratorTestGroup, Generator_Rebuild_Commands) { +TEST(FileGeneratorTestGroup, Generator_Rebuild_Commands) { constexpr const char *const NAME = "Rebuild_Commands"; { buildcc::FileGenerator generator(NAME, ""); @@ -259,27 +259,27 @@ TEST(GeneratorTestGroup, Generator_Rebuild_Commands) { mock().checkExpectations(); } -TEST(GeneratorTestGroup, Generator_AddDefaultArguments) { +TEST(FileGeneratorTestGroup, Generator_AddDefaultArguments) { constexpr const char *const NAME = "AddDefaultArgument"; buildcc::FileGenerator generator(NAME, ""); - generator.AddDefaultArguments({ + generator.AddPatterns({ {"key", "value"}, }); - const std::string &value = generator.GetValueByIdentifier("key"); + const std::string &value = generator.Get("key"); STRCMP_EQUAL(value.c_str(), "value"); STRCMP_EQUAL(generator.GetName().c_str(), "AddDefaultArgument"); } // FAILURE STATES -TEST(GeneratorTestGroup, Generator_FailedEnvTaskState) { +TEST(FileGeneratorTestGroup, Generator_FailedEnvTaskState) { buildcc::env::set_task_state(buildcc::env::TaskState::FAILURE); constexpr const char *const NAME = "FailedEnvTaskState"; buildcc::FileGenerator generator(NAME, ""); - generator.AddDefaultArguments({ + generator.AddPatterns({ {"compiler", "gcc"}, }); @@ -296,11 +296,11 @@ TEST(GeneratorTestGroup, Generator_FailedEnvTaskState) { buildcc::env::set_task_state(buildcc::env::TaskState::SUCCESS); } -TEST(GeneratorTestGroup, Generator_FailedGenerateConvert) { +TEST(FileGeneratorTestGroup, Generator_FailedGenerateConvert) { constexpr const char *const NAME = "FailedGenerateConvert"; buildcc::FileGenerator generator(NAME, ""); - generator.AddDefaultArguments({ + generator.AddPatterns({ {"compiler", "gcc"}, }); @@ -319,11 +319,11 @@ TEST(GeneratorTestGroup, Generator_FailedGenerateConvert) { buildcc::env::set_task_state(buildcc::env::TaskState::SUCCESS); } -TEST(GeneratorTestGroup, Generator_FailedGenerateCommand) { +TEST(FileGeneratorTestGroup, Generator_FailedGenerateCommand) { constexpr const char *const NAME = "FailedGenerateCommand"; buildcc::FileGenerator generator(NAME, ""); - generator.AddDefaultArguments({ + generator.AddPatterns({ {"compiler", "gcc"}, }); @@ -341,14 +341,14 @@ TEST(GeneratorTestGroup, Generator_FailedGenerateCommand) { buildcc::env::set_task_state(buildcc::env::TaskState::SUCCESS); } -TEST(GeneratorTestGroup, Generator_FailedStore) { +TEST(FileGeneratorTestGroup, Generator_FailedStore) { constexpr const char *const NAME = "FailedStore"; const fs::path test_build_dir = buildcc::Project::GetBuildDir() / NAME; buildcc::FileGenerator generator(NAME, ""); fs::remove_all(test_build_dir); - generator.AddDefaultArguments({ + generator.AddPatterns({ {"compiler", "gcc"}, }); @@ -369,14 +369,14 @@ TEST(GeneratorTestGroup, Generator_FailedStore) { buildcc::env::set_task_state(buildcc::env::TaskState::SUCCESS); } -TEST(GeneratorTestGroup, FailedEnvTaskState_Rebuild) { +TEST(FileGeneratorTestGroup, FailedEnvTaskState_Rebuild) { buildcc::env::set_task_state(buildcc::env::TaskState::FAILURE); constexpr const char *const NAME = "FailedEnvTaskState_Rebuild"; { buildcc::FileGenerator generator(NAME, ""); - generator.AddDefaultArguments({ + generator.AddPatterns({ {"compiler", "gcc"}, }); @@ -396,7 +396,7 @@ TEST(GeneratorTestGroup, FailedEnvTaskState_Rebuild) { { buildcc::FileGenerator generator(NAME, ""); - generator.AddDefaultArguments({ + generator.AddPatterns({ {"compiler", "gcc"}, }); @@ -413,13 +413,13 @@ TEST(GeneratorTestGroup, FailedEnvTaskState_Rebuild) { mock().checkExpectations(); } -TEST(GeneratorTestGroup, FailedGenerateCommand_Rebuild) { +TEST(FileGeneratorTestGroup, FailedGenerateCommand_Rebuild) { constexpr const char *const NAME = "FailedGenerateCommand_Rebuild"; { buildcc::FileGenerator generator(NAME, ""); - generator.AddDefaultArguments({ + generator.AddPatterns({ {"compiler", "gcc"}, }); @@ -440,7 +440,7 @@ TEST(GeneratorTestGroup, FailedGenerateCommand_Rebuild) { { buildcc::FileGenerator generator(NAME, ""); - generator.AddDefaultArguments({ + generator.AddPatterns({ {"compiler", "gcc"}, }); diff --git a/buildcc/lib/target/test/target/test_template_generator.cpp b/buildcc/lib/target/test/target/test_template_generator.cpp new file mode 100644 index 00000000..f84193fc --- /dev/null +++ b/buildcc/lib/target/test/target/test_template_generator.cpp @@ -0,0 +1,97 @@ +#include "target/template_generator.h" + +#include "expect_command.h" +#include "expect_custom_generator.h" +#include "test_target_util.h" + +// 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(TemplateGeneratorTestGroup) +{ + void teardown() { + mock().checkExpectations(); + mock().clear(); + buildcc::env::set_task_state(buildcc::env::TaskState::SUCCESS); + } +}; +// clang-format on + +fs::path BUILD_DIR = fs::current_path() / "intermediate" / "template_generator"; + +TEST(TemplateGeneratorTestGroup, Basic) { + buildcc::TemplateGenerator generator("basic", ""); + generator.Build(); + + buildcc::m::CustomGeneratorRunner(generator); +} + +TEST(TemplateGeneratorTestGroup, Basic_Parse) { + buildcc::TemplateGenerator generator("basic_parse", ""); + generator.AddPatterns({ + {"hello", "Hello"}, + {"world", "World"}, + }); + std::string parsed = generator.Parse("{hello} {world}"); + STRCMP_EQUAL(parsed.c_str(), "Hello World"); +} + +TEST(TemplateGeneratorTestGroup, Basic_InputParse) { + buildcc::TemplateGenerator generator("basic_inputparse", ""); + generator.AddPatterns({ + {"hello", "Hello"}, + {"world", "World"}, + }); + generator.AddTemplate("{gen_root_dir}/template/default_values.txt.in", + "{gen_build_dir}/default_values.txt"); + generator.AddTemplate("{gen_root_dir}/template/hello_world.txt.in", + "{gen_build_dir}/hello_world.txt"); + generator.Build(); + + buildcc::m::CustomGeneratorRunner(generator); + + CHECK(buildcc::env::get_task_state() == buildcc::env::TaskState::SUCCESS); +} + +TEST(TemplateGeneratorTestGroup, Basic_SaveFailure) { + constexpr const char *const NAME = "basic_save_failure"; + { + buildcc::TemplateGenerator generator(NAME, ""); + + fs::create_directories(generator.GetBuildDir() / "default_values.txt"); + + generator.AddTemplate("{gen_root_dir}/template/default_values.txt.in", + "{gen_build_dir}/default_values.txt"); + generator.Build(); + + buildcc::m::CustomGeneratorRunner(generator); + CHECK(buildcc::env::get_task_state() == buildcc::env::TaskState::FAILURE); + } +} + +TEST(TemplateGeneratorTestGroup, Basic_LoadFailure) { + constexpr const char *const NAME = "basic_load_failure"; + { + buildcc::TemplateGenerator generator(NAME, ""); + + fs::create_directories(generator.GetBuildDir() / "default_values.txt.in"); + + generator.AddTemplate("{gen_build_dir}/default_values.txt.in", + "{gen_build_dir}/default_values.txt"); + generator.Build(); + + buildcc::m::CustomGeneratorRunner(generator); + CHECK(buildcc::env::get_task_state() == buildcc::env::TaskState::FAILURE); + } +} + +int main(int ac, char **av) { + fs::remove_all(BUILD_DIR); + buildcc::Project::Init(fs::current_path() / "data", BUILD_DIR); + return CommandLineTestRunner::RunAllTests(ac, av); +} diff --git a/buildcc/schema/include/schema/target_serialization.h b/buildcc/schema/include/schema/target_serialization.h index 84914ffb..e4869f3b 100644 --- a/buildcc/schema/include/schema/target_serialization.h +++ b/buildcc/schema/include/schema/target_serialization.h @@ -28,7 +28,7 @@ namespace buildcc::internal { struct TargetSchema { std::string name; - TargetType type; + TargetType type{TargetType::Undefined}; path_unordered_set internal_sources; path_unordered_set internal_headers; diff --git a/buildcc/schema/include/schema/target_type.h b/buildcc/schema/include/schema/target_type.h index eb4632ab..866b030b 100644 --- a/buildcc/schema/include/schema/target_type.h +++ b/buildcc/schema/include/schema/target_type.h @@ -23,6 +23,7 @@ enum class TargetType { Executable, ///< Executable Target type StaticLibrary, ///< Static library target type DynamicLibrary, ///< Dynamic library target type + Undefined, ///< Undefined target type }; } diff --git a/example/hybrid/dep_chaining/build.cpp b/example/hybrid/dep_chaining/build.cpp index 906ecfe6..33f5bcff 100644 --- a/example/hybrid/dep_chaining/build.cpp +++ b/example/hybrid/dep_chaining/build.cpp @@ -83,15 +83,14 @@ static void clean_cb() { static void cpp_target_cb(BaseTarget &cpptarget, const FileGenerator &cpp_generator) { - const fs::path main_cpp = - fs::path(cpp_generator.GetValueByIdentifier("main_cpp")) - .lexically_relative(Project::GetRootDir()); + const fs::path main_cpp = fs::path(cpp_generator.Get("main_cpp")) + .lexically_relative(Project::GetRootDir()); cpptarget.AddSource(main_cpp); cpptarget.Build(); } static void c_target_cb(BaseTarget &ctarget, const FileGenerator &c_generator) { - const fs::path main_c = fs::path(c_generator.GetValueByIdentifier("main_c")) + const fs::path main_c = fs::path(c_generator.Get("main_c")) .lexically_relative(Project::GetRootDir()); ctarget.AddSource(main_c); ctarget.Build();