mirror of
https://github.com/lucannez64/darling-lol.git
synced 2026-10-26 19:47:42 +00:00
Merge commit 'refs/review/mint-148' into fix/mint-review-integration
This commit is contained in:
commit
2142b54d94
4 files changed
+171
-4
No files matched your search
@@ -43,3 +43,4 @@ jobs:
|
||||
- run: python -m unittest discover -s tests -p 'test_clean_stale_helpers.py'
|
||||
- run: python -m unittest discover -s tests -p 'test_hide_league_client_in_game.py'
|
||||
- run: python -m unittest discover -s tests -p 'test_client_in_game_tricks.py'
|
||||
- run: python -m unittest discover -s tests -p 'test_setup_portability.py'
|
||||
@@ -523,6 +523,31 @@ A separate multi-window path stopped the active async presenter when another dif
|
||||
- **Prebuilt Swift file contains Git LFS pointer text:** install Git LFS and fetch the original upstream assets; pointer text is not a usable library.
|
||||
- **Submodule fetch stops with no output right after `src/external/sqlite`:** the next submodule is `src/external/swift`, whose pinned `.lfsconfig` points at the retired `git-lfs.darlinghq.org`. The checkout is blocked on that host, not on sqlite. `prepare.py` redirects that submodule's LFS requests to GitHub. To finish a fetch that was interrupted before any patches were applied, run `git -C build/darling-src -c lfs.url=https://github.com/darlinghq/darling-swift.git/info/lfs submodule update --init --recursive --progress`, then re-run `./scripts/build.sh`. Do not run that submodule update once `prepare.py` has applied patches: it resets every submodule working tree to the pinned revision and discards the patches.
|
||||
|
||||
## Checkout moved to another path or account
|
||||
|
||||
`build/config.json`, the generated helpers and the CMake cache record absolute paths, so a checkout that was moved (for example from `/root/darling-lol` to `/home/<user>/darling-lol`, or renamed while staying in the same account) keeps pointing at the old location ([issue #142](https://github.com/lucannez64/darling-lol/issues/142)). `scripts/configure.py` now repairs the parts it owns and reports the rest on stderr:
|
||||
|
||||
- **Prefix:** a saved prefix that was exactly `<previous home>/.darling` follows the new host home. A prefix you chose yourself is kept, and a prefix inside the previous home prints a reminder to pass `--prefix` explicitly.
|
||||
- **`build/runtime/build`:** recreated as a relative link, so it survives later moves. An absolute or dangling leftover is replaced; a real directory at that path is reported and left untouched.
|
||||
- **CMake cache:** a `build/darling-src/build/CMakeCache.txt` whose `CMAKE_HOME_DIRECTORY` names a different checkout is reported, together with the path to remove. It is never deleted automatically because it can hold local build state.
|
||||
|
||||
After moving a checkout, run:
|
||||
|
||||
```sh
|
||||
python3 scripts/configure.py
|
||||
```
|
||||
|
||||
If the warning names another source directory, the cache still holds object files and dependency lists for the old path, and the build fails with `Permission denied` or `No such file or directory` against it. Remove it and rebuild (as the same user that owns the checkout):
|
||||
|
||||
```sh
|
||||
rm -rf build/darling-src/build
|
||||
./scripts/build.sh
|
||||
```
|
||||
|
||||
Patches are rendered at `scripts/prepare.py` time, so `@PROJECT_ROOT@` in a patched file keeps the old path until it runs again. `./scripts/build.sh` and `./scripts/update.sh` both do that; do not run `prepare.py` by hand while the checkout has other edits in `build/darling-src`, because it refuses rather than resetting them.
|
||||
|
||||
The opt-in RenderDoc capture bridge (`RCLOL_RENDERDOC_CAPTURE=1`) is a developer diagnostic, not part of the installer. It expects `build/renderdoc/capture-bridge.so` and a RenderDoc build under `build/renderdoc/`, and neither setup script creates them. Without those files the capture is skipped and the game runs normally; the absolute path baked into the Indium patch is refreshed by the same `prepare.py` run.
|
||||
|
||||
## launchd crashes at boot after changing compiler flags
|
||||
|
||||
`darling shell` fails with `Error connecting to shellspawn` and `/tmp/lolsig.log` shows `LOLSIGFAIL pid=1 sig=11 code=1 addr=0x0` in `memmove`, called from `snprintf` in libkqueue's `epoll_event_dump`. The binaries were tuned for AMD Zen: clang 23 with `-mtune=znver*` (also selected by `-march=native` or `-mtune=native` on Zen) loads a thread-local variable's descriptor into a register other than `%rdi`, but dyld's `tlv_get_addr` reads `%rdi`, so every `__thread` and `thread_local` access returns NULL. Rebuild with `-mtune=generic` (the default in `scripts/build.sh` and the overlay builders), and check any binary with:
|
||||
|
||||
+60
-4
@@ -1,15 +1,66 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Render local paths into ignored runtime tools; never alter the source snapshot."""
|
||||
import argparse,json,os,shutil
|
||||
import argparse,json,os,shutil,sys
|
||||
from pathlib import Path
|
||||
from common import ROOT,configuration,render
|
||||
|
||||
def warn(message):
|
||||
"""Diagnostics go to stderr: launcher/run.sh keep stdout for their own output."""
|
||||
print('configure:',message,file=sys.stderr)
|
||||
|
||||
def rehome_prefix(c,requested):
|
||||
"""The default prefix is derived from the host home, so a checkout that moved to another
|
||||
machine or account must follow the new home instead of keeping the previous one (issue #142)."""
|
||||
home=Path.home()
|
||||
if requested is not None:return str(requested)
|
||||
saved=c.get('prefix')
|
||||
if not saved:return str(home/'.darling')
|
||||
old_home=c.get('host_home')
|
||||
if old_home and old_home!=str(home):
|
||||
if saved==str(Path(old_home)/'.darling'):
|
||||
warn(f'previous home {old_home} is gone; the default prefix moved to {home/".darling"}')
|
||||
return str(home/'.darling')
|
||||
try:relative=Path(saved).is_relative_to(old_home)
|
||||
except (TypeError,ValueError):relative=False
|
||||
if relative:
|
||||
warn(f'prefix {saved} is inside the previous home {old_home}; pass --prefix to move it')
|
||||
return saved
|
||||
|
||||
def link_build(runtime):
|
||||
"""build/runtime/build must resolve to this checkout's build directory. A relative link keeps
|
||||
working after the checkout moves, and any absolute or dangling leftover is replaced instead of
|
||||
being treated as already correct (issue #142)."""
|
||||
link=runtime/'build'
|
||||
target='..' # build/runtime/build -> build
|
||||
if link.is_symlink():
|
||||
if os.readlink(link)==target:return
|
||||
link.unlink()
|
||||
elif os.path.lexists(link):
|
||||
warn(f'{link} is not a symlink; leaving it untouched')
|
||||
return
|
||||
link.symlink_to(target,target_is_directory=True)
|
||||
|
||||
def stale_cache(build):
|
||||
"""Return (cache, recorded source directory) when the CMake cache belongs to another checkout."""
|
||||
cache=build/'darling-src/build/CMakeCache.txt'
|
||||
try:lines=cache.read_text(errors='replace').splitlines()
|
||||
except OSError:return None
|
||||
expected=os.path.realpath(build/'darling-src')
|
||||
for line in lines:
|
||||
key,_,value=line.partition('=')
|
||||
if key.split(':')[0]!='CMAKE_HOME_DIRECTORY':continue
|
||||
if os.path.realpath(value)!=expected:return cache,value
|
||||
return None
|
||||
return None
|
||||
|
||||
p=argparse.ArgumentParser(description=__doc__)
|
||||
p.add_argument('--guest-user');p.add_argument('--prefix',type=Path);p.add_argument('--sdk',type=Path)
|
||||
a=p.parse_args();c=configuration()
|
||||
if a.guest_user:
|
||||
if not a.guest_user.replace('_','').replace('-','').isalnum():p.error('guest user must be a simple account name')
|
||||
c['guest_user']=a.guest_user;c['guest_home']='/Users/'+a.guest_user
|
||||
if a.prefix:c['prefix']=str(a.prefix.expanduser().resolve())
|
||||
# Resolve the prefix before overwriting host_home, so it can still see the previous home.
|
||||
c['prefix']=rehome_prefix(c,a.prefix.expanduser().resolve() if a.prefix else None)
|
||||
if a.sdk:c['sdk']=str(a.sdk.expanduser().resolve())
|
||||
c['project_root']=str(ROOT);c['host_home']=str(Path.home())
|
||||
build=ROOT/'build';build.mkdir(exist_ok=True)
|
||||
@@ -23,6 +74,11 @@ for source in (ROOT/'tools').iterdir():
|
||||
target.unlink(missing_ok=True)
|
||||
target.write_text(render(source.read_text(),c))
|
||||
os.chmod(target,source.stat().st_mode & 0o777)
|
||||
link=folder.parent/'build'
|
||||
if not link.exists():link.symlink_to(build,target_is_directory=True)
|
||||
link_build(folder.parent)
|
||||
stale=stale_cache(build)
|
||||
if stale:
|
||||
cache,previous=stale
|
||||
warn(f'{cache} was generated for {previous}, not {build/"darling-src"}; builds will fail with '
|
||||
f'missing files or permission errors against the old path. Remove {build/"darling-src/build"} '
|
||||
'and build again (it is never removed automatically because it may hold local work).')
|
||||
print('Configured',len(list(folder.iterdir())),'runtime sources for',c['guest_home'])
|
||||
@@ -120,6 +120,91 @@ exec REAL_INSTALL "$@"'''.replace('REAL_INSTALL', shutil.which('install')))
|
||||
self.assertFalse(target.is_symlink())
|
||||
|
||||
|
||||
def write_config(self, **changes):
|
||||
(self.root / 'build/config.json').write_text(json.dumps(dict(self.config, **changes)))
|
||||
|
||||
|
||||
def config_value(self, key):
|
||||
return json.loads((self.root / 'build/config.json').read_text())[key]
|
||||
|
||||
|
||||
def test_configure_rehomes_default_prefix_after_home_change(self):
|
||||
previous = Path(self.tmp.name) / 'previous home'
|
||||
self.write_config(host_home=str(previous), prefix=str(previous / '.darling'))
|
||||
result = self.run_script('scripts/configure.py')
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertEqual(self.config_value('prefix'), str(self.home / '.darling'))
|
||||
self.assertIn('previous home', result.stderr)
|
||||
|
||||
|
||||
def test_configure_keeps_explicit_prefix_after_home_change(self):
|
||||
previous = Path(self.tmp.name) / 'previous home'
|
||||
self.write_config(host_home=str(previous), prefix=str(self.prefix))
|
||||
self.configure()
|
||||
self.assertEqual(self.config_value('prefix'), str(self.prefix))
|
||||
self.assertEqual(self.config_value('host_home'), str(self.home))
|
||||
|
||||
|
||||
def test_configure_warns_about_prefix_inside_previous_home(self):
|
||||
previous = Path(self.tmp.name) / 'previous home'
|
||||
self.write_config(host_home=str(previous), prefix=str(previous / 'custom prefix'))
|
||||
result = self.run_script('scripts/configure.py')
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertEqual(self.config_value('prefix'), str(previous / 'custom prefix'))
|
||||
self.assertIn('--prefix', result.stderr)
|
||||
|
||||
|
||||
def test_configure_creates_relative_build_symlink(self):
|
||||
self.configure()
|
||||
link = self.root / 'build/runtime/build'
|
||||
self.assertEqual(os.readlink(link), '..')
|
||||
self.assertEqual(link.resolve(), (self.root / 'build').resolve())
|
||||
|
||||
|
||||
def test_configure_repairs_absolute_and_dangling_build_symlink(self):
|
||||
link = self.root / 'build/runtime/build'
|
||||
link.parent.mkdir(parents=True)
|
||||
link.symlink_to(self.root / 'build')
|
||||
self.configure()
|
||||
self.assertEqual(os.readlink(link), '..')
|
||||
link.unlink()
|
||||
link.symlink_to(self.root / 'moved away/build')
|
||||
self.configure()
|
||||
self.assertTrue(link.is_symlink())
|
||||
self.assertEqual(link.resolve(), (self.root / 'build').resolve())
|
||||
|
||||
|
||||
def test_configure_leaves_foreign_build_directory(self):
|
||||
link = self.root / 'build/runtime/build'
|
||||
link.mkdir(parents=True)
|
||||
(link / 'keep').write_text('local build')
|
||||
result = self.run_script('scripts/configure.py')
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertFalse(link.is_symlink())
|
||||
self.assertEqual((link / 'keep').read_text(), 'local build')
|
||||
self.assertIn('not a symlink', result.stderr)
|
||||
|
||||
|
||||
def test_configure_warns_about_stale_cmake_cache(self):
|
||||
cache = self.root / 'build/darling-src/build/CMakeCache.txt'
|
||||
cache.parent.mkdir(parents=True)
|
||||
cache.write_text('// generated\nCMAKE_HOME_DIRECTORY:INTERNAL=/root/old checkout/build/darling-src\n')
|
||||
result = self.run_script('scripts/configure.py')
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertTrue(cache.is_file(), 'configure removed the CMake cache')
|
||||
self.assertIn('/root/old checkout/build/darling-src', result.stderr)
|
||||
self.assertIn('Remove', result.stderr)
|
||||
|
||||
|
||||
def test_configure_accepts_current_cmake_cache(self):
|
||||
cache = self.root / 'build/darling-src/build/CMakeCache.txt'
|
||||
cache.parent.mkdir(parents=True)
|
||||
cache.write_text(f'CMAKE_HOME_DIRECTORY:INTERNAL={self.root}/build/darling-src\n')
|
||||
result = self.run_script('scripts/configure.py')
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertEqual(result.stderr, '')
|
||||
|
||||
|
||||
def test_presentation_creates_prerequisites_and_repeat_install(self):
|
||||
self.configure()
|
||||
self.runtime_stubs()
|
||||
|
||||
Reference in new issue
Block a user