summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ctor.cc1
-rw-r--r--src/bootstrap.cc6
-rw-r--r--src/deps.cc120
-rw-r--r--src/deps.h12
-rw-r--r--src/task_cc.cc9
-rw-r--r--src/util.cc60
-rw-r--r--src/util.h1
-rw-r--r--test/ctor.cc20
-rw-r--r--test/deps_test.cc97
-rw-r--r--test/deps_test_data/empty.d0
-rw-r--r--test/deps_test_data/missing_colon.d1
-rw-r--r--test/deps_test_data/multiline.d4
-rw-r--r--test/deps_test_data/no_deps.d1
-rw-r--r--test/deps_test_data/no_newline.d1
-rw-r--r--test/deps_test_data/spaces.d1
-rw-r--r--test/deps_test_data/trivial.d1
16 files changed, 271 insertions, 64 deletions
diff --git a/ctor.cc b/ctor.cc
index 92135c2..0edd877 100644
--- a/ctor.cc
+++ b/ctor.cc
@@ -15,6 +15,7 @@ ctor::build_configurations ctorConfigs(const ctor::settings& settings)
.sources = {
"src/build.cc",
"src/configure.cc",
+ "src/deps.cc",
"src/execute.cc",
"src/externals_manual.cc",
"src/libctor.cc",
diff --git a/src/bootstrap.cc b/src/bootstrap.cc
index 471c844..aa50561 100644
--- a/src/bootstrap.cc
+++ b/src/bootstrap.cc
@@ -81,6 +81,12 @@ const std::string& ctor::configuration::get(const std::string& key, const std::s
return default_value;
}
+std::vector<std::string> readDeps(const std::string& depFile,
+ ctor::toolchain toolchain)
+{
+ return {};
+}
+
int main(int argc, char* argv[])
{
auto args = std::span(argv, static_cast<std::size_t>(argc));
diff --git a/src/deps.cc b/src/deps.cc
new file mode 100644
index 0000000..9400b35
--- /dev/null
+++ b/src/deps.cc
@@ -0,0 +1,120 @@
+// -*- c++ -*-
+// Distributed under the BSD 2-Clause License.
+// See accompanying file LICENSE for details.
+#include "deps.h"
+
+#include "util.h"
+
+#include <fstream>
+
+namespace {
+/* Format example:
+build/src/libctor_a-libctor_cc.o: src/libctor.cc \
+ src/getoptpp/getoptpp.hpp src/ctor.h src/configure.h src/rebuild.h \
+ src/A\ B\ C.h src/task.h src/build.h src/unittest.h
+ */
+std::vector<std::string> readDepsMake(const std::string& dep_file)
+{
+ auto str = readFile(dep_file);
+
+ std::vector<std::string> output;
+ std::string tmp;
+
+ enum class State
+ {
+ pre_colon,
+ post_colon,
+ in_escape,
+ } state{State::pre_colon};
+
+ auto old_state{state};
+ for(const auto& c : str)
+ {
+ if(c == '\r')
+ {
+ // just always ignore windows extra newline char
+ continue;
+ }
+
+ switch(state)
+ {
+ case State::pre_colon:
+ if(c == ':') // ignore everything until the colon
+ {
+ state = State::post_colon;
+ continue;
+ }
+ continue;
+
+ case State::post_colon:
+ if(c == '\n')
+ {
+ // done
+ if(!tmp.empty())
+ {
+ output.emplace_back(tmp);
+ }
+ return output;
+ }
+ if(c == '\\')
+ {
+ old_state = state;
+ state = State::in_escape;
+ continue;
+ }
+ if(c == '\t' || c == ' ') // new token
+ {
+ if(!tmp.empty())
+ {
+ output.emplace_back(tmp);
+ }
+ tmp.clear();
+ continue;
+ }
+ break;
+
+ case State::in_escape:
+ if(c == '\n')
+ {
+ // linewrap
+ state = old_state;
+ continue;
+ }
+ state = old_state;
+ break;
+ }
+
+ tmp += c;
+ }
+
+ if(!tmp.empty())
+ {
+ output.emplace_back(tmp);
+ }
+
+ return output;
+}
+}
+
+std::vector<std::string> readDeps(const std::string& dep_file,
+ ctor::toolchain toolchain)
+{
+ if(!std::filesystem::exists(dep_file))
+ {
+ return {};
+ }
+
+ switch(toolchain)
+ {
+ case ctor::toolchain::any:
+ case ctor::toolchain::none:
+ return {};
+
+ // makefile .d file based:
+ case ctor::toolchain::gcc:
+ case ctor::toolchain::clang:
+ return readDepsMake(dep_file);
+ }
+
+ return {};
+}
diff --git a/src/deps.h b/src/deps.h
new file mode 100644
index 0000000..be0dfb2
--- /dev/null
+++ b/src/deps.h
@@ -0,0 +1,12 @@
+// -*- c++ -*-
+// Distributed under the BSD 2-Clause License.
+// See accompanying file LICENSE for details.
+#pragma once
+
+#include "ctor.h"
+
+#include <vector>
+#include <string>
+
+std::vector<std::string> readDeps(const std::string& dep_file,
+ ctor::toolchain toolchain);
diff --git a/src/task_cc.cc b/src/task_cc.cc
index 9a801b5..9de2657 100644
--- a/src/task_cc.cc
+++ b/src/task_cc.cc
@@ -12,6 +12,7 @@
#include "execute.h"
#include "util.h"
#include "tools.h"
+#include "deps.h"
TaskCC::TaskCC(const ctor::build_configuration& config_, const ctor::settings& settings_,
const std::string& sourceDir_, const ctor::source& source)
@@ -136,7 +137,8 @@ bool TaskCC::dirtyInner()
}
}
- auto depList = readDeps(depsFile.string());
+ auto toolchain = getToolChain(config.system);
+ auto depList = readDeps(depsFile.string(), toolchain);
for(const auto& dep : depList)
{
if(!std::filesystem::exists(dep) ||
@@ -288,6 +290,7 @@ std::vector<std::string> TaskCC::flags() const
exit(1);
break;
}
+
}
std::string TaskCC::flagsString() const
@@ -311,7 +314,7 @@ std::vector<std::string> TaskCC::getCompilerArgs() const
{
case ctor::language::c:
{
- append(args, c_option(toolchain, ctor::c_opt::generate_dep_tree));
+ append(args, c_option(toolchain, ctor::c_opt::generate_dep_tree, depsFile.string()));
if(std::filesystem::path(config.target).extension() == ".so")
{
@@ -353,7 +356,7 @@ std::vector<std::string> TaskCC::getCompilerArgs() const
case ctor::language::cpp:
{
- append(args, cxx_option(toolchain, ctor::cxx_opt::generate_dep_tree));
+ append(args, cxx_option(toolchain, ctor::cxx_opt::generate_dep_tree, depsFile.string()));
if(std::filesystem::path(config.target).extension() == ".so")
{
diff --git a/src/util.cc b/src/util.cc
index 73b158d..dbd4c3c 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -28,66 +28,6 @@ std::string readFile(const std::string& fileName)
return {bytes.data(), static_cast<std::size_t>(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;
-}
-
ctor::language languageFromExtension(const std::filesystem::path& file)
{
auto ext = file.extension().string();
diff --git a/src/util.h b/src/util.h
index af5bbd6..0a90049 100644
--- a/src/util.h
+++ b/src/util.h
@@ -12,7 +12,6 @@
std::string to_lower(const std::string& str);
std::string readFile(const std::string& fileName);
-std::vector<std::string> readDeps(const std::string& depFile);
ctor::language languageFromExtension(const std::filesystem::path& file);
std::string cleanUp(const std::string& path);
diff --git a/test/ctor.cc b/test/ctor.cc
index ccf1c31..1951a30 100644
--- a/test/ctor.cc
+++ b/test/ctor.cc
@@ -12,6 +12,25 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)
{
.type = ctor::target_type::unit_test,
.system = ctor::output_system::build,
+ .target = "deps_test",
+ .sources = {
+ "deps_test.cc",
+ "testmain.cc",
+ "../src/deps.cc",
+ "../src/util.cc",
+ },
+ .depends = { "testprog", },
+ .flags = {
+ .cxxflags = {
+ "-std=c++20", "-O3", "-Wall", "-Werror",
+ "-I../src", "-Iuunit",
+ "-DOUTPUT=\"deps\"",
+ },
+ },
+ },
+ {
+ .type = ctor::target_type::unit_test,
+ .system = ctor::output_system::build,
.target = "testprog",
.sources = {
"testprog.cc",
@@ -104,6 +123,7 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)
.sources = {
"../src/build.cc",
"../src/configure.cc",
+ "../src/deps.cc",
"../src/execute.cc",
"../src/rebuild.cc",
"../src/tasks.cc",
diff --git a/test/deps_test.cc b/test/deps_test.cc
new file mode 100644
index 0000000..762b0e5
--- /dev/null
+++ b/test/deps_test.cc
@@ -0,0 +1,97 @@
+#include <uunit.h>
+
+#include <fstream>
+#include <map>
+#include <vector>
+
+#include <deps.h>
+#include <algorithm>
+
+#include "paths.h"
+#include "tmpfile.h"
+
+class DepsTest
+ : public uUnit
+{
+public:
+ DepsTest()
+ {
+ uTEST(DepsTest::parser_test);
+ }
+
+ void parser_test()
+ {
+ using namespace std::string_literals;
+
+ auto test_data = paths::top_srcdir / "test" / "deps_test_data";
+
+ auto empty = test_data / "empty.d";
+ auto trivial = test_data / "trivial.d";
+ auto no_newline = test_data / "no_newline.d";
+ auto no_deps = test_data / "no_deps.d";
+ auto trailing_whitespace = test_data / "trailing_whitespace.d";
+ auto spaces = test_data / "spaces.d";
+ auto multiline = test_data / "multiline.d";
+ auto no_such_file = test_data / "no_such_file.d"; // doesn't exist
+ auto missing_colon = test_data / "missing_colon.d";
+
+ {
+ auto res = readDeps(empty.string(), ctor::toolchain::gcc);
+ uASSERT(res.empty());
+ }
+
+ {
+ auto res = readDeps(trivial.string(), ctor::toolchain::gcc);
+ uASSERT_EQUAL(1u, res.size());
+ uASSERT_EQUAL("x.cc"s, res[0]);
+ }
+
+ {
+ auto res = readDeps(no_newline.string(), ctor::toolchain::gcc);
+ uASSERT_EQUAL(1u, res.size());
+ uASSERT_EQUAL("x.cc"s, res[0]);
+ }
+
+ {
+ auto res = readDeps(no_deps.string(), ctor::toolchain::gcc);
+ uASSERT_EQUAL(0u, res.size());
+ }
+
+ {
+ auto res = readDeps(spaces.string(), ctor::toolchain::gcc);
+ uASSERT_EQUAL(2u, res.size());
+ uASSERT_EQUAL("x y.cc"s, res[0]);
+ uASSERT_EQUAL("x y.h"s, res[1]);
+ }
+
+ {
+ auto res = readDeps(multiline.string(), ctor::toolchain::gcc);
+ uASSERT_EQUAL(12u, res.size());
+ uASSERT_EQUAL("src/configure.cc"s, res[0]);
+ uASSERT_EQUAL("src/configure.h"s, res[1]);
+ uASSERT_EQUAL("src/getoptpp/getoptpp.hpp"s, res[2]);
+ uASSERT_EQUAL("src/execute.h"s, res[3]);
+ uASSERT_EQUAL("src/ctor.h"s, res[4]);
+ uASSERT_EQUAL("src/tasks.h"s, res[5]);
+ uASSERT_EQUAL("src/task.h"s, res[6]);
+ uASSERT_EQUAL("src/rebuild.h"s, res[7]);
+ uASSERT_EQUAL("src/externals.h"s, res[8]);
+ uASSERT_EQUAL("src/externals_manual.h"s, res[9]);
+ uASSERT_EQUAL("src/tools.h"s, res[10]);
+ uASSERT_EQUAL("src/util.h"s, res[11]);
+ }
+
+ {
+ auto res = readDeps(no_such_file.string(), ctor::toolchain::gcc);
+ uASSERT(res.empty());
+ }
+
+ {
+ auto res = readDeps(missing_colon.string(), ctor::toolchain::gcc);
+ uASSERT(res.empty());
+ }
+ }
+};
+
+// Registers the fixture into the 'registry'
+static DepsTest test;
diff --git a/test/deps_test_data/empty.d b/test/deps_test_data/empty.d
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/deps_test_data/empty.d
diff --git a/test/deps_test_data/missing_colon.d b/test/deps_test_data/missing_colon.d
new file mode 100644
index 0000000..e46996c
--- /dev/null
+++ b/test/deps_test_data/missing_colon.d
@@ -0,0 +1 @@
+x.cc x.h
diff --git a/test/deps_test_data/multiline.d b/test/deps_test_data/multiline.d
new file mode 100644
index 0000000..8862ab0
--- /dev/null
+++ b/test/deps_test_data/multiline.d
@@ -0,0 +1,4 @@
+build/src/libctor_a-configure_cc.o: src/configure.cc src/configure.h \
+ src/getoptpp/getoptpp.hpp src/execute.h src/ctor.h src/tasks.h \
+ src/task.h src/rebuild.h src/externals.h src/externals_manual.h \
+ src/tools.h src/util.h
diff --git a/test/deps_test_data/no_deps.d b/test/deps_test_data/no_deps.d
new file mode 100644
index 0000000..e7cccf6
--- /dev/null
+++ b/test/deps_test_data/no_deps.d
@@ -0,0 +1 @@
+x.o:
diff --git a/test/deps_test_data/no_newline.d b/test/deps_test_data/no_newline.d
new file mode 100644
index 0000000..88829ea
--- /dev/null
+++ b/test/deps_test_data/no_newline.d
@@ -0,0 +1 @@
+x.o: x.cc \ No newline at end of file
diff --git a/test/deps_test_data/spaces.d b/test/deps_test_data/spaces.d
new file mode 100644
index 0000000..c53fd64
--- /dev/null
+++ b/test/deps_test_data/spaces.d
@@ -0,0 +1 @@
+x\ y.o: x\ y.cc x\ y.h
diff --git a/test/deps_test_data/trivial.d b/test/deps_test_data/trivial.d
new file mode 100644
index 0000000..15a0c29
--- /dev/null
+++ b/test/deps_test_data/trivial.d
@@ -0,0 +1 @@
+x.o: x.cc