mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	
		
			
				
	
	
		
			581 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			581 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from build.ab import (
 | |
|     Rule,
 | |
|     Targets,
 | |
|     TargetsMap,
 | |
|     filenameof,
 | |
|     filenamesof,
 | |
|     flatten,
 | |
|     simplerule,
 | |
|     emit,
 | |
|     G,
 | |
| )
 | |
| from build.utils import stripext, collectattrs
 | |
| from build.toolchain import Toolchain, HostToolchain
 | |
| from os.path import *
 | |
| 
 | |
| if G.OSX != "yes":
 | |
|     G.STARTGROUP = "-Wl,--start-group"
 | |
|     G.ENDGROUP = "-Wl,--end-group"
 | |
| else:
 | |
|     G.STARTGROUP = ""
 | |
|     G.ENDGROUP = ""
 | |
| 
 | |
| Toolchain.CC = ["$(CC) -c -o $[outs[0]] $[ins[0]] $(CFLAGS) $[cflags]"]
 | |
| Toolchain.CPP = ["$(CC) -E -P -o $[outs] $[cflags] -x c $[ins]"]
 | |
| Toolchain.CXX = ["$(CXX) -c -o $[outs[0]] $[ins[0]] $(CXXFLAGS) $[cflags]"]
 | |
| Toolchain.AR = ["$(AR) cqs $[outs[0]] $[ins]"]
 | |
| Toolchain.ARXX = ["$(AR) cqs $[outs[0]] $[ins]"]
 | |
| Toolchain.CLINK = [
 | |
|     "$(CC) -o $[outs[0]] $(STARTGROUP) $[ins] $[ldflags] $(LDFLAGS) $(ENDGROUP)"
 | |
| ]
 | |
| Toolchain.CXXLINK = [
 | |
|     "$(CXX) -o $[outs[0]] $(STARTGROUP) $[ins] $[ldflags] $(LDFLAGS) $(ENDGROUP)"
 | |
| ]
 | |
| 
 | |
| Toolchain.is_source_file = (
 | |
|     lambda f: f.endswith(".c")
 | |
|     or f.endswith(".cc")
 | |
|     or f.endswith(".cpp")
 | |
|     or f.endswith(".S")
 | |
|     or f.endswith(".s")
 | |
|     or f.endswith(".m")
 | |
|     or f.endswith(".mm")
 | |
| )
 | |
| 
 | |
| 
 | |
| # Given a set of dependencies, finds the set of relevant library targets (i.e.
 | |
| # contributes *.a files) for compiling C programs.  The actual list of libraries
 | |
| # is in dep.clibrary_files.
 | |
| def _toolchain_find_library_targets(deps):
 | |
|     lib_deps = []
 | |
|     for d in deps:
 | |
|         lib_deps = _combine(lib_deps, d.args.get("clibrary_deps", []))
 | |
|     return lib_deps
 | |
| 
 | |
| 
 | |
| Toolchain.find_c_library_targets = _toolchain_find_library_targets
 | |
| 
 | |
| 
 | |
| # Given a set of dependencies, finds the set of relevant header targets (i.e.
 | |
| # contributes *.h files) for compiling C programs.  The actual list of libraries
 | |
| # is in dep.cheader_files.
 | |
| def _toolchain_find_header_targets(deps, initial=[]):
 | |
|     hdr_deps = initial
 | |
|     for d in deps:
 | |
|         hdr_deps = _combine(hdr_deps, d.args.get("cheader_deps", []))
 | |
|     return hdr_deps
 | |
| 
 | |
| 
 | |
| Toolchain.find_c_header_targets = _toolchain_find_header_targets
 | |
| 
 | |
| 
 | |
| HostToolchain.CC = ["$(HOSTCC) -c -o $[outs[0]] $[ins[0]] $(HOSTCFLAGS) $[cflags]"]
 | |
| HostToolchain.CPP = ["$(HOSTCC) -E -P -o $[outs] $[cflags] -x c $[ins]"]
 | |
| HostToolchain.CXX = ["$(HOSTCXX) -c -o $[outs[0]] $[ins[0]] $(HOSTCFLAGS) $[cflags]"]
 | |
| HostToolchain.AR = ["$(HOSTAR) cqs $[outs[0]] $[ins]"]
 | |
| HostToolchain.ARXX = ["$(HOSTAR) cqs $[outs[0]] $[ins]"]
 | |
| HostToolchain.CLINK = [
 | |
|     "$(HOSTCC) -o $[outs[0]] $(STARTGROUP) $[ins] $[ldflags] $(HOSTLDFLAGS) $(ENDGROUP)"
 | |
| ]
 | |
| HostToolchain.CXXLINK = [
 | |
|     "$(HOSTCXX) -o $[outs[0]] $(STARTGROUP) $[ins] $[ldflags] $(HOSTLDFLAGS) $(ENDGROUP)"
 | |
| ]
 | |
| 
 | |
| 
 | |
| def _combine(list1, list2):
 | |
|     r = list(list1)
 | |
|     for i in list2:
 | |
|         if i not in r:
 | |
|             r.append(i)
 | |
|     return r
 | |
| 
 | |
| 
 | |
| def _indirect(deps, name):
 | |
|     r = []
 | |
|     for d in deps:
 | |
|         r = _combine(r, d.args.get(name, [d]))
 | |
|     return r
 | |
| 
 | |
| 
 | |
| def cfileimpl(self, name, srcs, deps, suffix, commands, label, toolchain, cflags):
 | |
|     outleaf = "=" + stripext(basename(filenameof(srcs[0]))) + suffix
 | |
| 
 | |
|     hdr_deps = toolchain.find_c_header_targets(deps)
 | |
|     other_deps = [
 | |
|         d
 | |
|         for d in deps
 | |
|         if ("cheader_deps" not in d.args) and ("clibrary_deps" not in d.args)
 | |
|     ]
 | |
|     hdr_files = collectattrs(targets=hdr_deps, name="cheader_files")
 | |
|     cflags = collectattrs(targets=hdr_deps, name="caller_cflags", initial=cflags)
 | |
| 
 | |
|     t = simplerule(
 | |
|         replaces=self,
 | |
|         ins=srcs,
 | |
|         deps=other_deps + hdr_files,
 | |
|         outs=[outleaf],
 | |
|         label=label,
 | |
|         commands=commands,
 | |
|         args={"cflags": cflags},
 | |
|     )
 | |
| 
 | |
| 
 | |
| @Rule
 | |
| def cfile(
 | |
|     self,
 | |
|     name,
 | |
|     srcs: Targets = None,
 | |
|     deps: Targets = None,
 | |
|     cflags=[],
 | |
|     suffix=".o",
 | |
|     toolchain=Toolchain,
 | |
|     label="CC",
 | |
| ):
 | |
|     cfileimpl(
 | |
|         self,
 | |
|         name,
 | |
|         srcs,
 | |
|         deps,
 | |
|         suffix,
 | |
|         toolchain.CC,
 | |
|         toolchain.PREFIX + label,
 | |
|         toolchain,
 | |
|         cflags,
 | |
|     )
 | |
| 
 | |
| 
 | |
| @Rule
 | |
| def cxxfile(
 | |
|     self,
 | |
|     name,
 | |
|     srcs: Targets = None,
 | |
|     deps: Targets = None,
 | |
|     cflags=[],
 | |
|     suffix=".o",
 | |
|     toolchain=Toolchain,
 | |
|     label="CXX",
 | |
| ):
 | |
|     cfileimpl(
 | |
|         self,
 | |
|         name,
 | |
|         srcs,
 | |
|         deps,
 | |
|         suffix,
 | |
|         toolchain.CXX,
 | |
|         toolchain.PREFIX + label,
 | |
|         toolchain,
 | |
|         cflags,
 | |
|     )
 | |
| 
 | |
| 
 | |
| def _removeprefix(self, prefix):
 | |
|     if self.startswith(prefix):
 | |
|         return self[len(prefix) :]
 | |
|     else:
 | |
|         return self[:]
 | |
| 
 | |
| 
 | |
| def findsources(self, srcs, deps, cflags, filerule, toolchain, cwd):
 | |
|     for f in filenamesof(srcs):
 | |
|         if not toolchain.is_source_file(f):
 | |
|             cflags = cflags + [f"-I{dirname(f)}"]
 | |
|             deps = deps + [f]
 | |
| 
 | |
|     objs = []
 | |
|     for s in flatten(srcs):
 | |
|         objs += [
 | |
|             filerule(
 | |
|                 name=join(self.localname, _removeprefix(f, G.OBJ + "/")),
 | |
|                 srcs=[f],
 | |
|                 deps=deps,
 | |
|                 cflags=sorted(set(cflags)),
 | |
|                 toolchain=toolchain,
 | |
|                 cwd=cwd,
 | |
|                 args=getattr(self, "explicit_args", {}),
 | |
|             )
 | |
|             for f in filenamesof([s])
 | |
|             if toolchain.is_source_file(f)
 | |
|         ]
 | |
|         if any(f.endswith(".o") for f in filenamesof([s])):
 | |
|             objs += [s]
 | |
| 
 | |
|     return objs
 | |
| 
 | |
| 
 | |
| def libraryimpl(
 | |
|     self,
 | |
|     name,
 | |
|     srcs,
 | |
|     deps,
 | |
|     hdrs,
 | |
|     caller_cflags,
 | |
|     caller_ldflags,
 | |
|     cflags,
 | |
|     ldflags,
 | |
|     toolchain,
 | |
|     commands,
 | |
|     label,
 | |
|     filerule,
 | |
| ):
 | |
|     hdr_deps = toolchain.find_c_header_targets(deps) + [self]
 | |
|     lib_deps = toolchain.find_c_library_targets(deps) + [self]
 | |
| 
 | |
|     hr = None
 | |
|     hf = []
 | |
|     ar = None
 | |
|     if hdrs:
 | |
|         cs = []
 | |
|         ins = hdrs.values()
 | |
|         outs = []
 | |
|         i = 0
 | |
|         for dest, src in hdrs.items():
 | |
|             s = filenamesof([src])
 | |
|             assert len(s) == 1, "the target of a header must return exactly one file"
 | |
| 
 | |
|             cs += [f"$(CP) $[ins[{i}]] $[outs[{i}]]"]
 | |
|             outs += ["=" + dest]
 | |
|             i = i + 1
 | |
| 
 | |
|         hr = simplerule(
 | |
|             name=f"{self.localname}_hdr",
 | |
|             ins=ins,
 | |
|             outs=outs,
 | |
|             commands=cs,
 | |
|             label=toolchain.PREFIX + "CHEADERS",
 | |
|         )
 | |
|         hr.args["cheader_deps"] = [hr]
 | |
|         hr.args["cheader_files"] = [hr]
 | |
|         hf = [f"-I{hr.dir}"]
 | |
| 
 | |
|     if srcs:
 | |
|         # Can't depend on the current target to get the library headers, because
 | |
|         # if we do it'll cause a dependency loop.
 | |
|         objs = findsources(
 | |
|             self,
 | |
|             srcs,
 | |
|             deps + ([hr] if hr else []),
 | |
|             cflags + hf,
 | |
|             filerule,
 | |
|             toolchain,
 | |
|             self.cwd,
 | |
|         )
 | |
| 
 | |
|         ar = simplerule(
 | |
|             name=f"{self.localname}_lib",
 | |
|             ins=objs,
 | |
|             outs=[f"={self.localname}.a"],
 | |
|             deps=deps,
 | |
|             label=label,
 | |
|             commands=commands,
 | |
|         )
 | |
|         ar.materialise()
 | |
| 
 | |
|     self.outs = ([hr] if hr else []) + ([ar] if ar else [])
 | |
|     self.deps = self.outs
 | |
|     self.args["cheader_deps"] = hdr_deps
 | |
|     self.args["clibrary_deps"] = lib_deps
 | |
|     self.args["cheader_files"] = [hr] if hr else []
 | |
|     self.args["clibrary_files"] = [ar] if ar else []
 | |
|     self.args["caller_cflags"] = caller_cflags + hf
 | |
|     self.args["caller_ldflags"] = caller_ldflags
 | |
| 
 | |
| 
 | |
| @Rule
 | |
| def clibrary(
 | |
|     self,
 | |
|     name,
 | |
|     srcs: Targets = None,
 | |
|     deps: Targets = None,
 | |
|     hdrs: TargetsMap = None,
 | |
|     caller_cflags=[],
 | |
|     caller_ldflags=[],
 | |
|     cflags=[],
 | |
|     ldflags=[],
 | |
|     toolchain=Toolchain,
 | |
|     label="LIB",
 | |
|     cfilerule=cfile,
 | |
| ):
 | |
|     libraryimpl(
 | |
|         self,
 | |
|         name,
 | |
|         srcs,
 | |
|         deps,
 | |
|         hdrs,
 | |
|         caller_cflags,
 | |
|         caller_ldflags,
 | |
|         cflags,
 | |
|         ldflags,
 | |
|         toolchain,
 | |
|         toolchain.AR,
 | |
|         toolchain.PREFIX + label,
 | |
|         cfilerule,
 | |
|     )
 | |
| 
 | |
| 
 | |
| @Rule
 | |
| def hostclibrary(
 | |
|     self,
 | |
|     name,
 | |
|     srcs: Targets = None,
 | |
|     deps: Targets = None,
 | |
|     hdrs: TargetsMap = None,
 | |
|     caller_cflags=[],
 | |
|     caller_ldflags=[],
 | |
|     cflags=[],
 | |
|     ldflags=[],
 | |
|     toolchain=HostToolchain,
 | |
|     label="LIB",
 | |
|     cfilerule=cfile,
 | |
| ):
 | |
|     libraryimpl(
 | |
|         self,
 | |
|         name,
 | |
|         srcs,
 | |
|         deps,
 | |
|         hdrs,
 | |
|         caller_cflags,
 | |
|         caller_ldflags,
 | |
|         cflags,
 | |
|         ldflags,
 | |
|         toolchain,
 | |
|         toolchain.AR,
 | |
|         toolchain.PREFIX + label,
 | |
|         cfilerule,
 | |
|     )
 | |
| 
 | |
| 
 | |
| @Rule
 | |
| def cxxlibrary(
 | |
|     self,
 | |
|     name,
 | |
|     srcs: Targets = None,
 | |
|     deps: Targets = None,
 | |
|     hdrs: TargetsMap = None,
 | |
|     caller_cflags=[],
 | |
|     caller_ldflags=[],
 | |
|     cflags=[],
 | |
|     ldflags=[],
 | |
|     toolchain=Toolchain,
 | |
|     label="CXXLIB",
 | |
|     cxxfilerule=cxxfile,
 | |
| ):
 | |
|     libraryimpl(
 | |
|         self,
 | |
|         name,
 | |
|         srcs,
 | |
|         deps,
 | |
|         hdrs,
 | |
|         caller_cflags,
 | |
|         caller_ldflags,
 | |
|         cflags,
 | |
|         ldflags,
 | |
|         toolchain,
 | |
|         toolchain.ARXX,
 | |
|         toolchain.PREFIX + label,
 | |
|         cxxfilerule,
 | |
|     )
 | |
| 
 | |
| 
 | |
| @Rule
 | |
| def hostcxxlibrary(
 | |
|     self,
 | |
|     name,
 | |
|     srcs: Targets = None,
 | |
|     deps: Targets = None,
 | |
|     hdrs: TargetsMap = None,
 | |
|     caller_cflags=[],
 | |
|     caller_ldflags=[],
 | |
|     cflags=[],
 | |
|     ldflags=[],
 | |
|     toolchain=HostToolchain,
 | |
|     label="CXXLIB",
 | |
|     cxxfilerule=cxxfile,
 | |
| ):
 | |
|     libraryimpl(
 | |
|         self,
 | |
|         name,
 | |
|         srcs,
 | |
|         deps,
 | |
|         hdrs,
 | |
|         caller_cflags,
 | |
|         caller_ldflags,
 | |
|         cflags,
 | |
|         ldflags,
 | |
|         toolchain,
 | |
|         toolchain.ARXX,
 | |
|         toolchain.PREFIX + label,
 | |
|         cxxfilerule,
 | |
|     )
 | |
| 
 | |
| 
 | |
| def programimpl(
 | |
|     self,
 | |
|     name,
 | |
|     srcs,
 | |
|     deps,
 | |
|     cflags,
 | |
|     ldflags,
 | |
|     toolchain,
 | |
|     commands,
 | |
|     label,
 | |
|     filerule,
 | |
| ):
 | |
|     cfiles = findsources(self, srcs, deps, cflags, filerule, toolchain, self.cwd)
 | |
| 
 | |
|     lib_deps = toolchain.find_c_library_targets(deps)
 | |
|     libs = collectattrs(targets=lib_deps, name="clibrary_files")
 | |
|     ldflags = collectattrs(targets=lib_deps, name="caller_ldflags", initial=ldflags)
 | |
| 
 | |
|     simplerule(
 | |
|         replaces=self,
 | |
|         ins=cfiles + libs,
 | |
|         outs=[f"={self.localname}{toolchain.EXE}"],
 | |
|         deps=deps,
 | |
|         label=label,
 | |
|         commands=commands,
 | |
|         args={"ldflags": ldflags},
 | |
|     )
 | |
| 
 | |
| 
 | |
| @Rule
 | |
| def cprogram(
 | |
|     self,
 | |
|     name,
 | |
|     srcs: Targets = None,
 | |
|     deps: Targets = None,
 | |
|     cflags=[],
 | |
|     ldflags=[],
 | |
|     toolchain=Toolchain,
 | |
|     label="CLINK",
 | |
|     cfilerule=cfile,
 | |
| ):
 | |
|     programimpl(
 | |
|         self,
 | |
|         name,
 | |
|         srcs,
 | |
|         deps,
 | |
|         cflags,
 | |
|         ldflags,
 | |
|         toolchain,
 | |
|         toolchain.CLINK,
 | |
|         toolchain.PREFIX + label,
 | |
|         cfilerule,
 | |
|     )
 | |
| 
 | |
| 
 | |
| @Rule
 | |
| def hostcprogram(
 | |
|     self,
 | |
|     name,
 | |
|     srcs: Targets = None,
 | |
|     deps: Targets = None,
 | |
|     cflags=[],
 | |
|     ldflags=[],
 | |
|     toolchain=HostToolchain,
 | |
|     label="CLINK",
 | |
|     cfilerule=cfile,
 | |
| ):
 | |
|     programimpl(
 | |
|         self,
 | |
|         name,
 | |
|         srcs,
 | |
|         deps,
 | |
|         cflags,
 | |
|         ldflags,
 | |
|         toolchain,
 | |
|         toolchain.CLINK,
 | |
|         toolchain.PREFIX + label,
 | |
|         cfilerule,
 | |
|     )
 | |
| 
 | |
| 
 | |
| @Rule
 | |
| def cxxprogram(
 | |
|     self,
 | |
|     name,
 | |
|     srcs: Targets = None,
 | |
|     deps: Targets = None,
 | |
|     cflags=[],
 | |
|     ldflags=[],
 | |
|     toolchain=Toolchain,
 | |
|     label="CXXLINK",
 | |
|     cxxfilerule=cxxfile,
 | |
| ):
 | |
|     programimpl(
 | |
|         self,
 | |
|         name,
 | |
|         srcs,
 | |
|         deps,
 | |
|         cflags,
 | |
|         ldflags,
 | |
|         toolchain,
 | |
|         toolchain.CXXLINK,
 | |
|         toolchain.PREFIX + label,
 | |
|         cxxfilerule,
 | |
|     )
 | |
| 
 | |
| 
 | |
| @Rule
 | |
| def hostcxxprogram(
 | |
|     self,
 | |
|     name,
 | |
|     srcs: Targets = None,
 | |
|     deps: Targets = None,
 | |
|     cflags=[],
 | |
|     ldflags=[],
 | |
|     toolchain=HostToolchain,
 | |
|     label="CXXLINK",
 | |
|     cxxfilerule=cxxfile,
 | |
| ):
 | |
|     programimpl(
 | |
|         self,
 | |
|         name,
 | |
|         srcs,
 | |
|         deps,
 | |
|         cflags,
 | |
|         ldflags,
 | |
|         toolchain,
 | |
|         toolchain.CXXLINK,
 | |
|         toolchain.PREFIX + label,
 | |
|         cxxfilerule,
 | |
|     )
 | |
| 
 | |
| 
 | |
| def _cppfileimpl(self, name, srcs, deps, cflags, toolchain):
 | |
|     hdr_deps = _indirect(deps, "cheader_deps")
 | |
|     cflags = collectattrs(targets=hdr_deps, name="caller_cflags", initial=cflags)
 | |
| 
 | |
|     simplerule(
 | |
|         replaces=self,
 | |
|         ins=srcs,
 | |
|         outs=[f"={self.localname}"],
 | |
|         deps=deps,
 | |
|         commands=toolchain.CPP,
 | |
|         args={"cflags": cflags},
 | |
|         label=toolchain.PREFIX + "CPPFILE",
 | |
|     )
 | |
| 
 | |
| 
 | |
| @Rule
 | |
| def cppfile(
 | |
|     self,
 | |
|     name,
 | |
|     srcs: Targets = [],
 | |
|     deps: Targets = [],
 | |
|     cflags=[],
 | |
|     toolchain=Toolchain,
 | |
| ):
 | |
|     _cppfileimpl(self, name, srcs, deps, cflags, toolchain)
 | |
| 
 | |
| 
 | |
| @Rule
 | |
| def hostcppfile(
 | |
|     self,
 | |
|     name,
 | |
|     srcs: Targets = [],
 | |
|     deps: Targets = [],
 | |
|     cflags=[],
 | |
|     toolchain=HostToolchain,
 | |
| ):
 | |
|     _cppfileimpl(self, name, srcs, deps, cflags, toolchain)
 |