2017-08-08 6 views
0

特定のプログラミングブックから二重リンクリストプロジェクトをコンパイルしようとしました。このプロジェクトには、テストに役立つライブラリが付いています。ここでC: "未定義参照"およびcollect2:エラー:ldが1終了ステータスを返しました

はテスト

#include "minunit.h" 
#include <lcthw/list.h> 
#include <assert.h> 

static List *list = NULL; 
char *test1 = "test1 data"; 
char *test2 = "test2 data"; 
char *test3 = "test3 data"; 

char *test_create() 
{ 
    list = List_create(); 
    mu_assert(list != NULL, "Failed to create list."); 

    return NULL; 
} 

char *test_destroy() 
{ 
    List_clear_destroy(list); 

    return NULL; 
} 

char *test_push_pop() 
{ 
    List_push(list, test1); 
    mu_assert(List_last(list) == test1, "Wrong last value."); 

    List_push(list, test2); 
    mu_assert(list_last(list) == test2, "Wrong last value"); 

    List_push(list, test3); 
    mu_assert(List_last(list) == test3, "Wrong last value."); 
    mu_assert(List_count(list) == 3, "Wrong count on push."); 

    char *val = List_pop(list); 
    mu_assert(val == test3, "Wrong value on pop."); 

    val = List_pop(list); 
    mu_assert(val == test2, "Wrong value on pop."); 

    val = List_pop(list); 
    mu_assert(val == test1, "Wrong value on pop."); 
    mu_assert(List_count(list) == 0, "Wrong count after pop."); 

    return NULL; 
} 

char *test_unshift() 
{ 
    List_unshift(list, test1); 
    mu_assert(List_first(list) == test1, "Wrong first value."); 

    List_unshift(list, test2); 
    mu_assert(List_first(list) == test2, "Wrong first value."); 

    List_unshift(list, test3); 
    mu_assert(List_first(list) == test3, "Wrong last value."); 
    mu_assert(List_count(list) == 3, "Wrong count on unshift."); 

    return NULL; 
} 

char *test_remove() 
{ 
    // we only need to test the middle remove case since push/shift 
    // already tests the other cases 

    char *val = List_remove(list, list->first->next); 
    mu_assert(val == test2, "Wrong removed element."); 
    mu_assert(List_count(list) == 2, "Wrong count after remove."); 
    mu_assert(List_first(list) == test3, "Wrong first after remove"); 
    mu_assert(List_last(list) == test1, "Wrong last after remove."); 

    return NULL; 
} 

char *test_shift() 
{ 
    mu_assert(List_count(list) != 0, "Wrong count before shift."); 

    char *val = List_shift(list); 
    mu_assert(val == test3, "Wrong value on shift."); 

    val = List_shift(list); 
    mu_assert(val == test1, "Wrong value on shift."); 
    mu_assert(List_count(list) == 0, "Wrong count after shift."); 

    return NULL; 
} 

char *all_tests() 
{ 
    mu_suite_start(); 

    mu_run_test(test_create); 
    mu_run_test(test_push_pop); 
    mu_run_test(test_unshift); 
    mu_run_test(test_remove); 
    mu_run_test(test_shift); 
    mu_run_test(test_destroy); 

    return NULL; 
} 

RUN_TESTS(all_tests); 

ある。また、これは私がプロジェクト全体をコンパイルするために使用されたMakefileです:

CFLAGS=-g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG $(OPTFLAGS) 
#LDLIBS=-ldl $(OPTLIBS) 
PREFIX?=/usr/local 

SOURCES=$(wildcard src/**/*.c src/*.c) 
OBJECTS=$(patsubst %.c,%.o,$(SOURCES)) 

TEST_SRC=$(wildcard tests/*_tests.c) 
TESTS=$(patsubst %.c,%,$(TEST_SRC)) 

TARGET=build/liblcthw.a 
SO_TARGET=$(patsubst %.a,%.so,$(TARGET)) 

# The Target Build 
all: $(TARGET) $(SO_TARGET) tests 

dev: CFLAGS=-g -Wall -Isrc -Wall -Wextra $(OPTFLAGS) 
dev: all 

$(TARGET): CFLAGS += -fPIC 
$(TARGET): build $(OBJECTS) 
    ar rcs [email protected] $(OBJECTS) 
    ranlib [email protected] 
$(SO_TARGET): $(TARGET) $(OBJECTS) 
    $(CC) -shared -o [email protected] $(OBJECTS) 

build: 
    @mkdir -p build 
    @mkdir -p bin 

# The Unit Tests 
.PHONY: tests 
tests: CFLAGS += $(TARGET) 
tests: $(TESTS) 
    sh ./tests/runtests.sh 

# The Cleaner 
clean: 
    rm -rf build $(OBJECTS) $(TESTS) 
    rm -f tests/tests.log 
    find . -name ".gc*" -exec rm {} \; 
    rm -rf `find . -name ".dSYM" -print` 

#The Install 
install: all 
    install -d $(DESTDIR)/$(PREFIX)/lib/ 
    install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/ 

#The Checker 
check: 
    @echo Files with potentially dangerous function. 
    @egrep '[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)\ 
       |stpn?cpy|a?sn?printf|byte_)' $(SOURCES) || true 

私はmakeを実行すると、私はこの取得:

cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG -fPIC -c -o src/lcthw/list.o src/lcthw/list.c 
ar rcs build/liblcthw.a src/lcthw/list.o 
ranlib build/liblcthw.a 
cc -shared -o build/liblcthw.so src/lcthw/list.o 
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG build/liblcthw.a tests/list_tests.c -o tests/list_tests 
In file included from tests/list_tests.c:1:0: 
tests/list_tests.c: In function ‘main’: 
tests/minunit.h:16:38: warning: parameter ‘argc’ set but not used [-Wunused-but-set-parameter] 
#define RUN_TESTS(name) int main(int argc, char *argv[]) {\ 
            ^
tests/list_tests.c:107:1: note: in expansion of macro ‘RUN_TESTS’ 
RUN_TESTS(all_tests); 
^ 
/tmp/ccFfwxRB.o: In function `test_create': 
/home/pxcel/liblcthw/tests/list_tests.c:12: undefined reference to `List_create' 
/tmp/ccFfwxRB.o: In function `test_destroy': 
/home/pxcel/liblcthw/tests/list_tests.c:20: undefined reference to `List_clear_destroy' 
/tmp/ccFfwxRB.o: In function `test_push_pop': 
/home/pxcel/liblcthw/tests/list_tests.c:27: undefined reference to `List_push' 
/home/pxcel/liblcthw/tests/list_tests.c:30: undefined reference to `List_push' 
/home/pxcel/liblcthw/tests/list_tests.c:33: undefined reference to `List_push' 
/home/pxcel/liblcthw/tests/list_tests.c:37: undefined reference to `List_pop' 
/home/pxcel/liblcthw/tests/list_tests.c:40: undefined reference to `List_pop' 
/home/pxcel/liblcthw/tests/list_tests.c:43: undefined reference to `List_pop' 
/tmp/ccFfwxRB.o: In function `test_unshift': 
/home/pxcel/liblcthw/tests/list_tests.c:52: undefined reference to `List_unshift' 
/home/pxcel/liblcthw/tests/list_tests.c:55: undefined reference to `List_unshift' 
/home/pxcel/liblcthw/tests/list_tests.c:58: undefined reference to `List_unshift' 
/tmp/ccFfwxRB.o: In function `test_remove': 
/home/pxcel/liblcthw/tests/list_tests.c:70: undefined reference to `List_remove' 
/tmp/ccFfwxRB.o: In function `test_shift': 
/home/pxcel/liblcthw/tests/list_tests.c:83: undefined reference to `List_shift' 
/home/pxcel/liblcthw/tests/list_tests.c:86: undefined reference to `List_shift' 
/tmp/ccFfwxRB.o: In function `test_destroy': 
/home/pxcel/liblcthw/tests/list_tests.c:20: undefined reference to `List_clear_destroy' 
collect2: error: ld returned 1 exit status 
<builtin>: recipe for target 'tests/list_tests' failed 
make: *** [tests/list_tests] Error 1 

を私が得たエラーをGoogleで検出したところ、私がこれまでに得た答えは、タイプミスがあるかどうかを確認することを提案しています。ファイルを正しくリンクします。後者の場合は可能でしょうか?

+2

'undefined reference'はリンカーエラーですので、コードに構文上問題はありません – yano

+4

ほとんどの場合、問題を見つけるために無関係なすべての解析が行われません。可能な限りこれを減らそうとしましたか(最小限の例)? – Treeston

+1

@Treestonそれは良いアドバイスです。有用な参考文献を追加してみてください。あなたのコメントに '[mcve]'を加えて、あなたに[mcve]を与えます。 – Yunnosch

答えて

2

あなたが持っている:

cc … build/liblcthw.a tests/list_tests.c -o tests/list_tests 

あなたはライブラリをリストする必要があります - (ソースまたは)オブジェクトファイルの後に - .a接尾辞特に静的ライブラリ:

cc … tests/list_tests.c build/liblcthw.a -o tests/list_tests 

はい、ライブラリの順序をファイルオプションは本当に重要です! (一部のシステムでは、オブジェクトファイルの前に共有ライブラリのリストを表示することがあります)すべてシステムライブラリの後にオブジェクトファイル常にが動作します。たとえば、-o tests/list_testsオプションは問題なくコマンドラインの前に表示されます。しかし、ライブラリ(-l…オプション、およびこの例のようなライブラリへの簡単な参照)は、オブジェクトファイルの後にコマンドラインで表示する必要があります。リンクする前にオブジェクトファイルにソースをコンパイルしない場合は、ソースファイルです。

+0

これは私の問題を解決しました。 'makefile'の修正は' tests:CFLAGS + = $(TARGET) 'の' CFLAGS'を 'LDLIBS'で変更するだけでした – Pxcel

関連する問題