diff options
| author | Bent Bisballe Nyeng <deva@aasimon.org> | 2021-07-10 21:17:49 +0200 | 
|---|---|---|
| committer | Bent Bisballe Nyeng <deva@aasimon.org> | 2021-07-10 23:43:37 +0200 | 
| commit | 23b150fd0dedc012e85b405ec92bc3adacfe9959 (patch) | |
| tree | 2f919e89b74906eb15c14ff89e2936dab2936b74 /build.cc | |
| parent | bfbb506ff1a5e87401d4aa633f0707d1238082d0 (diff) | |
Individual target builds.
Diffstat (limited to 'build.cc')
| -rw-r--r-- | build.cc | 166 | 
1 files changed, 166 insertions, 0 deletions
| diff --git a/build.cc b/build.cc new file mode 100644 index 0000000..6302a18 --- /dev/null +++ b/build.cc @@ -0,0 +1,166 @@ +#include "build.h" + +#include <future> +#include <vector> +#include <iostream> +#include <chrono> +#include <set> + +#include "tasks.h" + +using namespace std::chrono_literals; + +int build(const Settings& settings, +          const std::string& name, +          const std::list<std::shared_ptr<Task>>& tasks, +          const std::list<std::shared_ptr<Task>>& all_tasks) +{ +	if(settings.verbose > 1) +	{ +		std::cout << "Building '" << name << "'\n"; +	} + +	std::list<std::shared_ptr<Task>> dirtyTasks; +	for(auto task : tasks) +	{ +		if(task->dirty()) +		{ +			dirtyTasks.push_back(task); +		} +	} + +	if(dirtyTasks.empty()) +	{ +		std::cout << "Nothing to be done for '"<< name << "'\n"; +		return 0; +	} + +	std::list<std::future<int>> processes; + +	// Start all tasks +	bool done{false}; +	while(!done) +	{ +		bool started_one{false}; +		while(processes.size() < settings.parallel_processes) +		{ +			if(dirtyTasks.empty()) +			{ +				done = true; +				break; +			} + +			auto task = getNextTask(all_tasks, dirtyTasks); +			if(task == nullptr) +			{ +				break; +			} + +			processes.emplace_back( +				std::async(std::launch::async, +				           [task]() +				           { +					           return task->run(); +				           })); +			started_one = true; +			std::this_thread::sleep_for(2ms); +		} + +		for(auto process = processes.begin(); +		    process != processes.end(); +		    ++process) +		{ +			if(process->valid()) +			{ +				if(process->get() != 0) +				{ +					// TODO: Wait for other processes to finish before returning +					return 1; +				} +				processes.erase(process); +				break; +			} +		} + +		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 1; +		} +	} + +	return 0; +} + +namespace +{ +std::set<std::shared_ptr<Task>> getDepTasks(std::shared_ptr<Task> task) +{ +	std::set<std::shared_ptr<Task>> tasks; +	tasks.insert(task); + +	auto deps = task->getDependsTasks(); +	for(const auto& dep : deps) +	{ +		auto depSet = getDepTasks(dep); +		for(const auto& dep : depSet) +		{ +			tasks.insert(dep); +		} +	} + +	return tasks; +} +} + +int build(const Settings& settings, +          const std::string& name, +          const std::list<std::shared_ptr<Task>>& all_tasks) +{ +	bool task_found{false}; +	for(auto task : all_tasks) +	{ +		if(task->name() == name || task->target() == name) +		{ +			std::cout << name << "\n"; +			task_found = true; + +			auto depSet = getDepTasks(task); +			std::list<std::shared_ptr<Task>> ts; +			for(const auto& task : depSet) +			{ +				ts.push_back(task); +			} +			auto ret = build(settings, name, ts, all_tasks); +			if(ret != 0) +			{ +				return ret; +			} + +			break; +		} +	} + +	if(!task_found) +	{ +		std::cerr << "*** No rule to make target '" << name << "'.  Stop.\n"; +		return 1; +	} + +	return 0; +} | 
