mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
The great header shift: It didn't make sense to regenerate headers for the same module for every target (boot/kernel/user) it appeared in. And now that core headers are out of src/include, this was going to cause problems for the new libc changes I've been working on. So I went back to re-design how module headers work. Pre-requisites: - A module's public headers should all be available in one location, not tied to target. - No accidental includes. Another module should not be able to include anything (creating an implicit dependency) from a module without declaring an explicit dependency. - Exception to the previous: libc's headers should be available to all, at least for the freestanding headers. New system: - A new "public_headers" property of module declares all public headers that should be available to dependant modules - All public headers (after possible processing) are installed relative to build/include/<module> with the same path as their source - This also means no "include" dir in modules is necessary. If a header should be included as <j6/types.h> then its source should be src/libraries/j6/j6/types.h - this caused the most churn as all public header sources moved one directory up. - The "includes" property of a module is local only to that module now, it does not create any implicit public interface Other changes: - The bonnibel concept of sources changed: instead of sources having actions, they themselves are an instance of a (sub)class of Source, which provides all the necessary information itself. - Along with the above, rule names were standardized into <type>.<ext>, eg "compile.cpp" or "parse.cog" - cog and cogflags variables moved from per-target scope to global scope in the build files. - libc gained a more dynamic .module file
120 lines
2.8 KiB
Python
120 lines
2.8 KiB
Python
from os.path import join, splitext
|
|
from . import mod_rel
|
|
|
|
def _resolve(path):
|
|
if path.startswith('/') or path.startswith('$'):
|
|
return path
|
|
from pathlib import Path
|
|
return str(Path(path).resolve())
|
|
|
|
def _dynamic_action(name):
|
|
def prop(self):
|
|
root, suffix = splitext(self.path)
|
|
return f"{name}{suffix}"
|
|
return prop
|
|
|
|
|
|
class Source:
|
|
next = tuple()
|
|
action = None
|
|
args = dict()
|
|
gather = False
|
|
outputs = tuple()
|
|
input = False
|
|
|
|
def __init__(self, path, root = "${module_dir}", deps=tuple()):
|
|
self.path = path
|
|
self.root = root
|
|
self.deps = deps
|
|
|
|
def add_deps(self, deps):
|
|
self.deps += tuple(deps)
|
|
|
|
@property
|
|
def fullpath(self):
|
|
return join(self.root, self.path)
|
|
|
|
class ParseSource(Source):
|
|
action = property(_dynamic_action("parse"))
|
|
|
|
@property
|
|
def output(self):
|
|
root, _ = splitext(self.path)
|
|
return root
|
|
|
|
@property
|
|
def outputs(self):
|
|
return (self.output,)
|
|
|
|
@property
|
|
def gather(self):
|
|
_, suffix = splitext(self.output)
|
|
return suffix in (".h", ".inc")
|
|
|
|
@property
|
|
def next(self):
|
|
_, suffix = splitext(self.output)
|
|
nextType = {
|
|
".s": CompileSource,
|
|
".cpp": CompileSource,
|
|
}.get(suffix)
|
|
|
|
if nextType:
|
|
return (nextType(self.output),)
|
|
return tuple()
|
|
|
|
@property
|
|
def args(self):
|
|
return dict(
|
|
outputs = list(map(mod_rel, self.outputs)),
|
|
inputs = [self.fullpath],
|
|
implicit = list(map(_resolve, self.deps)),
|
|
variables = dict(name=self.path),
|
|
)
|
|
|
|
class HeaderSource(Source):
|
|
action = "cp"
|
|
gather = True
|
|
|
|
@property
|
|
def outputs(self):
|
|
return (self.path,)
|
|
|
|
@property
|
|
def args(self):
|
|
return dict(
|
|
outputs = [mod_rel(self.path)],
|
|
inputs = [join(self.root, self.path)],
|
|
implicit = list(map(_resolve, self.deps)),
|
|
variables = dict(name=self.path),
|
|
)
|
|
|
|
class CompileSource(Source):
|
|
action = property(_dynamic_action("compile"))
|
|
input = True
|
|
|
|
@property
|
|
def outputs(self):
|
|
return (self.path + ".o",)
|
|
|
|
@property
|
|
def args(self):
|
|
return dict(
|
|
outputs = list(map(mod_rel, self.outputs)),
|
|
inputs = [join(self.root, self.path)],
|
|
implicit = list(map(_resolve, self.deps)) + [mod_rel(".headers.phony")],
|
|
variables = dict(name=self.path),
|
|
)
|
|
|
|
def make_source(root, path):
|
|
_, suffix = splitext(path)
|
|
|
|
if suffix in (".s", ".c", ".cpp"):
|
|
return CompileSource(path, root)
|
|
elif suffix in (".cog",):
|
|
return ParseSource(path, root)
|
|
elif suffix in (".h", ".inc"):
|
|
return HeaderSource(path, root)
|
|
else:
|
|
raise RuntimeError(f"{path} has no Source type")
|