summaryrefslogtreecommitdiff
path: root/libcppbuild.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libcppbuild.cc')
-rw-r--r--libcppbuild.cc184
1 files changed, 124 insertions, 60 deletions
diff --git a/libcppbuild.cc b/libcppbuild.cc
index bf1a7fa..7f0a355 100644
--- a/libcppbuild.cc
+++ b/libcppbuild.cc
@@ -7,16 +7,67 @@
#include <chrono>
#include <thread>
#include <memory>
+#include <algorithm>
+#include <list>
#include "libcppbuild.h"
#include "task_cc.h"
#include "task_ld.h"
+#include "task_ar.h"
#include "settings.h"
#include <unistd.h>
using namespace std::chrono_literals;
+std::list<std::shared_ptr<Task>> taskFactory(const BuildConfiguration& config,
+ const Settings& settings)
+{
+ std::vector<std::string> objects;
+ std::list<std::shared_ptr<Task>> tasks;
+ for(const auto& file : config.sources)
+ {
+ tasks.emplace_back(std::make_shared<TaskCC>(config, settings, file));
+ objects.push_back(tasks.back()->target());
+ }
+
+ std::filesystem::path targetFile(config.target);
+ if(targetFile.extension() == ".a")
+ {
+ // static lib
+ tasks.emplace_back(std::make_shared<TaskAR>(config, settings, config.target,
+ objects));
+ }
+ else
+ {
+ // binary
+ tasks.emplace_back(std::make_shared<TaskLD>(config, settings, config.target,
+ objects));
+
+ }
+
+ return tasks;
+}
+
+std::shared_ptr<Task> getNextTask(const std::list<std::shared_ptr<Task>>& allTasks,
+ std::list<std::shared_ptr<Task>>& dirtyTasks)
+{
+ for(auto dirtyTask = dirtyTasks.begin();
+ dirtyTask != dirtyTasks.end();
+ ++dirtyTask)
+ {
+ //std::cout << "Examining target " << (*dirtyTask)->target() << "\n";
+ if((*dirtyTask)->ready())
+ {
+ dirtyTasks.erase(dirtyTask);
+ return *dirtyTask;
+ }
+ }
+
+ //std::cout << "No task ready ... \n";
+ return nullptr;
+}
+
int main(int argc, const char* argv[])
{
Settings settings;
@@ -27,84 +78,79 @@ int main(int argc, const char* argv[])
settings.parallel_processes =
std::max(1u, std::thread::hardware_concurrency() * 2 - 1);
+ settings.verbose = 0;
+
std::filesystem::path builddir(settings.builddir);
std::filesystem::create_directories(builddir);
auto build_configs = configs();
+ std::list<std::shared_ptr<Task>> tasks;
for(const auto& build_config : build_configs)
{
std::vector<std::string> objects;
- std::vector<std::unique_ptr<Task>> tasks;
- for(const auto& file : build_config.sources)
- {
- tasks.emplace_back(std::make_unique<TaskCC>(build_config, settings, file));
- objects.push_back(tasks.back()->target());
- }
+ auto t = taskFactory(build_config, settings);
+ tasks.insert(tasks.end(), t.begin(), t.end());
+ }
- TaskLD task_ld(build_config, settings, build_config.target, objects);
+ for(auto task : tasks)
+ {
+ task->registerDepTasks(tasks);
+ }
- if(argc == 2 && std::string(argv[1]) == "clean")
+ std::list<std::shared_ptr<Task>> dirtyTasks;
+ for(auto task : tasks)
+ {
+ if(task->dirty())
{
- std::cout << "Cleaning\n";
- //std::filesystem::remove_all(builddir);
- for(auto& task : tasks)
- {
- if(task->clean() != 0)
- {
- return 1;
- }
- }
+ dirtyTasks.push_back(task);
+ }
+ }
- if(task_ld.clean() != 0)
+ if(argc == 2 && std::string(argv[1]) == "clean")
+ {
+ std::cout << "Cleaning\n";
+ //std::filesystem::remove_all(builddir);
+ for(auto& task : tasks)
+ {
+ if(task->clean() != 0)
{
return 1;
}
-
- return 0;
}
- std::cout << "Building\n";
+ return 0;
+ }
- std::list<std::future<int>> processes;
+ std::cout << "Building\n";
+ std::list<std::future<int>> processes;
- // Start all tasks
- auto task = tasks.begin();
- while(task != tasks.end())
+ // Start all tasks
+ bool done{false};
+ while(!done)
+ {
+ bool started_one{false};
+ while(processes.size() < settings.parallel_processes)
{
- while(processes.size() < settings.parallel_processes &&
- task != tasks.end())
+ if(dirtyTasks.empty())
{
- if(!(*task)->dirty())
- {
- ++task;
- continue;
- }
-
- processes.emplace_back(
- std::async(std::launch::async,
- [&t = *task]()
- {
- return t->run();
- }));
- ++task;
- std::this_thread::sleep_for(2ms);
+ done = true;
+ break;
}
- for(auto process = processes.begin();
- process != processes.end();
- ++process)
+ auto task = getNextTask(tasks, dirtyTasks);
+ if(task == nullptr)
{
- if(process->valid())
- {
- if(process->get() != 0)
- {
- return 1;
- }
- processes.erase(process);
- break;
- }
+ break;
+ //return 1;
}
+ processes.emplace_back(
+ std::async(std::launch::async,
+ [task]()
+ {
+ return task->run();
+ }));
+ started_one = true;
std::this_thread::sleep_for(2ms);
}
@@ -112,18 +158,36 @@ int main(int argc, const char* argv[])
process != processes.end();
++process)
{
- process->wait();
- auto ret = process->get();
- if(ret != 0)
+ if(process->valid())
{
- return 1;
+ if(process->get() != 0)
+ {
+ return 1;
+ }
+ processes.erase(process);
+ break;
}
}
- std::cout << "Linking\n";
- if(task_ld.dirty())
+ if(started_one)
+ {
+ std::this_thread::sleep_for(2ms);
+ }
+ else
+ {
+ std::this_thread::sleep_for(200ms);
+ }
+ }
+
+ for(auto process = processes.begin();
+ process != processes.end();
+ ++process)
+ {
+ process->wait();
+ auto ret = process->get();
+ if(ret != 0)
{
- return task_ld.run();
+ return 1;
}
}