 Attach mtimes to individual deps, not files. Fixes a miscompile (!!)
Fix bug:
- Assume X and Y depend on Z
- X and Y both compile clean.
- A change is made to Z
- X and Y are now "out-of-date," and marked to compile.
- The change causes a failure in X, but Y still compiles clean.
- Because X compiles clean, the database will be updated and store the new mtime of Z!
- Attempting to compile again, the mtime of Z will not be considered "changed" since the last compile.
- X depends on Z, but Z is not marked "changed," and X will not be recompiled, even though it is still in a dirty state!
- Linking of X and Y produces wild results. UB. ORD NDR. Badness.
The fix is to have the edges in the graph between inputs and outputs
store the mtime of the input, rather than to store that mtime on the
file itself. Thus, each individual relationship between inputs and
outputs will track the "outdated-ness" of themselves.
This also adds a test which can correctly reproduce the issue in absense of the fix.
5 vuotta sitten |
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- import subprocess
- import time
-
- import pytest
-
- from tests import dds, DDS, dds_fixture_conf_1
- from dds_ci import proc
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- def build_and_get_rc(dds: DDS) -> int:
- dds.build()
- app = dds.build_dir / ('app' + dds.exe_suffix)
- return proc.run(app).returncode
-
-
- def test_simple_rebuild(dds: DDS):
- """
- Check that changing a source file will update the resulting application.
- """
- assert build_and_get_rc(dds) == 0
- dds.scope.enter_context(
- dds.set_contents(
- 'src/1.cpp',
- b'''
- int value_1() { return 33; }
- ''',
- ))
-
- assert build_and_get_rc(dds) == 1
-
-
- def test_rebuild_header_change(dds: DDS):
- """Change the content of the header which defines the values"""
- assert build_and_get_rc(dds) == 0
- dds.scope.enter_context(
- dds.set_contents(
- 'src/values.hpp',
- b'''
- const int first_value = 63;
- const int second_value = 88;
- ''',
- ))
- assert build_and_get_rc(dds) == (88 - 63)
-
-
- def test_partial_build_rebuild(dds: DDS):
- """
- Change the content of a header, but cause one user of that header to fail
- compilation. The fact that compilation fails means it is still `out-of-date`,
- and will need to be compiled after we have fixed it up.
- """
- assert build_and_get_rc(dds) == 0
- dds.scope.enter_context(
- dds.set_contents(
- 'src/values.hpp',
- b'''
- const int first_value_q = 6;
- const int second_value_q = 99;
- ''',
- ))
-
- with pytest.raises(subprocess.CalledProcessError):
- dds.build()
-
- dds.scope.enter_context(
- dds.set_contents(
- 'src/1.cpp',
- b'''
- #include "./values.hpp"
-
- int value_1() { return first_value_q; }
- ''',
- ))
-
- with pytest.raises(subprocess.CalledProcessError):
- dds.build()
-
-
-
-
- with pytest.raises(subprocess.CalledProcessError):
- dds.build()
-
- dds.scope.enter_context(
- dds.set_contents(
- 'src/2.cpp',
- b'''
- #include "./values.hpp"
-
- int value_2() { return second_value_q; }
- ''',
- ))
-
- assert build_and_get_rc(dds) == (99 - 6)
|