Relink when linker commands change

This commit is contained in:
Hassan Raza 2026-08-12 16:21:24 +05:00
parent 00a5ca54ef
commit 111cd86f61
No known key found for this signature in database
2 changed files with 30 additions and 10 deletions

View file

@ -12,11 +12,31 @@ import tempfile
import textwrap
import unittest
from functools import partial
from unittest.mock import patch
from .base import BaseTest
class TestBuild(BaseTest):
def test_incremental_link_command_changes(self) -> None:
import setup
def scheduled_commands(command: list[str], stored_command: list[str]) -> list[setup.Command]:
scheduled: list[setup.Command] = []
with tempfile.TemporaryDirectory() as tdir, patch.object(setup, 'build_dir', tdir):
linkdb = [{'output': setup.LinkKey('kitty'), 'arguments': stored_command}]
with open(os.path.join(tdir, 'link_commands.json'), 'w') as f:
json.dump(linkdb, f)
with setup.CompilationDatabase(incremental=True) as database:
database.add_command('Linking launcher', command, lambda: False, key=setup.LinkKey('kitty'))
with patch.object(setup, 'parallel_run', side_effect=lambda items: scheduled.extend(items)):
database.build_all()
return scheduled
self.assertFalse(scheduled_commands(['cc', '-o', 'kitty'], ['cc', '-o', 'kitty']))
scheduled = scheduled_commands(['cc', '-lnew', '-o', 'kitty'], ['cc', '-lold', '-o', 'kitty'])
self.assertEqual([command.cmd for command in scheduled], [['cc', '-lnew', '-o', 'kitty']])
def test_exe(self) -> None:
from kitty.constants import kitten_exe, kitty_exe, slangc, str_version

View file

@ -207,6 +207,8 @@ class CompilationDatabase:
self.compile_commands: List[Command] = []
self.link_commands: List[Command] = []
self.post_link_commands: List[Command] = []
self.db: Dict[CompileKey, Sequence[str]] = {}
self.linkdb: Dict[CompileKey, Sequence[str]] = {}
def add_command(
self,
@ -236,15 +238,15 @@ class CompilationDatabase:
items = []
for compile_cmd in self.compile_commands:
if not self.incremental or self.cmd_changed(compile_cmd) or compile_cmd.is_newer_func():
if not self.incremental or self.cmd_changed(compile_cmd, self.db) or compile_cmd.is_newer_func():
items.append(compile_cmd)
items.sort(key=sort_key, reverse=True)
parallel_run(items)
items = []
for compile_cmd in self.link_commands:
if not self.incremental or compile_cmd.is_newer_func():
items.append(compile_cmd)
for link_cmd in self.link_commands:
if not self.incremental or self.cmd_changed(link_cmd, self.linkdb) or link_cmd.is_newer_func():
items.append(link_cmd)
parallel_run(items)
items = []
@ -253,12 +255,10 @@ class CompilationDatabase:
items.append(compile_cmd)
parallel_run(items)
def cmd_changed(self, compile_cmd: Command) -> bool:
key, cmd = compile_cmd.key, compile_cmd.cmd
dkey = self.db.get(key)
if dkey != cmd:
def cmd_changed(self, command: Command, database: Dict[CompileKey, Sequence[str]]) -> bool:
if command.key is None:
return True
return False
return database.get(command.key) != command.cmd
def __enter__(self) -> 'CompilationDatabase':
self.all_keys: Set[CompileKey] = set()
@ -276,7 +276,7 @@ class CompilationDatabase:
link_database = []
compilation_database = {CompileKey(k['file'], k['output']): k['arguments'] for k in compilation_database}
self.db = compilation_database
self.linkdb = {tuple(k['output']): k['arguments'] for k in link_database}
self.linkdb = {CompileKey(*k['output']): k['arguments'] for k in link_database}
return self
def __exit__(self, *a: object) -> None: