Make

Makefile未連結所需的依賴項

  • October 19, 2019

首先成功製作了兩個目標執行檔:

$ rm build/* bin/*
$ make
g++ -Wall -g -c -o build/Person.o src/Person.cpp
g++ -Wall -g -c -o build/PersonTests.o test/PersonTests.cpp
g++ -Wall -g -o bin/TestPerson build/Person.o build/PersonTests.o
g++ -Wall -g -c -o build/State.o src/State.cpp
g++ -Wall -g -c -o build/StateTests.o test/StateTests.cpp
g++ -Wall -g -o bin/TestState build/State.o build/StateTests.o

但是,當我編輯 PersonTests.cpp(包含 main 函式)時,它無法辨識我嘗試測試的類的成員:

$ touch test/PersonTests.cpp
$ make
g++ -Wall -g -c -o build/PersonTests.o test/PersonTests.cpp
g++ -Wall -g -o bin/TestPerson build/PersonTests.o
build/PersonTests.o: In function `main':
Bridge/test/PersonTests.cpp:14: undefined reference to `Person::Cross(Person&, Person&)'
Bridge/test/PersonTests.cpp:15: undefined reference to `Person::CrossBack(Person&)'
Bridge/test/PersonTests.cpp:17: undefined reference to `operator<<(std::ostream&, Person const&)'
Bridge/test/PersonTests.cpp:17: undefined reference to `operator<<(std::ostream&, Person const&)'
Bridge/test/PersonTests.cpp:17: undefined reference to `operator<<(std::ostream&, Person const&)'
Bridge/test/PersonTests.cpp:19: undefined reference to `Person::Cross(Person&, Person&)'
Bridge/test/PersonTests.cpp:20: undefined reference to `Person::CrossBack(Person&)'
collect2: error: ld returned 1 exit status
Makefile:10: recipe for target 'bin/TestPerson' failed
make: *** [bin/TestPerson] Error 1

然後再次使用 make 有效嗎?顯示:

$ make
g++ -Wall -g -o bin/TestPerson build/Person.o build/PersonTests.o

我是使用 make 的新手,並假設我的問題是由於我的 Makefile:

CXX = g++
CXXFLAGS = -Wall -g

#------EXECUTABLES------
all : bin/TestPerson bin/TestState #bin/BridgeSolution

bin/BridgeSolution : build/main.o   build/Person.o build/State.o
       $(CXX) $(CXXFLAGS) -o $@ $?
bin/TestPerson     : build/Person.o build/PersonTests.o
       $(CXX) $(CXXFLAGS) -o $@ $?
bin/TestState      : build/State.o  build/StateTests.o
       $(CXX) $(CXXFLAGS) -o $@ $?
#-----------------------

#-----TEST_OBJECTS------
build/PersonTests.o : test/PersonTests.cpp build/Person.o include/Person.h
       $(CXX) $(CXXFLAGS) -c -o $@ $<
build/StateTests.o  : test/StateTests.cpp  build/State.o include/State.h
       $(CXX) $(CXXFLAGS) -c -o $@ $<
#-----------------------

#--------OBJECTS--------
build/main.o   : src/main.cpp   include/State.h
       $(CXX) $(CXXFLAGS) -c -o $@ $<
build/Person.o : src/Person.cpp include/Person.h
       $(CXX) $(CXXFLAGS) -c -o $@ $<
build/State.o  : src/State.cpp  include/State.h include/Person.h
       $(CXX) $(CXXFLAGS) -c -o $@ $<
#-----------------------

我了解問題與輸出行的差異有關:

g++ -Wall -g -o bin/TestPerson build/Person.o build/PersonTests.o
g++ -Wall -g -o bin/TestPerson build/PersonTests.o

但我不知道為什麼會這樣

在 Makefile 的這一部分:

bin/BridgeSolution : build/main.o   build/Person.o build/State.o
       $(CXX) $(CXXFLAGS) -o $@ $?
bin/TestPerson     : build/Person.o build/PersonTests.o
       $(CXX) $(CXXFLAGS) -o $@ $?
bin/TestState      : build/State.o  build/StateTests.o
       $(CXX) $(CXXFLAGS) -o $@ $?

你需要使用$^,而不是$?$?表示比目標更新的先決條件子集;因此,當您在建構後進行編輯時,進行重新PersonTests.cpp建構,這是唯一比 更新的先決條件,因此變為.TestPerson``PersonTests.o``TestPerson``TestPerson``$?``TestPerson.o

如果你寫

       $(CXX) $(CXXFLAGS) -o $@ $^

取而代之的是,配方將一直擴展為包括所有先決條件。

引用自:https://unix.stackexchange.com/questions/547620