gcc로 링크 중 에러 : undefined reference to `xxx

young93의 이미지

다른 OS에서 다른 컴파일러로 만들었던 프로그램을 리눅스로 포팅중입니다.
프로그램은 여러 블럭으로 이루어져 있고
각 블럭을 컴파일하면 라이브러리 파일을 생성합니다.
마지막에 그 라이브러리를 링크하여 실행파일을 만들죠.

컴파일까지는 잘되는데 링크를 하면
undefined reference to `xxx' (xxx는 함수명 또는 전역변수명)
라는 에러가 수십개씩 나오네요.

분명히 다른 블럭의 라이브러리(*.a)에 있는 함수인데, 없다고 그럽니다.
라이브러리를 만들지 않고 그냥 오브젝트 파일(*.o)을 링크하면 잘 됩니다.

이 홈페이지의
http://kldp.org/Translations/html/LinkerLoader-KLDP/linkingwithstaticlibraries.html
의 내용이 관련된 것 같긴한데... 잘 모르겠네요.

혹시 이런 경험하신 분 안계신가요?
답변 부탁드립니다.

송지석의 이미지

메이크파일 내용을 보여주셔야 되지 않을까 합니다만..

물론 쉬운 문제 때문에 질문하신 것은 아니실테지만..

일단 ar로 묶으신 뒤

Quote:
$(AR) cr libmylib.a $(MYOBJS)

cc로 컴팔 하실 때
Quote:
$(CC) -o my_prog $(SOURCES) $(OBJS) -L$(MY_LIB_PATH) -lmylib

로 컴파일 하시면 별 문제 없으실 것 같은데..
메이크 파일을 보여주세요
ageldama의 이미지

답변 달렸지만 감히 더 달아봅니다.

혹시 ranlib을 잊으신건 아닌가요?

Quote:
man ranlib

----
The future is here. It's just not widely distributed yet.
- William Gibson

young93의 이미지

질문한 사람입니다.

각 모듈의 makefile은 다음과 같습니다.
(파일명, 모듈명은 공개하기가 뭐해서 변경했습니다....)

include ../config.mk

LIB     = libmod1.a
OBJS    = file1.o file2.o file3.o

INCLUDES += -I. -I../include
CFLAGS = -fsigned-char $(INCLUDES)

LIBNAME = ../$(LIBDIR)/$(LIB)

%.o:    %.c
    $(CC) $(CFLAGS) -c $< -o $@

all:    $(LIBNAME)

$(LIBNAME): $(OBJS)
    $(RM) -f $@
    $(AR) crv $@ $(OBJS)
    $(RANLIB) $@

clean:
    @echo Clean $(OBJS)
    @$(RM) -f `find . -name '*.o' `
    @$(RM) -f `find . -name '*.lib' `
    @$(RM) -f $(LIBNAME)

.depend:    makefile $(OBJS:.o=.c)
    $(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@

sinclude .depend

위와 같은 makefile로 libmod1.a libmod2.a libmod3.a 를 만들구요..
프로젝트의 root디렉토리에서는 다음과 같은makefile로 링크를 합니다.

include config.mk

MAKEFILE = makefile

FLDIRS = mod1 mod2 mod3 
SUBDIRS = $(FLDIRS)

FLLIBS = $(foreach file, $(FLDIRS), $(LIBDIR)/lib$(file).a)
OSLIBS = -lpthread

all: subdirs project

project: makefile $(FLLIBS)
    $(CC) -o $@ $(OSLIBS) $(FLLIBS)
    cp $@ ../../

subdirs:
    @for dirs in $(SUBDIRS); do \
        cd $${dirs}; \
        if test -f $(MAKEFILE); then \
            $(MAKE) all; \
        fi; \
        cd ..;  \
    done

clean:
    @for dirs in $(SUBDIRS); do \
        cd $${dirs}; \
        if test -f $(MAKEFILE); then \
            $(MAKE) clean; \
        fi; \
        cd ..; \
    done
    $(RM) project; \

이런 식으로 했지요.
main() 함수는 libmod1.a 에 있습니다.

관심가져 주셔서 감사합니다.

송지석의 이미지

앗 메이크 파일이 생각보다 복잡하군요. (전 Makefile에 변수 잘 안쓰고 autotools도 잘 못쓴다는... -- 손으로 다 쳐서 해결하지요..)

일단

project: makefile $(FLLIBS) 
    $(CC) -o $@ $(OSLIBS) $(FLLIBS) 
    cp $@ ../../ 

이걸로 보아선 지금은 오브젝트로 바로 링크하시는 것 같은데 맞나요?

FLLIBS = $(foreach file, $(FLDIRS), $(LIBDIR)/lib$(file).a)

이부분은 잘 모르겠지만 일단 사용하신 $(LIBDIR)이 file_lib이라고 가정하고 만드신 라이브러리가 libmod1.a libmod2.a libmod3.a 이라 하면

project: makefile $(FLLIBS) 
    $(CC) -o $@ $(OSLIBS) -L$(LIBDIR) -lmod1 -lmod2 -lmod3
    cp $@ ../../ 

이렇게 하시면 될 것 같은데요... 요는 -L$(LIBDIR) 이걸 해줘야 되지 않느냐 입니다.
이 문제가 맞을런지, 도움이 되길 바랍니다.
ihavnoid의 이미지

송지석 wrote:
이렇게 하시면 될 것 같은데요... 요는 -L$(LIBDIR) 이걸 해줘야 되지 않느냐 입니다.
이 문제가 맞을런지, 도움이 되길 바랍니다.

.a 파일을 같이 link할 때, -l(라이브러리) 뿐만 아니라, 직접 lib(어쩌구저쩌구).a 라는 형태로도 링크가 가능합니다. 굳이 -L(path) -l(라이브러리) 식으로 할 필요가 없는 것입니다...

즉,

gcc -o execfile obj1.o obj2.o obj3.o firstlib.a secondlib.a

이런식 역시 가능하다는 것이죠... 이분께서도 이 방식을 이용하신 듯 싶습니다.

혹시 이런 문제가 아닐까 싶어서 말씀드리는데요...
예전에 arm-gcc로 프로젝트를 할 때, 저 역시 멀쩡히 있는 함수들에서 undefined symbol이 대량으로 떠서 황당했던 경우가 있었습니다... sprintf 등의 루틴에서 floating-point 연산과 math를 못찾더군요.. 분명 같이 link해줬는데....

어이없게도 link할때 적어넣는 순서를 바꿔서 해결되었습니다...
지금도 테스트를 해서 라이브러리를 맨앞으로 집어넣어 보니, 멀쩡히 link되던것이 또 안되는군요... 몽땅 object으로 할때는 문제가 없다가, library를 도입하니 문제가 생기더군요....

linux kernel의 경우에는, 이들 object들을 하나의 큰 object로 뭉쳐서(.a파일이 아니라 .o파일로 묶어서) 한꺼번에 link를 하더군요... 이 방식을 이용하는 것도 하나의 방법이 될 듯 합니다.. 구체적으로 어떤 옵션을 줬는지는 linux kernel의 컴파일과정을 잘 지켜보시면 될 듯 합니다...

제가 쓰던 gcc의 설정입니다... cygwin에서 cross-complie해서 썼죠..

Administrator@IHAVNOID ~/arm7/exp_project/exp_project_complete] arm-elf-gcc -v
Reading specs from /tools/H-i686-pc-cygwin/lib/gcc-lib/arm-elf/3.1.1/specs
Configured with: /home/Administrator/gcc-3.1.1/configure --target=arm-elf --prefix=/tools --exec-prefix=/tools/H-i686-pc-cygwin --with-gnu-as --with-gnu-ld --with-newlib -v
Thread model: single
gcc version 3.1.1

Consider the ravens: for they neither sow nor reap; which neither have storehouse nor barn; and God feedeth them: how much more are ye better than the fowls?
Luke 12:24

young93의 이미지

질문한 사람입니다.

Quote:

혹시 이런 문제가 아닐까 싶어서 말씀드리는데요...
예전에 arm-gcc로 프로젝트를 할 때, 저 역시 멀쩡히 있는 함수들에서 undefined symbol이 대량으로 떠서 황당했던 경우가 있었습니다... sprintf 등의 루틴에서 floating-point 연산과 math를 못찾더군요.. 분명 같이 link해줬는데....

어이없게도 link할때 적어넣는 순서를 바꿔서 해결되었습니다...
지금도 테스트를 해서 라이브러리를 맨앞으로 집어넣어 보니, 멀쩡히 link되던것이 또 안되는군요... 몽땅 object으로 할때는 문제가 없다가, library를 도입하니 문제가 생기더군요....

말씀하신대로 님과 같은 문제입니다.
정확한 이유는 모르겠지만 링크할 때 심볼을 찾는 과정에서
순서를 맞추어야 하는 것이 있는 것 같습니다.
며칠 고심하다 해결책을 찾았습니다.

이런 식으로 하면 되더군요.

gcc -o exefile -Xlinker --start-group libmod1.a libmod2.a libmod3.a -Xlinker --end-group

-Xlinker는 뒤에 옵션을 링커(ld)에 넘기라는 옵션입니다.
링커옵션인 --start-group 와 --end-group는
이런 역할을 한답니다.
"The specified archives are searched repeatedly until
no new undefined references are created."

관심 가지고 답변올려주신 분들께 감사드립니다.

송지석의 이미지

순서 문제였다니 그렇군요.

저도 나중에 같은 현상이 나면 참고할 수 있겠습니다. 감사 :-)

그리고 위의 답변하신 분의 글에 딴지 거는 것은 아닌데요. libmod1.a를 링크하는 것이 -lmod1 하는 것과 같이 된다는 것은 알고 있었습니다. 다만 라이브러리를 사용하실 때 오류가 나고 그냥 링크걸면 된다고 하셔서 보여주신 메이크파일이 링크가 잘 되는 것으로 이해한 것이지요. 그래서 라이브러리(-lmod1)로 썼을 때 되게 하기 위한 답변을 쓴 것입니다. 보여주신 libmod1.a을 링크하는 부분이 링크가 제대로 되지 않는 것을 몰랐네요.

unipro의 이미지

저 역시 비슷한 문제가 있었는데 해결이 되었네요.
순서 문제였군요. ^^

내 블로그: http://unipro.tistory.com

merit326의 이미지

저도 순서를 변경하니 문제가 해결되었네요. 감사드립니다. 1시간 째 고민했어요.

ikpil의 이미지

순서 바꾸니까 잘 되네요. 전 2시간 째 고민했답니다. ... 험난한 경험입니다.

pchero의 이미지

같은 현상이 있었습니다.

현상 해결은 오브젝트 파일을 먼저 만든 후에, 생성된 오브젝트 파일과 라이브러리를 같이 묶음으로써 해결되었습니다.

즉,
(1) 오브젝트 파일 생성
(2) 링크

의 두 작업을 따로따로 해주었습니다.

---------------------------------
제일 왼쪽이 저입니다 :)

poplinux의 이미지

LDFLAGS 관련 내용은 제일 오른쪽에 붙이지 않으면 Xlinker 로 묶어 주어야 합니다.

========================
조직 : E.L.D(Embedded Linux Developer/Designer)
블로그 : poplinux@tistory.com
카페 : cafe.naver.com/poplinux

임베디드 리눅스 관련 프리렌서 지향

christ17의 이미지

Makefile 를 만들어서 사용하는 경우 어디의 순서를 바꾸어 주어야 할까요?

익명 사용자의 이미지

감사합니다.

장주영의 이미지

LINKER = -Xlinker

$(TARGET): $(OBJS)
$(CC) -o $(TARGET) $(LINKER) $(OBJS) $(LIB)

이런식으로 하시면 됩니다.

ysy05의 이미지

구글에서 검색하다 발견 했는데, 무려 18년전 글이네요.
감사합니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.