Skip to content

Commit d08aad0

Browse files
committed
Add macros test
1 parent 0c112d9 commit d08aad0

File tree

11 files changed

+282
-16
lines changed

11 files changed

+282
-16
lines changed

.github/workflows/tests-ubuntu.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,21 @@ jobs:
363363
-B build \
364364
-S /src/install_test
365365
cmake --build build
366+
rm -rf build
367+
368+
if [ 'xcpu' = 'x${{matrix.backend.name}}' ]
369+
then
370+
cmake \
371+
-D CMAKE_EXPORT_COMPILE_COMMANDS=ON \
372+
-B build \
373+
-S /src/install_test/check_macros
374+
python3 \
375+
/src/install_test/check_macros/check_macros.py \
376+
--db ./build/compile_commands.json \
377+
--with-src /src/install_test/check_macros/with_my_lib.cpp \
378+
--without-src /src/install_test/check_macros/without_my_lib.cpp \
379+
--reference /src/install_test/check_macros/whitelist_macros.json
380+
fi
366381
EOF
367382
368383
docker run \

include/ddc/kernels/splines/kokkos-kernels-ext/KokkosBatched_Gbtrs.hpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
// clang-format off
66
// NOLINTBEGIN(*)
77

8-
#ifndef KOKKOSBATCHED_GBTRS_HPP_
9-
#define KOKKOSBATCHED_GBTRS_HPP_
8+
#pragma once
109

1110
#include <KokkosBatched_Util.hpp>
1211

@@ -53,7 +52,5 @@ struct SerialGbtrs {
5352

5453
#include "KokkosBatched_Gbtrs_Serial_Impl.hpp"
5554

56-
#endif // KOKKOSBATCHED_GBTRS_HPP_
57-
5855
// NOLINTEND(*)
5956
// clang-format on

include/ddc/kernels/splines/kokkos-kernels-ext/KokkosBatched_Gbtrs_Serial_Impl.hpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
// clang-format off
66
// NOLINTBEGIN(*)
77

8-
#ifndef KOKKOSBATCHED_GBTRS_SERIAL_IMPL_HPP_
9-
#define KOKKOSBATCHED_GBTRS_SERIAL_IMPL_HPP_
8+
#pragma once
109

1110
#include <Kokkos_Swap.hpp>
1211
#include <KokkosBatched_Util.hpp>
@@ -164,7 +163,5 @@ struct SerialGbtrs<Trans::Transpose, Algo::Level3::Unblocked> {
164163
};
165164
} // namespace KokkosBatched
166165

167-
#endif // KOKKOSBATCHED_GBTRS_SERIAL_IMPL_HPP_
168-
169166
// NOLINTEND(*)
170167
// clang-format on

include/ddc/kernels/splines/kokkos-kernels-ext/KokkosBatched_Getrs.hpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
// clang-format off
66
// NOLINTBEGIN(*)
77

8-
#ifndef KOKKOSBATCHED_GETRS_HPP_
9-
#define KOKKOSBATCHED_GETRS_HPP_
8+
#pragma once
109

1110
#include <KokkosBatched_Util.hpp>
1211

@@ -42,7 +41,5 @@ struct SerialGetrs {
4241

4342
#include "KokkosBatched_Getrs_Serial_Impl.hpp"
4443

45-
#endif // KOKKOSBATCHED_GETRS_HPP_
46-
4744
// NOLINTEND(*)
4845
// clang-format on

include/ddc/kernels/splines/kokkos-kernels-ext/KokkosBatched_Getrs_Serial_Impl.hpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
// clang-format off
66
// NOLINTBEGIN(*)
77

8-
#ifndef KOKKOSBATCHED_GETRS_SERIAL_IMPL_HPP_
9-
#define KOKKOSBATCHED_GETRS_SERIAL_IMPL_HPP_
8+
#pragma once
109

1110
#include <KokkosBatched_Util.hpp>
1211
#include <KokkosBatched_Trsm_Decl.hpp>
@@ -93,7 +92,5 @@ struct SerialGetrs<Trans::Transpose, Algo::Level3::Unblocked> {
9392
};
9493
} // namespace KokkosBatched
9594

96-
#endif // KOKKOSBATCHED_GETRS_SERIAL_IMPL_HPP_
97-
9895
// NOLINTEND(*)
9996
// clang-format on
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright (C) The DDC development team, see COPYRIGHT.md file
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
cmake_minimum_required(VERSION 3.22)
6+
project(test-ddc-macros LANGUAGES CXX)
7+
8+
find_package(DDC 0.8 REQUIRED COMPONENTS fft pdi splines)
9+
10+
add_library(check-macros with_my_lib.cpp without_my_lib.cpp)
11+
target_link_libraries(check-macros PRIVATE DDC::core DDC::fft DDC::pdi DDC::splines)
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
#!/usr/bin/env python3
2+
3+
# Copyright (C) The DDC development team, see COPYRIGHT.md file
4+
#
5+
# SPDX-License-Identifier: MIT
6+
7+
"""
8+
Compare the difference in preprocessor macros between two source files
9+
(one with a library and one without), and check if that diff matches a reference.
10+
11+
Uses compile_commands.json to simulate compilation and extract preprocessor macros.
12+
The reference file must be a JSON file containing a list of expected #define macros.
13+
"""
14+
15+
import json
16+
import subprocess
17+
import shlex
18+
from pathlib import Path
19+
import argparse
20+
import sys
21+
22+
23+
def extract_command(entry):
24+
"""
25+
Modify compile command to only run preprocessor: remove -c/-o, add -dM -E.
26+
27+
Args:
28+
entry (dict): An entry from compile_commands.json
29+
30+
Returns:
31+
tuple[list[str], Path]: The modified command and working directory
32+
"""
33+
parts = shlex.split(entry["command"])
34+
new_parts = []
35+
skip_next = False
36+
for part in parts:
37+
if skip_next:
38+
skip_next = False
39+
continue
40+
if part == "-c":
41+
continue
42+
if part == "-o":
43+
skip_next = True
44+
continue
45+
new_parts.append(part)
46+
new_parts += ["-dM", "-E", entry["file"]]
47+
return new_parts, Path(entry["directory"])
48+
49+
50+
def run_preprocessor(command, cwd):
51+
"""
52+
Run the preprocessor and return unique macro lines.
53+
54+
Args:
55+
command (list[str]): Compiler command
56+
cwd (Path): Working directory
57+
58+
Returns:
59+
set[str]: Set of macro lines
60+
"""
61+
result = subprocess.run(
62+
command, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True
63+
)
64+
if result.returncode != 0:
65+
raise RuntimeError(f"Command failed:\n{' '.join(command)}\n{result.stderr}")
66+
return set(result.stdout.splitlines())
67+
68+
69+
def find_entry(commands, source_path):
70+
"""
71+
Find compile command for the given source file.
72+
73+
Args:
74+
commands (list[dict]): compile_commands.json content
75+
source_path (Path): Path to source file
76+
77+
Returns:
78+
dict: Matching compile command entry
79+
"""
80+
for entry in commands:
81+
if Path(entry["file"]) == source_path:
82+
return entry
83+
raise ValueError(f"Source file {source_path} not found in compile_commands.json")
84+
85+
86+
def prepare_commands(args):
87+
"""
88+
Load compilation database and extract preprocessor commands for both source files.
89+
90+
Args:
91+
args (argparse.Namespace): Parsed command-line arguments
92+
93+
Returns:
94+
tuple[set[str], set[str]]: Macros with and without the library
95+
"""
96+
commands = json.loads(args.db.read_text())
97+
98+
entry_with = find_entry(commands, args.with_src.resolve())
99+
entry_without = find_entry(commands, args.without_src.resolve())
100+
101+
cmd_with, dir_with = extract_command(entry_with)
102+
cmd_without, dir_without = extract_command(entry_without)
103+
104+
print(f"Running preprocessor for: {args.with_src.name}")
105+
macros_with = run_preprocessor(cmd_with, dir_with)
106+
107+
print(f"Running preprocessor for: {args.without_src.name}")
108+
macros_without = run_preprocessor(cmd_without, dir_without)
109+
110+
return macros_with, macros_without
111+
112+
113+
def extract_macro_diff(macros_with, macros_without):
114+
"""
115+
Compute the difference in #define macros between with/without source.
116+
117+
Args:
118+
macros_with (set[str]): Macros when library is included
119+
macros_without (set[str]): Macros without library
120+
121+
Returns:
122+
list[str]: Sorted list of macro differences
123+
"""
124+
define_with = {
125+
line.removeprefix("#define").strip() for line in macros_with if line.startswith("#define")
126+
}
127+
define_without = {
128+
line.removeprefix("#define").strip()
129+
for line in macros_without
130+
if line.startswith("#define")
131+
}
132+
return sorted(define_with - define_without)
133+
134+
135+
def compare_macro_diff(actual_diff, reference_file):
136+
"""
137+
Compare computed macro diff to expected one from JSON reference file.
138+
139+
Args:
140+
actual_diff (list[str]): Macros computed by diff
141+
reference_file (Path): Path to JSON reference
142+
143+
Returns:
144+
bool: True if matches, False otherwise
145+
"""
146+
try:
147+
ref_macros = set(json.loads(reference_file.read_text()))
148+
except Exception as exception:
149+
raise ValueError(f"Error reading reference JSON file: {exception}") from exception
150+
151+
added = sorted([m for m in actual_diff if m not in ref_macros])
152+
removed = sorted([m for m in ref_macros if m not in actual_diff])
153+
154+
has_error = False
155+
156+
if added:
157+
print("\n--- Unexpected Macros (in diff, not in reference) ---")
158+
print("\n".join(added))
159+
has_error = True
160+
161+
if removed:
162+
print("\n--- Missing Macros (in reference, not in diff) ---")
163+
print("\n".join(removed))
164+
has_error = True
165+
166+
if not has_error:
167+
print("\n✅ Macro diff matches the reference exactly.")
168+
return not has_error
169+
170+
171+
def main():
172+
"""Main entry point: run preprocessor and compare macro diff with reference."""
173+
parser = argparse.ArgumentParser(
174+
description="Compare macro diff against a JSON reference file."
175+
)
176+
parser.add_argument("--with-src", required=True, type=Path, help="Source file with the library")
177+
parser.add_argument(
178+
"--without-src", required=True, type=Path, help="Source file without the library"
179+
)
180+
parser.add_argument(
181+
"--reference", required=True, type=Path, help="Reference JSON file with expected macro diff"
182+
)
183+
parser.add_argument(
184+
"--db",
185+
default="build-install-test/compile_commands.json",
186+
type=Path,
187+
help="Path to compile_commands.json",
188+
)
189+
190+
args = parser.parse_args()
191+
192+
macros_with, macros_without = prepare_commands(args)
193+
actual_diff = extract_macro_diff(macros_with, macros_without)
194+
success = compare_macro_diff(actual_diff, args.reference)
195+
196+
sys.exit(0 if success else 1)
197+
198+
199+
if __name__ == "__main__":
200+
main()
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[
2+
"DDC_BUILD_DEPRECATED_CODE",
3+
"DDC_BUILD_DOUBLE_PRECISION",
4+
"DDC_CURRENT_KOKKOS_SPACE Kokkos::HostSpace",
5+
"DDC_IF_NVCC_THEN_POP",
6+
"DDC_IF_NVCC_THEN_PUSH(X)",
7+
"DDC_IF_NVCC_THEN_PUSH_AND_SUPPRESS(X)",
8+
"DDC_IF_NVCC_THEN_SUPPRESS(X)",
9+
"DDC_MDSPAN_ACCESS_OP(mds,...) mds(__VA_ARGS__)"
10+
]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Copyright (C) The DDC development team, see COPYRIGHT.md file
2+
3+
SPDX-License-Identifier: MIT
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Copyright (C) The DDC development team, see COPYRIGHT.md file
2+
//
3+
// SPDX-License-Identifier: MIT
4+
5+
#include <ddc/ddc.hpp>
6+
#include <ddc/kernels/fft.hpp>
7+
#include <ddc/kernels/splines.hpp>
8+
#include <ddc/pdi.hpp>

0 commit comments

Comments
 (0)