summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile9
-rw-r--r--libcppbuild.cc72
-rw-r--r--task.cc263
-rw-r--r--task.h30
-rw-r--r--task_cc.cc267
-rw-r--r--task_cc.h38
-rw-r--r--task_ld.cc89
-rw-r--r--task_ld.h38
8 files changed, 464 insertions, 342 deletions
diff --git a/Makefile b/Makefile
index 2462d3e..a7b0ee7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,13 @@
all: libcppbuild.a cppbuild
-libcppbuild.a: libcppbuild.cc task.cc libcppbuild.h
+libcppbuild.a: libcppbuild.cc libcppbuild.h task_cc.cc task_cc.h task_ld.cc task_ld.h task.h
g++ -g -std=c++17 libcppbuild.cc -c -o libcppbuild.o
- g++ -g -std=c++17 task.cc -c -o task.o
- ar rcs libcppbuild.a libcppbuild.o task.o
+ g++ -g -std=c++17 task_cc.cc -c -o task_cc.o
+ g++ -g -std=c++17 task_ld.cc -c -o task_ld.o
+ ar rcs libcppbuild.a libcppbuild.o task_cc.o task_ld.o
cppbuild: cppbuild.cc libcppbuild.h libcppbuild.a
g++ -g -std=c++17 cppbuild.cc libcppbuild.a -pthread -o cppbuild
clean:
- rm -f cppbuild libcppbuild.o task.o libcppbuild.a
+ rm -f cppbuild libcppbuild.o task_cc.o task_ld.o libcppbuild.a
diff --git a/libcppbuild.cc b/libcppbuild.cc
index 2167173..c75f43e 100644
--- a/libcppbuild.cc
+++ b/libcppbuild.cc
@@ -6,9 +6,11 @@
#include <list>
#include <chrono>
#include <thread>
+#include <memory>
#include "libcppbuild.h"
-#include "task.h"
+#include "task_cc.h"
+#include "task_ld.h"
#include "settings.h"
#include <unistd.h>
@@ -29,31 +31,33 @@ int main(int argc, const char* argv[])
std::filesystem::create_directories(builddir);
auto config = configs();
- std::string output = builddir / config.target;
- const auto& files = config.sources;
- std::vector<std::string> objects;
-
- std::vector<Task> tasks;
- for(const auto& file : files)
+ std::vector<std::string> objects;
+ std::vector<std::unique_ptr<Task>> tasks;
+ for(const auto& file : config.sources)
{
- tasks.emplace_back(config, settings, file);
- objects.push_back(tasks.back().target());
+ tasks.emplace_back(std::make_unique<TaskCC>(config, settings, file));
+ objects.push_back(tasks.back()->target());
}
+ TaskLD task_ld(config, settings, config.target, objects);
+
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)
+ if(task->clean() != 0)
{
return 1;
}
}
- std::filesystem::remove(output);
+ if(task_ld.clean() != 0)
+ {
+ return 1;
+ }
return 0;
}
@@ -69,7 +73,7 @@ int main(int argc, const char* argv[])
while(processes.size() < settings.parallel_processes &&
task != tasks.end())
{
- if(!task->dirty())
+ if(!(*task)->dirty())
{
++task;
continue;
@@ -77,9 +81,9 @@ int main(int argc, const char* argv[])
processes.emplace_back(
std::async(std::launch::async,
- [task]()
+ [&t = *task]()
{
- return task->run();
+ return t->run();
}));
++task;
std::this_thread::sleep_for(2ms);
@@ -108,49 +112,17 @@ int main(int argc, const char* argv[])
++process)
{
process->wait();
- if(process->get() != 0)
+ auto ret = process->get();
+ if(ret != 0)
{
return 1;
}
}
std::cout << "Linking\n";
- bool dolink{false};
- if(!std::filesystem::exists(output))
- {
- dolink = true;
- }
- else
- {
- for(const auto& object : objects)
- {
- if(std::filesystem::last_write_time(output) <=
- std::filesystem::last_write_time(object))
- {
- dolink = true;
- break;
- }
- }
- }
-
- if(!dolink)
- {
- std::cout << "No linking needed\n";
- return 0;
- }
-
- std::string objectlist;
- for(const auto& object : objects)
- {
- objectlist += object + " ";
- }
- std::string compiler = "g++ " + objectlist + " " +
- config.ldflags + " " +
- "-o " + output;
- std::cout << compiler << "\n";
- if(system(compiler.data()))
+ if(task_ld.dirty())
{
- return 1;
+ return task_ld.run();
}
return 0;
diff --git a/task.cc b/task.cc
index 030932e..e69de29 100644
--- a/task.cc
+++ b/task.cc
@@ -1,263 +0,0 @@
-#include "task.h"
-
-#include <iostream>
-#include <fstream>
-#include <unistd.h>
-#include <cstring>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <spawn.h>
-
-#include "libcppbuild.h"
-#include "settings.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);
-}
-
-std::vector<std::string> readDeps(const std::string& depFile)
-{
- if(!std::filesystem::exists(depFile))
- {
- return {};
- }
-
- auto str = readFile(depFile);
-
- std::vector<std::string> output;
- std::string tmp;
- bool start{false};
- bool in_whitespace{false};
- for(const auto& c : str)
- {
- if(c == '\\' || c == '\n')
- {
- continue;
- }
-
- if(c == ':')
- {
- start = true;
- continue;
- }
-
- if(!start)
- {
- continue;
- }
-
- if(c == ' ' || c == '\t')
- {
- if(in_whitespace)
- {
- continue;
- }
-
- if(!tmp.empty())
- {
- output.push_back(tmp);
- }
- tmp.clear();
- in_whitespace = true;
- }
- else
- {
- in_whitespace = false;
- tmp += c;
- }
- }
-
- if(!tmp.empty())
- {
- output.push_back(tmp);
- }
-
- return output;
-}
-} // namespace ::
-
-Task::Task(const BuildConfiguration& config, const Settings& settings,
- const std::string& source)
- : config(config)
- , settings(settings)
-{
- sourceFile = source;
- targetFile = settings.builddir / sourceFile.stem();
- targetFile += ".o";
- depsFile = settings.builddir / sourceFile.stem();
- depsFile += ".d";
-}
-
-bool Task::dirty()
-{
- 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::exists(depsFile))
- {
- //std::cout << "Missing depsFile\n";
- return true;
- }
-
- if(std::filesystem::last_write_time(sourceFile) >
- std::filesystem::last_write_time(depsFile))
- {
- //std::cout << "The sourceFile newer than depsFile\n";
- return true;
- }
-
- auto depList = readDeps(depsFile);
- for(const auto& dep : depList)
- {
- if(!std::filesystem::exists(dep) ||
- std::filesystem::last_write_time(targetFile) <
- std::filesystem::last_write_time(dep))
- {
- //std::cout << "The targetFile older than " << std::string(dep) << "\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 parent_waitpid(pid_t pid)
-{
- int status;
-
- if(waitpid(pid, &status, 0) != pid)
- {
- return 1;
- }
-
- return status;
-}
-int Task::run()
-{
- if(!std::filesystem::exists(sourceFile))
- {
- std::cout << "Missing source file: " << std::string(sourceFile) << "\n";
- return 1;
- }
-
- std::string comp = "/usr/bin/g++";
- auto flags = config.cxxflags;
- if(std::string(sourceFile.extension()) == ".c")
- {
- comp = "/usr/bin/gcc";
- flags = config.cflags;
- }
-
- char source[256];
- strcpy(source, std::string(sourceFile).data());
- char target[256];
- strcpy(target, std::string(targetFile).data());
- char pwd[256];
- strcpy(pwd, std::string(std::filesystem::current_path()).data());
- std::vector<const char*> argv;
- //args.push_back("/bin/echo");
- if(comp == "/usr/bin/gcc")
- {
- argv.push_back("/usr/bin/gcc");
- }
- else
- {
- argv.push_back("/usr/bin/g++");
- }
-
- argv.push_back("-MMD");
- argv.push_back("-c");
- argv.push_back(source);
- argv.push_back("-o");
- argv.push_back(target);
-
- for(const auto& flag : flags)
- {
- argv.push_back(flag.data());
- }
-
- std::string cmd;
- for(const auto& arg : argv)
- {
- if(arg == nullptr)
- {
- break;
- }
- if(!cmd.empty())
- {
- cmd += " ";
- }
- cmd += arg;
- }
- std::cout << cmd << "\n";
-
-#if 0
- auto pid = vfork();
- if(pid == 0)
- {
- execv(comp.data(), (char**)argv.data());
- }
-#else
- pid_t pid;
- if(posix_spawn(&pid, comp.data(), nullptr, nullptr, (char**)argv.data(), nullptr))
- {
- return 1;//exit(1);
- }
-#endif
-
- return parent_waitpid(pid);
-}
-
-int Task::clean()
-{
- if(std::filesystem::exists(targetFile))
- {
- std::cout << "Removing " << std::string(targetFile) << "\n";
- std::filesystem::remove(targetFile);
- }
-
- if(std::filesystem::exists(depsFile))
- {
- std::cout << "Removing " << std::string(depsFile) << "\n";
- std::filesystem::remove(depsFile);
- }
-
- return 0;
-}
-
-std::vector<std::string> Task::depends() const
-{
- return {};
-}
-
-std::string Task::target() const
-{
- return targetFile;
-}
diff --git a/task.h b/task.h
index bdd881b..443b6b7 100644
--- a/task.h
+++ b/task.h
@@ -3,33 +3,13 @@
#include <vector>
#include <string>
-#include <future>
-#include <filesystem>
-
-struct BuildConfiguration;
-struct Settings;
class Task
{
public:
- Task(const BuildConfiguration& config,
- const Settings& settings,
- const std::string& source);
-
- bool dirty();
-
- int run();
- int clean();
-
- std::vector<std::string> depends() const;
-
- std::string target() const;
-
-private:
- std::filesystem::path sourceFile;
- std::filesystem::path targetFile;
- std::filesystem::path depsFile;
-
- const BuildConfiguration& config;
- const Settings& settings;
+ virtual bool dirty() = 0;
+ virtual int run() = 0;
+ virtual int clean() = 0 ;
+ virtual std::vector<std::string> depends() const = 0;
+ virtual std::string target() const = 0;
};
diff --git a/task_cc.cc b/task_cc.cc
new file mode 100644
index 0000000..2a65698
--- /dev/null
+++ b/task_cc.cc
@@ -0,0 +1,267 @@
+#include "task_cc.h"
+
+#include <iostream>
+#include <fstream>
+#include <unistd.h>
+#include <cstring>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <spawn.h>
+
+#include "libcppbuild.h"
+#include "settings.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);
+}
+
+std::vector<std::string> readDeps(const std::string& depFile)
+{
+ if(!std::filesystem::exists(depFile))
+ {
+ return {};
+ }
+
+ auto str = readFile(depFile);
+
+ std::vector<std::string> output;
+ std::string tmp;
+ bool start{false};
+ bool in_whitespace{false};
+ for(const auto& c : str)
+ {
+ if(c == '\\' || c == '\n')
+ {
+ continue;
+ }
+
+ if(c == ':')
+ {
+ start = true;
+ continue;
+ }
+
+ if(!start)
+ {
+ continue;
+ }
+
+ if(c == ' ' || c == '\t')
+ {
+ if(in_whitespace)
+ {
+ continue;
+ }
+
+ if(!tmp.empty())
+ {
+ output.push_back(tmp);
+ }
+ tmp.clear();
+ in_whitespace = true;
+ }
+ else
+ {
+ in_whitespace = false;
+ tmp += c;
+ }
+ }
+
+ if(!tmp.empty())
+ {
+ output.push_back(tmp);
+ }
+
+ return output;
+}
+} // namespace ::
+
+TaskCC::TaskCC(const BuildConfiguration& config, const Settings& settings,
+ const std::string& source)
+ : config(config)
+ , settings(settings)
+{
+ sourceFile = source;
+ targetFile = settings.builddir / sourceFile.stem();
+ targetFile += ".o";
+ depsFile = settings.builddir / sourceFile.stem();
+ depsFile += ".d";
+}
+
+bool TaskCC::dirty()
+{
+ 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::exists(depsFile))
+ {
+ //std::cout << "Missing depsFile\n";
+ return true;
+ }
+
+ if(std::filesystem::last_write_time(sourceFile) >
+ std::filesystem::last_write_time(depsFile))
+ {
+ //std::cout << "The sourceFile newer than depsFile\n";
+ return true;
+ }
+
+ auto depList = readDeps(depsFile);
+ for(const auto& dep : depList)
+ {
+ if(!std::filesystem::exists(dep) ||
+ std::filesystem::last_write_time(targetFile) <
+ std::filesystem::last_write_time(dep))
+ {
+ //std::cout << "The targetFile older than " << std::string(dep) << "\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 parent_waitpid(pid_t pid)
+{
+ int status;
+
+ if(waitpid(pid, &status, 0) != pid)
+ {
+ return 1;
+ }
+
+ return status;
+}
+int TaskCC::run()
+{
+ if(!std::filesystem::exists(sourceFile))
+ {
+ std::cout << "Missing source file: " << std::string(sourceFile) << "\n";
+ return 1;
+ }
+
+ std::string comp = "/usr/bin/g++";
+ auto flags = config.cxxflags;
+ if(std::string(sourceFile.extension()) == ".c")
+ {
+ comp = "/usr/bin/gcc";
+ flags = config.cflags;
+ }
+
+ char source[256];
+ strcpy(source, std::string(sourceFile).data());
+ char target[256];
+ strcpy(target, std::string(targetFile).data());
+ char pwd[256];
+ strcpy(pwd, std::string(std::filesystem::current_path()).data());
+ std::vector<const char*> argv;
+ //args.push_back("/bin/echo");
+ if(comp == "/usr/bin/gcc")
+ {
+ argv.push_back("/usr/bin/gcc");
+ }
+ else
+ {
+ argv.push_back("/usr/bin/g++");
+ }
+
+ argv.push_back("-MMD");
+ argv.push_back("-c");
+ argv.push_back(source);
+ argv.push_back("-o");
+ argv.push_back(target);
+
+ for(const auto& flag : flags)
+ {
+ argv.push_back(flag.data());
+ }
+
+ std::string cmd;
+ for(const auto& arg : argv)
+ {
+ if(arg == nullptr)
+ {
+ break;
+ }
+ if(!cmd.empty())
+ {
+ cmd += " ";
+ }
+ cmd += arg;
+ }
+ std::cout << cmd << "\n";
+
+#if 0
+ auto pid = vfork();
+ if(pid == 0)
+ {
+ execv(comp.data(), (char**)argv.data());
+ }
+ auto ret = parent_waitpid(pid);
+#elif 0
+ pid_t pid;
+ if(posix_spawn(&pid, comp.data(), nullptr, nullptr, (char**)argv.data(), nullptr))
+ {
+ return 1;//exit(1);
+ }
+ auto ret = parent_waitpid(pid);
+#else
+ auto ret = system(cmd.data());
+#endif
+
+ return ret;
+}
+
+int TaskCC::clean()
+{
+ if(std::filesystem::exists(targetFile))
+ {
+ std::cout << "Removing " << std::string(targetFile) << "\n";
+ std::filesystem::remove(targetFile);
+ }
+
+ if(std::filesystem::exists(depsFile))
+ {
+ std::cout << "Removing " << std::string(depsFile) << "\n";
+ std::filesystem::remove(depsFile);
+ }
+
+ return 0;
+}
+
+std::vector<std::string> TaskCC::depends() const
+{
+ return {};
+}
+
+std::string TaskCC::target() const
+{
+ return targetFile;
+}
diff --git a/task_cc.h b/task_cc.h
new file mode 100644
index 0000000..c73a1e5
--- /dev/null
+++ b/task_cc.h
@@ -0,0 +1,38 @@
+// -*- c++ -*-
+#pragma once
+
+#include "task.h"
+
+#include <vector>
+#include <string>
+#include <future>
+#include <filesystem>
+
+struct BuildConfiguration;
+struct Settings;
+
+class TaskCC
+ : public Task
+{
+public:
+ TaskCC(const BuildConfiguration& config,
+ const Settings& settings,
+ const std::string& source);
+
+ bool dirty() override;
+
+ int run() override;
+ int clean() override;
+
+ std::vector<std::string> depends() const override;
+
+ std::string target() const override;
+
+private:
+ std::filesystem::path sourceFile;
+ std::filesystem::path targetFile;
+ std::filesystem::path depsFile;
+
+ const BuildConfiguration& config;
+ const Settings& settings;
+};
diff --git a/task_ld.cc b/task_ld.cc
new file mode 100644
index 0000000..235523f
--- /dev/null
+++ b/task_ld.cc
@@ -0,0 +1,89 @@
+#include "task_ld.h"
+
+#include <iostream>
+#include <fstream>
+#include <unistd.h>
+#include <cstring>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <spawn.h>
+
+#include "libcppbuild.h"
+#include "settings.h"
+
+TaskLD::TaskLD(const BuildConfiguration& config,
+ const Settings& settings,
+ const std::string& target,
+ const std::vector<std::string>& objects)
+ : config(config)
+ , settings(settings)
+{
+ targetFile = settings.builddir;
+ targetFile /= target;
+ for(const auto& object : objects)
+ {
+ //std::filesystem::path objectFile = settings.builddir;
+ //objectFile /= object;
+ std::filesystem::path objectFile = object;
+ objectFiles.push_back(objectFile);
+ }
+}
+
+bool TaskLD::dirty()
+{
+ if(!std::filesystem::exists(targetFile))
+ {
+ return true;
+ }
+
+ for(const auto& objectFile : objectFiles)
+ {
+ if(std::filesystem::last_write_time(targetFile) <=
+ std::filesystem::last_write_time(objectFile))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+int TaskLD::run()
+{
+ std::string objectlist;
+ for(const auto& objectFile : objectFiles)
+ {
+ if(!objectlist.empty())
+ {
+ objectlist += " ";
+ }
+ objectlist += std::string(objectFile);
+ }
+
+ std::string compiler = "g++ " + objectlist + " " +
+ config.ldflags + " " +
+ "-o " + std::string(targetFile);
+ std::cout << compiler << "\n";
+ if(system(compiler.data()))
+ {
+ return 1;
+ }
+ return 0;
+}
+
+int TaskLD::clean()
+{
+ std::filesystem::remove(targetFile);
+ return 0;
+}
+
+std::vector<std::string> TaskLD::depends() const
+{
+ return {};
+}
+
+std::string TaskLD::target() const
+{
+ std::cout << "Removing " << std::string(targetFile) << "\n";
+ return std::string(targetFile);
+}
diff --git a/task_ld.h b/task_ld.h
new file mode 100644
index 0000000..709f238
--- /dev/null
+++ b/task_ld.h
@@ -0,0 +1,38 @@
+// -*- c++ -*-
+#pragma once
+
+#include "task.h"
+
+#include <vector>
+#include <string>
+#include <future>
+#include <filesystem>
+
+struct BuildConfiguration;
+struct Settings;
+
+class TaskLD
+ : public Task
+{
+public:
+ TaskLD(const BuildConfiguration& config,
+ const Settings& settings,
+ const std::string& target,
+ const std::vector<std::string>& objects);
+
+ bool dirty() override;
+
+ int run() override;
+ int clean() override;
+
+ std::vector<std::string> depends() const override;
+
+ std::string target() const override;
+
+private:
+ std::vector<std::filesystem::path> objectFiles;
+ std::filesystem::path targetFile;
+
+ const BuildConfiguration& config;
+ const Settings& settings;
+};