diff --git a/kitty_tests/check_build.py b/kitty_tests/check_build.py index 63f21b302..cddb7e6a9 100644 --- a/kitty_tests/check_build.py +++ b/kitty_tests/check_build.py @@ -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 diff --git a/setup.py b/setup.py index 0aa9e7b79..5020c6101 100755 --- a/setup.py +++ b/setup.py @@ -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: