summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ctor.cc1
-rw-r--r--src/libctor.h9
-rw-r--r--src/task.cc2
-rw-r--r--src/task.h1
-rw-r--r--src/task_cc.cc14
-rw-r--r--src/task_cc.h3
-rw-r--r--src/task_fn.cc121
-rw-r--r--src/task_fn.h47
-rw-r--r--src/tasks.cc33
-rw-r--r--test/ctor.cc1
10 files changed, 225 insertions, 7 deletions
diff --git a/ctor.cc b/ctor.cc
index f434a3d..d795ff9 100644
--- a/ctor.cc
+++ b/ctor.cc
@@ -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)
diff --git a/src/task.h b/src/task.h
index a43e08f..be3995f 100644
--- a/src/task.h
+++ b/src/task.h
@@ -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",