diff --git a/justfile b/justfile index 59926d9..3d57fc0 100644 --- a/justfile +++ b/justfile @@ -30,4 +30,10 @@ test-scc: just clean just build-install just clean - cbuild run -cscc -- -h + cbuild build -cscc + +debug-scc: + just clean + just build-install + just clean + cbuild build -cscc --dev --record --dry-run diff --git a/libs/pproc/src/pproc_expand.c b/libs/pproc/src/pproc_expand.c index 1de31d1..0fad5c0 100644 --- a/libs/pproc/src/pproc_expand.c +++ b/libs/pproc/src/pproc_expand.c @@ -132,9 +132,16 @@ split_arguments(scc_pproc_macro_extened_params_t *splited_params, (named_count > 0 && scc_vec_at(macro->params, named_count - 1).type == SCC_TOK_ELLIPSIS); + int depth = 0; + scc_vec_foreach(*raw_args, i) { scc_lexer_tok_t *raw_arg = &scc_vec_at(*raw_args, i); - if (raw_arg->type != SCC_TOK_COMMA || + if (raw_arg->type == SCC_TOK_L_PAREN) { + depth++; + } else if (raw_arg->type == SCC_TOK_R_PAREN) { + depth--; + } + if (depth != 0 || raw_arg->type != SCC_TOK_COMMA || (is_variadic && scc_vec_size(*splited_params) == named_count - 1)) { if (scc_vec_size(arg) == 0 && raw_arg->type == SCC_TOK_BLANK) { scc_lexer_tok_drop(raw_arg); @@ -142,14 +149,15 @@ split_arguments(scc_pproc_macro_extened_params_t *splited_params, scc_vec_push(arg, *raw_arg); } continue; + } else { + scc_lexer_tok_drop(raw_arg); + if (scc_vec_size(arg) && + scc_vec_at(arg, scc_vec_size(arg) - 1).type == SCC_TOK_BLANK) { + scc_lexer_tok_drop(&scc_vec_pop(arg)); + } + scc_vec_push(*splited_params, arg); + scc_vec_init(arg); } - scc_lexer_tok_drop(raw_arg); - if (scc_vec_size(arg) && - scc_vec_at(arg, scc_vec_size(arg) - 1).type == SCC_TOK_BLANK) { - scc_lexer_tok_drop(&scc_vec_pop(arg)); - } - scc_vec_push(*splited_params, arg); - scc_vec_init(arg); } if (scc_vec_size(arg) && scc_vec_at(arg, scc_vec_size(arg) - 1).type == SCC_TOK_BLANK) { @@ -231,6 +239,25 @@ static int find_params(const scc_lexer_tok_t *tok, return -1; } +static inline int got_left_non_blank(int i, + const scc_lexer_tok_vec_t *replaces) { + int left_idx = i - 1; + while (left_idx >= 0 && + scc_vec_at(*replaces, left_idx).type == SCC_TOK_BLANK) { + left_idx--; + } + return left_idx; +} +static inline int got_right_non_blank(int i, + const scc_lexer_tok_vec_t *replaces) { + int right_idx = i + 1; + while (right_idx < (int)scc_vec_size(*replaces) && + scc_vec_at(*replaces, right_idx).type == SCC_TOK_BLANK) { + right_idx++; + } + return right_idx; +} + static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx, const scc_pproc_macro_t *macro) { scc_lexer_tok_vec_t tok_buffer; @@ -264,12 +291,7 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx, if (tok.type == SCC_TOK_SHARP) { // # stringify scc_lexer_tok_drop(&tok); - int right_idx = i + 1; - while (right_idx < (int)macro->replaces.size && - scc_vec_at(macro->replaces, right_idx).type == - SCC_TOK_BLANK) { - right_idx++; - } + int right_idx = got_right_non_blank(i, ¯o->replaces); if (right_idx >= (int)macro->replaces.size) { LOG_WARN("generate empty stringify"); scc_cstring_free(&tok.lexeme); @@ -286,21 +308,10 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx, continue; } else if (tok.type == SCC_TOK_SHARP_SHARP) { // ## contact - // 向左扫描找到上一个非空白 token scc_lexer_tok_drop(&tok); - int left_idx = i - 1; - while (left_idx >= 0 && - scc_vec_at(macro->replaces, left_idx).type == - SCC_TOK_BLANK) { - left_idx--; - } - // 向右扫描找到下一个非空白 token - int right_idx = i + 1; - while (right_idx < (int)macro->replaces.size && - scc_vec_at(macro->replaces, right_idx).type == - SCC_TOK_BLANK) { - right_idx++; - } + int left_idx = got_left_non_blank(i, ¯o->replaces); + int right_idx = got_right_non_blank(i, ¯o->replaces); + if (left_idx < 0 || right_idx >= (int)macro->replaces.size) { LOG_FATAL("Invalid ## operator"); } @@ -308,13 +319,53 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx, scc_lexer_tok_drop(&scc_vec_pop(tok_buffer)); } - int j; - j = find_params(&scc_vec_at(macro->replaces, left_idx), macro); - Assert(j != -1 && j < (int)scc_vec_size(splited_params)); - scc_lexer_tok_vec_t left_vec = scc_vec_at(splited_params, j); - j = find_params(&scc_vec_at(macro->replaces, right_idx), macro); - Assert(j != -1 && j < (int)scc_vec_size(splited_params)); - scc_lexer_tok_vec_t right_vec = scc_vec_at(splited_params, j); + scc_lexer_tok_t *left_tok = &scc_vec_at(macro->replaces, left_idx); + scc_lexer_tok_t *right_tok = + &scc_vec_at(macro->replaces, right_idx); + + if (left_tok->type == SCC_TOK_COMMA && + scc_strcmp(scc_cstring_as_cstr(&(right_tok->lexeme)), + "__VA_ARGS__") == 0) { + // GNU 扩展:处理逗号删除 + int right_param_idx = find_params(right_tok, macro); + Assert(right_param_idx != -1); + scc_lexer_tok_vec_t right_vec = + scc_vec_at(expanded_params, right_param_idx); + if (scc_vec_size(right_vec) != 0) { + // 可变参数非空:输出逗号副本,然后输出右侧参数的展开 + scc_lexer_tok_t comma_tok = scc_lexer_tok_copy(left_tok); + scc_vec_push(tok_buffer, comma_tok); + } + scc_vec_foreach(right_vec, k) { + scc_lexer_tok_t tok = + scc_lexer_tok_copy(&scc_vec_at(right_vec, k)); + scc_vec_push(tok_buffer, tok); + } + i = right_idx; + continue; + } + + int idx; + idx = find_params(left_tok, macro); + scc_lexer_tok_vec_t left_vec; + if (idx != -1) { + Assert(idx < (int)scc_vec_size(splited_params)); + left_vec = scc_vec_at(splited_params, idx); + } else { + scc_vec_init(left_vec); + scc_vec_push(left_vec, scc_lexer_tok_copy(left_tok)); + } + + idx = find_params(right_tok, macro); + scc_lexer_tok_vec_t right_vec; + if (idx != -1) { + Assert(idx < (int)scc_vec_size(splited_params)); + right_vec = scc_vec_at(splited_params, idx); + } else { + scc_vec_init(right_vec); + scc_vec_push(right_vec, scc_lexer_tok_copy(right_tok)); + } + scc_lexer_tok_t *left = scc_vec_size(left_vec) ? &scc_vec_at(left_vec, scc_vec_size(left_vec) - 1) @@ -380,25 +431,16 @@ static inline void expand_object_macro(scc_pproc_expand_t *expand_ctx, tok.lexeme = scc_cstring_from_cstr(" "); } else if (tok.type == SCC_TOK_SHARP_SHARP) { // ## contact - // 向左扫描找到上一个非空白 token - int left_idx = i - 1; - while (left_idx >= 0 && - scc_vec_at(macro->replaces, left_idx).type == - SCC_TOK_BLANK) { - left_idx--; - } - // 向右扫描找到下一个非空白 token - int right_idx = i + 1; - while (right_idx < (int)macro->replaces.size && - scc_vec_at(macro->replaces, right_idx).type == - SCC_TOK_BLANK) { - right_idx++; - } - if (left_idx < 0 || right_idx >= (int)macro->replaces.size) { + int left_idx = got_left_non_blank(i, ¯o->replaces); + int right_idx = got_right_non_blank(i, ¯o->replaces); + + if (left_idx < 0 || + right_idx >= (int)scc_vec_size(macro->replaces)) { LOG_FATAL("Invalid ## operator"); } scc_lexer_tok_t *left = &scc_vec_at(macro->replaces, left_idx); scc_lexer_tok_t *right = &scc_vec_at(macro->replaces, right_idx); + scc_lexer_tok_t concate_tok = concatenate_tokens(left, right); while (i++ < right_idx) { scc_lexer_tok_drop(&scc_vec_pop(tok_buffer)); diff --git a/libs/pproc/src/pproc_if.c b/libs/pproc/src/pproc_if.c index d78258a..5319ac3 100644 --- a/libs/pproc/src/pproc_if.c +++ b/libs/pproc/src/pproc_if.c @@ -113,7 +113,8 @@ cbool scc_pproc_parse_if_condition(scc_pproc_t *pp, scc_tok_type_t type, if (tok.type == SCC_TOK_INT_LITERAL) { condition = scc_cstring_as_cstr(&tok.lexeme)[0] == '0' ? 0 : 1; } else { - LOG_ERROR("expected integer constant"); + LOG_ERROR("expected integer constant but got %s", + scc_cstring_as_cstr(&tok.lexeme)); } scc_lexer_tok_drop(&tok); diff --git a/libs/pproc/src/pproc_include.c b/libs/pproc/src/pproc_include.c index d11b734..d40d8bc 100644 --- a/libs/pproc/src/pproc_include.c +++ b/libs/pproc/src/pproc_include.c @@ -33,7 +33,7 @@ static int switch_file_stack(scc_pproc_t *pp, scc_cstring_t *fname, goto FOPEN; } } - LOG_ERROR("In %s:%d:%d include %c%s%c , the file is not found", org_fname, + LOG_ERROR("In %s:%d:%d include %c%s%c, the file is not found", org_fname, pos->line, pos->col, is_system ? '<' : '\"', scc_cstring_as_cstr(fname), is_system ? '>' : '\"'); return -1; diff --git a/libs/pproc/tests/test_unit.c b/libs/pproc/tests/test_unit.c index 44426b9..f38e978 100644 --- a/libs/pproc/tests/test_unit.c +++ b/libs/pproc/tests/test_unit.c @@ -132,6 +132,35 @@ static void test_define_nested_macros(void) { CHECK_PP_OUTPUT_EXACT(" # define A 1\nA", "1"); // CHECK_PP_OUTPUT_EXACT(" # define A 1 \nA", "1"); // TODO + + CHECK_PP_OUTPUT_EXACT("#define CONCAT(str) __scc_##str\nCONCAT(int)", + "__scc_int"); + CHECK_PP_OUTPUT_EXACT("#define CONCAT(str) str##_scc__\nCONCAT(int)", + "int_scc__"); + + CHECK_PP_OUTPUT_EXACT("#define CONCAT(str) __scc_ ## str\nCONCAT(int)", + "__scc_int"); + + // TEST_CASE("TODO"); /*FALSE*/ + // CHECK_PP_OUTPUT_EXACT("#define str(x) # x\n" + // "str()\n", + // "\"\"\n"); + + TEST_CASE("TODO"); + CHECK_PP_OUTPUT_EXACT("#define x 1\n" + "#define f(a) f(x * (a))\n" + "f(0)\n" + "f(x)", + "f(1 * (0))\n" + "f(1 * (1))"); + CHECK_PP_OUTPUT_EXACT("#define x x(0)\n" + "#define f(a) f(x * (a))\n" + "f(f(0))\n" + "f(f(x))\n" + "f(f(a))\n", + "f(x(0) * (f(x(0) * (0))))\n" + "f(x(0) * (f(x(0) * (x(0)))))\n" + "f(x(0) * (f(x(0) * (a))))\n"); } static void test_undef_macros(void) { @@ -181,33 +210,19 @@ static void hard_test_define_func_macros(void) { "M3(M3(M2)(0))\n", "M1(0 + 1)\n"); - // TEST_CASE("TODO"); /*FALSE*/ - // CHECK_PP_OUTPUT_EXACT("#define str(x) # x\n" - // "str()\n", - // "\"\"\n"); + TEST_CASE("mulit braces"); + CHECK_PP_OUTPUT_EXACT("#define MACRO(a, b, c) a, b, c\n" + "MACRO(1, (2,3), 4)\n", + "1, (2,3), 4\n"); - TEST_CASE("TODO"); - CHECK_PP_OUTPUT_EXACT("#define x 1\n" - "#define f(a) f(x * (a))\n" - "f(0)\n" - "f(x)", - "f(1 * (0))\n" - "f(1 * (1))"); - CHECK_PP_OUTPUT_EXACT("#define x x(0)\n" - "#define f(a) f(x * (a))\n" - "f(f(0))\n" - "f(f(x))\n" - "f(f(a))\n", - "f(x(0) * (f(x(0) * (0))))\n" - "f(x(0) * (f(x(0) * (x(0)))))\n" - "f(x(0) * (f(x(0) * (a))))\n"); -} - -static void test_conditional_compilation(void) { - TEST_CASE("conditional compilation"); - CHECK_PP_OUTPUT_EXACT("#if 1\ntrue\n#endif\n", "true\n"); - CHECK_PP_OUTPUT_EXACT("#if 0\nfalse\n#endif\n", ""); - CHECK_PP_OUTPUT_EXACT("#define FLAG 1\n#if FLAG\ntrue\n#endif\n", "true\n"); + TEST_CASE("max_macro hard"); + CHECK_PP_OUTPUT_EXACT("#define max(a, b) ((a) > (b) ? (a) : (b))\n" + "max(1, 2)\n", + "((1) > (2) ? (1) : (2))\n"); + CHECK_PP_OUTPUT_EXACT("#define max(a, b) ((a) > (b) ? (a) : (b))\n" + "max(max(x, y), z)\n", + "((((x) > (y) ? (x) : (y))) > (z) ? (((x) > (y) ? " + "(x) : (y))) : (z))\n"); } static void test_error_cases(void) { @@ -406,6 +421,111 @@ static void test_variadic_macros(void) { CHECK_PP_OUTPUT_EXACT("#define FOO(x, ...) x __VA_ARGS__\n" "FOO(1)\n", "1 \n"); + + CHECK_PP_OUTPUT_EXACT("#define FOO(x, ...) #__VA_ARGS__\nFOO(1);", "\"\";"); +} + +static void test_gnu_comma_variadic_deletion(void) { + TEST_CASE("GNU comma deletion with ## and __VA_ARGS__"); + // 可变参数为空,逗号被删除 + CHECK_PP_OUTPUT_EXACT("#define FOO(fmt, ...) printf(fmt, ## __VA_ARGS__)\n" + "FOO(\"hello\")\n", + "printf(\"hello\")\n"); + // 可变参数非空,逗号保留 + CHECK_PP_OUTPUT_EXACT("#define FOO(fmt, ...) printf(fmt, ## __VA_ARGS__)\n" + "FOO(\"%d\", 42)\n", + "printf(\"%d\",42)\n"); + // 带空白变体 + CHECK_PP_OUTPUT_EXACT("#define FOO(fmt,...) printf(fmt,##__VA_ARGS__)\n" + "FOO(\"%d\", 42)\n", + "printf(\"%d\",42)\n"); +} + +static void test_c99_docs(void) { + TEST_CASE("6.10.3.3 The ## operator EXAMPLE"); + CHECK_PP_OUTPUT_EXACT("#define hash_hash # ## #\n" + "#define mkstr(a) # a\n" + "#define in_between(a) mkstr(a)\n" + "#define join(c, d) in_between(c hash_hash d)\n" + "char p[] = join(x, y);\n", + "char p[] = \"x ## y\";\n"); + + // 6.10.3.5 Scope of macrodefinitions + TEST_CASE("EXAMPLE 3 To illustrate the rules for redefinition and " + "reexamination, the sequence"); + /* + CHECK_PP_OUTPUT_EXACT( + "#define x 3\n" + "#define f(a) f(x * (a))\n" + "#undef x\n" + "#define x 2\n" + "#define g f\n" + "#define z z[0]\n" + "#define h g(~\n" + "#define m(a) a(w)\n" + "#define w 0,1\n" + "#define t(a) a\n" + "#define p() int\n" + "#define q(x) x\n" + "#define r(x,y) x ## y\n" + "#define str(x) # x\n" + "f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);\n" + "g(x+(3,4)-w) | h 5) & m\n" + " (f)^m(m);\n" + "p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };\n" + "char c[2][6] = { str(hello), str() };\n", + "f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);\n" + "f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);\n" + "int i[] = { 1, 23, 4, 5, };\n" + "char c[2][6] = { \"hello\", \"\" };\n"); + */ + + TEST_CASE("EXAMPLE 4 To illustrate the rules for creating character string " + "literals and concatenating tokens, the sequence"); + + TEST_CASE("EXAMPLE 5 To illustrate the rules for placemarker preprocessing " + "tokens, the sequence"); + /* + CHECK_PP_OUTPUT_EXACT("#define t(x,y,z) x ## y ## z\n" + "int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,),\n" + "\t\t\tt(10,,), t(,11,), t(,,12), t(,,) };\n", + "int j[] = { 123, 45, 67, 89,\n" + "\t\t\t10, 11, 12, };\n"); + */ + + TEST_CASE("EXAMPLE 6 To demonstrate the redefinition rules, the following " + "sequence is valid."); + CHECK_PP_OUTPUT_EXACT( + "#define OBJ_LIKE (1-1)\n" + "#define OBJ_LIKE /* white space */ (1-1) /* other */\n" + "#define FUNC_LIKE(a) (a)\n" + "#define FUNC_LIKE( a )( /* note the white space */ \\\n" + " a /* other stuffonthis line\n" + " */ )\n", + ""); + // INVALID + // CHECK_PP_OUTPUT_EXACT( + // "#define OBJ_LIKE (0) // different token sequence\n" + // "#define OBJ_LIKE (1 - 1) // different white space\n" + // "#define FUNC_LIKE(b) ( a ) // different parameter usage\n" + // "#define FUNC_LIKE(b) ( b ) // different parameter spelling\n"); + + TEST_CASE("EXAMPLE 7 Finally,to show the variable argument list macro " + "facilities:"); + CHECK_PP_OUTPUT_EXACT( + "#define debug(...) fprintf(stderr, __VA_ARGS__)\n" + "#define showlist(...) puts(#__VA_ARGS__)\n" + "#define report(test, ...) ((test)?puts(#test): \\\n" + " printf(__VA_ARGS__))\n" + "debug(\"Flag\");\n" + "debug(\"X = %d\\n\", x);\n" + "showlist(The first, second, and third items.);\n" + "report(x>y, \"x is %d but y is %d\", x, y);\n", + + "fprintf(stderr, \"Flag\");\n" + "fprintf(stderr, \"X = %d\\n\", x);\n" + "puts(\"The first, second, and third items.\");\n" + "((x>y)?puts(\"x>y\"): printf(\"x is %d but y is %d\", x, y));\n"); } #define TEST_LIST_CASE(func_name) {#func_name, func_name} @@ -423,5 +543,8 @@ TEST_LIST = { TEST_LIST_CASE(test_conditional_ifdef), TEST_LIST_CASE(test_simple_number_conditional_if), TEST_LIST_CASE(test_variadic_macros), + TEST_LIST_CASE(test_gnu_comma_variadic_deletion), + + TEST_LIST_CASE(test_c99_docs), {NULL, NULL}, }; diff --git a/runtime/log/include/log.h b/runtime/log/include/log.h index 487552a..6e2d726 100644 --- a/runtime/log/include/log.h +++ b/runtime/log/include/log.h @@ -187,13 +187,10 @@ void log_set_handler(logger_t *logger, log_handler handler); * 利用数组大小不能为负的特性 * 或使用 _Static_assert (C11) */ -#ifdef static_assert -#undef static_assert -#endif #if __STDC_VERSION__ >= 201112L -#define static_assert _Static_assert +#define StaticAssert static_assert #else -#define static_assert(cond, msg) extern char __static_assertion[(cond) ? 1 : -1] +#define StaticAssert(cond, msg) extern char __static_assertion[(cond) ? 1 : -1] #endif #ifdef __SCC_LOG_IMPL_IMPORT_SRC__ diff --git a/runtime/scc_core/include/scc_core_type.h b/runtime/scc_core/include/scc_core_type.h index 9ef5af9..0cb81c8 100644 --- a/runtime/scc_core/include/scc_core_type.h +++ b/runtime/scc_core/include/scc_core_type.h @@ -33,23 +33,6 @@ typedef bool cbool; static_assert(sizeof(cbool) == 1, "cbool size must 1"); #else -#define __scc_i8 -#define __scc_i16 -#define __scc_i32 -#define __scc_i64 -#define __scc_u8 -#define __scc_u16 -#define __scc_u32 -#define __scc_u64 -#define __scc_f32 -#define __scc_f64 -#define __scc_bool -#define __scc_char -#define __scc_void -#define __scc_null -#define __scc_isize -#define __scc_usize - /* clang-format off */ typedef __scc_i8 i8; typedef __scc_i16 i16; diff --git a/runtime/scc_core/tests/test_core_ring.c b/runtime/scc_core/tests/test_core_ring.c index 0c633ba..f457892 100644 --- a/runtime/scc_core/tests/test_core_ring.c +++ b/runtime/scc_core/tests/test_core_ring.c @@ -60,7 +60,7 @@ void test_char_ring_basic(void) { reset_char_fill(); char_ring_t ring; scc_ring_init(ring, 4, char_fill, 0); - char c; + char c = 0; cbool ok; scc_ring_next(ring, c, ok); @@ -109,7 +109,7 @@ void test_char_ring_full(void) { reset_char_fill(); char_ring_t ring; scc_ring_init(ring, 3, char_fill, 0); - char c; + char c = 0; cbool ok; scc_ring_next(ring, c, ok); @@ -140,7 +140,7 @@ void test_char_ring_eof(void) { reset_char_fill(); char_ring_t ring; scc_ring_init(ring, 32, char_fill, 0); - char c; + char c = 0; cbool ok; for (int i = 0; i < 26; i++) { @@ -160,7 +160,7 @@ void test_char_ring_back_boundary(void) { reset_char_fill(); char_ring_t ring; scc_ring_init(ring, 4, char_fill, 0); - char c; + char c = 0; cbool ok; scc_ring_next(ring, c, ok); @@ -186,7 +186,7 @@ void test_char_ring_consume_reset(void) { reset_char_fill(); char_ring_t ring; scc_ring_init(ring, 5, char_fill, 0); - char c; + char c = 0; cbool ok; scc_ring_next(ring, c, ok); @@ -219,7 +219,7 @@ void test_char_ring_wrap(void) { reset_char_fill(); char_ring_t ring; scc_ring_init(ring, 3, char_fill, 0); - char c; + char c = 0; cbool ok; for (int i = 0; i < 26; i++) { @@ -239,7 +239,7 @@ void test_token_ring_basic(void) { reset_token_fill(); token_ring_t ring; scc_ring_init(ring, 3, token_fill, 0); - test_token_t tok; + test_token_t tok = {0}; cbool ok; scc_ring_next(ring, tok, ok); @@ -284,7 +284,7 @@ void test_token_ring_full(void) { reset_token_fill(); token_ring_t ring; scc_ring_init(ring, 2, token_fill, 0); - test_token_t tok; + test_token_t tok = {0}; cbool ok; scc_ring_next(ring, tok, ok); diff --git a/tools/cbuild/cbuild.py b/tools/cbuild/cbuild.py index 6b1088e..0a58573 100644 --- a/tools/cbuild/cbuild.py +++ b/tools/cbuild/cbuild.py @@ -564,6 +564,7 @@ class Compiler(ABC): def __init__(self): self.recorded = [] self.recording = False + self.dry_run = False def enable_recording(self, enable=True): """启用命令记录""" @@ -580,6 +581,8 @@ class Compiler(ABC): """运行命令""" self.record(cmd) logger.debug("执行命令: %s", cmd) + if self.dry_run: + return # 只打印,不执行 try: subprocess.run(cmd, check=True) except subprocess.CalledProcessError as e: @@ -689,8 +692,9 @@ class SccCompiler(Compiler): self, source: Path, output: Path, includes: list[Path], flags: list[str] ): # cmd = ["clang"] + flags + ["-c", str(source), "-o", str(output)] - cmd = ["scc", "--emit-pp", "-o", str(output), str(source)] - cmd += [f"-I{inc}" for inc in includes] + cmd = ["scc", "--emit-pp", "-o", str(output), str(source), "-I", "scc_libs"] + for inc in includes: + cmd += ["-I", f"{inc}"] self.run(cmd) def link(self, objects: list[Path], output: Path, flags: list[str]): @@ -1036,7 +1040,6 @@ def create_parser(): parser = argparse.ArgumentParser(description="轻量C构建系统", prog="cbuild") parser.add_argument("--verbose", "-v", action="store_true", help="详细输出") parser.add_argument("--path", "-p", default=".", help="项目路径") - subparsers = parser.add_subparsers(dest="command", required=True, metavar="COMMAND") def add_common_args(subparser): @@ -1047,6 +1050,9 @@ def create_parser(): default="gcc", help="编译器", ) + subparser.add_argument( + "--dry-run", "-d", action="store_true", help="仅打印命令,不实际执行" + ) subparser.add_argument("--record", "-r", action="store_true", help="记录命令") subparser.add_argument( "--jobs", "-j", type=int, default=0, help="并行编译任务数 (0=自动检测)" @@ -1144,6 +1150,8 @@ def main(): } compiler = compiler_map.get(args.compiler, GccCompiler()) + if hasattr(args, "dry_run") and args.dry_run: + compiler.dry_run = True if hasattr(args, "record") and args.record: compiler.enable_recording()