使用avr-g++/gcc配置项目报错:无法识别‘--out-implib’选项
解决AVR GCC链接器无法识别
--out-implib选项的问题 问题场景
执行以下CMake配置命令:
cmake -B../build_atmega328 -S. -G Ninja -D CMAKE_C_COMPILER=C:\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\bin\avr-gcc.exe -D CMAKE_CXX_COMPILER=C:\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\bin\avr-g++.exe
出现链接器错误,核心提示:
c:/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld.exe: unrecognized option '--out-implib'
导致C++编译器检测失败,完整错误输出如下:
E:\MyProject\display\display_controller>cmake -B../build_atmega328 -S. -G Ninja -D CMAKE_C_COMPILER=C:\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\bin\avr-gcc.exe -D CMAKE_CXX_COMPILER=C:\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\bin\avr-g++.exe -- The CXX compiler identification is GNU 7.3.0 -- The C compiler identification is GNU 7.3.0 -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - failed -- Check for working CXX compiler: C:/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++.exe -- Check for working CXX compiler: C:/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++.exe - broken CMake Error at C:/Program Files/CMake/share/cmake-3.31/Modules/CMakeTestCXXCompiler.cmake:73 (message): The C++ compiler "C:/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++.exe" is not able to compile a simple test program. It fails with the following output: Change Dir: 'E:/MyProject/display/build_atmega328/CMakeFiles/CMakeScratch/TryCompile-njpofd' Run Build Command(s): E:/ninja/ninja.exe -v cmTC_3ce41 [1/2] C:\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\bin\avr-g++.exe -o CMakeFiles/cmTC_3ce41.dir/testCXXCompiler.cxx.obj -c E:/MyProject/display/build_atmega328/CMakeFiles/CMakeScratch/TryCompile-njpofd/testCXXCompiler.cxx [2/2] C:\Windows\system32\cmd.exe /C "cd . && C:\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\bin\avr-g++.exe CMakeFiles/cmTC_3ce41.dir/testCXXCompiler.cxx.obj -o cmTC_3ce41.exe -Wl,--out-implib,libcmTC_3ce41.dll.a -Wl,--major-image-version,0,--minor-image-version,0 -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ." FAILED: cmTC_3ce41.exe C:\Windows\system32\cmd.exe /C "cd . && C:\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\bin\avr-g++.exe CMakeFiles/cmTC_3ce41.dir/testCXXCompiler.cxx.obj -o cmTC_3ce41.exe -Wl,--out-implib,libcmTC_3ce41.dll.a -Wl,--major-image-version,0,--minor-image-version,0 -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ." c:/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld.exe: unrecognized option '--out-implib' c:/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld.exe: use the --help option for usage information collect2.exe: error: ld returned 1 exit status ninja: build stopped: subcommand failed.
错误原因
CMake默认认为是编译主机(Windows)平台的程序,自动添加了Windows特有的链接选项(--out-implib用于生成导入库,-lkernel32等Windows系统库),但AVR GCC是交叉编译工具链,其链接器avr-ld不支持这些Windows平台选项,因此报错。
解决方案
修改CMakeLists.txt,明确告诉CMake这是交叉编译,不要添加主机平台的链接选项:
- 在
cmake_minimum_required之后、project之前,添加交叉编译配置:
# 声明交叉编译模式 set(CMAKE_CROSSCOMPILING ON) # 设置目标系统为无OS的嵌入式平台 set(CMAKE_SYSTEM_NAME Generic) # 指定目标架构为AVR set(CMAKE_SYSTEM_PROCESSOR avr) # 强制跳过编译器ABI检测(交叉编译时ABI检测通常无效) set(CMAKE_CXX_COMPILER_FORCED ON) set(CMAKE_C_COMPILER_FORCED ON)
修改后的完整CMakeLists.txt如下:
# I target a recent cmake, it shouldn't be a problem on a dev machine cmake_minimum_required(VERSION 3.11) # 交叉编译配置 set(CMAKE_CROSSCOMPILING ON) set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_PROCESSOR avr) set(CMAKE_CXX_COMPILER_FORCED ON) set(CMAKE_C_COMPILER_FORCED ON) # Project name project("ConnectionsDisplay" VERSION 0.1 LANGUAGES CXX C) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Product filename set(PRODUCT_NAME connections_display) ## AVR Chip Configuration # 8Mhz, this should match the crystal on your board, # I use 8Mhz and 3.3V for the lowest power consumption set(F_CPU 8000000UL) # CPU, you can find the list here: # https://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html set(MCU atmega328p) # Default Baudrate for UART, read avr include/util/setbaud.h for usage set(BAUD 9600) # The programmer to use, read avrdude manual for list set(PROG_TYPE avrispmkII) # AVR Fuses, must be in concordance with your hardware and F_CPU # http://eleccelerator.com/fusecalc/fusecalc.php?chip=atmega328p set(E_FUSE 0xfd) set(H_FUSE 0xda) set(L_FUSE 0xfd) set(LOCK_BIT 0xff) set(CMAKE_AVR_TOOL_COMPILERS "C:\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7\\bin") # Pass defines to compiler add_definitions( -DF_CPU=${F_CPU} -DBAUD=${BAUD} ) # mmcu MUST be passed to bot the compiler and linker, this handle the linker set(CMAKE_EXE_LINKER_FLAGS -mmcu=${MCU}) add_compile_options( -mmcu=${MCU} # MCU -Os # optimize -Wall # enable warnings -Wno-main -Wundef -pedantic -Wstrict-prototypes -Werror -Wfatal-errors -Wl,--relax,--gc-sections -g -gdwarf-2 -funsigned-char # a few optimizations -funsigned-bitfields -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -fno-split-wide-types -fno-tree-scev-cprop ) file(GLOB SRC_FILES "src/*.cpp" "src/*.c") # Load all files in src folder # Create one target add_executable(${PRODUCT_NAME} ${SRC_FILES}) # Rename the output to .elf as we will create multiple files set_target_properties(${PRODUCT_NAME} PROPERTIES OUTPUT_NAME ${PRODUCT_NAME}.elf) # Strip binary for upload add_custom_target(strip ALL avr-strip ${PRODUCT_NAME}.elf DEPENDS ${PRODUCT_NAME}) # Transform binary into hex file, we ignore the eeprom segments in the step add_custom_target(hex ALL avr-objcopy -R .eeprom -O ihex ${PRODUCT_NAME}.elf ${PRODUCT_NAME}.hex DEPENDS strip) # Transform binary into hex file, this is the eeprom part (empty if you don't # use eeprom static variables) add_custom_target(eeprom avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex ${PRODUCT_NAME}.elf ${PRODUCT_NAME}.eep DEPENDS strip) # Clean extra files set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${PRODUCT_NAME}.hex;${PRODUCT_NAME}.eeprom;${PRODUCT_NAME}.lst")
验证步骤
- 删除已有的
build_atmega328目录 - 重新运行原来的CMake配置命令
- 检查输出,确认编译器检测通过,没有
--out-implib相关错误
内容的提问来源于stack exchange,提问作者Tomáš Zato
相关产品推荐
相关产品推荐

