summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlejandro Sior <aho@sior.be>2022-08-03 16:10:58 +0200
committerAlejandro Sior <aho@sior.be>2022-08-03 16:10:58 +0200
commit938de3acc4a0972cff01d12a9549222c23c1a656 (patch)
tree28aa4d31cea245873f94f61b72d788873c8aaeea
parent65f13dba60cab28c5b6cae2d72b792ade51c86c8 (diff)
cook: add C compiler, manage header dependencies
-rwxr-xr-xcook.py165
-rw-r--r--test/.build2
-rw-r--r--test/hai.h3
-rw-r--r--test/main.c3
4 files changed, 94 insertions, 79 deletions
diff --git a/cook.py b/cook.py
index d1057b6..784c38b 100755
--- a/cook.py
+++ b/cook.py
@@ -12,32 +12,36 @@ def find_program(prog, required=True):
raise Exception("Required program '%s' not found on the system" % (prog))
return File(path)
+def flatten(el):
+ if type(el) == list or type(el) == tuple:
+ return [a for b in el for a in flatten(b)]
+ else:
+ return [el]
+
ROOT = Path.cwd()
BUILD = Path("bld").resolve().relative_to(ROOT)
DEFDESC = lambda o, i, cmd: "%s" % (cmd)
+#self, name, exe, mkargs, mkout, mkinc, desc=DEFDESC
+
C_COMPILERS = {
- 'gcc': lambda: Vec(
+ 'gcc': lambda: CC(
"gcc",
- find_program("gcc"),
- lambda o, i, ea: "-o %s -c %s %s" % (o, i, ea),
- lambda i: i.name + ".o",
- lambda o, i, cmd: "CC %s" % (o)
+ exe=find_program("gcc"),
+ mkargs=lambda o, i, ea: "-MD -MF %s.d -o %s -c %s %s" % (o, o, i, ea),
+ mkout=lambda i: i.name + ".o",
+ mkinc=lambda i: "-I" + i,
+ mkdep=lambda o: "%s.d" % (o),
+ desc=lambda o, i, cmd: "CC %s" % (o),
),
- 'clang': lambda: Vec(
+ 'clang': lambda: CC(
"clang",
find_program("clang"),
- lambda o, i, ea: "-o %s -c %s %s" % (o, i, ea),
+ lambda o, i, ea: "-MD -MF %s.d -o %s -c %s %s" % (o, i, ea),
lambda i: i.name + ".o",
+ lambda i: "-I" + i,
lambda o, i, cmd: "CC %s" % (o)
- ),
- 'cc': lambda: Vec(
- "cc",
- find_program("cc"),
- lambda o, i, ea: "-o %s -c %s %s" % (o, i, ea),
- lambda i: i.name + ".o",
- lambda o, i, cmd: "CC %s" % (o)
- ),
+ )
}
C_LINKERS = {
@@ -52,12 +56,6 @@ C_LINKERS = {
find_program("clang"),
lambda o, i, ea: "-o %s %s %s" % (o, i, ea),
lambda o, i, cmd: "LD %s" % (o)
- ),
- 'cc': lambda: Machine(
- "ld-cc",
- find_program("cc"),
- lambda o, i, ea: "-o %s %s %s" % (o, i, ea),
- lambda o, i, cmd: "LD %s" % (o)
)
}
@@ -107,24 +105,12 @@ class File(metaclass = FileMeta):
def __str__(self):
return str(self.path)
-
- def resolve_inner(tgt, arg):
- if type(arg) == list or type(arg) == tuple:
- for a in arg:
- File.resolve_inner(tgt, a)
- elif type(arg) == str:
- tgt.append(File(arg))
- elif issubclass(type(arg), File):
- tgt.append(arg)
-
+
def resolve(*args):
- tgt = []
- for a in args:
- File.resolve_inner(tgt, a)
- return tgt
+ return [File(file) for file in flatten(args)]
class Process(File):
- def __init__(self, path, machine, inputs, extra_args = None):
+ def __init__(self, path, machine, inputs, extra_args = []):
super().__init__(path)
# The generator that created this process
@@ -135,26 +121,12 @@ class Process(File):
# The extra arguments taken
self.extra_args = extra_args
-
+
def gen_makefile(self):
- inputs = " ".join([str(x) for x in self.inputs])
-
- extra_args = self.extra_args if self.extra_args else ""
-
- out = "%s: %s\n" % (self.path, inputs)
- out += "\t@$(%s) %s\n" % (self.machine.name, self.machine.mkargs("$@", "$^", extra_args))
- out += "\t@echo '%s'" % (self.machine.desc("$@", "$^", extra_args))
-
- return out
+ return self.machine.gen_proc_makefile(self)
def gen_ninja(self):
- inputs = " ".join([str(x) for x in self.inputs])
-
- out = "build %s: %s %s" % (self.path, self.machine.name, inputs)
- if self.extra_args != None:
- out += "\n extra = %s" % (self.extra_args)
-
- return out
+ return self.machine.gen_proc_ninja(self)
class MachineMeta(type):
def __call__(cls, name, *rest, **krest):
@@ -186,31 +158,45 @@ class Machine(metaclass = MachineMeta):
# The description
self.desc = wrap_lambda(desc)
- def __call__(self, name, *args, extra_args=None):
- return self.gen(name, *args, extra_args=extra_args)
+ def __call__(self, name, *args, extra_args = []):
+ return self.gen(name, *args, extra_args = extra_args)
- def fork(self, name, mkargs, desc=None):
- if not desc:
- desc = self.desc
- args = lambda o, i, ea: self.mkargs(o, i, ea) + " " + mkargs(o, i, ea)
- return Machine(name, self.exe, args, desc)
-
- def gen(self, name, *args, extra_args=None):
+ def gen(self, name, *args, extra_args = []):
inputs = File.resolve(args)
path = BUILD / Path.cwd().relative_to(ROOT) / name
return Process(path, self, inputs, extra_args)
+
+ def gen_proc_makefile(self, proc):
+ inputs = " ".join([str(x) for x in proc.inputs])
+ extra_args = " ".join([x for x in proc.extra_args])
+
+ out = "%s: %s\n" % (proc.path, inputs)
+ out += "\t@$(%s) %s\n" % (self.name, self.mkargs("$@", inputs, extra_args))
+ out += "\t@echo '%s'" % (self.desc("$@", inputs, extra_args))
+ return out
+
def gen_makefile(self):
return "%s = %s" % (self.name, self.exe)
+ def gen_proc_ninja(self, proc):
+ inputs = " ".join([str(x) for x in proc.inputs])
+
+ out = "build %s: %s %s" % (proc.path, self.name, inputs)
+ if proc.extra_args != []:
+ extra_args = " ".join([x for x in proc.extra_args])
+ out += "\n extra = %s" % (extra_args)
+
+ return out
+
def gen_ninja(self):
out = "rule %s\n" % (self.name)
cmd = "%s %s" % (self.exe, self.mkargs("$out", "$in", "$extra"))
out += " command = %s\n" % (cmd)
- out += " description = %s" % (self.desc("$out", "$in", cmd))
+ out += " description = %s\n" % (self.desc("$out", "$in", cmd))
return out
class Vec(Machine):
@@ -218,25 +204,54 @@ class Vec(Machine):
super().__init__(name, exe, mkargs, desc=desc)
self.mkout = wrap_lambda(mkout)
- def __call__(self, *args, extra_args=None):
- return self.gen(*args, extra_args=extra_args)
-
- def fork(self, name, mkargs, desc=None):
- if not desc:
- desc = self.desc
- args = lambda o, i, ea: self.mkargs(o, i, ea) + " " + wrap_lambda(mkargs)(o, i, ea)
- return Vec(name, self.exe, args, self.mkout, desc)
+ def __call__(self, *args, extra_args = []):
+ return self.gen(*args, extra_args = extra_args)
- def gen(self, *args, extra_args=None):
+ def gen(self, *args, extra_args = []):
+ args = File.resolve(args)
+ extra_args = flatten(extra_args)
+
procs = []
- inputs = File.resolve(args)
- for i in inputs:
+ for i in args:
path = BUILD / i.path.parent / self.mkout(i.path)
procs.append(Process(path, self, [i], extra_args))
return procs
+class CC(Vec):
+ def __init__(self, name, exe, mkargs, mkout, mkinc, mkdep=None, desc=DEFDESC):
+ super().__init__(name, exe, mkargs, mkout, desc=desc)
+ self.mkinc = mkinc
+ self.mkdep = mkdep
+
+ def __call__(self, *args, extra_args = [], include_dirs = []):
+ return self.gen(*args, extra_args = extra_args, include_dirs = include_dirs)
+
+ def gen(self, *args, extra_args = [], include_dirs = []):
+ extra_args = flatten(extra_args)
+ include_dirs = File.resolve(include_dirs)
+
+ include_args = [self.mkinc(str(x)) for x in include_dirs]
+ extra_args += include_args
+
+ return super().gen(*args, extra_args = extra_args)
+
+ def gen_ninja(self):
+ out = super().gen_ninja()
+
+ if self.mkdep:
+ out += " depfile = %s\n" % (self.mkdep("$out"))
+
+ return out
+
+ def gen_proc_makefile(self, proc):
+ out = "-include %s\n" % self.mkdep(proc.path)
+
+ out += super().gen_proc_makefile(proc)
+
+ return out
+
def find_one(names):
for name in names:
program = find_program(name, required=False)
@@ -302,8 +317,6 @@ def gen_ninja():
out += mach.gen_ninja()
out += "\n"
- out += "\n"
-
for proc in File.fdb.values():
if not issubclass(type(proc), Process):
continue
diff --git a/test/.build b/test/.build
index 74fa78d..06f704a 100644
--- a/test/.build
+++ b/test/.build
@@ -1,4 +1,2 @@
-linker_sc = CWD / "linker.sc"
-
obj = cc("main.c", "test.S")
aout = ld("a.out", obj) \ No newline at end of file
diff --git a/test/hai.h b/test/hai.h
new file mode 100644
index 0000000..12e75bc
--- /dev/null
+++ b/test/hai.h
@@ -0,0 +1,3 @@
+int varchanged = 4;
+
+// header changed! \ No newline at end of file
diff --git a/test/main.c b/test/main.c
index 9298b76..fd0dc26 100644
--- a/test/main.c
+++ b/test/main.c
@@ -1,9 +1,10 @@
#include <stdio.h>
+#include "hai.h"
+
int test();
int main() {
-
printf("test returned: %d\n", test());
return 0;
} \ No newline at end of file