Skip to content

Read the Variables() saved-variables file from the source directory (#816)#4875

Open
CornElDos wants to merge 1 commit into
SCons:masterfrom
CornElDos:fix/816-variables-source-dir
Open

Read the Variables() saved-variables file from the source directory (#816)#4875
CornElDos wants to merge 1 commit into
SCons:masterfrom
CornElDos:fix/816-variables-source-dir

Conversation

@CornElDos

Copy link
Copy Markdown

Summary

Variables() reads its saved-variables file(s) (e.g. custom.py) with a hand-rolled os.path.exists() / open(), which only ever looks in the build directory. When the source directory differs from the build directory — for example when building against a separate source tree via Repository() — a custom.py placed in the source tree is not found and its values are silently ignored. This is issue #816 (the code even carried a # TODO: issue #816 marker on the offending lines).

Change

Resolve the saved-variables file through the File() node infrastructure instead of touching the filesystem directly:

  • env.File(filename) with rexists() / srcnode() locates the file in the build directory, the source (variant) directory, or a repository.
  • rfile().get_text_contents() reads the actual on-disk file, and rfile().get_abspath() is used for the sys.path entry so imports inside the file resolve against its real location.

This follows the approach suggested by the maintainers in the issue (use the File() infrastructure / get_text_contents()).

Testing

  • New regression test test/Variables/source-dir.py builds against a separate source tree via Repository() and asserts the source-tree custom.py is applied. It fails without this change and passes with it.
  • The full test/Variables/ suite passes (10 tests, no regressions).

Note: the Save() path still writes relative to the build directory (also mentioned in the original report). That is a separate concern and is intentionally left out here to keep the change focused; happy to follow up separately.

@mwichmann

Copy link
Copy Markdown
Collaborator

Thanks for the submission! I've been looking at related issues, where the variantdir mechanism (which counts on remapping filenames if in effect), and to some extent Repository as well, are bypassed by code going directly to the file system. I will say it's little murky what the intent is when the object in question isn't going to be part of the build graph - the saved-variables file being one of those cases. Should those be relocated or not? I guess you're prodding us to answer that question...

@mwichmann mwichmann added the Variables Variables() subsystem label Jul 8, 2026
)

Variables() read its saved-variables file(s) (e.g. custom.py) by hand
with os.path.exists()/open(), which only looks in the build directory.
When the source directory differs from the build directory (for example
when building against a separate source tree via Repository), a custom.py
placed in the source tree was not found.

Resolve the file through the File() node infrastructure instead
(rexists()/srcnode() + rfile()), so it is located in the source directory
or a repository as well as the build directory.

Add a regression test and a CHANGES.txt entry.

Signed-off-by: Cornelii Sandberg <corresandberg@gmail.com>
Assisted-by: Claude Code (Anthropic)
@CornElDos CornElDos force-pushed the fix/816-variables-source-dir branch from 0edf6a2 to 8c9149e Compare July 8, 2026 13:35
@CornElDos

CornElDos commented Jul 8, 2026 via email

Copy link
Copy Markdown
Author

@mwichmann

Copy link
Copy Markdown
Collaborator

I've done some more digging since I'm interested in the general topic, and there's a fair bit to consider. Even though I added the TODO lines which asked if we should use the node system to resolve the path (fairly recently - only about two years ago), I'm not currently convinced that adding a saved-variables file to the node graph is the best approach. There are other ways to resolve the path that should work (SConstruct-relative). Meanwhile, there are expectations built in to existing tests about paths - see test/Variables/chdir.py and test/Variables/import.py - they use a trick with a relative path which seems dodgy to me (as in, may have come from: "oops, this test didn't work. How can I fiddle it so it passes"), but could have been intentional - see the line opts = Variables('../bin/opts.cfg', ARGUMENTS).

@CornElDos

CornElDos commented Jul 8, 2026 via email

Copy link
Copy Markdown
Author

@mwichmann

Copy link
Copy Markdown
Collaborator

There's another point, perhaps not fair to layer it onto a quite specific PR... in all existing versions, you can't use top-relative addressing for specifying saved-variables files (#/saved.py). Using File() magically "fixes" that, although it was never documented as possible; other approaches would have to do a bit more work.

@CornElDos

CornElDos commented Jul 8, 2026 via email

Copy link
Copy Markdown
Author

for filename in self.files:
# TODO: issue #816 use Node to access saved-variables file?
if os.path.exists(filename):
# Resolve the saved-variables file through the File() node so it

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

At first glance, seems like all this can be replaced by
contents=File(filename).get_text_contents()

Any reason (that I"m missing) not to do that?

return self.dict[key]
def __contains__(self, key) -> bool:
return key in self.dict
def File(self, name):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you just import File and use that directly?

@bdbaddog

bdbaddog commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Looks good.

I added a few comments which may simplify your logic.

Also, please add a blurb to RELEASE.txt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Variables Variables() subsystem

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants