diff --git a/.github/workflows/gen_matrix.py b/.github/workflows/gen_matrix.py index 61ddca1..e4bdc8b 100755 --- a/.github/workflows/gen_matrix.py +++ b/.github/workflows/gen_matrix.py @@ -49,6 +49,12 @@ def find_include_paths(line: str) -> Generator[Path, None, None]: yield curr_path break + elif path.name == "Makefile": + + def find_include_paths(line: str) -> Generator[Path, None, None]: + if line.strip().startswith("include "): + yield path.parent / line.strip().removeprefix("include ") + else: return frozenset() @@ -72,31 +78,40 @@ def get_transitive_dependencies(path: Path, *include_dirs: Path) -> frozenset[Pa @dataclass(order=True, frozen=True, kw_only=True) class Target: base_dir: Path - day: int + day: int | None prefix: str extra: str + @property + def _day_str(self) -> str: + if self.day is None: + return "" + return f"{self.day:02d}" + @property def suffix(self) -> str: - return f"{self.day:02d}{self.extra}" + return f"{self._day_str}{self.extra}" def __str__(self) -> str: - return f"{self.prefix}{self.day:02d}{self.extra}" + return f"{self.prefix}{self._day_str}{self.extra}" @classmethod def from_file(cls, base_dir: Path, source_file: Path) -> Target: m = re.match( - r"(?Pday|test)(?P\d+)(?P.*)$", source_file.stem + r"(?Pday|test)(?P\d+)?(?P.*)$", source_file.stem ) assert m is not None, source_file - return cls( - base_dir=base_dir, day=int(m["day"]), prefix=m["prefix"], extra=m["extra"] - ) + if m["day"] is None: + assert m["prefix"] == "test", "only unit tests may omit a day number" + day = None + else: + day = int(m["day"]) + return cls(base_dir=base_dir, day=day, prefix=m["prefix"], extra=m["extra"]) def get_deps(self, mode: str) -> frozenset[Path]: deps = set() src = self.base_dir / "src" - aoc_lib = self.base_dir.parent / "aoc_lib" + aoc_lib = self.base_dir.parent / "aoc_lib/src" deps.add(src / f"{self}.cpp") for included_file in get_transitive_dependencies( src / f"{self}.cpp", src, aoc_lib diff --git a/.github/workflows/test_gen_matrix.py b/.github/workflows/test_gen_matrix.py index edc3e92..5c6cddc 100644 --- a/.github/workflows/test_gen_matrix.py +++ b/.github/workflows/test_gen_matrix.py @@ -1,4 +1,12 @@ -from gen_matrix import ROOT, WORKFLOWS_DIR, Matrix, get_dependencies +from pathlib import Path + +from gen_matrix import ( + ROOT, + WORKFLOWS_DIR, + Matrix, + get_dependencies, + get_transitive_dependencies, +) ACTIONS_DIR = ROOT / ".github/actions" @@ -6,7 +14,7 @@ def test_get_dependencies_cpp(): base_dir = ROOT / "2023" src = base_dir / "src" - aoc_lib = base_dir.parent / "aoc_lib" + aoc_lib = base_dir.parent / "aoc_lib/src" include_dirs = (src, aoc_lib) assert get_dependencies(src / "day01.cpp", *include_dirs) == {aoc_lib / "lib.hpp"} assert get_dependencies(src / "day05.cpp", *include_dirs) == { @@ -19,6 +27,39 @@ def test_get_dependencies_cpp(): aoc_lib / "unit_test/unit_test.hpp", } + assert get_dependencies(ROOT / "2022/src/day16.cpp", *include_dirs) == { + ROOT / "2022/src/lib.h" + } + + +def test_get_transitive_dependencies(): + base_dir = ROOT / "2023" + src = base_dir / "src" + aoc_lib = base_dir.parent / "aoc_lib/src" + include_dirs = (src, aoc_lib) + assert get_transitive_dependencies(src / "day22.cpp", *include_dirs) == frozenset( + { + src / "day22.hpp", + aoc_lib / "lib.hpp", + aoc_lib / "util/hash.hpp", + aoc_lib / "util/concepts.hpp", + aoc_lib / "graph_traversal.hpp", + } + ) + + assert get_transitive_dependencies(aoc_lib / "test_ds.cpp", aoc_lib) == frozenset( + { + aoc_lib / "ds/grid.hpp", + aoc_lib / "ds/pairing_heap.hpp", + aoc_lib / "unit_test/pretty_print.hpp", + aoc_lib / "unit_test/unit_test.hpp", + aoc_lib / "util/util.hpp", + aoc_lib / "lib.hpp", + aoc_lib / "util/hash.hpp", + aoc_lib / "util/concepts.hpp", + } + ) + def test_get_dependencies_workflows(): assert get_dependencies(WORKFLOWS_DIR / "unit-tests.yml") == { @@ -41,60 +82,95 @@ def test_get_dependencies_workflows(): } -def matrix_helper(*changed_files: str) -> dict[str, set[str]]: - result = {} - for mode in ("build", "answer", "unit"): - matrix = Matrix(mode) - for f in changed_files: - matrix.process_changed_file(ROOT / f) - result[mode] = { - "{directory}/{name}".format(**target.to_dict()) for target in matrix.targets - } - return result +class MatrixHelper: + def __init__(self) -> None: + self.matrices = {mode: Matrix(mode) for mode in ("build", "answer", "unit")} + + def get_targets(self, *changed_files: str | Path) -> dict[str, set[str]]: + result = {} + for mode in ("build", "answer", "unit"): + matrix = self.matrices[mode] + for f in changed_files: + matrix.process_changed_file(ROOT / f) + result[mode] = { + "{directory}/{name}".format(**target.to_dict()) + for target in matrix.targets + } + matrix.targets.clear() + return result def test_matrix(): # pylint: disable=use-dict-literal - everything = matrix_helper("2022/Makefile", "tools/cpp/Makefile") + helper = MatrixHelper() + everything = helper.get_targets(*ROOT.glob("*/Makefile"), "tools/cpp/Makefile") # C++ source files - assert matrix_helper("2023/src/day05.cpp") == dict( + assert helper.get_targets("2023/src/day05.cpp") == dict( build={"2023/day05"}, answer={"2023/day05"}, unit=set() ) - assert matrix_helper("2023/src/day05.hpp") == dict( - build={"2023/day05", "2023/test05"}, answer={"2023/day05"}, unit={"2023/test05"} + assert helper.get_targets("2023/src/day05.hpp") == dict( + build={"2023/day05", "2023/test05"}, + answer={"2023/day05"}, + unit={"2023/test05"}, ) - assert matrix_helper("2023/src/test05.cpp") == dict( + assert helper.get_targets("2023/src/test05.cpp") == dict( build={"2023/test05"}, answer=set(), unit={"2023/test05"} ) + # 2022 doesn't use aoc_lib/src/lib.hpp + matrix = Matrix("build") + matrix.process_changed_file(ROOT / "aoc_lib/src/lib.hpp") + assert all(target.base_dir != ROOT / "2022" for target in matrix.targets) + + # unit tests for aoc_lib + assert helper.get_targets("aoc_lib/src/test_graph.cpp") == dict( + build={"aoc_lib/test_graph"}, + answer=set(), + unit={"aoc_lib/test_graph"}, + ) + assert "aoc_lib/test_lib" in helper.get_targets("aoc_lib/src/lib.hpp")["unit"] + assert ( + "aoc_lib/test_graph" + in helper.get_targets("aoc_lib/src/graph_traversal.hpp")["unit"] + ) + assert "aoc_lib/test_ds" in helper.get_targets("aoc_lib/src/ds/grid.hpp")["unit"] + assert ( + "aoc_lib/test_ds" + in helper.get_targets("aoc_lib/src/ds/pairing_heap.hpp")["unit"] + ) + assert ( + "aoc_lib/test_unit_test" + in helper.get_targets("aoc_lib/src/unit_test/unit_test.hpp")["unit"] + ) + # answer tests - assert matrix_helper("2023/answer_tests/day01/example2.txt") == dict( + assert helper.get_targets("2023/answer_tests/day01/example2.txt") == dict( build=set(), answer={"2023/day01"}, unit=set() ) # workflow files - assert matrix_helper(".github/workflows/gen_matrix.py") == everything - assert matrix_helper(".github/workflows/generate-matrix.yml") == everything - assert matrix_helper(".github/workflows/docker-build.yml") == everything + assert helper.get_targets(".github/workflows/gen_matrix.py") == everything + assert helper.get_targets(".github/workflows/generate-matrix.yml") == everything + assert helper.get_targets(".github/workflows/docker-build.yml") == everything - assert matrix_helper(".github/workflows/test-build.yml") == dict( + assert helper.get_targets(".github/workflows/test-build.yml") == dict( build=everything["build"], answer=set(), unit=set() ) - assert matrix_helper(".github/workflows/answer-tests.yml") == dict( + assert helper.get_targets(".github/workflows/answer-tests.yml") == dict( build=set(), answer=everything["answer"], unit=set() ) - assert matrix_helper(".github/workflows/unit-tests.yml") == dict( + assert helper.get_targets(".github/workflows/unit-tests.yml") == dict( build=set(), answer=set(), unit=everything["unit"] ) # workflow action helpers - assert matrix_helper(".github/actions/build-action/action.yml") == matrix_helper( - ".github/workflows/test-build.yml" - ) - assert matrix_helper( + assert helper.get_targets( + ".github/actions/build-action/action.yml" + ) == helper.get_targets(".github/workflows/test-build.yml") + assert helper.get_targets( ".github/actions/answer-test-action/action.yml" - ) == matrix_helper(".github/workflows/answer-tests.yml") - assert matrix_helper( + ) == helper.get_targets(".github/workflows/answer-tests.yml") + assert helper.get_targets( ".github/actions/unit-test-action/action.yml" - ) == matrix_helper(".github/workflows/unit-tests.yml") + ) == helper.get_targets(".github/workflows/unit-tests.yml") diff --git a/.lvimrc b/.lvimrc index a8d84a6..a641977 100644 --- a/.lvimrc +++ b/.lvimrc @@ -1,5 +1,5 @@ " add the aoc_lib dir to 'path', so gf works as expected -let &path = lh#path#munge(&path, lh#path#fix(g:localvimrc_script_dir . '/aoc_lib')) +let &path = lh#path#munge(&path, lh#path#fix(g:localvimrc_script_dir . '/aoc_lib/src')) if &filetype ==# 'cpp' let b:surround_{char2nr('D')} = "if constexpr (aoc::DEBUG) {\n\r\n}" diff --git a/aoc_lib/.autoenv.zsh b/aoc_lib/.autoenv.zsh new file mode 100644 index 0000000..7ee2433 --- /dev/null +++ b/aoc_lib/.autoenv.zsh @@ -0,0 +1,13 @@ +local wrapper_cmd=${0:h}/make_wrapper.sh +if [[ $autoenv_event == 'enter' ]]; then + alias iwyu=${0:h}/iwyu + alias make="$wrapper_cmd -f ${(q)0:h}/Makefile" + compdef "$wrapper_cmd"=make + export AOC_YEAR=aoc_lib +else + unalias iwyu make + # remove completion definition + unset "_comps[$wrapper_cmd]" + unset "_services[$wrapper_cmd]" + unset AOC_YEAR +fi diff --git a/aoc_lib/Makefile b/aoc_lib/Makefile new file mode 100644 index 0000000..de3b016 --- /dev/null +++ b/aoc_lib/Makefile @@ -0,0 +1,3 @@ +# set default target +test: +include ../tools/cpp/Makefile diff --git a/aoc_lib/iwyu b/aoc_lib/iwyu new file mode 120000 index 0000000..bcca1ed --- /dev/null +++ b/aoc_lib/iwyu @@ -0,0 +1 @@ +../tools/cpp/iwyu \ No newline at end of file diff --git a/aoc_lib/make_wrapper.sh b/aoc_lib/make_wrapper.sh new file mode 120000 index 0000000..fb7fc1f --- /dev/null +++ b/aoc_lib/make_wrapper.sh @@ -0,0 +1 @@ +../tools/cpp/make_wrapper.sh \ No newline at end of file diff --git a/aoc_lib/ds/grid.hpp b/aoc_lib/src/ds/grid.hpp similarity index 100% rename from aoc_lib/ds/grid.hpp rename to aoc_lib/src/ds/grid.hpp diff --git a/aoc_lib/ds/pairing_heap.hpp b/aoc_lib/src/ds/pairing_heap.hpp similarity index 100% rename from aoc_lib/ds/pairing_heap.hpp rename to aoc_lib/src/ds/pairing_heap.hpp diff --git a/aoc_lib/gauss_elim.hpp b/aoc_lib/src/gauss_elim.hpp similarity index 100% rename from aoc_lib/gauss_elim.hpp rename to aoc_lib/src/gauss_elim.hpp diff --git a/aoc_lib/graph_traversal.hpp b/aoc_lib/src/graph_traversal.hpp similarity index 100% rename from aoc_lib/graph_traversal.hpp rename to aoc_lib/src/graph_traversal.hpp diff --git a/aoc_lib/lib.hpp b/aoc_lib/src/lib.hpp similarity index 100% rename from aoc_lib/lib.hpp rename to aoc_lib/src/lib.hpp diff --git a/2023/src/test00_ds.cpp b/aoc_lib/src/test_ds.cpp similarity index 99% rename from 2023/src/test00_ds.cpp rename to aoc_lib/src/test_ds.cpp index e545ec1..87aa054 100644 --- a/2023/src/test00_ds.cpp +++ b/aoc_lib/src/test_ds.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * File: test00_ds.cpp + * File: test_ds.cpp * * Author: Eric T. Johnson (yut23) * Created: 2024-01-01 diff --git a/2023/src/test00_graph.cpp b/aoc_lib/src/test_graph.cpp similarity index 98% rename from 2023/src/test00_graph.cpp rename to aoc_lib/src/test_graph.cpp index 1c7944b..35363e7 100644 --- a/2023/src/test00_graph.cpp +++ b/aoc_lib/src/test_graph.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * File: test00_graph.cpp + * File: test_graph.cpp * * Author: Eric T. Johnson (yut23) * Created: 2024-01-15 diff --git a/2023/src/test00.cpp b/aoc_lib/src/test_lib.cpp similarity index 99% rename from 2023/src/test00.cpp rename to aoc_lib/src/test_lib.cpp index aa172b1..1d14816 100644 --- a/2023/src/test00.cpp +++ b/aoc_lib/src/test_lib.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * File: test00.cpp + * File: test_lib.cpp * * Author: Eric T. Johnson (yut23) * Created: 2023-12-19 diff --git a/2023/src/test00_unit_test.cpp b/aoc_lib/src/test_unit_test.cpp similarity index 98% rename from 2023/src/test00_unit_test.cpp rename to aoc_lib/src/test_unit_test.cpp index 93caea6..e80548b 100644 --- a/2023/src/test00_unit_test.cpp +++ b/aoc_lib/src/test_unit_test.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * File: test00_unit_test.cpp + * File: test_unit_test.cpp * * Author: Eric T. Johnson (yut23) * Created: 2024-01-23 diff --git a/aoc_lib/unit_test/pretty_print.hpp b/aoc_lib/src/unit_test/pretty_print.hpp similarity index 100% rename from aoc_lib/unit_test/pretty_print.hpp rename to aoc_lib/src/unit_test/pretty_print.hpp diff --git a/aoc_lib/unit_test/unit_test.hpp b/aoc_lib/src/unit_test/unit_test.hpp similarity index 100% rename from aoc_lib/unit_test/unit_test.hpp rename to aoc_lib/src/unit_test/unit_test.hpp diff --git a/aoc_lib/util/concepts.hpp b/aoc_lib/src/util/concepts.hpp similarity index 100% rename from aoc_lib/util/concepts.hpp rename to aoc_lib/src/util/concepts.hpp diff --git a/aoc_lib/util/hash.hpp b/aoc_lib/src/util/hash.hpp similarity index 100% rename from aoc_lib/util/hash.hpp rename to aoc_lib/src/util/hash.hpp diff --git a/aoc_lib/util/util.hpp b/aoc_lib/src/util/util.hpp similarity index 100% rename from aoc_lib/util/util.hpp rename to aoc_lib/src/util/util.hpp diff --git a/tools/cpp/Makefile b/tools/cpp/Makefile index 28d627d..041784b 100644 --- a/tools/cpp/Makefile +++ b/tools/cpp/Makefile @@ -13,7 +13,7 @@ ifeq ($(USE_LIBCXX),TRUE) endif # These are searched left-to-right -INCLUDES = -Isrc -I../aoc_lib +INCLUDES = -Isrc -I../aoc_lib/src LOCAL_CXXFLAGS = -Wall -Wextra -O3 -g -std=c++20 $(INCLUDES) $(STDLIB_CXXFLAGS) DEBUG_CXXFLAGS = $(LOCAL_CXXFLAGS) -O0 -DDEBUG_MODE