Skip to content

Commit 3875b43

Browse files
Copilotbashandbone
andauthored
fix: resolve remaining CI failures - thread-flow doctests, REUSE .license files, WASM C stubs
Agent-Logs-Url: https://github.com/knitli/thread/sessions/af60cbe1-26cf-4b98-bc5d-e1377d4159a6 Co-authored-by: bashandbone <89049923+bashandbone@users.noreply.github.com>
1 parent ab2e613 commit 3875b43

24 files changed

+185
-25
lines changed

.github/workflows/ci.yml

Lines changed: 122 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -133,26 +133,130 @@ jobs:
133133
- name: Install clang for WASM C compilation
134134
run: sudo apt-get update -qq && sudo apt-get install -y clang
135135
- name: Set up C header stubs for wasm32-unknown-unknown
136-
# tree-sitter 0.25+ includes stdio.h in its C source, but wasm32-unknown-unknown
137-
# has no OS and therefore no standard C library headers. Provide a minimal stub
138-
# so that tree-sitter's error-reporting code (fprintf to stderr) compiles as a no-op.
136+
# tree-sitter 0.25+ compiles C sources that #include standard C library headers
137+
# (stdio.h, stdlib.h, string.h, etc.). The wasm32-unknown-unknown target has no OS
138+
# and therefore no libc headers. We provide minimal stubs so the code compiles;
139+
# actual implementations (malloc, memcpy, etc.) come from the wasm runtime / Rust.
139140
run: |
140-
# CLANG_RES: clang's built-in resource directory, used below to provide
141-
# low-level headers (e.g. stdarg.h, stddef.h) alongside the stdio.h stub.
142141
CLANG_RES=$(clang --print-resource-dir)
143-
mkdir -p /tmp/wasm-stubs
144-
cat > /tmp/wasm-stubs/stdio.h << 'WASM_STDIO_STUB'
145-
#pragma once
146-
#include <stdarg.h>
147-
typedef void FILE;
148-
#define stderr ((FILE*)0)
149-
#define stdout ((FILE*)0)
150-
#define stdin ((FILE*)0)
151-
static inline int fprintf(FILE *f, const char *fmt, ...) { (void)f; (void)fmt; return 0; }
152-
static inline int vfprintf(FILE *f, const char *fmt, va_list ap) { (void)f; (void)fmt; (void)ap; return 0; }
153-
static inline int printf(const char *fmt, ...) { (void)fmt; return 0; }
154-
WASM_STDIO_STUB
155-
echo "CFLAGS_wasm32_unknown_unknown=-I/tmp/wasm-stubs -I${CLANG_RES}/include" >> "$GITHUB_ENV"
142+
STUBS=/tmp/wasm-stubs
143+
mkdir -p "$STUBS"
144+
145+
# Use Python to write the stub files cleanly without heredoc indentation issues.
146+
python3 - << 'PYEOF'
147+
import os
148+
STUBS = '/tmp/wasm-stubs'
149+
stubs = {}
150+
151+
stubs['stdio.h'] = """\
152+
#pragma once
153+
#include <stddef.h>
154+
#include <stdarg.h>
155+
typedef void FILE;
156+
#define stderr ((FILE*)0)
157+
#define stdout ((FILE*)0)
158+
#define stdin ((FILE*)0)
159+
#define EOF (-1)
160+
static inline int fprintf(FILE *f, const char *fmt, ...) { (void)f; (void)fmt; return 0; }
161+
static inline int vfprintf(FILE *f, const char *fmt, va_list ap) { (void)f; (void)fmt; (void)ap; return 0; }
162+
static inline int printf(const char *fmt, ...) { (void)fmt; return 0; }
163+
static inline int snprintf(char *s, size_t n, const char *fmt, ...) { (void)s; (void)n; (void)fmt; return 0; }
164+
static inline int sprintf(char *s, const char *fmt, ...) { (void)s; (void)fmt; return 0; }
165+
static inline int fputc(int c, FILE *f) { (void)f; return c; }
166+
static inline int fputs(const char *s, FILE *f) { (void)s; (void)f; return 0; }
167+
static inline int fflush(FILE *f) { (void)f; return 0; }
168+
"""
169+
170+
stubs['stdlib.h'] = """\
171+
#pragma once
172+
#include <stddef.h>
173+
#define EXIT_SUCCESS 0
174+
#define EXIT_FAILURE 1
175+
extern void *malloc(size_t size);
176+
extern void *calloc(size_t count, size_t size);
177+
extern void *realloc(void *ptr, size_t size);
178+
extern void free(void *ptr);
179+
extern void abort(void);
180+
extern void exit(int status);
181+
static inline int abs(int x) { return x < 0 ? -x : x; }
182+
"""
183+
184+
stubs['string.h'] = """\
185+
#pragma once
186+
#include <stddef.h>
187+
extern void *memcpy(void *dest, const void *src, size_t n);
188+
extern void *memmove(void *dest, const void *src, size_t n);
189+
extern void *memset(void *s, int c, size_t n);
190+
extern int memcmp(const void *s1, const void *s2, size_t n);
191+
extern void *memchr(const void *s, int c, size_t n);
192+
extern size_t strlen(const char *s);
193+
extern int strcmp(const char *s1, const char *s2);
194+
extern int strncmp(const char *s1, const char *s2, size_t n);
195+
extern char *strcpy(char *dest, const char *src);
196+
extern char *strncpy(char *dest, const char *src, size_t n);
197+
extern char *strcat(char *dest, const char *src);
198+
extern char *strncat(char *dest, const char *src, size_t n);
199+
extern char *strchr(const char *s, int c);
200+
extern char *strrchr(const char *s, int c);
201+
extern char *strstr(const char *haystack, const char *needle);
202+
"""
203+
204+
stubs['time.h'] = """\
205+
#pragma once
206+
#include <stdint.h>
207+
typedef uint64_t time_t;
208+
typedef uint64_t clock_t;
209+
#define CLOCKS_PER_SEC ((clock_t)1000000)
210+
static inline time_t time(time_t *t) { if (t) *t = 0; return 0; }
211+
static inline clock_t clock(void) { return 0; }
212+
"""
213+
214+
stubs['ctype.h'] = """\
215+
#pragma once
216+
static inline int isalpha(int c) { return (c>='a'&&c<='z')||(c>='A'&&c<='Z'); }
217+
static inline int isdigit(int c) { return c>='0'&&c<='9'; }
218+
static inline int isalnum(int c) { return isalpha(c)||isdigit(c); }
219+
static inline int isspace(int c) { return c==' '||c=='\\t'||c=='\\n'||c=='\\r'||c=='\\f'||c=='\\v'; }
220+
static inline int isupper(int c) { return c>='A'&&c<='Z'; }
221+
static inline int islower(int c) { return c>='a'&&c<='z'; }
222+
static inline int toupper(int c) { return islower(c)?c-('a'-'A'):c; }
223+
static inline int tolower(int c) { return isupper(c)?c+('a'-'A'):c; }
224+
static inline int isprint(int c) { return c>=' '&&c<='~'; }
225+
static inline int iscntrl(int c) { return c<' '||c==127; }
226+
static inline int isxdigit(int c) { return isdigit(c)||(c>='a'&&c<='f')||(c>='A'&&c<='F'); }
227+
static inline int ispunct(int c) { return isprint(c)&&!isalnum(c)&&c!=' '; }
228+
"""
229+
230+
stubs['wctype.h'] = """\
231+
#pragma once
232+
#include <stdint.h>
233+
typedef uint32_t wint_t;
234+
#define WEOF ((wint_t)-1)
235+
static inline int iswspace(wint_t c) { return c==' '||c=='\\t'||c=='\\n'||c=='\\r'||c=='\\f'||c=='\\v'; }
236+
static inline int iswalpha(wint_t c) { return (c>='a'&&c<='z')||(c>='A'&&c<='Z'); }
237+
static inline int iswdigit(wint_t c) { return c>='0'&&c<='9'; }
238+
static inline int iswalnum(wint_t c) { return iswalpha(c)||iswdigit(c); }
239+
static inline int iswupper(wint_t c) { return c>='A'&&c<='Z'; }
240+
static inline int iswlower(wint_t c) { return c>='a'&&c<='z'; }
241+
static inline int iswprint(wint_t c) { return c>=' '&&c<='~'; }
242+
static inline int iswpunct(wint_t c) { return iswprint(c)&&!iswalnum(c)&&c!=' '; }
243+
static inline wint_t towlower(wint_t c) { return iswupper(c)?c+('a'-'A'):c; }
244+
static inline wint_t towupper(wint_t c) { return iswlower(c)?c-('a'-'A'):c; }
245+
"""
246+
247+
stubs['assert.h'] = """\
248+
#pragma once
249+
#define assert(x) ((void)(x))
250+
"""
251+
252+
for name, content in stubs.items():
253+
path = os.path.join(STUBS, name)
254+
with open(path, 'w') as f:
255+
f.write(content)
256+
print(f' wrote {path}')
257+
PYEOF
258+
259+
echo "CFLAGS_wasm32_unknown_unknown=-I${STUBS} -I${CLANG_RES}/include" >> "$GITHUB_ENV"
156260
- name: Install wasm-pack
157261
uses: jetli/wasm-pack-action@v0.4.0
158262
- name: Build WASM (dev)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SPDX-FileCopyrightText: 2025 Knitli Inc. <knitli@knit.li>
2+
3+
SPDX-License-Identifier: AGPL-3.0-or-later

crates/flow/src/incremental/graph.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ impl DependencyGraph {
260260
/// ));
261261
///
262262
/// // Change C -> affects B and A
263-
/// let changed = RapidSet::from([PathBuf::from("C")]);
263+
/// let changed: RapidSet<PathBuf> = [PathBuf::from("C")].into_iter().collect();
264264
/// let affected = graph.find_affected_files(&changed);
265265
/// assert!(affected.contains(&PathBuf::from("A")));
266266
/// assert!(affected.contains(&PathBuf::from("B")));
@@ -325,9 +325,9 @@ impl DependencyGraph {
325325
/// PathBuf::from("B"), PathBuf::from("C"), DependencyType::Import,
326326
/// ));
327327
///
328-
/// let files = RapidSet::from([
328+
/// let files: RapidSet<PathBuf> = [
329329
/// PathBuf::from("A"), PathBuf::from("B"), PathBuf::from("C"),
330-
/// ]);
330+
/// ].into_iter().collect();
331331
/// let sorted = graph.topological_sort(&files).unwrap();
332332
/// // C should come before B, B before A
333333
/// let pos_a = sorted.iter().position(|p| p == &PathBuf::from("A")).unwrap();

crates/flow/src/incremental/invalidation.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ pub enum InvalidationError {
4545
/// ```rust
4646
/// use thread_flow::incremental::invalidation::InvalidationDetector;
4747
/// use thread_flow::incremental::DependencyGraph;
48-
/// use thread_utilities::RapishSet;
4948
/// use std::path::PathBuf;
5049
///
5150
/// let graph = DependencyGraph::new();

crates/flow/src/incremental/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@
3636
//! AnalysisDefFingerprint, DependencyEdge, DependencyType,
3737
//! };
3838
//! use thread_flow::incremental::graph::DependencyGraph;
39+
//! use thread_utilities::RapidSet;
3940
//! use std::path::PathBuf;
40-
//! use std::collections::HashSet;
4141
//!
4242
//! // Create a dependency graph
4343
//! let mut graph = DependencyGraph::new();
@@ -51,7 +51,7 @@
5151
//! });
5252
//!
5353
//! // Find files affected by a change to utils.rs
54-
//! let changed = HashSet::from([PathBuf::from("src/utils.rs")]);
54+
//! let changed: RapidSet<PathBuf> = [PathBuf::from("src/utils.rs")].into_iter().collect();
5555
//! let affected = graph.find_affected_files(&changed);
5656
//! assert!(affected.contains(&PathBuf::from("src/main.rs")));
5757
//! ```

crates/flow/src/incremental/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ impl AnalysisDefFingerprint {
220220
/// use thread_utilities::RapidSet;
221221
/// use std::path::PathBuf;
222222
///
223-
/// let sources = RapidSet::from([PathBuf::from("dep.rs")]);
223+
/// let sources: RapidSet<PathBuf> = [PathBuf::from("dep.rs")].into_iter().collect();
224224
/// let fp = AnalysisDefFingerprint::with_sources(b"content", sources);
225225
/// assert_eq!(fp.source_files.len(), 1);
226226
/// ```
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SPDX-FileCopyrightText: 2025 Knitli Inc. <knitli@knit.li>
2+
3+
SPDX-License-Identifier: MIT OR Apache-2.0

ctx-plugin/PLAN.md.license

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SPDX-FileCopyrightText: 2025 Knitli Inc. <knitli@knit.li>
2+
3+
SPDX-License-Identifier: MIT OR Apache-2.0

ctx-plugin/README.md.license

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SPDX-FileCopyrightText: 2025 Knitli Inc. <knitli@knit.li>
2+
3+
SPDX-License-Identifier: MIT OR Apache-2.0
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SPDX-FileCopyrightText: 2025 Knitli Inc. <knitli@knit.li>
2+
3+
SPDX-License-Identifier: MIT OR Apache-2.0

0 commit comments

Comments
 (0)