Skip to content

Commit 9b00472

Browse files
authored
Merge pull request #858 from zapta/main
Added support for macros within apio.ini values.
2 parents 313b8d1 + 56770c2 commit 9b00472

File tree

3 files changed

+46
-19
lines changed

3 files changed

+46
-19
lines changed

apio/managers/project.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from apio.utils import util
2121
from apio.common.apio_console import cout, cerror, cwarning
2222
from apio.common.apio_styles import INFO, SUCCESS, EMPH2
23+
from apio.common.common_util import PROJECT_BUILD_PATH
2324

2425

2526
DEFAULT_TOP_MODULE = "main"
@@ -343,11 +344,10 @@ def _determine_default_env_name(
343344
return env_name
344345

345346
@staticmethod
346-
def _unescape_value(s: str) -> str:
347-
"""Unescape # and ; in values. This allows to add these two
348-
chars in values."""
349-
s = s.replace("\\#", "#")
350-
s = s.replace("\\;", ";")
347+
def _expand_value(s: str, macros: Dict[str, str]) -> str:
348+
"""Expand macros by replacing macros keys with macro values."""
349+
for k, v in macros.items():
350+
s = s.replace(k, v)
351351
return s
352352

353353
@staticmethod
@@ -361,6 +361,18 @@ def _parse_env_options(
361361
and list options are returned as list of strings.
362362
"""
363363

364+
# -- Key/Value dict for macro expansion.
365+
macros = {
366+
# -- The ';' char. (de-conflicted from ; comment)
367+
"{semicolon}": ";",
368+
# -- The '#' char. (de-conflicted from # comment)
369+
"{hash}": "#",
370+
# -- The env name.
371+
"{env-name}": env_name,
372+
# -- The relative path to env build directory (linux / style)
373+
"{env-build}": (PROJECT_BUILD_PATH / env_name).as_posix(),
374+
}
375+
364376
# -- Select the env section by name.
365377
env_section = env_sections[env_name]
366378

@@ -372,11 +384,11 @@ def _parse_env_options(
372384
# -- Add common options that are not in env section
373385
for name, val in common_section.items():
374386
if name not in env_section:
375-
result[name] = Project._unescape_value(val)
387+
result[name] = Project._expand_value(val, macros)
376388

377389
# -- Add all the options from the env section.
378390
for name, val in env_section.items():
379-
result[name] = Project._unescape_value(val)
391+
result[name] = Project._expand_value(val, macros)
380392

381393
# -- check that all the required options exist.
382394
for option_spec in ENV_OPTIONS_SPEC.values():

docs/project-file.md

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,23 @@ At runtime, apio select the env to use based using the following rules in decrea
3838
2. The value of the `default-env` option in the `[apio]` section, if exists.
3939
3. The first env that is listed in `apio.ini`.
4040

41+
4142
When apio determines the env to use, it collects its options
4243
from the `[common]` and the [env:name] section, with options in the `[env:name]` section
4344
having higher priority, and executes the command with the resolved set options.
4445

46+
## Value macros
47+
48+
When processing env values, apio replaces the following macros with their
49+
respective values.
50+
51+
| MACRO_NAME | VALUE |
52+
| :------------ | :--------------------------------------------------------------- |
53+
| `{semicolon}` | The character `;` |
54+
| `{hash}` | The character `#` |
55+
| `{env-name}` | The env name, e.g. `my-env`. |
56+
| `{env-build}` | The posix path of the env build directory, e.g. `_build/my-env`. |
57+
4558
---
4659

4760
## The \[apio] section
@@ -92,11 +105,11 @@ board ID must be from that file.
92105

93106
The optional `constraint-file` option allows to specify the constraint file
94107
(aka pinout file) and to use different constraint file for different envs. Its
95-
value is a relative path to a constraint file under the project's root.
108+
value is a relative path to a constraint file under the project's root.
96109
The constraint file extension must be the one expected by the
97110
FPGA architecture, for example `.lpf` for ICE40 architecture.
98111

99-
If `constraint-file` is not specified and the project directory tree
112+
If `constraint-file` is not specified and the project directory tree
100113
contains exactly one file with the expected extension, that files is used
101114
automatically as the constraint file, otherwise Apio exists with an error
102115
message.
@@ -233,6 +246,7 @@ verilator command that that is invoked by the `apio lint`. For a list of
233246
verilator's command line options type `apio raw -- verilator --help`.
234247

235248
Example:
249+
236250
```
237251
[env:default]
238252
verilator-extra-options =
@@ -255,8 +269,8 @@ yosys-extra-options =
255269
-verbose
256270
```
257271

258-
In the example below, the command `write_verilog` is added to the Yosys
259-
build command to generate all file `_build/default/hardware-synth.v` with
272+
In the example below, the command `write_verilog` is added to the Yosys
273+
build command to generate all file `_build/default/yosys-synth.v` with
260274
a flattened representation of the synthesized design. This is helpful when
261275
diagnosing Yosys related synthesis issues.
262276

@@ -265,5 +279,6 @@ diagnosing Yosys related synthesis issues.
265279
board = alhambra-ii
266280
top-module = leds
267281
yosys-extra-options =
268-
\; write_verilog _build/my-env/hardware-synth.v
282+
{semicolon} write_verilog {env-build}/yosys-synth.v
269283
``
284+
```

tests/unit_tests/managers/test_project.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -155,17 +155,17 @@ def test_list_options(apio_runner: ApioRunner, capsys: LogCaptureFixture):
155155
]
156156

157157

158-
def test_escaping(apio_runner: ApioRunner, capsys: LogCaptureFixture):
159-
"""Tests escaping of comment markers in values.."""
158+
def test_macro_expansion(apio_runner: ApioRunner, capsys: LogCaptureFixture):
159+
"""Tests the expansion of macros within values."""
160160

161161
project, _ = load_apio_ini(
162162
apio_ini={
163163
"[env:default]": {
164164
"board": "alhambra-ii",
165165
"top-module": "my_top_module",
166-
"constraint-file": " \\; value ",
167-
"yosys-extra-options": " k1=\\;v1 k2=v2; \n ; "
168-
"Comment \n k3=v3\\# \n\n",
166+
"constraint-file": " {semicolon} value ",
167+
"yosys-extra-options": " k1={env-build}/v1 k2=v2; \n ; "
168+
"Comment \n k3=v3{hash} {env-name}\n\n",
169169
}
170170
},
171171
env_arg=None,
@@ -176,8 +176,8 @@ def test_escaping(apio_runner: ApioRunner, capsys: LogCaptureFixture):
176176
assert project.get_str_option("constraint-file") == "; value"
177177

178178
assert project.get_list_option("yosys-extra-options") == [
179-
"k1=;v1 k2=v2;",
180-
"k3=v3#",
179+
"k1=_build/default/v1 k2=v2;",
180+
"k3=v3# default",
181181
]
182182

183183

0 commit comments

Comments
 (0)