Refactor build script toolchain lookups.
Now environment variable overrides no longer infect the build scripts. _toolchain.overrides is dropped as probably misguided in the first place. Fixes #251.
This commit is contained in:
parent
29253295ee
commit
a783e4645d
|
@ -2,45 +2,36 @@ import os
|
|||
import shutil
|
||||
|
||||
|
||||
__all__ = ["ToolNotFound", "get_tool", "has_tool", "require_tool"]
|
||||
__all__ = ["ToolNotFound", "tool_env_var", "has_tool", "require_tool"]
|
||||
|
||||
|
||||
class ToolNotFound(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def _tool_env_var(name):
|
||||
def tool_env_var(name):
|
||||
return name.upper().replace("-", "_")
|
||||
|
||||
|
||||
def get_tool(name):
|
||||
return os.environ.get(_tool_env_var(name), overrides.get(name, name))
|
||||
def _get_tool(name):
|
||||
return os.environ.get(tool_env_var(name), name)
|
||||
|
||||
|
||||
def has_tool(name):
|
||||
return shutil.which(get_tool(name)) is not None
|
||||
return shutil.which(_get_tool(name)) is not None
|
||||
|
||||
|
||||
def require_tool(name):
|
||||
env_var = _tool_env_var(name)
|
||||
path = get_tool(name)
|
||||
env_var = tool_env_var(name)
|
||||
path = _get_tool(name)
|
||||
if shutil.which(path) is None:
|
||||
if path == name:
|
||||
if env_var in os.environ:
|
||||
raise ToolNotFound("Could not find required tool {} in {} as "
|
||||
"specified via the {} environment variable".
|
||||
format(name, path, env_var))
|
||||
else:
|
||||
raise ToolNotFound("Could not find required tool {} in PATH. Place "
|
||||
"it directly in PATH or specify path explicitly "
|
||||
"via the {} environment variable".
|
||||
format(name, env_var))
|
||||
else:
|
||||
if os.getenv(env_var):
|
||||
via = "the {} environment variable".format(env_var)
|
||||
else:
|
||||
via = "your packager's toolchain overrides. This is either an " \
|
||||
"nMigen bug or a packaging error"
|
||||
raise ToolNotFound("Could not find required tool {} in {} as "
|
||||
"specified via {}".format(name, path, via))
|
||||
return path
|
||||
|
||||
|
||||
# Packages for systems like Nix can inject full paths to certain tools by adding them in
|
||||
# this dictionary, e.g. ``overrides = {"yosys": "/full/path/to/yosys"}``.
|
||||
overrides = {}
|
||||
|
|
|
@ -247,12 +247,14 @@ class TemplatedPlatform(Platform):
|
|||
# {{autogenerated}}
|
||||
set -e{{verbose("x")}}
|
||||
[ -n "${{platform._toolchain_env_var}}" ] && . "${{platform._toolchain_env_var}}"
|
||||
{{emit_prelude("sh")}}
|
||||
{{emit_commands("sh")}}
|
||||
""",
|
||||
"build_{{name}}.bat": """
|
||||
@rem {{autogenerated}}
|
||||
{{quiet("@echo off")}}
|
||||
if defined {{platform._toolchain_env_var}} call %{{platform._toolchain_env_var}}%
|
||||
{{emit_prelude("bat")}}
|
||||
{{emit_commands("bat")}}
|
||||
""",
|
||||
}
|
||||
|
@ -286,14 +288,30 @@ class TemplatedPlatform(Platform):
|
|||
return verilog._convert_rtlil_text(rtlil_text,
|
||||
strip_internal_attrs=False, write_verilog_opts=opts)
|
||||
|
||||
def emit_commands(format):
|
||||
def emit_prelude(syntax):
|
||||
commands = []
|
||||
for name in self.required_tools:
|
||||
env_var = tool_env_var(name)
|
||||
if syntax == "sh":
|
||||
template = ": ${{{env_var}:={name}}}"
|
||||
elif syntax == "bat":
|
||||
template = \
|
||||
"if [%{env_var}%] eq [\"\"] set {env_var}=\n" \
|
||||
"if [%{env_var}%] eq [] set {env_var}={name}"
|
||||
else:
|
||||
assert False
|
||||
commands.append(template.format(env_var=env_var, name=name))
|
||||
return "\n".join(commands)
|
||||
|
||||
def emit_commands(syntax):
|
||||
commands = []
|
||||
for index, command_tpl in enumerate(self.command_templates):
|
||||
command = render(command_tpl, origin="<command#{}>".format(index + 1))
|
||||
command = render(command_tpl, origin="<command#{}>".format(index + 1),
|
||||
syntax=syntax)
|
||||
command = re.sub(r"\s+", " ", command)
|
||||
if format == "sh":
|
||||
if syntax == "sh":
|
||||
commands.append(command)
|
||||
elif format == "bat":
|
||||
elif syntax == "bat":
|
||||
commands.append(command + " || exit /b")
|
||||
else:
|
||||
assert False
|
||||
|
@ -315,6 +333,16 @@ class TemplatedPlatform(Platform):
|
|||
else:
|
||||
return jinja2.Undefined(name=var)
|
||||
|
||||
@jinja2.contextfunction
|
||||
def invoke_tool(context, name):
|
||||
env_var = tool_env_var(name)
|
||||
if context.parent["syntax"] == "sh":
|
||||
return "\"${}\"".format(env_var)
|
||||
elif context.parent["syntax"] == "bat":
|
||||
return "%{}%".format(env_var)
|
||||
else:
|
||||
assert False
|
||||
|
||||
def options(opts):
|
||||
if isinstance(opts, str):
|
||||
return opts
|
||||
|
@ -336,7 +364,7 @@ class TemplatedPlatform(Platform):
|
|||
else:
|
||||
return arg
|
||||
|
||||
def render(source, origin):
|
||||
def render(source, origin, syntax=None):
|
||||
try:
|
||||
source = textwrap.dedent(source).strip()
|
||||
compiled = jinja2.Template(source, trim_blocks=True, lstrip_blocks=True)
|
||||
|
@ -351,8 +379,10 @@ class TemplatedPlatform(Platform):
|
|||
"emit_rtlil": emit_rtlil,
|
||||
"emit_verilog": emit_verilog,
|
||||
"emit_debug_verilog": emit_debug_verilog,
|
||||
"emit_prelude": emit_prelude,
|
||||
"emit_commands": emit_commands,
|
||||
"get_tool": get_tool,
|
||||
"syntax": syntax,
|
||||
"invoke_tool": invoke_tool,
|
||||
"get_override": get_override,
|
||||
"verbose": verbose,
|
||||
"quiet": quiet,
|
||||
|
|
8
nmigen/vendor/intel.py
vendored
8
nmigen/vendor/intel.py
vendored
|
@ -103,22 +103,22 @@ class IntelPlatform(TemplatedPlatform):
|
|||
}
|
||||
command_templates = [
|
||||
r"""
|
||||
{{get_tool("quartus_map")}}
|
||||
{{invoke_tool("quartus_map")}}
|
||||
{{get_override("quartus_map_opts")|options}}
|
||||
--rev={{name}} {{name}}
|
||||
""",
|
||||
r"""
|
||||
{{get_tool("quartus_fit")}}
|
||||
{{invoke_tool("quartus_fit")}}
|
||||
{{get_override("quartus_fit_opts")|options}}
|
||||
--rev={{name}} {{name}}
|
||||
""",
|
||||
r"""
|
||||
{{get_tool("quartus_asm")}}
|
||||
{{invoke_tool("quartus_asm")}}
|
||||
{{get_override("quartus_asm_opts")|options}}
|
||||
--rev={{name}} {{name}}
|
||||
""",
|
||||
r"""
|
||||
{{get_tool("quartus_sta")}}
|
||||
{{invoke_tool("quartus_sta")}}
|
||||
{{get_override("quartus_sta_opts")|options}}
|
||||
--rev={{name}} {{name}}
|
||||
""",
|
||||
|
|
12
nmigen/vendor/lattice_ecp5.py
vendored
12
nmigen/vendor/lattice_ecp5.py
vendored
|
@ -136,14 +136,14 @@ class LatticeECP5Platform(TemplatedPlatform):
|
|||
}
|
||||
_trellis_command_templates = [
|
||||
r"""
|
||||
{{get_tool("yosys")}}
|
||||
{{invoke_tool("yosys")}}
|
||||
{{quiet("-q")}}
|
||||
{{get_override("yosys_opts")|options}}
|
||||
-l {{name}}.rpt
|
||||
{{name}}.ys
|
||||
""",
|
||||
r"""
|
||||
{{get_tool("nextpnr-ecp5")}}
|
||||
{{invoke_tool("nextpnr-ecp5")}}
|
||||
{{quiet("--quiet")}}
|
||||
{{get_override("nextpnr_opts")|options}}
|
||||
--log {{name}}.tim
|
||||
|
@ -155,7 +155,7 @@ class LatticeECP5Platform(TemplatedPlatform):
|
|||
--textcfg {{name}}.config
|
||||
""",
|
||||
r"""
|
||||
{{get_tool("ecppack")}}
|
||||
{{invoke_tool("ecppack")}}
|
||||
{{verbose("--verbose")}}
|
||||
{{get_override("ecppack_opts")|options}}
|
||||
--input {{name}}.config
|
||||
|
@ -235,16 +235,16 @@ class LatticeECP5Platform(TemplatedPlatform):
|
|||
_diamond_command_templates = [
|
||||
# These don't have any usable command-line option overrides.
|
||||
r"""
|
||||
{{get_tool("pnmainc")}}
|
||||
{{invoke_tool("pnmainc")}}
|
||||
{{name}}.tcl
|
||||
""",
|
||||
r"""
|
||||
{{get_tool("ddtcmd")}}
|
||||
{{invoke_tool("ddtcmd")}}
|
||||
-oft -bit
|
||||
-if {{name}}_impl/{{name}}_impl.bit -of {{name}}.bit
|
||||
""",
|
||||
r"""
|
||||
{{get_tool("ddtcmd")}}
|
||||
{{invoke_tool("ddtcmd")}}
|
||||
-oft -svfsingle -revd -op "Fast Program"
|
||||
-if {{name}}_impl/{{name}}_impl.bit -of {{name}}.svf
|
||||
""",
|
||||
|
|
6
nmigen/vendor/lattice_ice40.py
vendored
6
nmigen/vendor/lattice_ice40.py
vendored
|
@ -140,14 +140,14 @@ class LatticeICE40Platform(TemplatedPlatform):
|
|||
}
|
||||
_icestorm_command_templates = [
|
||||
r"""
|
||||
{{get_tool("yosys")}}
|
||||
{{invoke_tool("yosys")}}
|
||||
{{quiet("-q")}}
|
||||
{{get_override("yosys_opts")|options}}
|
||||
-l {{name}}.rpt
|
||||
{{name}}.ys
|
||||
""",
|
||||
r"""
|
||||
{{get_tool("nextpnr-ice40")}}
|
||||
{{invoke_tool("nextpnr-ice40")}}
|
||||
{{quiet("--quiet")}}
|
||||
{{get_override("nextpnr_opts")|options}}
|
||||
--log {{name}}.tim
|
||||
|
@ -160,7 +160,7 @@ class LatticeICE40Platform(TemplatedPlatform):
|
|||
--asc {{name}}.asc
|
||||
""",
|
||||
r"""
|
||||
{{get_tool("icepack")}}
|
||||
{{invoke_tool("icepack")}}
|
||||
{{verbose("-v")}}
|
||||
{{name}}.asc
|
||||
{{name}}.bin
|
||||
|
|
6
nmigen/vendor/lattice_machxo2.py
vendored
6
nmigen/vendor/lattice_machxo2.py
vendored
|
@ -106,17 +106,17 @@ class LatticeMachXO2Platform(TemplatedPlatform):
|
|||
command_templates = [
|
||||
# These don't have any usable command-line option overrides.
|
||||
r"""
|
||||
{{get_tool("pnmainc")}}
|
||||
{{invoke_tool("pnmainc")}}
|
||||
{{name}}.tcl
|
||||
""",
|
||||
r"""
|
||||
{{get_tool("ddtcmd")}}
|
||||
{{invoke_tool("ddtcmd")}}
|
||||
-oft -jed
|
||||
-dev {{platform.device}}-{{platform.speed}}{{platform.package}}{{platform.grade}}
|
||||
-if {{name}}_impl/{{name}}_impl.jed -of {{name}}.jed
|
||||
""",
|
||||
r"""
|
||||
{{get_tool("ddtcmd")}}
|
||||
{{invoke_tool("ddtcmd")}}
|
||||
-oft -svfsingle -revd -op "FLASH Erase,Program,Verify"
|
||||
-if {{name}}_impl/{{name}}_impl.jed -of {{name}}.svf
|
||||
""",
|
||||
|
|
2
nmigen/vendor/xilinx_7series.py
vendored
2
nmigen/vendor/xilinx_7series.py
vendored
|
@ -139,7 +139,7 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
|
|||
}
|
||||
command_templates = [
|
||||
r"""
|
||||
{{get_tool("vivado")}}
|
||||
{{invoke_tool("vivado")}}
|
||||
{{verbose("-verbose")}}
|
||||
{{get_override("vivado_opts")|options}}
|
||||
-mode batch
|
||||
|
|
10
nmigen/vendor/xilinx_spartan_3_6.py
vendored
10
nmigen/vendor/xilinx_spartan_3_6.py
vendored
|
@ -141,12 +141,12 @@ class XilinxSpartan3Or6Platform(TemplatedPlatform):
|
|||
}
|
||||
command_templates = [
|
||||
r"""
|
||||
{{get_tool("xst")}}
|
||||
{{invoke_tool("xst")}}
|
||||
{{get_override("xst_opts")|options}}
|
||||
-ifn {{name}}.xst
|
||||
""",
|
||||
r"""
|
||||
{{get_tool("ngdbuild")}}
|
||||
{{invoke_tool("ngdbuild")}}
|
||||
{{quiet("-quiet")}}
|
||||
{{verbose("-verbose")}}
|
||||
{{get_override("ngdbuild_opts")|options}}
|
||||
|
@ -154,7 +154,7 @@ class XilinxSpartan3Or6Platform(TemplatedPlatform):
|
|||
{{name}}.ngc
|
||||
""",
|
||||
r"""
|
||||
{{get_tool("map")}}
|
||||
{{invoke_tool("map")}}
|
||||
{{verbose("-detail")}}
|
||||
{{get_override("map_opts")|default([])|options}}
|
||||
-w
|
||||
|
@ -163,7 +163,7 @@ class XilinxSpartan3Or6Platform(TemplatedPlatform):
|
|||
{{name}}.pcf
|
||||
""",
|
||||
r"""
|
||||
{{get_tool("par")}}
|
||||
{{invoke_tool("par")}}
|
||||
{{get_override("par_opts")|default([])|options}}
|
||||
-w
|
||||
{{name}}_map.ncd
|
||||
|
@ -171,7 +171,7 @@ class XilinxSpartan3Or6Platform(TemplatedPlatform):
|
|||
{{name}}.pcf
|
||||
""",
|
||||
r"""
|
||||
{{get_tool("bitgen")}}
|
||||
{{invoke_tool("bitgen")}}
|
||||
{{get_override("bitgen_opts")|default(["-g Compress"])|options}}
|
||||
-w
|
||||
-g Binary:Yes
|
||||
|
|
2
nmigen/vendor/xilinx_ultrascale.py
vendored
2
nmigen/vendor/xilinx_ultrascale.py
vendored
|
@ -139,7 +139,7 @@ class XilinxUltraScalePlatform(TemplatedPlatform):
|
|||
}
|
||||
command_templates = [
|
||||
r"""
|
||||
{{get_tool("vivado")}}
|
||||
{{invoke_tool("vivado")}}
|
||||
{{verbose("-verbose")}}
|
||||
{{get_override("vivado_opts")|options}}
|
||||
-mode batch
|
||||
|
|
Loading…
Reference in a new issue