Skip to content

Commit 60b9fc5

Browse files
coverage
1 parent 23d9820 commit 60b9fc5

16 files changed

Lines changed: 628 additions & 40 deletions

File tree

meikyu/build.manifest

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
# 'dodai=' field of the platform row, appended by both readers.
88
host_src src/platform/host_main.c
99
host_src src/platform/project_gen.c
10+
host_src src/platform/tests_gen.c
1011
host_src src/platform/seni_answers.c
1112
host_src src/platform/build_manifest.c
1213
host_src src/platform/migrate_core.c
@@ -50,11 +51,13 @@ platform windows builddir=build exe=.exe dll=.dll dodai=dodai_windows.c
5051
# test.c is implicit; src= lists EXTRA TUs (rel to the lib dir). A dodai_*.c
5152
# src is the per-OS source -- tests_gen substitutes the active platform's
5253
# dodai= when generating. std defaults c99; pedantic defaults on.
54+
# test.c that #includes its lib's .c (seni/kansi/kaji) lists NO src for it --
55+
# only genuinely separate TUs (the per-OS dodai source) go in src=.
5356
lib_test ito std=c99
5457
lib_test michi std=c99 include=lib/ito
55-
lib_test seni std=c89 src=seni.c,arena.c
56-
lib_test kansi std=c99 src=kansi.c,../dodai/dodai_posix.c include=lib/dodai link=pthread
57-
lib_test kaji std=c99 src=kaji.c,../dodai/dodai_posix.c include=lib/dodai link=pthread
58+
lib_test seni std=c99
59+
lib_test kansi std=c99 src=../dodai/dodai_posix.c include=lib/dodai link=pthread
60+
lib_test kaji std=c99 src=../dodai/dodai_posix.c include=lib/dodai link=pthread
5861
lib_test horu std=c89 src=horu.c link=m
5962

6063
# ---- coverage (MC/DC) ----------------------------------------------------

meikyu/lib/horu/horu.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#include "horu.h"
2+
#include <math.h>
3+
4+
/* normalize the normal; scale d by the same factor so the described plane
5+
(the point set dot(n,p) = d) is unchanged. sqrt (not sqrtf) keeps this
6+
strict-C89. A zero-length normal yields the degenerate zero plane. */
7+
horu_plane horu_plane_make(float nx, float ny, float nz, float d) {
8+
horu_plane p;
9+
float len = (float)sqrt((double)(nx * nx + ny * ny + nz * nz));
10+
if (len > 0.0f) {
11+
p.nx = nx / len;
12+
p.ny = ny / len;
13+
p.nz = nz / len;
14+
p.d = d / len;
15+
} else {
16+
p.nx = p.ny = p.nz = 0.0f;
17+
p.d = 0.0f;
18+
}
19+
return p;
20+
}
21+
22+
/* signed distance of (x,y,z) from the plane, bucketed by HORU_EPS. */
23+
int horu_side(horu_plane p, float x, float y, float z) {
24+
float dist = p.nx * x + p.ny * y + p.nz * z - p.d;
25+
if (dist > HORU_EPS) return 1;
26+
if (dist < -HORU_EPS) return -1;
27+
return 0;
28+
}
29+
30+
horu_plane horu_plane_from_points(float ax, float ay, float az,
31+
float bx, float by, float bz,
32+
float cx, float cy, float cz) {
33+
float ux = bx - ax, uy = by - ay, uz = bz - az; /* edge a->b */
34+
float vx = cx - ax, vy = cy - ay, vz = cz - az; /* edge a->c */
35+
float nx = uy * vz - uz * vy; /* n = u x v */
36+
float ny = uz * vx - ux * vz;
37+
float nz = ux * vy - uy * vx;
38+
float d = nx * ax + ny * ay + nz * az; /* plane through a */
39+
return horu_plane_make(nx, ny, nz, d); /* normalizes n and d */
40+
}

meikyu/lib/horu/horu.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,11 @@ horu_plane horu_plane_make(float nx, float ny, float nz, float d);
3636
0 = on (|signed distance| <= HORU_EPS) */
3737
int horu_side(horu_plane p, float x, float y, float z);
3838

39+
/* Plane through three points, normal = normalize(cross(b-a, c-a)) -- so the
40+
winding a->b->c is counter-clockwise when viewed from the +normal (solid)
41+
side. This is how a solid's faces become half-spaces. */
42+
horu_plane horu_plane_from_points(float ax, float ay, float az,
43+
float bx, float by, float bz,
44+
float cx, float cy, float cz);
45+
3946
#endif /* HORU_H */

meikyu/lib/horu/test.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,34 @@ static void test_plane_make_normalizes(void) {
3030
CHECK(feq(p.d, 2.0f));
3131
}
3232

33+
static void test_side_classifies(void) {
34+
/* plane y = 2 with +normal pointing +y: the front (solid/inside) side is
35+
y > 2, behind is y < 2, and |dist| <= HORU_EPS counts as on. */
36+
horu_plane p = horu_plane_make(0.0f, 1.0f, 0.0f, 2.0f);
37+
CHECK(horu_side(p, 0.0f, 5.0f, 0.0f) == 1); /* above -> front */
38+
CHECK(horu_side(p, 0.0f, 0.0f, 0.0f) == -1); /* below -> behind */
39+
CHECK(horu_side(p, 3.0f, 2.0f, -7.0f) == 0); /* exactly on */
40+
CHECK(horu_side(p, 0.0f, 2.0f + 1e-6f, 0.0f) == 0); /* within epsilon */
41+
}
42+
43+
static void test_plane_from_points(void) {
44+
/* a=(0,0,0) b=(1,0,0) c=(0,1,0): CCW seen from +z, so normal is +z and the
45+
plane is z = 0. */
46+
horu_plane p = horu_plane_from_points(0.0f, 0.0f, 0.0f,
47+
1.0f, 0.0f, 0.0f,
48+
0.0f, 1.0f, 0.0f);
49+
CHECK(feq(p.nx, 0.0f));
50+
CHECK(feq(p.ny, 0.0f));
51+
CHECK(feq(p.nz, 1.0f));
52+
CHECK(feq(p.d, 0.0f));
53+
CHECK(horu_side(p, 0.0f, 0.0f, 1.0f) == 1); /* above -> front */
54+
CHECK(horu_side(p, 0.0f, 0.0f, -1.0f) == -1); /* below -> behind */
55+
}
56+
3357
int main(void) {
3458
test_plane_make_normalizes();
59+
test_side_classifies();
60+
test_plane_from_points();
3561
if (g_fail) {
3662
printf("%d check(s) failed\n", g_fail);
3763
return 1;

meikyu/lib/kaji/kaji.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,13 @@ static void kaji_opts_to_flags(kaji_cc_kind kind, const kaji_compile_opts *opts,
100100
case KAJI_C11: ito_buf_append(&b, ITO(" -std=c11")); break;
101101
case KAJI_STD_DEFAULT: default: break;
102102
}
103-
if (opts->pedantic) ito_buf_append(&b, ITO(" -pedantic -Wall -Wextra -Werror"));
103+
if (opts->pedantic) {
104+
/* -Wno-unused-function: header-only libs carry per-TU-unused statics;
105+
that is the nature of the pattern, not a defect, so keep -Werror
106+
strict for everything else but silence this one */
107+
ito_buf_append(&b, ITO(" -pedantic -Wall -Wextra -Werror"
108+
" -Wno-unused-function"));
109+
}
104110
/* MC/DC coverage diverges by backend (the one place gcc != clang here) */
105111
if (opts->coverage) {
106112
if (kind == KAJI_CC_CLANG) {

meikyu/lib/kaji/kaji.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ typedef enum { KAJI_STD_DEFAULT, KAJI_C89, KAJI_C99, KAJI_C11 } kaji_cstd;
9292

9393
typedef struct {
9494
kaji_cstd std; /* gcc: -std=c89 ; msvc: /std:c11 ; tcc: -std=... */
95-
int pedantic; /* gcc: -pedantic -Wall -Wextra -Werror ; msvc: /W4 /WX */
95+
int pedantic; /* gcc: -pedantic -Wall -Wextra -Werror
96+
-Wno-unused-function ; msvc: /W4 /WX */
9697
int coverage; /* MC/DC instrumentation. clang: -fcoverage-mcdc
9798
-fprofile-instr-generate -fcoverage-mapping ;
9899
gcc 14+: --coverage -fcondition-coverage */

meikyu/lib/kaji/test.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,18 @@ static void settle_ms(int ms) {
2727

2828
UTEST(compile, opts_to_flags_gcc) {
2929
char b[256];
30-
kaji_compile_opts c89 = { KAJI_C89, 1 };
30+
kaji_compile_opts c89 = { KAJI_C89, 1, 0 };
3131
kaji_opts_to_flags(KAJI_CC_GCC, &c89, b, sizeof(b));
3232
ASSERT_TRUE(strstr(b, "-std=c89") != NULL);
3333
ASSERT_TRUE(strstr(b, "-pedantic") != NULL);
3434
ASSERT_TRUE(strstr(b, "-Wall") != NULL);
3535
ASSERT_TRUE(strstr(b, "-Wextra") != NULL);
3636
ASSERT_TRUE(strstr(b, "-Werror") != NULL); /* warnings-as-errors discipline */
37+
/* header-only libs have per-TU-unused statics: noise under -Werror, not a
38+
bug -- so unused-function is disabled while keeping -Werror otherwise */
39+
ASSERT_TRUE(strstr(b, "-Wno-unused-function") != NULL);
3740

38-
kaji_compile_opts deflt = { KAJI_STD_DEFAULT, 0 };
41+
kaji_compile_opts deflt = { KAJI_STD_DEFAULT, 0, 0 };
3942
kaji_opts_to_flags(KAJI_CC_GCC, &deflt, b, sizeof(b));
4043
ASSERT_TRUE(strstr(b, "-std=") == NULL);
4144
ASSERT_TRUE(strstr(b, "-pedantic") == NULL);
@@ -431,4 +434,4 @@ UTEST(e2e, exe_with_post_copy) {
431434
kaji_free(k);
432435
}
433436

434-
UTEST_MAIN();
437+
UTEST_MAIN()

meikyu/lib/kansi/test.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ UTEST(e2e, change_triggers_pipeline_to_built) {
351351

352352
/* no change yet: stays idle across several polls */
353353
for (int i = 0; i < 3; i++) {
354-
ASSERT_EQ(KANSI_IDLE, kansi_update(k));
354+
ASSERT_EQ(KANSI_IDLE, (int)kansi_update(k));
355355
}
356356

357357
/* touch the source (different size, past the mtime quantum) -> expect
@@ -369,7 +369,7 @@ UTEST(e2e, change_triggers_pipeline_to_built) {
369369
break;
370370
}
371371
}
372-
ASSERT_EQ(KANSI_BUILT, final);
372+
ASSERT_EQ(KANSI_BUILT, (int)final);
373373

374374
#ifdef _WIN32
375375
FILE *dll = fopen("build/e2e/mod.dll", "rb");
@@ -418,11 +418,11 @@ UTEST(e2e, compile_failure_reports_error_once) {
418418
break;
419419
}
420420
}
421-
ASSERT_EQ(KANSI_ERROR, final);
421+
ASSERT_EQ(KANSI_ERROR, (int)final);
422422

423423
/* edge-triggered: next update is back to idle, no error loop */
424-
ASSERT_EQ(KANSI_IDLE, kansi_update(k));
424+
ASSERT_EQ(KANSI_IDLE, (int)kansi_update(k));
425425
kansi_stop(k);
426426
}
427427

428-
UTEST_MAIN();
428+
UTEST_MAIN()

meikyu/lib/seni/test.c

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ UTEST(parse, header) {
1919
ASSERT_EQ((size_t)2,r.value.structs[0].fields_count);
2020
ASSERT_STREQ("enemy",r.value.structs[0].name);
2121
ASSERT_STREQ("x",r.value.structs[0].fields[0].name);
22-
ASSERT_EQ(ast_float,r.value.structs[0].fields[0].type);
22+
ASSERT_EQ(ast_float, (int)r.value.structs[0].fields[0].type);
2323
}
2424

2525
UTEST(parse, unknown_type) {
@@ -99,25 +99,25 @@ UTEST(parse, multiple_structs) {
9999
ASSERT_STREQ("enemy", r.value.structs[0].name);
100100
ASSERT_EQ((size_t)4, r.value.structs[0].fields_count);
101101
ASSERT_STREQ("x", r.value.structs[0].fields[0].name);
102-
ASSERT_EQ(ast_float, r.value.structs[0].fields[0].type);
102+
ASSERT_EQ(ast_float, (int)r.value.structs[0].fields[0].type);
103103
ASSERT_STREQ("y", r.value.structs[0].fields[1].name);
104-
ASSERT_EQ(ast_float, r.value.structs[0].fields[1].type);
104+
ASSERT_EQ(ast_float, (int)r.value.structs[0].fields[1].type);
105105
ASSERT_STREQ("health", r.value.structs[0].fields[2].name);
106-
ASSERT_EQ(ast_int, r.value.structs[0].fields[2].type);
106+
ASSERT_EQ(ast_int, (int)r.value.structs[0].fields[2].type);
107107
ASSERT_STREQ("speed", r.value.structs[0].fields[3].name);
108-
ASSERT_EQ(ast_double, r.value.structs[0].fields[3].type);
108+
ASSERT_EQ(ast_double, (int)r.value.structs[0].fields[3].type);
109109

110110
// player: char id, int score, int level, float damage
111111
ASSERT_STREQ("player", r.value.structs[1].name);
112112
ASSERT_EQ((size_t)4, r.value.structs[1].fields_count);
113113
ASSERT_STREQ("id", r.value.structs[1].fields[0].name);
114-
ASSERT_EQ(ast_char, r.value.structs[1].fields[0].type);
114+
ASSERT_EQ(ast_char, (int)r.value.structs[1].fields[0].type);
115115
ASSERT_STREQ("score", r.value.structs[1].fields[1].name);
116-
ASSERT_EQ(ast_int, r.value.structs[1].fields[1].type);
116+
ASSERT_EQ(ast_int, (int)r.value.structs[1].fields[1].type);
117117
ASSERT_STREQ("level", r.value.structs[1].fields[2].name);
118-
ASSERT_EQ(ast_int, r.value.structs[1].fields[2].type);
118+
ASSERT_EQ(ast_int, (int)r.value.structs[1].fields[2].type);
119119
ASSERT_STREQ("damage", r.value.structs[1].fields[3].name);
120-
ASSERT_EQ(ast_float, r.value.structs[1].fields[3].type);
120+
ASSERT_EQ(ast_float, (int)r.value.structs[1].fields[3].type);
121121
}
122122

123123
UTEST(parse, many_structs_no_cap) {
@@ -480,9 +480,9 @@ UTEST(parse, tab_or_newline_after_type) {
480480
ASSERT_FALSE(r.err);
481481
ASSERT_EQ((size_t)2, r.value.structs[0].fields_count);
482482
ASSERT_STREQ("x", r.value.structs[0].fields[0].name);
483-
ASSERT_EQ(ast_int, r.value.structs[0].fields[0].type);
483+
ASSERT_EQ(ast_int, (int)r.value.structs[0].fields[0].type);
484484
ASSERT_STREQ("y", r.value.structs[0].fields[1].name);
485-
ASSERT_EQ(ast_float, r.value.structs[0].fields[1].type);
485+
ASSERT_EQ(ast_float, (int)r.value.structs[0].fields[1].type);
486486
}
487487

488488
/* fuzz-derived: 'typedef struct {' inside a struct-name region made the
@@ -536,7 +536,7 @@ UTEST(parse, array_field) {
536536
ASSERT_EQ((size_t)3, r.value.structs[0].fields_count);
537537
ASSERT_STREQ("pos", r.value.structs[0].fields[0].name);
538538
ASSERT_EQ((size_t)4, r.value.structs[0].fields[0].array_size);
539-
ASSERT_EQ(ast_float, r.value.structs[0].fields[0].type);
539+
ASSERT_EQ(ast_float, (int)r.value.structs[0].fields[0].type);
540540
ASSERT_STREQ("name", r.value.structs[0].fields[1].name);
541541
ASSERT_EQ((size_t)32, r.value.structs[0].fields[1].array_size);
542542
ASSERT_STREQ("id", r.value.structs[0].fields[2].name);
@@ -596,11 +596,11 @@ UTEST(diff, array_resize) {
596596
ASSERT_FALSE(r.err);
597597
struct_diff* sd = &r.value.structs[0];
598598
ASSERT_EQ((size_t)2, sd->ops_count);
599-
ASSERT_EQ(field_op_copy, sd->ops[0].kind);
599+
ASSERT_EQ(field_op_copy, (int)sd->ops[0].kind);
600600
ASSERT_STREQ("pos", sd->ops[0].name);
601601
ASSERT_EQ((size_t)4, sd->ops[0].old_array_size);
602602
ASSERT_EQ((size_t)2, sd->ops[0].new_array_size);
603-
ASSERT_EQ(field_op_zero, sd->ops[1].kind);
603+
ASSERT_EQ(field_op_zero, (int)sd->ops[1].kind);
604604
ASSERT_STREQ("vel", sd->ops[1].name);
605605
ASSERT_EQ((size_t)3, sd->ops[1].new_array_size);
606606
}
@@ -649,13 +649,13 @@ UTEST(diff, add_field) {
649649
ASSERT_EQ((size_t)2, sd->old_count);
650650
ASSERT_EQ((size_t)3, sd->new_count);
651651
ASSERT_EQ((size_t)3, sd->ops_count);
652-
ASSERT_EQ(field_op_copy, sd->ops[0].kind);
652+
ASSERT_EQ(field_op_copy, (int)sd->ops[0].kind);
653653
ASSERT_STREQ("x", sd->ops[0].name);
654-
ASSERT_EQ(field_op_copy, sd->ops[1].kind);
654+
ASSERT_EQ(field_op_copy, (int)sd->ops[1].kind);
655655
ASSERT_STREQ("y", sd->ops[1].name);
656-
ASSERT_EQ(field_op_zero, sd->ops[2].kind);
656+
ASSERT_EQ(field_op_zero, (int)sd->ops[2].kind);
657657
ASSERT_STREQ("health", sd->ops[2].name);
658-
ASSERT_EQ(ast_int, sd->ops[2].type);
658+
ASSERT_EQ(ast_int, (int)sd->ops[2].type);
659659
}
660660

661661
UTEST(diff, remove_field) {
@@ -675,8 +675,8 @@ UTEST(diff, remove_field) {
675675
ASSERT_FALSE(r.err);
676676
struct_diff* sd = &r.value.structs[0];
677677
ASSERT_EQ((size_t)2, sd->ops_count);
678-
ASSERT_EQ(field_op_copy, sd->ops[0].kind);
679-
ASSERT_EQ(field_op_copy, sd->ops[1].kind);
678+
ASSERT_EQ(field_op_copy, (int)sd->ops[0].kind);
679+
ASSERT_EQ(field_op_copy, (int)sd->ops[1].kind);
680680
}
681681

682682
UTEST(diff, new_struct) {
@@ -693,7 +693,7 @@ UTEST(diff, new_struct) {
693693
ASSERT_EQ((size_t)1, r.value.struct_count);
694694
struct_diff* sd = &r.value.structs[0];
695695
ASSERT_EQ((size_t)0, sd->old_count);
696-
ASSERT_EQ(field_op_zero, sd->ops[0].kind);
696+
ASSERT_EQ(field_op_zero, (int)sd->ops[0].kind);
697697
}
698698

699699
UTEST(diff, bad_old_header) {
@@ -836,7 +836,7 @@ UTEST(diff, rename_via_was) {
836836
"typedef struct { float x; int light_count SENI_WAS(num_lights); } enemy;");
837837
ASSERT_FALSE(d.err);
838838
ASSERT_EQ((size_t)0, d.question_count);
839-
ASSERT_EQ(field_op_copy, d.value.structs[0].ops[1].kind);
839+
ASSERT_EQ(field_op_copy, (int)d.value.structs[0].ops[1].kind);
840840
ASSERT_STREQ("light_count", d.value.structs[0].ops[1].name);
841841
ASSERT_STREQ("num_lights", d.value.structs[0].ops[1].old_name);
842842
}
@@ -860,7 +860,7 @@ UTEST(diff, rename_ambiguity_question) {
860860
ASSERT_TRUE(strstr(d.questions[0].message,
861861
"really removed? annotate: SENI_DROPPED(num_lights)") != NULL);
862862
/* meanwhile the conservative op stands: added field zeroes */
863-
ASSERT_EQ(field_op_zero, d.value.structs[0].ops[1].kind);
863+
ASSERT_EQ(field_op_zero, (int)d.value.structs[0].ops[1].kind);
864864
}
865865

866866
UTEST(diff, dropped_silences_question) {
@@ -872,7 +872,7 @@ UTEST(diff, dropped_silences_question) {
872872
"typedef struct { float x; int light_count; SENI_DROPPED(num_lights) } enemy;");
873873
ASSERT_FALSE(d.err);
874874
ASSERT_EQ((size_t)0, d.question_count);
875-
ASSERT_EQ(field_op_zero, d.value.structs[0].ops[1].kind);
875+
ASSERT_EQ(field_op_zero, (int)d.value.structs[0].ops[1].kind);
876876
}
877877

878878
UTEST(diff, no_question_when_types_differ) {
@@ -921,7 +921,7 @@ UTEST(diff, stale_was_is_inert) {
921921
"typedef struct { float x; int light_count SENI_WAS(num_lights); } enemy;");
922922
ASSERT_FALSE(d.err);
923923
ASSERT_EQ((size_t)0, d.question_count);
924-
ASSERT_EQ(field_op_copy, d.value.structs[0].ops[1].kind);
924+
ASSERT_EQ(field_op_copy, (int)d.value.structs[0].ops[1].kind);
925925
ASSERT_STREQ("light_count", d.value.structs[0].ops[1].old_name);
926926
}
927927

@@ -944,7 +944,7 @@ UTEST(annotate, rename_round_trip) {
944944
diff_result d = diff_structs(&a, old_header, an.code);
945945
ASSERT_FALSE(d.err);
946946
ASSERT_EQ((size_t)0, d.question_count);
947-
ASSERT_EQ(field_op_copy, d.value.structs[0].ops[1].kind);
947+
ASSERT_EQ(field_op_copy, (int)d.value.structs[0].ops[1].kind);
948948
ASSERT_STREQ("num_lights", d.value.structs[0].ops[1].old_name);
949949
}
950950

@@ -1007,7 +1007,7 @@ UTEST(annotate, dropped_round_trip) {
10071007
diff_result d = diff_structs(&a, old_header, an.code);
10081008
ASSERT_FALSE(d.err);
10091009
ASSERT_EQ((size_t)0, d.question_count);
1010-
ASSERT_EQ(field_op_zero, d.value.structs[0].ops[1].kind);
1010+
ASSERT_EQ(field_op_zero, (int)d.value.structs[0].ops[1].kind);
10111011
/* answering twice is refused */
10121012
an = annotate_dropped(&a, an.code, "enemy", "num_lights");
10131013
ASSERT_TRUE(an.err != NULL);

meikyu/src/platform/build_manifest.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,19 @@ b32 build_manifest_resolve_cc(const BuildManifest *m,
245245
return resolve_candidates(m->cc_candidate, m->cc_count,
246246
getenv_fn, exists_fn, out_buf, cap);
247247
}
248+
249+
b32 build_manifest_resolve_llvmcov(const BuildManifest *m,
250+
const char *(*getenv_fn)(const char *),
251+
b32 (*exists_fn)(const char *),
252+
char *out_buf, size_t cap) {
253+
return resolve_candidates(m->llvmcov_candidate, m->llvmcov_count,
254+
getenv_fn, exists_fn, out_buf, cap);
255+
}
256+
257+
b32 build_manifest_resolve_llvmprofdata(const BuildManifest *m,
258+
const char *(*getenv_fn)(const char *),
259+
b32 (*exists_fn)(const char *),
260+
char *out_buf, size_t cap) {
261+
return resolve_candidates(m->llvmprofdata_candidate, m->llvmprofdata_count,
262+
getenv_fn, exists_fn, out_buf, cap);
263+
}

0 commit comments

Comments
 (0)