2017-08-08 111 views
0

我無法編譯某個編程手冊中的雙鏈表項目。該項目由一些幫助進行測試的圖書館陪同。C:「undefined reference to」和collect2:error: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 

當我運行使我得到這個:

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 

我搜索了我收到的錯誤,並且迄今爲止得到的答案都建議檢查我是否有錯別字或者如果我沒有正確鏈接文件。後者會是這樣嗎?

+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

相關問題