使用XC32+Ceedling进行嵌入式C单元测试:编译失败问题
问题
基于PIC32MX575F256H的项目在MPLAB X中可正常编译,但执行ceedling --trace test:all时编译失败,提示找不到proc/ppic32mx.h文件。报错信息如下:
[12:18:12] user@mypc:~/MPLAB$ ceedling --trace test:all Test 'test_main.c' - In file included from /opt/microchip/xc32/v4.35/pic32mx/include/xc.h:376, from src/config/default/device.h:47, from src/config/default/peripheral/gpio/plib_gpio.h:45, from src/config/default/definitions.h:52, from test/test_main.c:10: /opt/microchip/xc32/v4.35/pic32mx/include/proc/PIC32MX/p32mx575f256h.h:29106:10: fatal error: proc/ppic32mx.h: No such file or directory 29106 | #include "proc/ppic32mx.h" | ^~~~~~~~~~~~~~~~~~~~~ compilation terminated. ERROR: Shell command failed. > Shell executed command: > 'gcc -E -I"/home/user/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/ceedling-0.31.1/vendor/unity/src" -I"/home/user/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/ceedling-0.31.1/vendor/cmock/src" -I"build/test/mocks" -I"test" -I"test/simulation" -I"test/support" -I"src" -I"src/config" -I"src/config/default" -I"src/config/default/PIC32MX_DFP" -I"src/config/default/default.mhc" -I"src/config/default/peripheral" -I"src/config/default/peripheral/clk" -I"src/config/default/peripheral/evic" -I"src/config/default/peripheral/gpio" -I"src/config/default/stdio" -I"/opt/microchip/xc32/v4.35/pic32mx/include" -D__PIC32MX__ -D__32MX575F256H__ -D__LANGUAGE_C__ -DUNITY_INT_WIDTH=32 -DCMOCK_MEM_INDEX_TYPE=uint32_t -DCMOCK_MEM_PTR_AS_INT=uint32_t -DCMOCK_MEM_SIZE=2056 -DTEST -D__PIC32MX__ -D__32MX575F256H__ -D__LANGUAGE_C__ -DTEST -DGNU_COMPILER "test/test_main.c" -o "build/test/preprocess/files/test_main.c"' > And exited with status: [1]. rake aborted! ShellExecutionException: ShellExecutionException /home/user/.rbenv/versions/3.0.0/bin/ceedling:23:in `load' /home/user/.rbenv/versions/3.0.0/bin/ceedling:23:in `<main>' Tasks: TOP => test:all (See full trace by running task with --trace) ERROR: Ceedling Failed
当前Ceedling配置YAML:
:project: :use_exceptions: FALSE :use_test_preprocessor: TRUE :use_auxiliary_dependencies: TRUE :build_root: build # :release_build: TRUE :test_file_prefix: test_ :which_ceedling: gem :ceedling_version: 0.31.1 :default_tasks: - test:all #:test_build: # :use_assembly: TRUE #:release_build: # :output: MyApp.out # :use_assembly: FALSE :environment: - :mcu: 32MX575F256L - :freq: 80000000UL :extension: :executable: .elf :paths: :test: - +:test/** - -:test/support :source: - src/** :support: - test/support :libraries: [] :include: - "/opt/microchip/xc32/v4.35/pic32mx/include/" :defines: :common: &common_defines - __PIC32MX__ - __32MX575F256H__ - __LANGUAGE_C__ :test: - *common_defines - UNITY_INT_WIDTH=32 - CMOCK_MEM_INDEX_TYPE=uint32_t - CMOCK_MEM_PTR_AS_INT=uint32_t - CMOCK_MEM_SIZE=2056 - TEST :test_preprocess: - *common_defines - TEST :cmock: :mock_prefix: mock_ :when_no_prototypes: :warn :enforce_strict_ordering: TRUE :plugins: - :ignore - :callback :treat_as: uint8: HEX8 uint16: HEX16 uint32: UINT32 int8: INT8 bool: UINT8 :gcov: :reports: - HtmlDetailed :gcovr: :html_medium_threshold: 75 :html_high_threshold: 90 :libraries: :placement: :end :flag: "-l${1}" :path_flag: "-L ${1}" :system: [] # for example, you might list 'm' to grab the math library :test: [] :release: [] :tools: :test_compiler: :executable: "/opt/microchip/xc32/v4.35/bin/xc32-gcc" :arguments: - -mprocessor=32MX575F256L - -x c - -c - "${1}" - -o "${2}" - -D$: COLLECTION_DEFINES_TEST_AND_VENDOR - -I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR - -Iinclude/ - -Wall :test_linker: :executable: "/opt/microchip/xc32/v4.35/bin/xc32-gcc" :arguments: - -mprocessor=32MX575F256L - -gdwarf-3 - -D"$": COLLECTION_DEFINES_TEST_AND_VENDOR - -I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR - -Wl,-Map="${3}" - -o"./build/ceedling/generated/test/out/test_build.elf" - "{'${1}'.split(' ').map { |x| (x.include? '/out/c/') ? (Pathname(x).sub_ext('.p1')).to_s : x }.join(' ') }" - "${4}" :test_fixture: :executable: ruby :name: "Microchip simulator test fixture" :stderr_redirect: :win #inform Ceedling what model of $stderr capture to use :arguments: - test/simulation/sim_test_fixture.rb :plugins: :load_paths: - "#{Ceedling.load_path}" :enabled: - stdout_pretty_tests_report - module_generator
原因分析
从报错的编译命令能看到,Ceedling在预编译阶段用了系统默认的gcc,而非你配置的XC32编译器xc32-gcc。系统gcc无法正确解析XC32头文件的相对引用逻辑,即便添加了include路径,也找不到proc/ppic32mx.h。另外,你的配置只指定了test_compiler和test_linker,没配置test_preprocessor,导致预编译环节使用默认编译器。
解决方案
在tools节点下添加test_preprocessor配置,指定用XC32的xc32-gcc作为预处理器,并传入正确的编译参数,确保头文件路径和宏定义被正确加载。同时移除test_compiler中多余的-Iinclude/参数,因为COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR已经包含了你配置的include路径。
修改后的tools配置片段如下:
:tools: :test_compiler: :executable: "/opt/microchip/xc32/v4.35/bin/xc32-gcc" :arguments: - -mprocessor=32MX575F256L - -x c - -c - "${1}" - -o "${2}" - -D$: COLLECTION_DEFINES_TEST_AND_VENDOR - -I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR - -Wall :test_linker: :executable: "/opt/microchip/xc32/v4.35/bin/xc32-gcc" :arguments: - -mprocessor=32MX575F256L - -gdwarf-3 - -D"$": COLLECTION_DEFINES_TEST_AND_VENDOR - -I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR - -Wl,-Map="${3}" - -o"./build/ceedling/generated/test/out/test_build.elf" - "{'${1}'.split(' ').map { |x| (x.include? '/out/c/') ? (Pathname(x).sub_ext('.p1')).to_s : x }.join(' ') }" - "${4}" # 添加预处理器配置 :test_preprocessor: :executable: "/opt/microchip/xc32/v4.35/bin/xc32-gcc" :arguments: - -E - "${1}" - -o "${2}" - -D$: COLLECTION_DEFINES_TEST_AND_VENDOR - -I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR - -mprocessor=32MX575F256L
验证
修改配置后重新执行ceedling --trace test:all,预编译阶段会使用xc32-gcc,能正确解析XC32的头文件结构,解决找不到proc/ppic32mx.h的问题。
内容的提问来源于stack exchange,提问作者treeman
相关产品推荐
相关产品推荐

