extern을 언제 사용해야 하는지, 그리고 어쩔 때 빼도 되는지 잘 모르겠습니다.


이 코드를 컴파일해보려고 하는데, 자꾸 해당 오류가 뜹니다.

[GCC]     : Compiling C file "MIDIWidget.c"
avr-gcc -c -pipe -gdwarf-2 -g2 -mmcu=atmega32u2 -fshort-enums -fno-inline-small-functions -fpack-struct -Wall -fno-strict-aliasing -funsigned-char -funsigned-bitfields -ffunction-sections -I. -DARCH=ARCH_AVR8 -DF_CPU=16000000UL -mrelax -fno-jump-tables -x c -Os -std=gnu99 -Wstrict-prototypes -DUSE_LUFA_CONFIG_HEADER -IConfig/  -I. -I../../LUFA/.. -DARCH=ARCH_AVR8 -DBOARD=BOARD_NONE -DF_USB=16000000UL  -MMD -MP -MF obj/MIDIWidget.d MIDIWidget.c -o obj/MIDIWidget.o
MIDIWidget.c:25: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'LATCH'
MIDIWidget.c:26: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'LATCH0_INV'
MIDIWidget.c:27: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'LATCH1_INV'
MIDIWidget.c:28: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'LATCH2_INV'
MIDIWidget.c:29: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'BLINK_COUNTER'
MIDIWidget.c: In function 'main':
MIDIWidget.c:36: warning: implicit declaration of function 'LatchInit'
MIDIWidget.c:37: warning: implicit declaration of function 'PortInit'
MIDIWidget.c:38: warning: implicit declaration of function 'WriteLatches'
MIDIWidget.c:39: warning: implicit declaration of function 'OutputEnable'
MIDIWidget.c:41: warning: implicit declaration of function 'STBYOn'
MIDIWidget.c:42: warning: implicit declaration of function 'ACTOn'
MIDIWidget.c:44: warning: implicit declaration of function 'USARTInit'
MIDIWidget.c:45: warning: implicit declaration of function 'Timer0Init'
MIDIWidget.c:46: warning: implicit declaration of function 'SetupUSB'
MIDIWidget.c:48: warning: implicit declaration of function 'GlobalVariableInit'
MIDIWidget.c:49: warning: implicit declaration of function 'ConfigVariableInit'
MIDIWidget.c:51: warning: implicit declaration of function 'GlobalInterruptEnable'
MIDIWidget.c:55: error: 'MIDI_EventPacket_t' undeclared (first use in this function)
MIDIWidget.c:55: error: (Each undeclared identifier is reported only once
MIDIWidget.c:55: error: for each function it appears in.)
MIDIWidget.c:55: error: expected ';' before 'ReceivedMIDIEvent'
MIDIWidget.c:56: warning: implicit declaration of function 'MIDI_Device_ReceiveEventPacket'
MIDIWidget.c:56: error: 'Keyboard_MIDI_Interface' undeclared (first use in this function)
MIDIWidget.c:56: error: 'ReceivedMIDIEvent' undeclared (first use in this function)
MIDIWidget.c:61: warning: implicit declaration of function 'ProcessNoteOff'
MIDIWidget.c:62: error: 'OPERATION_FLAGS' undeclared (first use in this function)
MIDIWidget.c:62: error: 'DISABLE_USB_MIDI_THRU_FLAG' undeclared (first use in this function)
MIDIWidget.c:64: warning: implicit declaration of function 'QueueMIDIEvent'
MIDIWidget.c:68: warning: implicit declaration of function 'ProcessNoteOn'
MIDIWidget.c:77: warning: implicit declaration of function 'ProcessConfigController'
MIDIWidget.c:79: warning: implicit declaration of function 'ProcessController'
MIDIWidget.c:80: error: 'CONFIG_MODE_FLAG' undeclared (first use in this function)
MIDIWidget.c:86: warning: implicit declaration of function 'ProcessProgramChange'
MIDIWidget.c:93: warning: implicit declaration of function 'ProcessPitchWheel'
MIDIWidget.c:100: warning: implicit declaration of function 'ProcessAftertouch'
MIDIWidget.c:107: warning: implicit declaration of function 'ProcessChannelPressure'
MIDIWidget.c:114: warning: implicit declaration of function 'ParseMIDIByte'
MIDIWidget.c:114: error: 'STREAM_USB_MIDI' undeclared (first use in this function)
MIDIWidget.c:120: warning: implicit declaration of function 'MIDI_Device_USBTask'
MIDIWidget.c:121: warning: implicit declaration of function 'USB_USBTask'
MIDIWidget.c:122: warning: implicit declaration of function 'ProcessSerialMIDI'
MIDIWidget.c:125: error: 'SWITCH_DEBOUNCE_COUNTER' undeclared (first use in this function)
MIDIWidget.c:128: warning: implicit declaration of function 'ReadSwitches'
make: *** [obj/MIDIWidget.o] Error 1
error: 'SWITCH_DEBOUNCE_COUNTER' undeclared (first use in this function)

이 오류가 선언이 안되어 있는 변수를 사용할 때 생기는 오류라고 하는데, 해당 변수는 MIDIWidget.h에 선언되어 있습니다. header를 include 했는데도 왜 알지 못하는 건지 모르겠습니다.

그리고 extern은 그냥 다른 파일에서 해당 변수를 사용하고 있다고 알려주는 것으로 알고 있는데, 해당 header를 include 한 c 파일들 중 변수가 선언된 파일의 변수만을 다른 파일들에서 사용하는건가요?

안녕하세요.

extern은 외부에 변수가 있다고 컴파일러에게 알려주는겁니다.

예를들어 변수 a가 a.c에 전역변수로 있는데 b.c에서 사용한다고 합시다.
컴파일러는 b.c를 컴파일할때 a라는 변수가 뭔지 몰라서 오류가 나오겠죠??

따라서 컴파일러에게 이 a변수는 외부에 있는 변수이니 일단 컴파일을 하고 링킹단계에서 찾으라고 하는겁니다.

만약 링킹 단계에서 못찾으면?? 링커 에러가 발생하겠죠?

3 Likes

extern 설명은 @Lukas_J_Han 님이 잘 해주신 것 같고…

build를 어떻게 하셨는지 모르겠네요.

Repository commit log를 보니까 2015 June에 주요 작업이 끝났네요.
readme에는 LUFA에 넣고 make 하라고 guide 되어있네요.
LUFA Library document를 보니까 해당 시간 기준의 가장 최신 official document가 140928입니다.
http://www.fourwalledcubicle.com/files/LUFA/Doc/140928/html/

아래에서 해당 버전을 ubuntu 18.04에 다운 받았습니다.
http://www.fourwalledcubicle.com/files/LUFA/

binutils, gcc-avr, avr-libc, avrdude

대충 avr build 하려면 필요 할거 같은 package들을 apt-get으로 install 하였습니다.


build가 되었습니다.

관리가 안되는 project 같은데, 대체재가 없는 게 아니라면 안 쓰시는 것이 좋아 보이네요.

2 Likes

저는 winAVR을 이용해서 컴파일을 진행하였습니다. 에디터는 vscode를 사용하였고, LUFA 버전은 17년도를 사용하였구요. vscode에서 그냥 windows terminal을 사용하여 make를 실행했습니다.
그런데 제 생각에 LUFA 버전이 문제인것 같지는 않은것 같아요.
항상 환경 설정이 문제네요, 남의 코드를 사용할때는…
소스 코드도 어렵지 않은 코드인데…

이유를 알것 같습니다 헤더 파일을 컴파일러가 찾지 못하네요 왜인지는 모르겠지만…
팬져님이 구성하신 환경 그대로 작업해보니 uint8_t type 을 못찾고 헤더에 정의되어 있는 것들 전혀 못찾고 있네요…

이유 알았습니다…vscode에서 intellisense때문에 임의로 코드 상에

#ifndef __AVR_ATmega32U2__
#define __AVR_ATmega32U2__

를 추가해서 그런거였습니다…
코드를 변경하지 않고 intellisense 상에서 인식시키려면 properties 상에서 defines에 넣어주어야 하는거더라구요
이렇게 코드 수정 없이 컴파일을 해보았는데 여전히 안되었습니다

이유를 알아보니 winAVR 버전이 낮아서, 혹은 호환이 안되어서 없는 기능이 있어 그런것 같았습니다
팬져님이 작업하신 구성으로 컴파일 해보니 잘되네요

도와주셔서 감사합니다 !!

1 Like

음 해결되셨다니 좋습니다만 ㅎㅎ

이 project의 경우 LUFA 버전 문제는 존재해요.
최신 LUFA가지고 빌드하면 type conflicting이 CALLBACK_USB_GetDescriptor에 대해서 발생합니다.
backward compatibility를 잘 해 주는 framework가 많지 않아요.
이런건 보통 관리 되고 있는 project에서는 maintainer가 dependency의 official release를 따라가면서 맞춰주는데요. 죽은 project에서는 이런 것을 기대하기 힘들죠.

그리고 error report 할 때는 reproducing step을 다른 사람이 따라 할 수 있는 수준으로 적는 습관을 기르시는게 좋아요. 그렇게 하시면 추가적인 communication cost가 발생하지도 않고 문제가 해결 될 확률도 올라갈 겁니다.

1 Like

네 지금 생각해보면 이상하긴 한데 제가 작업하면서도 제가 뭘 했는지 잘 기억이 안날 때가 많네요… 깃 이런거 써야 할까봐요

1 Like