From 3c8bf76a6ddcf6dc77d42356b5af3ed1e06e9b6b Mon Sep 17 00:00:00 2001 From: yut23 Date: Wed, 11 Dec 2024 21:11:04 -0500 Subject: [PATCH 1/6] aoc_lib: move source files into a subdirectory This will have the same structure as the individual year directories. --- .github/workflows/gen_matrix.py | 2 +- .github/workflows/test_gen_matrix.py | 7 ++++++- aoc_lib/{ => src}/ds/grid.hpp | 0 aoc_lib/{ => src}/ds/pairing_heap.hpp | 0 aoc_lib/{ => src}/gauss_elim.hpp | 0 aoc_lib/{ => src}/graph_traversal.hpp | 0 aoc_lib/{ => src}/lib.hpp | 0 aoc_lib/{ => src}/unit_test/pretty_print.hpp | 0 aoc_lib/{ => src}/unit_test/unit_test.hpp | 0 aoc_lib/{ => src}/util/concepts.hpp | 0 aoc_lib/{ => src}/util/hash.hpp | 0 aoc_lib/{ => src}/util/util.hpp | 0 tools/cpp/Makefile | 2 +- 13 files changed, 8 insertions(+), 3 deletions(-) rename aoc_lib/{ => src}/ds/grid.hpp (100%) rename aoc_lib/{ => src}/ds/pairing_heap.hpp (100%) rename aoc_lib/{ => src}/gauss_elim.hpp (100%) rename aoc_lib/{ => src}/graph_traversal.hpp (100%) rename aoc_lib/{ => src}/lib.hpp (100%) rename aoc_lib/{ => src}/unit_test/pretty_print.hpp (100%) rename aoc_lib/{ => src}/unit_test/unit_test.hpp (100%) rename aoc_lib/{ => src}/util/concepts.hpp (100%) rename aoc_lib/{ => src}/util/hash.hpp (100%) rename aoc_lib/{ => src}/util/util.hpp (100%) diff --git a/.github/workflows/gen_matrix.py b/.github/workflows/gen_matrix.py index 61ddca1..c7c396b 100755 --- a/.github/workflows/gen_matrix.py +++ b/.github/workflows/gen_matrix.py @@ -96,7 +96,7 @@ def from_file(cls, base_dir: Path, source_file: Path) -> Target: 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..24bdf88 100644 --- a/.github/workflows/test_gen_matrix.py +++ b/.github/workflows/test_gen_matrix.py @@ -6,7 +6,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) == { @@ -68,6 +68,11 @@ def test_matrix(): 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) + # answer tests assert matrix_helper("2023/answer_tests/day01/example2.txt") == dict( build=set(), answer={"2023/day01"}, unit=set() 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/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 From c3d6ee870459fcebdcee2cddd9df043f71c54b6e Mon Sep 17 00:00:00 2001 From: yut23 Date: Wed, 11 Dec 2024 22:06:52 -0500 Subject: [PATCH 2/6] aoc_lib: move tests from 2023/ --- aoc_lib/.autoenv.zsh | 13 +++++++++++++ aoc_lib/Makefile | 3 +++ aoc_lib/iwyu | 1 + aoc_lib/make_wrapper.sh | 1 + 2023/src/test00_ds.cpp => aoc_lib/src/test_ds.cpp | 2 +- .../test00_graph.cpp => aoc_lib/src/test_graph.cpp | 2 +- 2023/src/test00.cpp => aoc_lib/src/test_lib.cpp | 2 +- .../src/test_unit_test.cpp | 2 +- 8 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 aoc_lib/.autoenv.zsh create mode 100644 aoc_lib/Makefile create mode 120000 aoc_lib/iwyu create mode 120000 aoc_lib/make_wrapper.sh rename 2023/src/test00_ds.cpp => aoc_lib/src/test_ds.cpp (99%) rename 2023/src/test00_graph.cpp => aoc_lib/src/test_graph.cpp (98%) rename 2023/src/test00.cpp => aoc_lib/src/test_lib.cpp (99%) rename 2023/src/test00_unit_test.cpp => aoc_lib/src/test_unit_test.cpp (98%) 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/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 From dc0ce939a3846e23ea15fb3372bedfbc66b1c7de Mon Sep 17 00:00:00 2001 From: yut23 Date: Wed, 11 Dec 2024 22:08:53 -0500 Subject: [PATCH 3/6] Update gen_matrix.py to handle tests without day numbers --- .github/workflows/gen_matrix.py | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/.github/workflows/gen_matrix.py b/.github/workflows/gen_matrix.py index c7c396b..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,26 +78,35 @@ 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() From ee37af91b174b9c987b8a15948c30ca8bd06d276 Mon Sep 17 00:00:00 2001 From: yut23 Date: Wed, 11 Dec 2024 22:11:51 -0500 Subject: [PATCH 4/6] Update test_gen_matrix.py --- .github/workflows/test_gen_matrix.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_gen_matrix.py b/.github/workflows/test_gen_matrix.py index 24bdf88..fb9acc4 100644 --- a/.github/workflows/test_gen_matrix.py +++ b/.github/workflows/test_gen_matrix.py @@ -1,3 +1,5 @@ +from pathlib import Path + from gen_matrix import ROOT, WORKFLOWS_DIR, Matrix, get_dependencies ACTIONS_DIR = ROOT / ".github/actions" @@ -41,7 +43,7 @@ def test_get_dependencies_workflows(): } -def matrix_helper(*changed_files: str) -> dict[str, set[str]]: +def matrix_helper(*changed_files: str | Path) -> dict[str, set[str]]: result = {} for mode in ("build", "answer", "unit"): matrix = Matrix(mode) @@ -55,7 +57,7 @@ def matrix_helper(*changed_files: str) -> dict[str, set[str]]: def test_matrix(): # pylint: disable=use-dict-literal - everything = matrix_helper("2022/Makefile", "tools/cpp/Makefile") + everything = matrix_helper(*ROOT.glob("*/Makefile"), "tools/cpp/Makefile") # C++ source files assert matrix_helper("2023/src/day05.cpp") == dict( From 3a3f64f5fa5a9a799b31fd15cd1c0ca9d4fdd53f Mon Sep 17 00:00:00 2001 From: yut23 Date: Wed, 11 Dec 2024 23:08:11 -0500 Subject: [PATCH 5/6] Update aoc_lib source path in .lvimrc --- .lvimrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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}" From fff2bce02ef24b15e54460c266abc86485c7eaeb Mon Sep 17 00:00:00 2001 From: yut23 Date: Wed, 11 Dec 2024 23:08:47 -0500 Subject: [PATCH 6/6] Add more tests for gen_matrix.py --- .github/workflows/test_gen_matrix.py | 129 ++++++++++++++++++++------- 1 file changed, 99 insertions(+), 30 deletions(-) diff --git a/.github/workflows/test_gen_matrix.py b/.github/workflows/test_gen_matrix.py index fb9acc4..5c6cddc 100644 --- a/.github/workflows/test_gen_matrix.py +++ b/.github/workflows/test_gen_matrix.py @@ -1,6 +1,12 @@ from pathlib import Path -from gen_matrix import ROOT, WORKFLOWS_DIR, Matrix, get_dependencies +from gen_matrix import ( + ROOT, + WORKFLOWS_DIR, + Matrix, + get_dependencies, + get_transitive_dependencies, +) ACTIONS_DIR = ROOT / ".github/actions" @@ -21,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") == { @@ -43,30 +82,39 @@ def test_get_dependencies_workflows(): } -def matrix_helper(*changed_files: str | Path) -> 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(*ROOT.glob("*/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"} ) @@ -75,33 +123,54 @@ def test_matrix(): 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")