Skip to content

flow/util/generate_klayout_tech: write absolute LEF paths for Bazel sandbox#4234

Open
oharboe wants to merge 6 commits into
The-OpenROAD-Project:masterfrom
oharboe:klayout-sandbox-abspath
Open

flow/util/generate_klayout_tech: write absolute LEF paths for Bazel sandbox#4234
oharboe wants to merge 6 commits into
The-OpenROAD-Project:masterfrom
oharboe:klayout-sandbox-abspath

Conversation

@oharboe
Copy link
Copy Markdown
Collaborator

@oharboe oharboe commented May 18, 2026

Summary

flow/util/generate_klayout_tech.py used to emit LEF entries into the
generated .lyt as paths relative to reference_dir, with the file
first canonicalised via os.path.realpath. Both choices break the
orfs_gds step when ORFS runs under a Bazel sandbox:

  1. realpath() follows symlinks. Inside a Bazel sandbox, bazel-out/
    is symlinked back to the bare execroot, so paths get rewritten to
    the execroot location — which doesn't carry the per-action sibling
    files that exist only in the per-action sandbox.

  2. Even after dropping realpath(), klayout's Layout.read(def, layout_options) resolves the <lef-files> relative entries against
    the realpath of the DEF it's merging — which is again the bare
    execroot. Sibling intermediates like objects/klayout_tech.lef only
    exist in the per-action sandbox, so resolution fails with errno=2:

    RuntimeError: Unable to open file:
      .../sandbox/.../execroot/_main/flow/designs/sky130hd/.../tech.lef
    

Plain abspath (no symlink following) writes the in-sandbox absolute
LEF path into the LYT, which klayout then opens directly with no
relative-resolution dance. Same fix is applied to the .map paths a
few lines below.

Test (flow/test/test_generate_klayout_tech.py::test_with_template)
is updated to assert os.path.abspath(lef_path) instead of the prior
os.path.relpath-against-realpath form.

Test plan

  • Existing flow/test/test_generate_klayout_tech.py (13 tests)
    passes against the new behaviour.
  • Existing classic-make flows that consume the generated LYT
    still work — paths going abspath rather than relpath should be
    a strict superset of what klayout accepts.

🤖 Generated with Claude Code

oharboe added 3 commits May 18, 2026 06:37
os.path.realpath() follows symlinks.  Inside a Bazel sandbox, the
bazel-out/ tree is symlinked from the sandbox back to the bare
execroot; realpath resolves through that symlink and yields the
bare-execroot path, not the sandbox path.

That alone doesn't matter for os.path.relpath(a, b) when both
operands are realpath'd from the same sandbox — the relative
result is unchanged.  But the resulting <lef-files> path in the
generated klayout.lyt is later resolved by klayout against the LYT
file's location.  Klayout opens the LYT (also through a symlink),
resolves through to the bare execroot, and then looks for the
sibling klayout_tech.lef at the bare-execroot path — where the
in-flight file does not exist during action execution (only the
sandbox copy does), so def2stream fails with errno=2.

Fix: don't realpath.  os.path.relpath produces the correct relative
path from sandbox-relative inputs directly.  Map files keep their
absolute form via abspath for the unchanged-under-non-sandbox case.

Surfaced for the first time on bazelisk build
//flow/designs/sky130hd/gcd:gcd_final_blender_html — the
orfs_blender macro is the first bazel-side consumer of orfs_gds
(klayout def2stream), so the latent path bug had no prior trigger.

Mirrors bazel-orfs's patches/0037-fix-generate_klayout_tech-drop-realpath.patch
into ORFS directly so bazel-orfs no longer needs to carry it.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
The previous switch to relpath (commit 01652ca) cleaned up the
content but did not actually fix def2stream's errno=2 under a Bazel
sandbox.  Investigation via strace shows klayout's
Layout.read(def, layout_options) opens the input DEF (a sandbox
symlink to the bare execroot, staged from orfs_final), realpath's
it to the bare-execroot results dir, and then resolves <lef-files>
relative paths against THAT dir.  Sibling intermediates like
objects/klayout_tech.lef only exist in the per-action sandbox, not
at the bare execroot, so the lookup lands at
.../execroot/_main/bazel-out/.../klayout_tech.lef and fails with
errno=2.

Declaring klayout_tech.lef as a Bazel output of orfs_gds doesn't
help -- Bazel only materialises declared outputs at the bare
execroot at action completion, not while the action is still
running and klayout is reading them.

Plain abspath (NOT realpath -- realpath would chase Bazel
input-file symlinks back out to the bare execroot for any input
already at the bare execroot) writes the in-sandbox absolute LEF
path into the LYT.  KLayout opens that absolute path directly with
no relative-path resolution involved, so the sibling lookup never
escapes the sandbox.

Cost: the LYT's content now embeds the per-invocation sandbox
number, so the orfs_gds action cannot be cross-action cached.
That's an acceptable trade-off for correctness while we wait for
a klayout-level fix or a Bazel feature that lets us write a
stable bare-execroot path from inside the action.

Confirmed end-to-end:
  bazelisk build //flow/designs/sky130hd/gcd:gcd_final_blender_html
produces 6_final.gds and the blender_html sh_binary, with both
the sandbox sandbox-id N going forward and after fresh action
re-runs (verified by deleting outputs and rebuilding).

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
Earlier commit a1552a8 switched generate_klayout_tech.py to write
absolute LEF paths into the LYT (bypasses klayout's relative-resolution
escape to the bare-execroot under a Bazel sandbox).  The unit test
test_basic_generation still asserted the old relpath form and failed
in CI:

  AssertionError: '../tech.lef' not found in
    '...<lef-files>/tmp/tmpwlgkq96a/tech.lef</lef-files>...'

Update the assertion to expect os.path.abspath(lef_path).

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
@oharboe oharboe requested a review from maliberty May 18, 2026 04:43
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the Klayout technology generation to use absolute paths instead of relative or real paths for LEF and map files, ensuring correct resolution within Bazel sandboxes. Review feedback highlights that the reference_dir and use_relative_paths parameters are now unused and should be cleaned up. Additionally, an inconsistency was noted where the test_with_map_files test still expects realpath, which may cause failures on certain platforms.

Comment thread flow/util/generate_klayout_tech.py Outdated
Comment thread flow/util/generate_klayout_tech.py Outdated
…enROAD-Project#4234

Two follow-ups from gemini's review of The-OpenROAD-Project#4234:

  * The map-file test in test_with_map_files still asserted
    `os.path.realpath(map_path)`, inconsistent with the LEF test's
    `os.path.abspath` switch.  On platforms whose tmpdir contains
    symlinks (macOS /var -> /private/var) the test would fail.
    Switch to `os.path.abspath` to match the LEF case.

  * `reference_dir` and `use_relative_paths` are now both unused.
    Update the function docstring to say so, default both to
    `None` / `False` so callers can drop them, and demote the CLI
    flags to `required=False` so external scripts that don't pass
    them still work.  flow/Makefile still passes `--reference-dir`
    so we keep accepting the flag.

Signed-off-by: Øyvind Harboe <oyvind@ascenium.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
@oharboe
Copy link
Copy Markdown
Collaborator Author

oharboe commented May 18, 2026

/gemini review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the KLayout technology generation utility to use absolute paths for LEF and map files, which prevents path resolution failures within Bazel sandboxes. It also deprecates the reference_dir and use_relative_paths parameters by making them optional. The review feedback correctly identifies that the change in the function's argument order breaks backward compatibility for positional calls and suggests restoring the original order, updating the docstring for consistency, and ensuring map_files is handled safely if passed as null.

Comment thread flow/util/generate_klayout_tech.py Outdated
Comment thread flow/util/generate_klayout_tech.py Outdated
Comment thread flow/util/generate_klayout_tech.py Outdated
…ect#4234

Three follow-ups from gemini's second review pass:

  * Restore the original positional argument order
    (template_lyt, output_lyt, lef_files, reference_dir, map_files,
     use_relative_paths) so Python callers that pass the args
    positionally still work.  Prior fix reshuffled `map_files` ahead
    of `reference_dir`, breaking positional compatibility.

  * Re-order the Args block in the docstring to match the new
    signature order.

  * `map_files` is now `None`-defaulted (to keep the positional-order
    fix above), so iterate via `map_files or []` rather than dereferencing
    `None` directly.

Signed-off-by: Øyvind Harboe <oyvind@ascenium.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
@oharboe
Copy link
Copy Markdown
Collaborator Author

oharboe commented May 18, 2026

/gemini review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the Klayout technology generation utility to use absolute paths for LEF and map files instead of relative or real paths. This change ensures that file resolution works correctly within Bazel sandboxed environments where relative path resolution against the realpath of the input DEF would otherwise fail. The reference_dir and use_relative_paths parameters have been deprecated and are now unused, though they remain for backward compatibility. I have no feedback to provide as there were no review comments.

Comment thread flow/util/generate_klayout_tech.py Outdated
Comment on lines +47 to +49
reference_dir: Unused. Accepted for backward compatibility with
callers (e.g. flow/Makefile) that still pass it from when
paths were resolved relative to this directory.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just remove the unused args and update the Makefile.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like so?

…e_paths

Per maliberty's review on The-OpenROAD-Project#4234: rather than keep `reference_dir` and
`use_relative_paths` around as ignored backward-compat parameters,
drop them entirely and update flow/Makefile to stop passing
`--reference-dir`.  No remaining caller in the tree relies on either.

Changes:
  * flow/util/generate_klayout_tech.py — `generate_klayout_tech()`
    signature is now (template_lyt, output_lyt, lef_files,
    map_files=None).  CLI loses `--reference-dir` and
    `--use-relative-paths`.  Stale comment / docstring lines about
    the dropped args go too.
  * flow/Makefile — `do-klayout` and `do-klayout_wrap` both stop
    passing `--reference-dir`.
  * flow/test/test_generate_klayout_tech.py — drops the now-invalid
    `reference_dir=` / `use_relative_paths=` kwargs from the three
    integration-style tests.  Existing 13 tests still pass.
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
@oharboe oharboe requested a review from maliberty May 18, 2026 15:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants