diff options
-rw-r--r-- | .gitmodules | 3 | ||||
-rwxr-xr-x | bootstrap.sh | 2 | ||||
-rw-r--r-- | src/build.cc | 38 | ||||
-rw-r--r-- | src/build.h | 6 | ||||
-rw-r--r-- | src/libctor.cc | 60 | ||||
-rw-r--r-- | src/libctor.h | 1 | ||||
-rw-r--r-- | src/task_ld.cc | 7 | ||||
-rw-r--r-- | src/tasks.cc | 16 | ||||
-rw-r--r-- | src/tasks.h | 3 | ||||
-rw-r--r-- | src/unittest.cc | 34 | ||||
-rw-r--r-- | src/unittest.h | 10 | ||||
-rw-r--r-- | test/ctor.cc | 28 | ||||
m--------- | test/uunit | 0 |
13 files changed, 191 insertions, 17 deletions
diff --git a/.gitmodules b/.gitmodules index 3e401a5..c765825 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "getoptpp"] path = src/getoptpp url = git://git.drumgizmo.org/getoptpp.git +[submodule "test/uunit"] + path = test/uunit + url = git://git.drumgizmo.org/uunit.git diff --git a/bootstrap.sh b/bootstrap.sh index e589a2c..833d3be 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -1,4 +1,4 @@ #!/bin/bash echo "Bootstrapping..." -g++ -std=c++17 -I. -Isrc -pthread src/*.cc ctor.cc -o ctor && \ +g++ -std=c++17 -I. -Isrc -pthread src/*.cc ctor.cc test/ctor.cc -o ctor && \ echo "Done. Now run ./ctor to build." diff --git a/src/build.cc b/src/build.cc index 445979e..4cec3b9 100644 --- a/src/build.cc +++ b/src/build.cc @@ -7,8 +7,6 @@ #include <set> #include <thread> -#include "tasks.h" - using namespace std::chrono_literals; int build(const Settings& settings, @@ -171,3 +169,39 @@ int build(const Settings& settings, return 0; } + +int build(const Settings& settings, + const std::string& name, + const std::vector<Target>& targets, + const std::list<std::shared_ptr<Task>>& all_tasks) +{ + bool task_found{false}; + std::list<std::shared_ptr<Task>> ts; + + for(const auto& target : targets) + { + for(auto task : all_tasks) + { + if(task->name() == target.config.target || + task->target() == target.config.target) + { + std::cout << target.config.target << "\n"; + task_found = true; + + auto depSet = getDepTasks(task); + for(const auto& task : depSet) + { + ts.push_back(task); + } + } + } + } + + if(!task_found) + { + std::cerr << "*** No rule to make target '" << name << "'. Stop.\n"; + return 1; + } + + return build(settings, name, ts, all_tasks); +} diff --git a/src/build.h b/src/build.h index 36e48ad..0c4c3fd 100644 --- a/src/build.h +++ b/src/build.h @@ -7,6 +7,7 @@ #include "task.h" #include "settings.h" +#include "tasks.h" int build(const Settings& settings, const std::string& name, @@ -16,3 +17,8 @@ int build(const Settings& settings, int build(const Settings& settings, const std::string& name, const std::list<std::shared_ptr<Task>>& all_tasks); + +int build(const Settings& settings, + const std::string& name, + const std::vector<Target>& targets, + const std::list<std::shared_ptr<Task>>& all_tasks); diff --git a/src/libctor.cc b/src/libctor.cc index c7a7400..e166e51 100644 --- a/src/libctor.cc +++ b/src/libctor.cc @@ -22,6 +22,7 @@ #include "rebuild.h" #include "tasks.h" #include "build.h" +#include "unittest.h" int main(int argc, char* argv[]) { if(argc > 1 && std::string(argv[1]) == "configure") @@ -46,6 +47,7 @@ int main(int argc, char* argv[]) bool list_files{false}; bool list_targets{false}; bool no_relaunch{false}; // true means no re-launch after rebuild. + bool run_unittests{false}; dg::Options opt; int key{128}; @@ -206,12 +208,10 @@ Options: if(list_targets) { no_default_build = true; - for(const auto& task : all_tasks) + auto& targets = getTargets(settings); + for(const auto& target : targets) { - if(task->targetType() != TargetType::Object) - { - std::cout << task->name() << "\n"; - } + std::cout << target.config.target << "\n"; } } @@ -286,13 +286,44 @@ Options: } } } + else if(arg == "check") + { + build_all = false; + run_unittests = true; + + std::vector<Target> unittest_targets; + auto& targets = getTargets(settings); + for(const auto& target : targets) + { + if(target.config.type == TargetType::UnitTest) + { + unittest_targets.push_back(target); + } + } + + auto ret = build(settings, "check", unittest_targets, all_tasks); + if(ret != 0) + { + return ret; + } + } else { build_all = false; if(arg == "all") { - auto ret = build(settings, "all", all_tasks, all_tasks); + std::vector<Target> non_unittest_targets; + auto& targets = getTargets(settings); + for(const auto& target : targets) + { + if(target.config.type != TargetType::UnitTest) + { + non_unittest_targets.push_back(target); + } + } + + auto ret = build(settings, "all", non_unittest_targets, all_tasks); if(ret != 0) { return ret; @@ -311,12 +342,27 @@ Options: if(build_all) { - auto ret = build(settings, "all", all_tasks, all_tasks); + std::vector<Target> non_unittest_targets; + auto& targets = getTargets(settings); + for(const auto& target : targets) + { + if(target.config.type != TargetType::UnitTest) + { + non_unittest_targets.push_back(target); + } + } + + auto ret = build(settings, "all", non_unittest_targets, all_tasks); if(ret != 0) { return ret; } } + if(run_unittests) + { + return runUnitTests(all_tasks, settings); + } + return 0; } diff --git a/src/libctor.h b/src/libctor.h index d0a0080..4ad0e32 100644 --- a/src/libctor.h +++ b/src/libctor.h @@ -13,6 +13,7 @@ enum class TargetType StaticLibrary, DynamicLibrary, Object, + UnitTest, }; enum class Language diff --git a/src/task_ld.cc b/src/task_ld.cc index 4a77c72..ec68190 100644 --- a/src/task_ld.cc +++ b/src/task_ld.cc @@ -44,7 +44,11 @@ TaskLD::TaskLD(const BuildConfiguration& config, , config(config) , settings(settings) { - target_type = TargetType::Executable; + target_type = config.type; + if(target_type == TargetType::Auto) + { + target_type = TargetType::Executable; + } targetFile = settings.builddir; targetFile /= target; @@ -65,7 +69,6 @@ TaskLD::TaskLD(const BuildConfiguration& config, flagsFile = settings.builddir / targetFile.stem(); flagsFile += ".flags"; - target_type = TargetType::Executable; source_language = Language::C; for(const auto& source : config.sources) { diff --git a/src/tasks.cc b/src/tasks.cc index 1607b37..3113564 100644 --- a/src/tasks.cc +++ b/src/tasks.cc @@ -3,6 +3,7 @@ #include <filesystem> #include <deque> #include <iostream> +#include <algorithm> #include "settings.h" #include "libctor.h" @@ -101,6 +102,7 @@ std::list<std::shared_ptr<Task>> taskFactory(const BuildConfiguration& config, break; case TargetType::Executable: + case TargetType::UnitTest: tasks.emplace_back(std::make_shared<TaskLD>(config, settings, config.target, objects)); break; @@ -111,6 +113,7 @@ std::list<std::shared_ptr<Task>> taskFactory(const BuildConfiguration& config, return tasks; } +} std::shared_ptr<Task> getNextTask(const std::list<std::shared_ptr<Task>>& allTasks, std::list<std::shared_ptr<Task>>& dirtyTasks) @@ -131,15 +134,20 @@ std::shared_ptr<Task> getNextTask(const std::list<std::shared_ptr<Task>>& allTas return nullptr; } -std::list<std::shared_ptr<Task>> getTasks(const Settings& settings) +std::list<std::shared_ptr<Task>> getTasks(const Settings& settings, + const std::vector<std::string> names) { auto& targets = getTargets(settings); std::list<std::shared_ptr<Task>> tasks; for(const auto& target : targets) { - std::vector<std::string> objects; - auto t = taskFactory(target.config, settings, target.path); - tasks.insert(tasks.end(), t.begin(), t.end()); + if(names.empty() || + std::find(std::begin(names), std::end(names), target.config.target) != std::end(names)) + { + std::vector<std::string> objects; + auto t = taskFactory(target.config, settings, target.path); + tasks.insert(tasks.end(), t.begin(), t.end()); + } } return tasks; diff --git a/src/tasks.h b/src/tasks.h index 04610e6..e5d1daf 100644 --- a/src/tasks.h +++ b/src/tasks.h @@ -21,4 +21,5 @@ const std::deque<Target>& getTargets(const Settings& settings); std::shared_ptr<Task> getNextTask(const std::list<std::shared_ptr<Task>>& allTasks, std::list<std::shared_ptr<Task>>& dirtyTasks); -std::list<std::shared_ptr<Task>> getTasks(const Settings& settings); +std::list<std::shared_ptr<Task>> getTasks(const Settings& settings, + const std::vector<std::string> names = {}); diff --git a/src/unittest.cc b/src/unittest.cc new file mode 100644 index 0000000..d2d5167 --- /dev/null +++ b/src/unittest.cc @@ -0,0 +1,34 @@ +#include "unittest.h" + +#include <iostream> + +#include "execute.h" +#include "settings.h" +#include "task.h" + +int runUnitTests(std::list<std::shared_ptr<Task>>& tasks, + const Settings& settings) +{ + bool ok{true}; + std::cout << "Running unit-tests:\n"; + // Run unit-tests + for(const auto& task : tasks) + { + if(task->targetType() == TargetType::UnitTest) + { + std::cout << task->name() << ": "; + auto ret = execute(task->target(), {}, false); + ok &= ret == 0; + if(ret == 0) + { + std::cout << "OK\n"; + } + else + { + std::cout << "FAILED\n"; + } + } + } + + return ok ? 0 : 1; +} diff --git a/src/unittest.h b/src/unittest.h new file mode 100644 index 0000000..144dbdb --- /dev/null +++ b/src/unittest.h @@ -0,0 +1,10 @@ +#pragma once + +#include <list> +#include <memory> + +class Task; +class Settings; + +int runUnitTests(std::list<std::shared_ptr<Task>>& tasks, + const Settings& settings); diff --git a/test/ctor.cc b/test/ctor.cc new file mode 100644 index 0000000..aed3ee5 --- /dev/null +++ b/test/ctor.cc @@ -0,0 +1,28 @@ +#include "libctor.h" + +namespace +{ +BuildConfigurations ctorTestConfigs() +{ + return + { + { + .type = TargetType::UnitTest, + .target = "execute_test", + .sources = { + "execute_test.cc", + "uunit/uunit.cc", + "../src/execute.cc", + }, + .cxxflags = { + "-std=c++17", "-O3", "-s", "-Wall", "-Werror", + "-I../src", "-Iuunit", + "-DOUTPUT=\"execute\"", + }, + } + }; +} +} + +// Convenience macro +REG(ctorTestConfigs); diff --git a/test/uunit b/test/uunit new file mode 160000 +Subproject fd83de802d05a227cc00489f66ea70fccb4dda0 |