red64-cli 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -58
- package/dist/components/screens/StartScreen.d.ts.map +1 -1
- package/dist/components/screens/StartScreen.js +2 -2
- package/dist/components/screens/StartScreen.js.map +1 -1
- package/dist/services/AgentInvoker.js +4 -4
- package/dist/services/AgentInvoker.js.map +1 -1
- package/dist/services/ClaudeHealthCheck.d.ts +5 -0
- package/dist/services/ClaudeHealthCheck.d.ts.map +1 -1
- package/dist/services/ClaudeHealthCheck.js +43 -5
- package/dist/services/ClaudeHealthCheck.js.map +1 -1
- package/dist/services/index.d.ts +1 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +1 -1
- package/dist/services/index.js.map +1 -1
- package/framework/stacks/c/code-quality.md +326 -0
- package/framework/stacks/c/coding-style.md +347 -0
- package/framework/stacks/c/conventions.md +513 -0
- package/framework/stacks/c/error-handling.md +350 -0
- package/framework/stacks/c/feedback.md +158 -0
- package/framework/stacks/c/memory-safety.md +408 -0
- package/framework/stacks/c/tech.md +122 -0
- package/framework/stacks/c/testing.md +472 -0
- package/framework/stacks/cpp/code-quality.md +282 -0
- package/framework/stacks/cpp/coding-style.md +363 -0
- package/framework/stacks/cpp/conventions.md +420 -0
- package/framework/stacks/cpp/error-handling.md +264 -0
- package/framework/stacks/cpp/feedback.md +104 -0
- package/framework/stacks/cpp/memory-safety.md +351 -0
- package/framework/stacks/cpp/tech.md +160 -0
- package/framework/stacks/cpp/testing.md +323 -0
- package/framework/stacks/java/code-quality.md +357 -0
- package/framework/stacks/java/coding-style.md +400 -0
- package/framework/stacks/java/conventions.md +437 -0
- package/framework/stacks/java/error-handling.md +408 -0
- package/framework/stacks/java/feedback.md +180 -0
- package/framework/stacks/java/tech.md +126 -0
- package/framework/stacks/java/testing.md +485 -0
- package/framework/stacks/javascript/async-patterns.md +216 -0
- package/framework/stacks/javascript/code-quality.md +182 -0
- package/framework/stacks/javascript/coding-style.md +293 -0
- package/framework/stacks/javascript/conventions.md +268 -0
- package/framework/stacks/javascript/error-handling.md +216 -0
- package/framework/stacks/javascript/feedback.md +80 -0
- package/framework/stacks/javascript/tech.md +114 -0
- package/framework/stacks/javascript/testing.md +209 -0
- package/framework/stacks/loco/code-quality.md +156 -0
- package/framework/stacks/loco/coding-style.md +247 -0
- package/framework/stacks/loco/error-handling.md +225 -0
- package/framework/stacks/loco/feedback.md +35 -0
- package/framework/stacks/loco/loco.md +342 -0
- package/framework/stacks/loco/structure.md +193 -0
- package/framework/stacks/loco/tech.md +129 -0
- package/framework/stacks/loco/testing.md +211 -0
- package/framework/stacks/rust/code-quality.md +370 -0
- package/framework/stacks/rust/coding-style.md +475 -0
- package/framework/stacks/rust/conventions.md +430 -0
- package/framework/stacks/rust/error-handling.md +399 -0
- package/framework/stacks/rust/feedback.md +152 -0
- package/framework/stacks/rust/memory-safety.md +398 -0
- package/framework/stacks/rust/tech.md +121 -0
- package/framework/stacks/rust/testing.md +528 -0
- package/package.json +14 -2
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# Error Handling Patterns
|
|
2
|
+
|
|
3
|
+
Structured error handling for C projects using return codes, errno, and the goto cleanup pattern for safe resource management.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Philosophy
|
|
8
|
+
|
|
9
|
+
- **Return codes as the primary pattern**: Functions return `0` for success, negative values for errors
|
|
10
|
+
- **Fail fast**: Validate inputs early, return errors immediately on invalid state
|
|
11
|
+
- **Resource safety via goto cleanup**: A single cleanup label per function ensures all resources are freed
|
|
12
|
+
- **Make errors visible**: Every call that can fail must have its return value checked
|
|
13
|
+
- **Ref**: CERT C ERR00-C through ERR06-C, SEI CERT Secure Coding
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Return Code Conventions
|
|
18
|
+
|
|
19
|
+
### Standard Return Pattern
|
|
20
|
+
|
|
21
|
+
| Return Value | Meaning |
|
|
22
|
+
|---|---|
|
|
23
|
+
| `0` | Success |
|
|
24
|
+
| `-1` or negative | Error (specific codes for specific errors) |
|
|
25
|
+
| Positive | Context-dependent (e.g., byte count, item count) |
|
|
26
|
+
|
|
27
|
+
### Error Code Enum
|
|
28
|
+
|
|
29
|
+
```c
|
|
30
|
+
/* GOOD: Centralized error codes */
|
|
31
|
+
typedef enum {
|
|
32
|
+
ERR_OK = 0,
|
|
33
|
+
ERR_NULL_PARAM = -1,
|
|
34
|
+
ERR_NOMEM = -2,
|
|
35
|
+
ERR_NOT_FOUND = -3,
|
|
36
|
+
ERR_ALREADY_EXISTS = -4,
|
|
37
|
+
ERR_VALIDATION = -5,
|
|
38
|
+
ERR_IO = -6,
|
|
39
|
+
ERR_TIMEOUT = -7,
|
|
40
|
+
ERR_INTERNAL = -8,
|
|
41
|
+
} error_code_t;
|
|
42
|
+
|
|
43
|
+
/* GOOD: Human-readable error strings */
|
|
44
|
+
const char *error_string(error_code_t code) {
|
|
45
|
+
switch (code) {
|
|
46
|
+
case ERR_OK: return "success";
|
|
47
|
+
case ERR_NULL_PARAM: return "null parameter";
|
|
48
|
+
case ERR_NOMEM: return "out of memory";
|
|
49
|
+
case ERR_NOT_FOUND: return "not found";
|
|
50
|
+
case ERR_ALREADY_EXISTS: return "already exists";
|
|
51
|
+
case ERR_VALIDATION: return "validation failed";
|
|
52
|
+
case ERR_IO: return "I/O error";
|
|
53
|
+
case ERR_TIMEOUT: return "timeout";
|
|
54
|
+
case ERR_INTERNAL: return "internal error";
|
|
55
|
+
default: return "unknown error";
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## The goto Cleanup Pattern
|
|
63
|
+
|
|
64
|
+
The most important error-handling pattern in C. A single `cleanup` label at the end of the function ensures every allocated resource is freed, regardless of which step failed.
|
|
65
|
+
|
|
66
|
+
### GOOD: goto Cleanup
|
|
67
|
+
|
|
68
|
+
```c
|
|
69
|
+
int process_file(const char *path, result_t *out) {
|
|
70
|
+
int rc = ERR_OK;
|
|
71
|
+
FILE *fp = NULL;
|
|
72
|
+
char *buffer = NULL;
|
|
73
|
+
cJSON *json = NULL;
|
|
74
|
+
|
|
75
|
+
if (!path || !out) {
|
|
76
|
+
return ERR_NULL_PARAM;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
fp = fopen(path, "r");
|
|
80
|
+
if (!fp) {
|
|
81
|
+
rc = ERR_IO;
|
|
82
|
+
goto cleanup;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
buffer = malloc(MAX_FILE_SIZE);
|
|
86
|
+
if (!buffer) {
|
|
87
|
+
rc = ERR_NOMEM;
|
|
88
|
+
goto cleanup;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
size_t bytes = fread(buffer, 1, MAX_FILE_SIZE - 1, fp);
|
|
92
|
+
buffer[bytes] = '\0';
|
|
93
|
+
|
|
94
|
+
json = cJSON_Parse(buffer);
|
|
95
|
+
if (!json) {
|
|
96
|
+
rc = ERR_VALIDATION;
|
|
97
|
+
goto cleanup;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
rc = extract_result(json, out);
|
|
101
|
+
|
|
102
|
+
cleanup:
|
|
103
|
+
if (json) cJSON_Delete(json);
|
|
104
|
+
if (buffer) free(buffer);
|
|
105
|
+
if (fp) fclose(fp);
|
|
106
|
+
return rc;
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### BAD: Nested Ifs (The Pyramid of Doom)
|
|
111
|
+
|
|
112
|
+
```c
|
|
113
|
+
/* BAD: Deeply nested, easy to miss a free, hard to maintain */
|
|
114
|
+
int process_file(const char *path, result_t *out) {
|
|
115
|
+
if (path && out) {
|
|
116
|
+
FILE *fp = fopen(path, "r");
|
|
117
|
+
if (fp) {
|
|
118
|
+
char *buffer = malloc(MAX_FILE_SIZE);
|
|
119
|
+
if (buffer) {
|
|
120
|
+
size_t bytes = fread(buffer, 1, MAX_FILE_SIZE - 1, fp);
|
|
121
|
+
buffer[bytes] = '\0';
|
|
122
|
+
cJSON *json = cJSON_Parse(buffer);
|
|
123
|
+
if (json) {
|
|
124
|
+
int rc = extract_result(json, out);
|
|
125
|
+
cJSON_Delete(json);
|
|
126
|
+
free(buffer);
|
|
127
|
+
fclose(fp);
|
|
128
|
+
return rc;
|
|
129
|
+
}
|
|
130
|
+
free(buffer);
|
|
131
|
+
}
|
|
132
|
+
fclose(fp);
|
|
133
|
+
}
|
|
134
|
+
return ERR_IO;
|
|
135
|
+
}
|
|
136
|
+
return ERR_NULL_PARAM;
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### BAD: Multiple Return Points with Duplicated Cleanup
|
|
141
|
+
|
|
142
|
+
```c
|
|
143
|
+
/* BAD: Cleanup code duplicated at every error point */
|
|
144
|
+
int process_file(const char *path, result_t *out) {
|
|
145
|
+
FILE *fp = fopen(path, "r");
|
|
146
|
+
if (!fp) return ERR_IO;
|
|
147
|
+
|
|
148
|
+
char *buffer = malloc(MAX_FILE_SIZE);
|
|
149
|
+
if (!buffer) {
|
|
150
|
+
fclose(fp); /* Must remember to free fp here */
|
|
151
|
+
return ERR_NOMEM;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
cJSON *json = cJSON_Parse(buffer);
|
|
155
|
+
if (!json) {
|
|
156
|
+
free(buffer); /* Must free buffer AND fp */
|
|
157
|
+
fclose(fp);
|
|
158
|
+
return ERR_VALIDATION;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/* ... more code, more duplicated cleanup ... */
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## errno for System Calls
|
|
168
|
+
|
|
169
|
+
```c
|
|
170
|
+
#include <errno.h>
|
|
171
|
+
#include <string.h>
|
|
172
|
+
|
|
173
|
+
/* GOOD: Check errno after system calls that set it */
|
|
174
|
+
int read_file(const char *path, char *buf, size_t buf_size) {
|
|
175
|
+
FILE *fp = fopen(path, "r");
|
|
176
|
+
if (!fp) {
|
|
177
|
+
log_error("fopen failed: %s (errno=%d)", strerror(errno), errno);
|
|
178
|
+
return ERR_IO;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
size_t n = fread(buf, 1, buf_size - 1, fp);
|
|
182
|
+
if (ferror(fp)) {
|
|
183
|
+
log_error("fread failed: %s", strerror(errno));
|
|
184
|
+
fclose(fp);
|
|
185
|
+
return ERR_IO;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
buf[n] = '\0';
|
|
189
|
+
fclose(fp);
|
|
190
|
+
return ERR_OK;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/* GOOD: Save errno before calling other functions that may overwrite it */
|
|
194
|
+
int safe_open(const char *path) {
|
|
195
|
+
int fd = open(path, O_RDONLY);
|
|
196
|
+
if (fd < 0) {
|
|
197
|
+
int saved_errno = errno; /* Save before log call */
|
|
198
|
+
log_error("open(%s) failed: %s", path, strerror(saved_errno));
|
|
199
|
+
errno = saved_errno; /* Restore for caller */
|
|
200
|
+
return -1;
|
|
201
|
+
}
|
|
202
|
+
return fd;
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Error Propagation Macros
|
|
209
|
+
|
|
210
|
+
```c
|
|
211
|
+
/* GOOD: Propagate errors with a macro to reduce boilerplate */
|
|
212
|
+
#define RETURN_IF_ERROR(expr) \
|
|
213
|
+
do { \
|
|
214
|
+
int _rc = (expr); \
|
|
215
|
+
if (_rc != ERR_OK) { \
|
|
216
|
+
return _rc; \
|
|
217
|
+
} \
|
|
218
|
+
} while (0)
|
|
219
|
+
|
|
220
|
+
#define GOTO_IF_ERROR(expr, label) \
|
|
221
|
+
do { \
|
|
222
|
+
rc = (expr); \
|
|
223
|
+
if (rc != ERR_OK) { \
|
|
224
|
+
goto label; \
|
|
225
|
+
} \
|
|
226
|
+
} while (0)
|
|
227
|
+
|
|
228
|
+
/* Usage */
|
|
229
|
+
int init_system(config_t *cfg) {
|
|
230
|
+
RETURN_IF_ERROR(config_load(cfg));
|
|
231
|
+
RETURN_IF_ERROR(logger_init(cfg->log_level));
|
|
232
|
+
RETURN_IF_ERROR(database_connect(cfg->db_url));
|
|
233
|
+
return ERR_OK;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
int process_request(const request_t *req, response_t *resp) {
|
|
237
|
+
int rc = ERR_OK;
|
|
238
|
+
char *buffer = NULL;
|
|
239
|
+
db_conn_t *conn = NULL;
|
|
240
|
+
|
|
241
|
+
buffer = malloc(BUFFER_SIZE);
|
|
242
|
+
if (!buffer) { rc = ERR_NOMEM; goto cleanup; }
|
|
243
|
+
|
|
244
|
+
conn = db_pool_acquire();
|
|
245
|
+
if (!conn) { rc = ERR_INTERNAL; goto cleanup; }
|
|
246
|
+
|
|
247
|
+
GOTO_IF_ERROR(validate_request(req), cleanup);
|
|
248
|
+
GOTO_IF_ERROR(execute_query(conn, req, buffer, BUFFER_SIZE), cleanup);
|
|
249
|
+
GOTO_IF_ERROR(build_response(buffer, resp), cleanup);
|
|
250
|
+
|
|
251
|
+
cleanup:
|
|
252
|
+
if (conn) db_pool_release(conn);
|
|
253
|
+
if (buffer) free(buffer);
|
|
254
|
+
return rc;
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Error Logging
|
|
261
|
+
|
|
262
|
+
```c
|
|
263
|
+
/* GOOD: Log with context at the point of failure */
|
|
264
|
+
#define LOG_ERROR(fmt, ...) \
|
|
265
|
+
fprintf(stderr, "[ERROR] %s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
|
|
266
|
+
|
|
267
|
+
#define LOG_WARN(fmt, ...) \
|
|
268
|
+
fprintf(stderr, "[WARN] %s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
|
|
269
|
+
|
|
270
|
+
/* Usage */
|
|
271
|
+
int connect_to_server(const char *host, int port) {
|
|
272
|
+
int fd = socket(AF_INET, SOCK_STREAM, 0);
|
|
273
|
+
if (fd < 0) {
|
|
274
|
+
LOG_ERROR("socket() failed: %s", strerror(errno));
|
|
275
|
+
return ERR_IO;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
struct sockaddr_in addr = {0};
|
|
279
|
+
addr.sin_family = AF_INET;
|
|
280
|
+
addr.sin_port = htons((uint16_t)port);
|
|
281
|
+
|
|
282
|
+
if (inet_pton(AF_INET, host, &addr.sin_addr) != 1) {
|
|
283
|
+
LOG_ERROR("invalid address: %s", host);
|
|
284
|
+
close(fd);
|
|
285
|
+
return ERR_VALIDATION;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
289
|
+
LOG_ERROR("connect(%s:%d) failed: %s", host, port, strerror(errno));
|
|
290
|
+
close(fd);
|
|
291
|
+
return ERR_IO;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return fd;
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## Output Parameters for Results
|
|
301
|
+
|
|
302
|
+
```c
|
|
303
|
+
/* GOOD: Return error code, write result to output parameter */
|
|
304
|
+
int config_get_int(const config_t *cfg, const char *key, int *out_value) {
|
|
305
|
+
if (!cfg || !key || !out_value) {
|
|
306
|
+
return ERR_NULL_PARAM;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const config_entry_t *entry = config_find(cfg, key);
|
|
310
|
+
if (!entry) {
|
|
311
|
+
return ERR_NOT_FOUND;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
char *endptr = NULL;
|
|
315
|
+
long val = strtol(entry->value, &endptr, 10);
|
|
316
|
+
if (*endptr != '\0') {
|
|
317
|
+
return ERR_VALIDATION;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
*out_value = (int)val;
|
|
321
|
+
return ERR_OK;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/* Usage */
|
|
325
|
+
int port;
|
|
326
|
+
int rc = config_get_int(&cfg, "server.port", &port);
|
|
327
|
+
if (rc != ERR_OK) {
|
|
328
|
+
LOG_ERROR("failed to read port: %s", error_string(rc));
|
|
329
|
+
port = DEFAULT_PORT;
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## Anti-Patterns
|
|
336
|
+
|
|
337
|
+
| Anti-Pattern | Problem | Correct Approach |
|
|
338
|
+
|---|---|---|
|
|
339
|
+
| Ignoring return values | Errors propagate silently, crash later | Always check; use `RETURN_IF_ERROR` macro |
|
|
340
|
+
| Nested if for resource cleanup | Pyramid of doom, missed frees | `goto cleanup` pattern |
|
|
341
|
+
| Duplicated cleanup at each error | Maintenance nightmare, easy to miss | Single `cleanup` label with all frees |
|
|
342
|
+
| Using `errno` without checking call result | `errno` is only valid after a failed call | Check return value first, then errno |
|
|
343
|
+
| Not saving `errno` before logging | `fprintf`/`log` may overwrite errno | Save to local variable immediately |
|
|
344
|
+
| Returning magic numbers | Caller cannot interpret meaning | Use named enum constants |
|
|
345
|
+
| `assert()` for runtime errors | Disabled in release builds | `assert` for programmer bugs only; return codes for runtime errors |
|
|
346
|
+
| `exit()` deep in library code | Prevents caller from handling error | Return error codes; let `main()` decide |
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
_Errors in C are values. Return them, check them, propagate them, and always clean up. The goto cleanup pattern is your best friend for resource safety._
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Feedback Configuration
|
|
2
|
+
|
|
3
|
+
Project-specific commands for automated feedback during C implementation.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Build Commands
|
|
8
|
+
|
|
9
|
+
Commands to build the project during implementation.
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
# Primary build command (REQUIRED)
|
|
13
|
+
build: cmake --build build
|
|
14
|
+
|
|
15
|
+
# Configure (first time or after CMakeLists changes)
|
|
16
|
+
configure: cmake --preset default
|
|
17
|
+
|
|
18
|
+
# Configure debug
|
|
19
|
+
configure_debug: cmake --preset debug
|
|
20
|
+
|
|
21
|
+
# Clean build
|
|
22
|
+
clean_build: cmake --build build --clean-first
|
|
23
|
+
|
|
24
|
+
# Release build
|
|
25
|
+
build_release: cmake --preset release && cmake --build build-release
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Test Commands
|
|
31
|
+
|
|
32
|
+
Commands to run tests during implementation. The agent will use these to verify code changes.
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
# Primary test command (REQUIRED)
|
|
36
|
+
test: ctest --test-dir build --output-on-failure
|
|
37
|
+
|
|
38
|
+
# Run specific test suite
|
|
39
|
+
test_suite: ctest --test-dir build -R "{suite_name}" --output-on-failure
|
|
40
|
+
|
|
41
|
+
# Run with verbose output
|
|
42
|
+
test_verbose: ctest --test-dir build -V
|
|
43
|
+
|
|
44
|
+
# Run only unit tests
|
|
45
|
+
test_unit: ctest --test-dir build -L unit --output-on-failure
|
|
46
|
+
|
|
47
|
+
# Run only integration tests
|
|
48
|
+
test_integration: ctest --test-dir build -L integration --output-on-failure
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Linting Commands
|
|
54
|
+
|
|
55
|
+
Commands for code quality checks.
|
|
56
|
+
|
|
57
|
+
```yaml
|
|
58
|
+
# Primary lint command (clang-tidy)
|
|
59
|
+
lint: run-clang-tidy -p build
|
|
60
|
+
|
|
61
|
+
# Lint single file
|
|
62
|
+
lint_file: clang-tidy -p build {file}
|
|
63
|
+
|
|
64
|
+
# Lint with auto-fix
|
|
65
|
+
lint_fix: run-clang-tidy -p build -fix
|
|
66
|
+
|
|
67
|
+
# Static analysis with cppcheck
|
|
68
|
+
static_analysis: cppcheck --project=build/compile_commands.json --std=c17 --enable=all --error-exitcode=1
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Format Commands
|
|
74
|
+
|
|
75
|
+
Commands for code formatting.
|
|
76
|
+
|
|
77
|
+
```yaml
|
|
78
|
+
# Format check (CI)
|
|
79
|
+
format_check: clang-format --dry-run --Werror $(find src include -name '*.c' -o -name '*.h')
|
|
80
|
+
|
|
81
|
+
# Format fix
|
|
82
|
+
format: clang-format -i $(find src include -name '*.c' -o -name '*.h')
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Sanitizer Builds
|
|
88
|
+
|
|
89
|
+
Commands for sanitizer-instrumented builds.
|
|
90
|
+
|
|
91
|
+
```yaml
|
|
92
|
+
# ASan + UBSan build and test
|
|
93
|
+
test_asan: cmake --preset asan && cmake --build build-asan && ctest --test-dir build-asan --output-on-failure
|
|
94
|
+
|
|
95
|
+
# TSan build and test
|
|
96
|
+
test_tsan: cmake --preset tsan && cmake --build build-tsan && ctest --test-dir build-tsan --output-on-failure
|
|
97
|
+
|
|
98
|
+
# MSan build and test (Clang only)
|
|
99
|
+
test_msan: cmake -B build-msan -DCMAKE_C_FLAGS="-fsanitize=memory -fno-omit-frame-pointer" && cmake --build build-msan && ctest --test-dir build-msan --output-on-failure
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Coverage Commands
|
|
105
|
+
|
|
106
|
+
Commands for code coverage reporting.
|
|
107
|
+
|
|
108
|
+
```yaml
|
|
109
|
+
# Build with coverage
|
|
110
|
+
build_coverage: cmake --preset coverage && cmake --build build-coverage
|
|
111
|
+
|
|
112
|
+
# Run tests and generate report
|
|
113
|
+
coverage: cmake --build build-coverage && ctest --test-dir build-coverage --output-on-failure && lcov --capture --directory build-coverage --output-file coverage.info && lcov --remove coverage.info '/usr/*' '*/test/*' '*/vendor/*' --output-file coverage.info && genhtml coverage.info --output-directory coverage-report/
|
|
114
|
+
|
|
115
|
+
# Quick coverage summary
|
|
116
|
+
coverage_summary: cmake --build build-coverage && ctest --test-dir build-coverage && gcovr --root . --print-summary
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Valgrind Commands
|
|
122
|
+
|
|
123
|
+
Commands for memory checking with Valgrind.
|
|
124
|
+
|
|
125
|
+
```yaml
|
|
126
|
+
# Full leak check on executable
|
|
127
|
+
valgrind: valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --error-exitcode=1 ./build/myapp
|
|
128
|
+
|
|
129
|
+
# Valgrind on test binary
|
|
130
|
+
valgrind_tests: valgrind --leak-check=full --show-leak-kinds=all --error-exitcode=1 ./build/tests/test_user
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Packaging Commands
|
|
136
|
+
|
|
137
|
+
Commands for packaging with CPack.
|
|
138
|
+
|
|
139
|
+
```yaml
|
|
140
|
+
# Generate package
|
|
141
|
+
package: cd build && cpack
|
|
142
|
+
|
|
143
|
+
# Generate specific package type
|
|
144
|
+
package_tar: cd build && cpack -G TGZ
|
|
145
|
+
package_deb: cd build && cpack -G DEB
|
|
146
|
+
package_rpm: cd build && cpack -G RPM
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Notes
|
|
152
|
+
|
|
153
|
+
- Uses CMake as the build system with Ninja backend
|
|
154
|
+
- Requires `compile_commands.json` for clang-tidy (set `CMAKE_EXPORT_COMPILE_COMMANDS=ON`)
|
|
155
|
+
- vcpkg or Conan for dependency management
|
|
156
|
+
- ASan and TSan cannot be combined; run as separate CI jobs
|
|
157
|
+
- Unity is the primary test framework, CTest is the test runner
|
|
158
|
+
- Valgrind and ASan serve similar purposes; use ASan in CI for speed, Valgrind for deep investigation
|