嘗試執行 C 程序時 Makefile 失敗
我在製作 Makefile 文件時有很多任務,我有這些文件:
https://raw.githubusercontent.com/systems-cs-pub-ro/uso/master/tema1/boo.c https://github.com/systems-cs-pub-ro/uso/raw/master/tema1/light.o https://raw.githubusercontent.com/systems-cs-pub-ro/uso/master/tema1/sound.c https://raw.githubusercontent.com/systems-cs-pub-ro/uso/master/tema1/sound.h
而且我必須創建一個 Makefile :“生成一個執行檔,
exec
使用light.o
並在以前sound.o
編譯時創建sound.c
。在接收任何命令時make
,或者make build
它必須生成文件exec
。如果有必要,在 Makefilerun
中添加一個符合整個程序的規則,然後執行它。另外,添加一條clean
刪除您創建的目標文件的規則。還添加一條在編譯後templates
創建中間文件(boo.s
, )的規則“。boo.o``boo.c
這是我的makefile
build: light.o sound.o gcc light.o sound.o -o exec sound.o: sound.c gcc -c sound.c templates: boo.c gcc -c boo.c gcc -S boo.c run: exec ./exec clean: rm -f sound.o boo.o boo.s exec
但它告訴我我沒有創建“正確的”執行檔,我做錯了什麼?我認為我應該
boo.o
在 exec 文件中添加,但是當我嘗試這樣做時,我得到:boo.c multiple definition of main light.o:light.c:first defined here
.
(這聞起來像家庭作業。)
一、報錯資訊:
boo.c multiple definition of main light.o:light.c:first defined here.
它表明您嘗試連結在一起的文件具有名為 的函式的多個副本,
main()
這顯然是不正確的。您正在嘗試重用
light.o
,但只有當它具有除main()
. 讓我們稱之為light()
。您還需要一個.h
文件#include
d in ,以便編譯器無需查看其原始碼即可boo.c
知道函式的屬性(基本上是參數的類型和返回值的類型,如果有的話) 。light()
在我看來,您的文件組合在一起的方式與作業中的預期有些不同。您的教授可能已經創建了一系列關聯在一起的作業:如果您在該系列的先前作業中走捷徑,那麼重用先前程式碼的後續作業將無法正常工作。
你的教授正試圖教你如何安排你的程式碼以便它可以重用,如果你不這樣做會發生什麼。
Makefile 規則的基本形式是:
<name of target>: <names of files the creation process depends on> <command(s) to create the target file>
文件的創建
.c
不僅取決於文件本身,還取決於.h
它包含的文件。通常,您可以假設任何系統包含文件(您包含的那些文件#include <filename>
不會改變您,因此您不需要將它們添加到您的 Makefile 規則中。但是任何.h
屬於您項目的文件也應該包含在內。也可能存在實際上不是文件的“虛擬目標”。他們允許你做類似的事情
make clean
。您還可以將虛擬目標用作另一個目標的依賴項:由於虛擬目標沒有與之關聯的真實文件,因此每次將虛擬目標列為依賴項時都會執行“創建”虛擬目標的命令對於其他東西,並且需要建造其他東西。此外,可能存在其中沒有任何命令的 Makefile 規則,但會列出一個或多個 Makefile 目標作為其依賴項。如果只有一個依賴項,那麼沒有命令的目標將作為作為依賴項列出的目標的另一個名稱。如果它有多個依賴項,那麼無命令目標將成為一種使用單個命令建構多個 Makefile 目標的方法。
在我看來,您的教授打算將
build:
目標變成這樣一個沒有自己命令的目標。它應該只取決於兩個目標:
- 一個單獨的目標來建構實際的執行檔
templates
目標_
light.o
你可能想知道我怎麼不看原始碼就知道它的內容?很簡單 - 我下載了你的light.o
然後使用了這個命令:$ readelf -s light.o Symbol table '.symtab' contains 12 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 FILE LOCAL DEFAULT ABS light.c 2: 00000000 0 SECTION LOCAL DEFAULT 1 3: 00000000 0 SECTION LOCAL DEFAULT 3 4: 00000000 0 SECTION LOCAL DEFAULT 4 5: 00000000 0 SECTION LOCAL DEFAULT 5 6: 00000000 0 SECTION LOCAL DEFAULT 7 7: 00000000 0 SECTION LOCAL DEFAULT 8 8: 00000000 0 SECTION LOCAL DEFAULT 6 9: 00000000 51 FUNC GLOBAL DEFAULT 1 main 10: 00000000 0 NOTYPE GLOBAL DEFAULT UND puts 11: 00000000 0 NOTYPE GLOBAL DEFAULT UND sound
這告訴我
light.o
來自一個名為 的源文件light.c
,定義了一個名為的函式main()
並使用了名為puts()
and的函式sound()
,這裡沒有定義。puts()
來自標準庫,但sound()
需要在與該文件連結在一起的其他文件中定義以生成完整的執行檔。