目标 *.elf 的 AtmelStudio 配方失败
AtmelStudio recipe for target *.elf failed
我已将代码分成文件(*.c 和 *.h)并包含它们。我有 guard headers 并且所有分离的文件都被报告为正在构建:
Finished building: .././test.c
但是我的项目构建导致了这个错误:
recipe for target 'Midi.elf' failed
,因为
undefined reference to 'some_test()'
(所有函数调用)定义在这些单独的文件中。
而且我不知道如何调试它。我插入了编译器警告,可以证明要处理的函数定义和声明。也许 avr-g++.exe 和 avr-gcc.exe 构建输出无法链接?
Sketch.cpp:
#include "test.h"
void setup() {
some_test();
}
void loop() {
}
test.h:
#ifndef TEST_H
#define TEST_H
void some_test(void);
#warning "processing test.h"
#endif //TEST_H
test.c:
#include "test.h"
void some_test(void){
#warning "processing test.c"
}
输出(项目相关部分):
...
Done building project "ArduinoCore.cppproj".
Build succeeded.
------ Build started: Project: Midi, Configuration: Debug AVR ------
Build started.
Project "Midi.cppproj" (default targets):
Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!='').
Target "CoreBuild" in file "C:\Program Files\Atmel\Studio.0\Vs\Compiler.targets" from project "D:\Mirror\Anwendungen\AVRStudio\Arduino\MIDIout\MIDIout\MIDIout\Midi\Midi.cppproj" (target "Build" depends on it):
Task "RunCompilerTask"
Shell Utils Path C:\Program Files\Atmel\Studio.0\shellUtils
C:\Program Files\Atmel\Studio.0\shellUtils\make.exe all --jobs 4 --output-sync
Building file: .././Sketch.cpp
Invoking: AVR8/GNU C Compiler : 4.9.2
"C:\Program Files\Atmel\Studio.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-g++.exe" -funsigned-char -funsigned-bitfields -DDEBUG -DF_CPU=16000000L -DARDUINO=108013 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR -DUSB_VID=0x2341 -DUSB_PID=0x0010 -DUSB_MANUFACTURER="\"Arduino LLC\"" -I"C:\Program Files\Atmel\Studio.0\Packs\atmel\ATmega_DFP.1.130\include" -I"..\..\ArduinoCore\include\core" -I"..\..\ArduinoCore\include\variants\mega" -Os -fno-threadsafe-statics -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -mrelax -g2 -Wall -w -mmcu=atmega2560 -B "C:\Program Files\Atmel\Studio.0\Packs\atmel\ATmega_DFP.1.130\gcc\dev\atmega2560" -c -std=gnu++11 -MD -MP -MF "Sketch.d" -MT"Sketch.d" -MT"Sketch.o" -o "Sketch.o" ".././Sketch.cpp"
Finished building: .././Sketch.cpp
Building file: .././test.c
Invoking: AVR8/GNU C Compiler : 4.9.2
"C:\Program Files\Atmel\Studio.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe" -x c -funsigned-char -funsigned-bitfields -DDEBUG -DF_CPU=16000000L -DARDUINO=108013 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR -DUSB_VID=0x2341 -DUSB_PID=0x0010 -DUSB_MANUFACTURER="\"Arduino LLC\"" -I"C:\Program Files\Atmel\Studio.0\Packs\atmel\ATmega_DFP.1.130\include" -I"..\..\ArduinoCore\include\core" -I"..\..\ArduinoCore\include\variants\mega" -Os -fno-threadsafe-statics -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -mrelax -g2 -Wall -mmcu=atmega2560 -B "C:\Program Files\Atmel\Studio.0\Packs\atmel\ATmega_DFP.1.130\gcc\dev\atmega2560" -c -std=gnu99 -std=gnu11 -MD -MP -MF "test.d" -MT"test.d" -MT"test.o" -o "test.o" ".././test.c"
Finished building: .././test.c
cc1.exe(0,0): warning: command line option '-fno-threadsafe-statics' is valid for C++/ObjC++ but not for C
In file included from .././test.c:1:0:
D:\Mirror\Anwendungen\AVRStudio\Arduino\MIDIout\MIDIout\MIDIout\Midi\test.h(5,2): warning: #warning "processing test.h" [-Wcpp]
#warning "processing test.h"
^
.././test.c: In function 'some_test':
D:\Mirror\Anwendungen\AVRStudio\Arduino\MIDIout\MIDIout\MIDIout\Midi\test.c(4,3): warning: #warning "processing test.c" [-Wcpp]
#warning "processing test.c"
^
Building target: Midi.elf
Invoking: AVR8/GNU Linker : 4.9.2
"C:\Program Files\Atmel\Studio.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-g++.exe" -o Midi.elf Sketch.o test.o -Wl,-Map="Midi.map" -Wl,--start-group -Wl,-lm -Wl,-lArduinoCore -Wl,--end-group -Wl,-L"D:\Mirror\Anwendungen\AVRStudio\Arduino\MIDIout\MIDIout\MIDIout\ArduinoCore\Debug" -Wl,--gc-sections -mrelax -mmcu=atmega2560 -B "C:\Program Files\Atmel\Studio.0\Packs\atmel\ATmega_DFP.1.130\gcc\dev\atmega2560" -Os
Sketch.o: In function `setup':
D:\Mirror\Anwendungen\AVRStudio\Arduino\MIDIout\MIDIout\MIDIout\Midi\Sketch.cpp(20,1): error: undefined reference to `some_test()'
collect2.exe(0,0): error: ld returned 1 exit status
make: *** [Midi.elf] Error 1
D:\Mirror\Anwendungen\AVRStudio\Arduino\MIDIout\MIDIout\MIDIout\Midi\Debug\Makefile(123,1): error: recipe for target 'Midi.elf' failed
The command exited with code 2.
Done executing task "RunCompilerTask" -- FAILED.
Done building target "CoreBuild" in project "Midi.cppproj" -- FAILED.
Done building project "Midi.cppproj" -- FAILED.
Build FAILED.
========== Build: 1 succeeded or up-to-date, 1 failed, 0 skipped ==========
Sketch.cpp 编译为 C++,包括 test.h。为了支持函数重载、class 成员资格等,C++ 使用 name mangling 在符号名称中编码这些 C++ 特性。因此,Sketch.cpp 中 some_test
的符号名称与 test.c 中的符号名称不同,后者被编译为 C 且未应用名称混淆。
解决方案是在 header 是 C++ 编译时通过指定符号具有 C 链接来防止此符号的名称混淆:
#ifndef TEST_H
#define TEST_H
#if defined __cplusplus
extern "C"
{
#warning Using C linkage in C++ for test.h
#endif
void some_test(void);
#warning "processing test.h"
#if defined __cplusplus
}
#endif
#endif //TEST_H
extern "C"
声明中的大括号({...}
)表示所有包含在其中的符号声明都具有 C 链接。对于 C/C++ 互操作性,所有 C 代码 header 都应包含此包装器。
当然,另一种解决方案是将 test.c 编译为 C++(最简单的方法是将其重命名为 text.cpp)。请注意,Arduino Sketch 代码和库 是 C++ 代码。通常最好始终坚持 C++ 编译,以允许访问 Arduino 库,该库将具有 C++ 链接,并且需要大量包装代码才能从 C 访问。
毫无帮助的是,构建日志明显地使用 C++ 编译时显示“Invoking: AVR8/GNU C Compiler
”。我认为这只是 Atmel Studio 的事情,不是由编译器本身生成的。
我已将代码分成文件(*.c 和 *.h)并包含它们。我有 guard headers 并且所有分离的文件都被报告为正在构建:
Finished building: .././test.c
但是我的项目构建导致了这个错误:
recipe for target 'Midi.elf' failed
,因为
undefined reference to 'some_test()'
(所有函数调用)定义在这些单独的文件中。 而且我不知道如何调试它。我插入了编译器警告,可以证明要处理的函数定义和声明。也许 avr-g++.exe 和 avr-gcc.exe 构建输出无法链接?
Sketch.cpp:
#include "test.h"
void setup() {
some_test();
}
void loop() {
}
test.h:
#ifndef TEST_H
#define TEST_H
void some_test(void);
#warning "processing test.h"
#endif //TEST_H
test.c:
#include "test.h"
void some_test(void){
#warning "processing test.c"
}
输出(项目相关部分):
...
Done building project "ArduinoCore.cppproj".
Build succeeded.
------ Build started: Project: Midi, Configuration: Debug AVR ------
Build started.
Project "Midi.cppproj" (default targets):
Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!='').
Target "CoreBuild" in file "C:\Program Files\Atmel\Studio.0\Vs\Compiler.targets" from project "D:\Mirror\Anwendungen\AVRStudio\Arduino\MIDIout\MIDIout\MIDIout\Midi\Midi.cppproj" (target "Build" depends on it):
Task "RunCompilerTask"
Shell Utils Path C:\Program Files\Atmel\Studio.0\shellUtils
C:\Program Files\Atmel\Studio.0\shellUtils\make.exe all --jobs 4 --output-sync
Building file: .././Sketch.cpp
Invoking: AVR8/GNU C Compiler : 4.9.2
"C:\Program Files\Atmel\Studio.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-g++.exe" -funsigned-char -funsigned-bitfields -DDEBUG -DF_CPU=16000000L -DARDUINO=108013 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR -DUSB_VID=0x2341 -DUSB_PID=0x0010 -DUSB_MANUFACTURER="\"Arduino LLC\"" -I"C:\Program Files\Atmel\Studio.0\Packs\atmel\ATmega_DFP.1.130\include" -I"..\..\ArduinoCore\include\core" -I"..\..\ArduinoCore\include\variants\mega" -Os -fno-threadsafe-statics -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -mrelax -g2 -Wall -w -mmcu=atmega2560 -B "C:\Program Files\Atmel\Studio.0\Packs\atmel\ATmega_DFP.1.130\gcc\dev\atmega2560" -c -std=gnu++11 -MD -MP -MF "Sketch.d" -MT"Sketch.d" -MT"Sketch.o" -o "Sketch.o" ".././Sketch.cpp"
Finished building: .././Sketch.cpp
Building file: .././test.c
Invoking: AVR8/GNU C Compiler : 4.9.2
"C:\Program Files\Atmel\Studio.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe" -x c -funsigned-char -funsigned-bitfields -DDEBUG -DF_CPU=16000000L -DARDUINO=108013 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR -DUSB_VID=0x2341 -DUSB_PID=0x0010 -DUSB_MANUFACTURER="\"Arduino LLC\"" -I"C:\Program Files\Atmel\Studio.0\Packs\atmel\ATmega_DFP.1.130\include" -I"..\..\ArduinoCore\include\core" -I"..\..\ArduinoCore\include\variants\mega" -Os -fno-threadsafe-statics -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -mrelax -g2 -Wall -mmcu=atmega2560 -B "C:\Program Files\Atmel\Studio.0\Packs\atmel\ATmega_DFP.1.130\gcc\dev\atmega2560" -c -std=gnu99 -std=gnu11 -MD -MP -MF "test.d" -MT"test.d" -MT"test.o" -o "test.o" ".././test.c"
Finished building: .././test.c
cc1.exe(0,0): warning: command line option '-fno-threadsafe-statics' is valid for C++/ObjC++ but not for C
In file included from .././test.c:1:0:
D:\Mirror\Anwendungen\AVRStudio\Arduino\MIDIout\MIDIout\MIDIout\Midi\test.h(5,2): warning: #warning "processing test.h" [-Wcpp]
#warning "processing test.h"
^
.././test.c: In function 'some_test':
D:\Mirror\Anwendungen\AVRStudio\Arduino\MIDIout\MIDIout\MIDIout\Midi\test.c(4,3): warning: #warning "processing test.c" [-Wcpp]
#warning "processing test.c"
^
Building target: Midi.elf
Invoking: AVR8/GNU Linker : 4.9.2
"C:\Program Files\Atmel\Studio.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-g++.exe" -o Midi.elf Sketch.o test.o -Wl,-Map="Midi.map" -Wl,--start-group -Wl,-lm -Wl,-lArduinoCore -Wl,--end-group -Wl,-L"D:\Mirror\Anwendungen\AVRStudio\Arduino\MIDIout\MIDIout\MIDIout\ArduinoCore\Debug" -Wl,--gc-sections -mrelax -mmcu=atmega2560 -B "C:\Program Files\Atmel\Studio.0\Packs\atmel\ATmega_DFP.1.130\gcc\dev\atmega2560" -Os
Sketch.o: In function `setup':
D:\Mirror\Anwendungen\AVRStudio\Arduino\MIDIout\MIDIout\MIDIout\Midi\Sketch.cpp(20,1): error: undefined reference to `some_test()'
collect2.exe(0,0): error: ld returned 1 exit status
make: *** [Midi.elf] Error 1
D:\Mirror\Anwendungen\AVRStudio\Arduino\MIDIout\MIDIout\MIDIout\Midi\Debug\Makefile(123,1): error: recipe for target 'Midi.elf' failed
The command exited with code 2.
Done executing task "RunCompilerTask" -- FAILED.
Done building target "CoreBuild" in project "Midi.cppproj" -- FAILED.
Done building project "Midi.cppproj" -- FAILED.
Build FAILED.
========== Build: 1 succeeded or up-to-date, 1 failed, 0 skipped ==========
Sketch.cpp 编译为 C++,包括 test.h。为了支持函数重载、class 成员资格等,C++ 使用 name mangling 在符号名称中编码这些 C++ 特性。因此,Sketch.cpp 中 some_test
的符号名称与 test.c 中的符号名称不同,后者被编译为 C 且未应用名称混淆。
解决方案是在 header 是 C++ 编译时通过指定符号具有 C 链接来防止此符号的名称混淆:
#ifndef TEST_H
#define TEST_H
#if defined __cplusplus
extern "C"
{
#warning Using C linkage in C++ for test.h
#endif
void some_test(void);
#warning "processing test.h"
#if defined __cplusplus
}
#endif
#endif //TEST_H
extern "C"
声明中的大括号({...}
)表示所有包含在其中的符号声明都具有 C 链接。对于 C/C++ 互操作性,所有 C 代码 header 都应包含此包装器。
当然,另一种解决方案是将 test.c 编译为 C++(最简单的方法是将其重命名为 text.cpp)。请注意,Arduino Sketch 代码和库 是 C++ 代码。通常最好始终坚持 C++ 编译,以允许访问 Arduino 库,该库将具有 C++ 链接,并且需要大量包装代码才能从 C 访问。
毫无帮助的是,构建日志明显地使用 C++ 编译时显示“Invoking: AVR8/GNU C Compiler
”。我认为这只是 Atmel Studio 的事情,不是由编译器本身生成的。