From dafd592cf44c184f9d24e2216bbed5c23e4b23c2 Mon Sep 17 00:00:00 2001
From: Bent Bisballe Nyeng <deva@aasimon.org>
Date: Tue, 7 Jun 2022 18:06:57 +0200
Subject: Refactor the way task names are looked up.

---
 src/build.cc    |  8 +------
 src/task.cc     | 24 +++++++++++++++------
 src/task.h      | 16 +++++++++++++-
 src/task_ar.cc  | 42 +++++++++++++++++++-----------------
 src/task_ar.h   |  7 ++++--
 src/task_cc.cc  | 67 ++++++++++++++++++++-------------------------------------
 src/task_cc.h   |  4 +++-
 src/task_ld.cc  | 55 ++++++++++++++++++----------------------------
 src/task_ld.h   |  7 ++++--
 src/task_so.cc  | 33 ++++++++++++++++------------
 src/task_so.h   |  7 ++++--
 src/tasks.cc    |  2 +-
 src/unittest.cc |  2 +-
 src/util.cc     | 25 +++++++++++++++++++++
 src/util.h      |  1 +
 15 files changed, 164 insertions(+), 136 deletions(-)

(limited to 'src')

diff --git a/src/build.cc b/src/build.cc
index b0b4d06..cb830ac 100644
--- a/src/build.cc
+++ b/src/build.cc
@@ -162,13 +162,7 @@ int build(const Settings& settings,
 	bool task_found{false};
 	for(auto task : all_tasks)
 	{
-		if(task->target() == name || // match exact target output (ex. build/foo.o)
-
-		   (!task->derived() && // if non-derived task:
-		    ( task->buildConfig().target == name || // match name
-		      task->buildConfig().name == name ) // or target
-			  )
-			)
+		if(*task == name)
 		{
 			task_found = true;
 
diff --git a/src/task.cc b/src/task.cc
index b8fce06..3ec48f5 100644
--- a/src/task.cc
+++ b/src/task.cc
@@ -6,9 +6,14 @@
 #include <unistd.h>
 #include <iostream>
 
-Task::Task(const BuildConfiguration& config)
+#include "settings.h"
+
+Task::Task(const BuildConfiguration& config, const Settings& settings,
+           const std::string& sourceDir)
 	: config(config)
 	, output_system(config.system)
+	, settings(settings)
+	, sourceDir(sourceDir)
 {
 }
 
@@ -19,7 +24,7 @@ int Task::registerDepTasks(const std::set<std::shared_ptr<Task>>& tasks)
 		bool found{false};
 		for(const auto& task : tasks)
 		{
-			if(task->target() == depStr)
+			if(*task == depStr)
 			{
 				dependsTasks.insert(task);
 				found = true;
@@ -36,13 +41,18 @@ int Task::registerDepTasks(const std::set<std::shared_ptr<Task>>& tasks)
 	return 0;
 }
 
+bool Task::operator==(const std::string& depStr)
+{
+	return
+		name() == depStr ||
+		target() == depStr ||
+		sourceDir + "/" + target() == depStr ||
+		targetFile().string() == depStr
+		;
+}
+
 std::string Task::name() const
 {
-	// If config name is not set, use target instead.
-	if(config.name.empty())
-	{
-		return config.target;
-	}
 	return config.name;
 }
 
diff --git a/src/task.h b/src/task.h
index 47f4d1b..a43e08f 100644
--- a/src/task.h
+++ b/src/task.h
@@ -8,6 +8,7 @@
 #include <atomic>
 #include <set>
 #include <memory>
+#include <filesystem>
 
 #include "libctor.h"
 
@@ -20,13 +21,18 @@ enum class State
 	Error,
 };
 
+struct Settings;
+
 class Task
 {
 public:
-	Task(const BuildConfiguration& config);
+	Task(const BuildConfiguration& config, const Settings& settings,
+	     const std::string& sourceDir);
 
 	int registerDepTasks(const std::set<std::shared_ptr<Task>>& tasks);
 
+	bool operator==(const std::string& dep);
+
 	virtual std::string name() const;
 	bool dirty();
 	bool ready();
@@ -34,8 +40,14 @@ public:
 	State state() const;
 	virtual int clean() = 0 ;
 	virtual std::vector<std::string> depends() const = 0;
+
+	//! Raw target name as stated in ctor.cc config file or (in case of a derived
+	//! target) the calculated target without builddir prefix.
 	virtual std::string target() const = 0;
 
+	//! Target file with full path prefix
+	virtual std::filesystem::path targetFile() const = 0;
+
 	//! Returns true for tasks that are non-target tasks, ie. for example derived
 	//! objects files from target sources.
 	virtual bool derived() const = 0;
@@ -67,4 +79,6 @@ protected:
 	TargetType target_type{TargetType::Auto};
 	Language source_language{Language::Auto};
 	OutputSystem output_system{OutputSystem::Host};
+	const Settings& settings;
+	std::string sourceDir;
 };
diff --git a/src/task_ar.cc b/src/task_ar.cc
index 086ffa1..5a86ead 100644
--- a/src/task_ar.cc
+++ b/src/task_ar.cc
@@ -15,16 +15,15 @@ TaskAR::TaskAR(const BuildConfiguration& config,
                const Settings& settings,
                const std::string& target,
                const std::vector<std::string>& objects,
-               const std::string& sourcePath)
-	: Task(config)
+               const std::string& sourceDir)
+	: Task(config, settings, sourceDir)
 	, config(config)
 	, settings(settings)
+	, sourceDir(sourceDir)
 {
-	std::filesystem::path base = settings.builddir;
-	base /= sourcePath;
-	std::filesystem::create_directories(base);
+	std::filesystem::create_directories(std::filesystem::path(settings.builddir) / sourceDir);
 
-	targetFile = base / target;
+	_targetFile = target;
 	for(const auto& object : objects)
 	{
 		std::filesystem::path objectFile = object;
@@ -34,12 +33,10 @@ TaskAR::TaskAR(const BuildConfiguration& config,
 
 	for(const auto& dep : config.depends)
 	{
-		std::filesystem::path depFile = settings.builddir;
-		depFile /= dep;
-		depFiles.push_back(depFile);
+		depFiles.push_back(dep);
 	}
 
-	flagsFile = base / targetFile.stem();
+	flagsFile = std::filesystem::path(settings.builddir) / cleanUp(sourceDir) / targetFile().stem();
 	flagsFile += ".flags";
 
 	target_type = TargetType::StaticLibrary;
@@ -57,7 +54,7 @@ TaskAR::TaskAR(const BuildConfiguration& config,
 
 bool TaskAR::dirtyInner()
 {
-	if(!std::filesystem::exists(targetFile))
+	if(!std::filesystem::exists(targetFile()))
 	{
 		return true;
 	}
@@ -83,10 +80,10 @@ int TaskAR::runInner()
 {
 	std::vector<std::string> args;
 	args.push_back("rcs");
-	args.push_back(targetFile.string());
+	args.push_back(targetFile().string());
 	for(const auto& task : getDependsTasks())
 	{
-		args.push_back(task->target());
+		args.push_back(task->targetFile().string());
 	}
 
 	{ // Write flags to file.
@@ -96,7 +93,7 @@ int TaskAR::runInner()
 
 	if(settings.verbose == 0)
 	{
-		std::cout << "AR => " << targetFile.string() << "\n";
+		std::cout << "AR => " << targetFile().string() << "\n";
 	}
 
 	std::string tool;
@@ -115,10 +112,10 @@ int TaskAR::runInner()
 
 int TaskAR::clean()
 {
-	if(std::filesystem::exists(targetFile))
+	if(std::filesystem::exists(targetFile()))
 	{
-		std::cout << "Removing " << targetFile.string() << "\n";
-		std::filesystem::remove(targetFile);
+		std::cout << "Removing " << targetFile().string() << "\n";
+		std::filesystem::remove(targetFile());
 	}
 
 	if(std::filesystem::exists(flagsFile))
@@ -138,9 +135,9 @@ std::vector<std::string> TaskAR::depends() const
 		deps.push_back(objectFile.string());
 	}
 
-	for(const auto& depFile : depFiles)
+	for(const auto& dep : config.depends)
 	{
-		deps.push_back(depFile.string());
+		deps.push_back(dep);
 	}
 
 	return deps;
@@ -148,7 +145,12 @@ std::vector<std::string> TaskAR::depends() const
 
 std::string TaskAR::target() const
 {
-	return targetFile.string();
+	return _targetFile.string();
+}
+
+std::filesystem::path TaskAR::targetFile() const
+{
+	return std::filesystem::path(settings.builddir) / sourceDir / _targetFile;
 }
 
 bool TaskAR::derived() const
diff --git a/src/task_ar.h b/src/task_ar.h
index d021a2e..c76a852 100644
--- a/src/task_ar.h
+++ b/src/task_ar.h
@@ -21,7 +21,7 @@ public:
 	       const Settings& settings,
 	       const std::string& target,
 	       const std::vector<std::string>& objects,
-	       const std::string& sourcePath);
+	       const std::string& sourceDir);
 	virtual ~TaskAR() = default;
 
 	bool dirtyInner() override;
@@ -32,6 +32,8 @@ public:
 	std::vector<std::string> depends() const override;
 
 	std::string target() const override;
+	std::filesystem::path targetFile() const override;
+
 	bool derived() const override;
 
 private:
@@ -39,9 +41,10 @@ private:
 
 	std::vector<std::filesystem::path> objectFiles;
 	std::vector<std::filesystem::path> depFiles;
-	std::filesystem::path targetFile;
+	std::filesystem::path _targetFile;
 	std::filesystem::path flagsFile;
 
 	const BuildConfiguration& config;
 	const Settings& settings;
+	std::string sourceDir;
 };
diff --git a/src/task_cc.cc b/src/task_cc.cc
index 1db9767..41a97f3 100644
--- a/src/task_cc.cc
+++ b/src/task_cc.cc
@@ -12,34 +12,9 @@
 #include "execute.h"
 #include "util.h"
 
-namespace
-{
-bool isClean(char c)
-{
-	return c != '.' && c != '/';
-}
-
-std::string cleanUp(const std::string& path)
-{
-	std::string cleaned;
-	for(const auto& c : path)
-	{
-		if(isClean(c))
-		{
-			cleaned += c;
-		}
-		else
-		{
-			cleaned += '_';
-		}
-	}
-	return cleaned;
-}
-}
-
 TaskCC::TaskCC(const BuildConfiguration& config, const Settings& settings,
                const std::string& sourceDir, const Source& source)
-	: Task(config)
+	: Task(config, settings, sourceDir)
 	, config(config)
 	, settings(settings)
 	, sourceDir(sourceDir)
@@ -47,9 +22,8 @@ TaskCC::TaskCC(const BuildConfiguration& config, const Settings& settings,
 	sourceFile = sourceDir;
 	sourceFile /= source.file;
 
-	std::filesystem::path base = settings.builddir;
-	base /= sourceFile.parent_path();
-	std::filesystem::create_directories(base);
+	std::filesystem::path base = sourceFile.parent_path();
+	std::filesystem::create_directories(std::filesystem::path(settings.builddir) / base);
 
 	base /= cleanUp(config.target);
 	base += "-";
@@ -78,17 +52,17 @@ TaskCC::TaskCC(const BuildConfiguration& config, const Settings& settings,
 		break;
 	}
 
-	targetFile = base;
-	targetFile += ".o";
-	depsFile = base;
+	_targetFile = base;
+	_targetFile += ".o";
+	depsFile = targetFile().parent_path() / targetFile().stem();
 	depsFile += ".d";
-	flagsFile = base;
+	flagsFile = targetFile().parent_path() / targetFile().stem();
 	flagsFile += ".flags";
 }
 
 std::string TaskCC::name() const
 {
-	return target();
+	return {};
 }
 
 bool TaskCC::dirtyInner()
@@ -99,7 +73,7 @@ bool TaskCC::dirtyInner()
 		return true;
 	}
 
-	if(!std::filesystem::exists(targetFile))
+	if(!std::filesystem::exists(targetFile()))
 	{
 		//std::cout << "Missing targetFile\n";
 		return true;
@@ -137,7 +111,7 @@ bool TaskCC::dirtyInner()
 	for(const auto& dep : depList)
 	{
 		if(!std::filesystem::exists(dep) ||
-		   std::filesystem::last_write_time(targetFile) <
+		   std::filesystem::last_write_time(targetFile()) <
 		   std::filesystem::last_write_time(dep))
 		{
 			//std::cout << "The targetFile older than " << std::string(dep) << "\n";
@@ -146,7 +120,7 @@ bool TaskCC::dirtyInner()
 	}
 
 	if(std::filesystem::last_write_time(sourceFile) >
-	   std::filesystem::last_write_time(targetFile))
+	   std::filesystem::last_write_time(targetFile()))
 	{
 		//std::cout << "The targetFile older than sourceFile\n";
 		return true;
@@ -174,7 +148,7 @@ int TaskCC::runInner()
 	{
 		std::cout << compiler() << " " <<
 			sourceFile.lexically_normal().string() << " => " <<
-			targetFile.lexically_normal().string() << "\n";
+			targetFile().lexically_normal().string() << "\n";
 	}
 
 	return execute(compiler(), args, settings.verbose > 0);
@@ -182,10 +156,10 @@ int TaskCC::runInner()
 
 int TaskCC::clean()
 {
-	if(std::filesystem::exists(targetFile))
+	if(std::filesystem::exists(targetFile()))
 	{
-		std::cout << "Removing " << targetFile.string() << "\n";
-		std::filesystem::remove(targetFile);
+		std::cout << "Removing " << targetFile().string() << "\n";
+		std::filesystem::remove(targetFile());
 	}
 
 	if(std::filesystem::exists(depsFile))
@@ -210,7 +184,12 @@ std::vector<std::string> TaskCC::depends() const
 
 std::string TaskCC::target() const
 {
-	return targetFile.string();
+	return _targetFile.string();
+}
+
+std::filesystem::path TaskCC::targetFile() const
+{
+	return std::filesystem::path(settings.builddir) / _targetFile;
 }
 
 bool TaskCC::derived() const
@@ -224,7 +203,7 @@ std::string TaskCC::toJSON() const
 	json += "\t{\n";
 	json += "\t\t\"directory\": \"" + sourceDir.string() + "\",\n";
 	json += "\t\t\"file\": \"" + sourceFile.lexically_normal().string() + "\",\n";
-	json += "\t\t\"output\": \"" + targetFile.string() + "\",\n";
+	json += "\t\t\"output\": \"" + targetFile().string() + "\",\n";
 	json += "\t\t\"arguments\": [ \"" + compiler() + "\"";
 	auto args = getCompilerArgs();
 	for(const auto& arg : args)
@@ -282,7 +261,7 @@ std::vector<std::string> TaskCC::getCompilerArgs() const
 	args.push_back("-c");
 	args.push_back(sourceFile.string());
 	args.push_back("-o");
-	args.push_back(targetFile.string());
+	args.push_back(targetFile().string());
 
 	for(const auto& flag : compiler_flags)
 	{
diff --git a/src/task_cc.h b/src/task_cc.h
index 4ba5679..26c81a4 100644
--- a/src/task_cc.h
+++ b/src/task_cc.h
@@ -31,6 +31,8 @@ public:
 	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;
@@ -43,7 +45,7 @@ protected:
 	std::vector<std::string> getCompilerArgs() const;
 
 	std::filesystem::path sourceFile;
-	std::filesystem::path targetFile;
+	std::filesystem::path _targetFile;
 	std::filesystem::path depsFile;
 	std::filesystem::path flagsFile;
 
diff --git a/src/task_ld.cc b/src/task_ld.cc
index 600de8e..e78a1e6 100644
--- a/src/task_ld.cc
+++ b/src/task_ld.cc
@@ -9,31 +9,17 @@
 #include "libctor.h"
 #include "settings.h"
 #include "execute.h"
-
-namespace
-{
-std::string readFile(const std::string &fileName)
-{
-	std::ifstream ifs(fileName.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
-
-	std::ifstream::pos_type fileSize = ifs.tellg();
-	ifs.seekg(0, std::ios::beg);
-
-	std::vector<char> bytes(fileSize);
-	ifs.read(bytes.data(), fileSize);
-
-	return std::string(bytes.data(), fileSize);
-}
-} // namespace ::
+#include "util.h"
 
 TaskLD::TaskLD(const BuildConfiguration& config,
                const Settings& settings,
                const std::string& target,
                const std::vector<std::string>& objects,
-               const std::string& sourcePath)
-	: Task(config)
+               const std::string& sourceDir)
+	: Task(config, settings, sourceDir)
 	, config(config)
 	, settings(settings)
+	, sourceDir(sourceDir)
 {
 	target_type = config.type;
 	if(target_type == TargetType::Auto)
@@ -41,11 +27,9 @@ TaskLD::TaskLD(const BuildConfiguration& config,
 		target_type = TargetType::Executable;
 	}
 
-	std::filesystem::path base = settings.builddir;
-	base /= sourcePath;
-	std::filesystem::create_directories(base);
+	std::filesystem::create_directories(std::filesystem::path(settings.builddir) / sourceDir);
 
-	targetFile = base / target;
+	_targetFile = target;
 	for(const auto& object : objects)
 	{
 		std::filesystem::path objectFile = object;
@@ -55,12 +39,10 @@ TaskLD::TaskLD(const BuildConfiguration& config,
 
 	for(const auto& dep : config.depends)
 	{
-		std::filesystem::path depFile = settings.builddir;
-		depFile /= dep;
-		depFiles.push_back(depFile);
+		depFiles.push_back(dep);
 	}
 
-	flagsFile = base / targetFile.stem();
+	flagsFile = std::filesystem::path(settings.builddir) / cleanUp(sourceDir) / targetFile().stem();
 	flagsFile += ".flags";
 
 	source_language = Language::C;
@@ -76,7 +58,7 @@ TaskLD::TaskLD(const BuildConfiguration& config,
 
 bool TaskLD::dirtyInner()
 {
-	if(!std::filesystem::exists(targetFile))
+	if(!std::filesystem::exists(targetFile()))
 	{
 		return true;
 	}
@@ -103,7 +85,7 @@ int TaskLD::runInner()
 	std::vector<std::string> args;
 	for(const auto& dep : getDependsTasks())
 	{
-		std::filesystem::path depFile = dep->target();
+		auto depFile = dep->targetFile();
 		if(depFile.extension() == ".so")
 		{
 			args.push_back(std::string("-L") + settings.builddir);
@@ -121,7 +103,7 @@ int TaskLD::runInner()
 		args.push_back(flag);
 	}
 	args.push_back("-o");
-	args.push_back(targetFile.string());
+	args.push_back(targetFile().string());
 
 	{ // Write flags to file.
 		std::ofstream flagsStream(flagsFile);
@@ -130,7 +112,7 @@ int TaskLD::runInner()
 
 	if(settings.verbose == 0)
 	{
-		std::cout << "LD => " << targetFile.string() << "\n";
+		std::cout << "LD => " << targetFile().string() << "\n";
 	}
 
 	auto tool = compiler();
@@ -139,10 +121,10 @@ int TaskLD::runInner()
 
 int TaskLD::clean()
 {
-	if(std::filesystem::exists(targetFile))
+	if(std::filesystem::exists(targetFile()))
 	{
-		std::cout << "Removing " << targetFile.string() << "\n";
-		std::filesystem::remove(targetFile);
+		std::cout << "Removing " << targetFile().string() << "\n";
+		std::filesystem::remove(targetFile());
 	}
 
 	if(std::filesystem::exists(flagsFile))
@@ -172,7 +154,12 @@ std::vector<std::string> TaskLD::depends() const
 
 std::string TaskLD::target() const
 {
-	return targetFile.string();
+	return _targetFile.string();
+}
+
+std::filesystem::path TaskLD::targetFile() const
+{
+	return std::filesystem::path(settings.builddir) / sourceDir / _targetFile;
 }
 
 bool TaskLD::derived() const
diff --git a/src/task_ld.h b/src/task_ld.h
index 08d5a22..8625075 100644
--- a/src/task_ld.h
+++ b/src/task_ld.h
@@ -21,7 +21,7 @@ public:
 	       const Settings& settings,
 	       const std::string& target,
 	       const std::vector<std::string>& objects,
-	       const std::string& sourcePath);
+	       const std::string& _sourceDir);
 	virtual ~TaskLD() = default;
 
 	bool dirtyInner() override;
@@ -32,6 +32,8 @@ public:
 	std::vector<std::string> depends() const override;
 
 	std::string target() const override;
+	std::filesystem::path targetFile() const override;
+
 	bool derived() const override;
 
 private:
@@ -39,9 +41,10 @@ private:
 
 	std::vector<std::filesystem::path> objectFiles;
 	std::vector<std::filesystem::path> depFiles;
-	std::filesystem::path targetFile;
+	std::filesystem::path _targetFile;
 	std::filesystem::path flagsFile;
 
 	const BuildConfiguration& config;
 	const Settings& settings;
+	std::string sourceDir;
 };
diff --git a/src/task_so.cc b/src/task_so.cc
index 44340dd..34de2bb 100644
--- a/src/task_so.cc
+++ b/src/task_so.cc
@@ -15,16 +15,16 @@ TaskSO::TaskSO(const BuildConfiguration& config,
                const Settings& settings,
                const std::string& target,
                const std::vector<std::string>& objects,
-               const std::string& sourcePath)
-	: Task(config)
+               const std::string& sourceDir)
+	: Task(config, settings, sourceDir)
 	, config(config)
 	, settings(settings)
+	, sourceDir(sourceDir)
 {
-	std::filesystem::path base = settings.builddir;
-	base /= sourcePath;
-	std::filesystem::create_directories(base);
+	std::filesystem::path base = sourceDir;
+	std::filesystem::create_directories(std::filesystem::path(settings.builddir) / base);
 
-	targetFile = base / target;
+	_targetFile = base / target;
 	for(const auto& object : objects)
 	{
 		std::filesystem::path objectFile = object;
@@ -39,7 +39,7 @@ TaskSO::TaskSO(const BuildConfiguration& config,
 		depFiles.push_back(depFile);
 	}
 
-	flagsFile = base / targetFile.stem();
+	flagsFile = std::filesystem::path(settings.builddir) / cleanUp(sourceDir) / targetFile().stem();
 	flagsFile += ".flags";
 
 	target_type = TargetType::DynamicLibrary;
@@ -57,7 +57,7 @@ TaskSO::TaskSO(const BuildConfiguration& config,
 
 bool TaskSO::dirtyInner()
 {
-	if(!std::filesystem::exists(targetFile))
+	if(!std::filesystem::exists(targetFile()))
 	{
 		return true;
 	}
@@ -87,7 +87,7 @@ int TaskSO::runInner()
 	args.push_back("-shared");
 
 	args.push_back("-o");
-	args.push_back(targetFile.string());
+	args.push_back(targetFile().string());
 
 	for(const auto& task : getDependsTasks())
 	{
@@ -111,7 +111,7 @@ int TaskSO::runInner()
 
 	if(settings.verbose == 0)
 	{
-		std::cout << "LD => " << targetFile.string() << "\n";
+		std::cout << "LD => " << targetFile().string() << "\n";
 	}
 
 	auto tool = compiler();
@@ -120,10 +120,10 @@ int TaskSO::runInner()
 
 int TaskSO::clean()
 {
-	if(std::filesystem::exists(targetFile))
+	if(std::filesystem::exists(targetFile()))
 	{
-		std::cout << "Removing " << targetFile.string() << "\n";
-		std::filesystem::remove(targetFile);
+		std::cout << "Removing " << targetFile().string() << "\n";
+		std::filesystem::remove(targetFile());
 	}
 
 	if(std::filesystem::exists(flagsFile))
@@ -153,7 +153,12 @@ std::vector<std::string> TaskSO::depends() const
 
 std::string TaskSO::target() const
 {
-	return targetFile.string();
+	return _targetFile.string();
+}
+
+std::filesystem::path TaskSO::targetFile() const
+{
+	return std::filesystem::path(settings.builddir) / sourceDir / _targetFile;
 }
 
 bool TaskSO::derived() const
diff --git a/src/task_so.h b/src/task_so.h
index abd43c4..fe5d2fd 100644
--- a/src/task_so.h
+++ b/src/task_so.h
@@ -21,7 +21,7 @@ public:
 	       const Settings& settings,
 	       const std::string& target,
 	       const std::vector<std::string>& objects,
-	       const std::string& sourcePath);
+	       const std::string& sourceDir);
 	virtual ~TaskSO() = default;
 
 	bool dirtyInner() override;
@@ -32,6 +32,8 @@ public:
 	std::vector<std::string> depends() const override;
 
 	std::string target() const override;
+	std::filesystem::path targetFile() const override;
+
 	bool derived() const override;
 
 private:
@@ -39,9 +41,10 @@ private:
 
 	std::vector<std::filesystem::path> objectFiles;
 	std::vector<std::filesystem::path> depFiles;
-	std::filesystem::path targetFile;
+	std::filesystem::path _targetFile;
 	std::filesystem::path flagsFile;
 
 	const BuildConfiguration& config;
 	const Settings& settings;
+	std::string sourceDir;
 };
diff --git a/src/tasks.cc b/src/tasks.cc
index 8bb8de6..f24f3cb 100644
--- a/src/tasks.cc
+++ b/src/tasks.cc
@@ -112,7 +112,7 @@ std::set<std::shared_ptr<Task>> taskFactory(const BuildConfiguration& config,
 	{
 		auto task = std::make_shared<TaskCC>(config, settings, sourceDir, file);
 		tasks.insert(task);
-		objects.push_back(task->target());
+		objects.push_back(task->targetFile().string());
 	}
 
 	switch(target_type)
diff --git a/src/unittest.cc b/src/unittest.cc
index d02e4f2..ab82ab9 100644
--- a/src/unittest.cc
+++ b/src/unittest.cc
@@ -20,7 +20,7 @@ int runUnitTests(std::set<std::shared_ptr<Task>>& tasks,
 		if(task->targetType() == TargetType::UnitTest)
 		{
 			std::cout << task->name() << ": ";
-			auto ret = execute(task->target(), {}, false);
+			auto ret = execute(task->targetFile(), {}, false);
 			ok &= ret == 0;
 			if(ret == 0)
 			{
diff --git a/src/util.cc b/src/util.cc
index 9bf83cc..92560b6 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -110,3 +110,28 @@ Language languageFromExtension(const std::filesystem::path& file)
 	exit(1);
 	return {};
 }
+
+namespace
+{
+bool isClean(char c)
+{
+	return c != '.' && c != '/';
+}
+}
+
+std::string cleanUp(const std::string& path)
+{
+	std::string cleaned;
+	for(const auto& c : path)
+	{
+		if(isClean(c))
+		{
+			cleaned += c;
+		}
+		else
+		{
+			cleaned += '_';
+		}
+	}
+	return cleaned;
+}
diff --git a/src/util.h b/src/util.h
index dc9cd41..d164fbf 100644
--- a/src/util.h
+++ b/src/util.h
@@ -11,3 +11,4 @@
 std::string readFile(const std::string& fileName);
 std::vector<std::string> readDeps(const std::string& depFile);
 Language languageFromExtension(const std::filesystem::path& file);
+std::string cleanUp(const std::string& path);
-- 
cgit v1.2.3