diff options
| author | Alejandro Sior <aho@sior.be> | 2022-08-03 16:10:58 +0200 |
|---|---|---|
| committer | Alejandro Sior <aho@sior.be> | 2022-08-03 16:10:58 +0200 |
| commit | 938de3acc4a0972cff01d12a9549222c23c1a656 (patch) | |
| tree | 28aa4d31cea245873f94f61b72d788873c8aaeea /cook.py | |
| parent | 65f13dba60cab28c5b6cae2d72b792ade51c86c8 (diff) | |
cook: add C compiler, manage header dependencies
Diffstat (limited to 'cook.py')
| -rwxr-xr-x | cook.py | 165 |
1 files changed, 89 insertions, 76 deletions
@@ -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 |
