This is an archive of the discontinued LLVM Phabricator instance.

[lit] Avoid os.path.realpath in lit.py due to MAX_PATH limitations on Windows
ClosedPublic

Authored by MrTrillian on Jun 12 2023, 7:35 AM.

Details

Summary

lit.py uses os.path.realpath on file paths. Somewhere between Python 3.7 and 3.9, os.path.realpath was updated to resolve substitute drives on Windows (subst S: C:\Long\Path\To\My\Code). This is a problem because it prevents using substitute drives to work around MAX_PATH path length limitations on Windows.

We run into this while building & testing, the Swift compiler on Windows, which uses a substitute drive in CI to shorten the workspace directory. cmake builds without resolving the substitute drive and can apply its logic to avoid output files exceeding MAX_PATH. However, when running tests, lit.py's use of os.path.realpath will resolve the substitute drive (with newer Python versions), resulting in some paths being longer than MAX_PATH, which cause all kinds of failures (for example rd in tests fails, or link.exe fails, etc).

How tested: Ran check-all, and lit tests, saw no failures

> ninja -C build check-all
Testing Time: 262.63s
  Skipped          :    24
  Unsupported      :  2074
  Passed           : 51812
  Expectedly Failed:   167

> python utils\lit\lit.py --path ..\build\bin utils\lit\tests
Testing Time: 12.17s
  Unsupported:  6
  Passed     : 47

Diff Detail

Event Timeline

MrTrillian created this revision.Jun 12 2023, 7:35 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 12 2023, 7:35 AM
Herald added a subscriber: delcypher. · View Herald Transcript
MrTrillian requested review of this revision.Jun 12 2023, 7:35 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 12 2023, 7:35 AM
rnk accepted this revision.Jun 12 2023, 2:18 PM

lgtm

llvm/utils/lit/lit/discovery.py
59

I see this uses realpath and that must be intentional.

This revision is now accepted and ready to land.Jun 12 2023, 2:18 PM
MrTrillian added inline comments.Jun 13 2023, 7:42 AM
llvm/utils/lit/lit/discovery.py
59

@rnk The reason was that this is looking up a param from outside the script and I thought it might regress something, but let me try locally if I can convert this and the one in def search below as well.

Converted final two instances of realpath to abspath. Reran tests.

compnerd accepted this revision.Jun 14 2023, 11:10 AM
nlopes added a subscriber: nlopes.Jun 15 2023, 2:01 AM

This commit started failing running llvm-lit outside the llvm directory:

$ ~/llvm/build/bin/llvm-lit -vv ~/llvm/llvm/test/Transforms
llvm-lit: /bitbucket/nlopes/llvm/llvm/utils/lit/lit/TestingConfig.py:151: fatal: unable to parse config file '/home/nlopes/llvm/llvm/test/lit.cfg.py', traceback: Traceback (most recent call last):
  File "/bitbucket/nlopes/llvm/llvm/utils/lit/lit/TestingConfig.py", line 139, in load_from_path
    exec(compile(data, path, "exec"), cfg_globals, None)
  File "/home/nlopes/llvm/llvm/test/lit.cfg.py", line 21, in <module>
    config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell)
AttributeError: 'NoneType' object has no attribute 'use_lit_shell'

Any idea of what's going on?

This commit started failing running llvm-lit outside the llvm directory:

$ ~/llvm/build/bin/llvm-lit -vv ~/llvm/llvm/test/Transforms
llvm-lit: /bitbucket/nlopes/llvm/llvm/utils/lit/lit/TestingConfig.py:151: fatal: unable to parse config file '/home/nlopes/llvm/llvm/test/lit.cfg.py', traceback: Traceback (most recent call last):
  File "/bitbucket/nlopes/llvm/llvm/utils/lit/lit/TestingConfig.py", line 139, in load_from_path
    exec(compile(data, path, "exec"), cfg_globals, None)
  File "/home/nlopes/llvm/llvm/test/lit.cfg.py", line 21, in <module>
    config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell)
AttributeError: 'NoneType' object has no attribute 'use_lit_shell'

Any idea of what's going on?

I suspect it has to do with the remaining os.path.realpath in llvm\utils\llvm-lit\llvm-lit.in. How can I repro this?

This caused a failure on AIX
https://lab.llvm.org/buildbot/#/builders/214/builds/7990/steps/6/logs/FAIL__lit___use-llvm-tool_py

It looks like the test expects /home but on AIX we use a temporary directory /scratch

This commit started failing running llvm-lit outside the llvm directory:

$ ~/llvm/build/bin/llvm-lit -vv ~/llvm/llvm/test/Transforms
llvm-lit: /bitbucket/nlopes/llvm/llvm/utils/lit/lit/TestingConfig.py:151: fatal: unable to parse config file '/home/nlopes/llvm/llvm/test/lit.cfg.py', traceback: Traceback (most recent call last):
  File "/bitbucket/nlopes/llvm/llvm/utils/lit/lit/TestingConfig.py", line 139, in load_from_path
    exec(compile(data, path, "exec"), cfg_globals, None)
  File "/home/nlopes/llvm/llvm/test/lit.cfg.py", line 21, in <module>
    config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell)
AttributeError: 'NoneType' object has no attribute 'use_lit_shell'

Any idea of what's going on?

I suspect it has to do with the remaining os.path.realpath in llvm\utils\llvm-lit\llvm-lit.in. How can I repro this?

my ~/llvm dir is a symlink

my ~/llvm dir is a symlink

This change doesn't break symlinks. It would only cause issues if some code resolves symlinks to real paths whereas other code does not and we expect the two paths to be the same.