diff options
| -rw-r--r-- | ctor.cc | 1 | ||||
| -rw-r--r-- | src/libctor.h | 9 | ||||
| -rw-r--r-- | src/task.cc | 2 | ||||
| -rw-r--r-- | src/task.h | 1 | ||||
| -rw-r--r-- | src/task_cc.cc | 14 | ||||
| -rw-r--r-- | src/task_cc.h | 3 | ||||
| -rw-r--r-- | src/task_fn.cc | 121 | ||||
| -rw-r--r-- | src/task_fn.h | 47 | ||||
| -rw-r--r-- | src/tasks.cc | 33 | ||||
| -rw-r--r-- | test/ctor.cc | 1 | 
10 files changed, 225 insertions, 7 deletions
| @@ -21,6 +21,7 @@ BuildConfigurations ctorConfigs(const Settings& settings)  				"src/rebuild.cc",  				"src/task.cc",  				"src/task_ar.cc", +				"src/task_fn.cc",  				"src/task_cc.cc",  				"src/task_ld.cc",  				"src/task_so.cc", diff --git a/src/libctor.h b/src/libctor.h index b539910..14fdf1d 100644 --- a/src/libctor.h +++ b/src/libctor.h @@ -9,6 +9,7 @@  #include <map>  #include <variant>  #include <cstddef> +#include <functional>  enum class TargetType  { @@ -20,6 +21,7 @@ enum class TargetType  	Object,  	UnitTest,  	UnitTestLib, +	Function,  };  enum class Language @@ -69,6 +71,12 @@ struct Settings  	int verbose{0}; // -1: completely silent, 0: normal, 1: verbose, ...  }; +struct BuildConfiguration; +using GeneratorCb = std::function<int(const std::string& input, +                                      const std::string& output, +                                      const BuildConfiguration& config, +                                      const Settings& settings)>; +  struct BuildConfiguration  {  	std::string name; // Name - used for referring in other configurations. @@ -79,6 +87,7 @@ struct BuildConfiguration  	std::vector<std::string> depends; // internal target dependencies  	Flags flags;  	std::vector<std::string> externals; // externals used by this configuration +	GeneratorCb function;  };  using BuildConfigurations = std::vector<BuildConfiguration>; diff --git a/src/task.cc b/src/task.cc index 37e1879..fb50765 100644 --- a/src/task.cc +++ b/src/task.cc @@ -36,7 +36,7 @@ int Task::registerDepTasks(const std::set<std::shared_ptr<Task>>& tasks)  		}  	} -	return 0; +	return registerDepTasksInner(tasks);  }  bool Task::operator==(const std::string& depStr) @@ -30,6 +30,7 @@ public:  	     const std::string& sourceDir);  	int registerDepTasks(const std::set<std::shared_ptr<Task>>& tasks); +	virtual int registerDepTasksInner(const std::set<std::shared_ptr<Task>>& tasks) { return 0; }  	bool operator==(const std::string& dep); diff --git a/src/task_cc.cc b/src/task_cc.cc index ee25abf..a55a619 100644 --- a/src/task_cc.cc +++ b/src/task_cc.cc @@ -17,6 +17,7 @@ TaskCC::TaskCC(const BuildConfiguration& config, const Settings& settings,  	, config(config)  	, settings(settings)  	, sourceDir(sourceDir) +	, _source(source)  {  	sourceFile = sourceDir;  	sourceFile /= source.file; @@ -66,6 +67,19 @@ TaskCC::TaskCC(const BuildConfiguration& config, const Settings& settings,  	flagsFile += ".flags";  } +int TaskCC::registerDepTasksInner(const std::set<std::shared_ptr<Task>>& tasks) +{ +	for(const auto& task : tasks) +	{ +		if(*task == _source.file) +		{ +			dependsTasks.insert(task); +		} +	} + +	return 0; +} +  std::string TaskCC::name() const  {  	return {}; diff --git a/src/task_cc.h b/src/task_cc.h index 26c81a4..0a0d96a 100644 --- a/src/task_cc.h +++ b/src/task_cc.h @@ -22,6 +22,8 @@ public:  	       const std::string& sourceDir, const Source& source);  	virtual ~TaskCC() = default; +	int registerDepTasksInner(const std::set<std::shared_ptr<Task>>& tasks) override; +  	std::string name() const override;  	bool dirtyInner() override; @@ -52,4 +54,5 @@ protected:  	const BuildConfiguration& config;  	const Settings& settings;  	std::filesystem::path sourceDir; +	const Source& _source;  }; diff --git a/src/task_fn.cc b/src/task_fn.cc new file mode 100644 index 0000000..ab00fae --- /dev/null +++ b/src/task_fn.cc @@ -0,0 +1,121 @@ +// -*- c++ -*- +// Distributed under the BSD 2-Clause License. +// See accompanying file LICENSE for details. +#include "task_fn.h" + +#include <iostream> +#include <fstream> +#include <cassert> + +#include "libctor.h" +#include "execute.h" +#include "util.h" + +TaskFn::TaskFn(const BuildConfiguration& config, const Settings& settings, +               const std::string& sourceDir, const Source& source) +	: Task(config, settings, sourceDir) +	, config(config) +	, settings(settings) +{ +	sourceFile = sourceDir; +	sourceFile /= source.file; + +	std::filesystem::create_directories(std::filesystem::path(settings.builddir) / sourceFile.parent_path()); + +	target_type = config.type; +	source_language = source.language; + +	if(source.output.empty()) +	{ +		std::cerr << "Missing output file for functional target\n"; +		exit(1); +	} + +	_targetFile = source.output; +} + +bool TaskFn::dirtyInner() +{ +	if(!std::filesystem::exists(sourceFile)) +	{ +		//std::cout << "Missing source file: " << std::string(sourceFile) << "\n"; +		return true; +	} + +	if(!std::filesystem::exists(targetFile())) +	{ +		//std::cout << "Missing targetFile\n"; +		return true; +	} + +	if(std::filesystem::last_write_time(sourceFile) > +	   std::filesystem::last_write_time(targetFile())) +	{ +		//std::cout << "The targetFile older than sourceFile\n"; +		return true; +	} + +	return false; +} + +int TaskFn::runInner() +{ +	if(!std::filesystem::exists(sourceFile)) +	{ +		std::cout << "Missing source file: " << sourceFile.string() << "\n"; +		return 1; +	} + +	if(settings.verbose >= 0) +	{ +		std::cout << "Fn" << " " << +			sourceFile.lexically_normal().string() << " => " << +			targetFile().lexically_normal().string() << "\n"; +	} + +	return config.function(sourceFile.string(), +	                       targetFile().string(), +	                       config, +	                       settings); +} + +int TaskFn::clean() +{ +	if(std::filesystem::exists(targetFile())) +	{ +		std::cout << "Removing " << targetFile().string() << "\n"; +		std::filesystem::remove(targetFile()); +	} + +	return 0; +} + +std::vector<std::string> TaskFn::depends() const +{ +	return {}; +} + +std::string TaskFn::target() const +{ +	return _targetFile; +} + +std::filesystem::path TaskFn::targetFile() const +{ +	return std::filesystem::path(settings.builddir) / sourceDir / _targetFile; +} + +bool TaskFn::derived() const +{ +	return false; +} + +std::string TaskFn::toJSON() const +{ +	return {}; // TODO: Not sure how to express this... +} + +std::string TaskFn::source() const +{ +	return sourceFile.string(); +} diff --git a/src/task_fn.h b/src/task_fn.h new file mode 100644 index 0000000..e350395 --- /dev/null +++ b/src/task_fn.h @@ -0,0 +1,47 @@ +// -*- c++ -*- +// Distributed under the BSD 2-Clause License. +// See accompanying file LICENSE for details. +#pragma once + +#include "task.h" + +#include <vector> +#include <string> +#include <future> +#include <filesystem> + +struct BuildConfiguration; +struct Settings; + +class TaskFn +	: public Task +{ +public: +	TaskFn(const BuildConfiguration& config, +	       const Settings& settings, +	       const std::string& sourceDir, const Source& source); +	virtual ~TaskFn() = default; + +	bool dirtyInner() override; + +	int runInner() override; +	int clean() override; + +	std::vector<std::string> depends() const override; + +	std::string target() const override; +	std::filesystem::path targetFile() const override; +	bool derived() const override; + +	std::string toJSON() const override; + +	std::string source() const override; + +protected: +	std::filesystem::path sourceFile; +	std::filesystem::path _targetFile; + +	const BuildConfiguration& config; +	const Settings& settings; +	std::filesystem::path sourceDir; +}; diff --git a/src/tasks.cc b/src/tasks.cc index 646292a..68b2476 100644 --- a/src/tasks.cc +++ b/src/tasks.cc @@ -15,6 +15,7 @@  #include "task_ld.h"  #include "task_ar.h"  #include "task_so.h" +#include "task_fn.h"  #include "rebuild.h"  #include "configure.h" @@ -80,12 +81,18 @@ std::set<std::shared_ptr<Task>> taskFactory(const BuildConfiguration& config,                                              const Settings& settings,                                              const std::string& sourceDir)  { +	std::set<std::shared_ptr<Task>> tasks; +  	std::filesystem::path targetFile(config.target);  	TargetType target_type{config.type};  	if(target_type == TargetType::Auto)  	{ -		if(targetFile.extension() == ".a") +		if(config.function != nullptr) +		{ +			target_type = TargetType::Function; +		} +		else if(targetFile.extension() == ".a")  		{  			target_type = TargetType::StaticLibrary;  		} @@ -106,13 +113,26 @@ std::set<std::shared_ptr<Task>> taskFactory(const BuildConfiguration& config,  	}  	std::vector<std::string> objects; -	std::set<std::shared_ptr<Task>> tasks; -	for(const auto& file : config.sources) +	if(target_type != TargetType::Function)  	{ -		auto task = std::make_shared<TaskCC>(config, settings, sourceDir, file); -		tasks.insert(task); -		objects.push_back(task->targetFile().string()); +		for(const auto& file : config.sources) +		{ +			auto task = std::make_shared<TaskCC>(config, settings, sourceDir, file); +			tasks.insert(task); +			objects.push_back(task->targetFile().string()); +		}  	} +#ifndef BOOTSTRAP +	else +	{ +		for(const auto& file : config.sources) +		{ +			auto task = std::make_shared<TaskFn>(config, settings, sourceDir, file); +			tasks.insert(task); +			objects.push_back(task->target()); +		} +	} +#endif  	switch(target_type)  	{ @@ -144,6 +164,7 @@ std::set<std::shared_ptr<Task>> taskFactory(const BuildConfiguration& config,  		break;  	case TargetType::Object: +	case TargetType::Function:  		break;  #else  	default: diff --git a/test/ctor.cc b/test/ctor.cc index 7d7a53c..c24ded7 100644 --- a/test/ctor.cc +++ b/test/ctor.cc @@ -72,6 +72,7 @@ BuildConfigurations ctorTestConfigs(const Settings& settings)  				"../src/task.cc",  				"../src/task_ar.cc",  				"../src/task_cc.cc", +				"../src/task_fn.cc",  				"../src/task_ld.cc",  				"../src/task_so.cc",  				"../src/util.cc", | 
