2017-04-06 61 views
0

我正在開發一個包含兩個程序,一個服務器和一個客戶端的C項目。
我的項目結構:Makefile:通配符,用於具有不同源文件的兩個程序

. 
+--/bin 
| +--/client 
| +--/server 
| 
+--/lib 
| +--header1.h 
| +--header2.h 
| +--header3.h 
| 
+--/obj 
| +--/client 
| +--/server 
| 
+--/src 
| +--/client 
| | +--files.c 
| +--/server 
|  +--otherfiles.c 
| 
+--Makefile 

現在我被困在Makefile文件,我的兩個節目需要不同的,有些重疊頭。我試圖尋找其他項目/存儲庫,但這並沒有幫助我。
這是我目前得到:

SOURCES_CLIENT = ${wildcard src/client/files.c} 
SOURCES_SERVER = ${wildcard src/client/otherfiles.c} 

HEADERS_CLIENT = ${wildcard lib/header1.h lib/header2.h} 
HEADERS_SERVER = ${wildcard lib/header2.h lib/header3.h} 

OBJ_CLIENT = ${SOURCES_CLIENT:.c=.o} 
OBJ_SERVER = ${SOURCES_SERVER:.c=.o} 

CC = gcc 
CFLAGS = #not relevant 

all: client server 

client: ${OBJ_CLIENT} 
    ${CC} -o [email protected] $^ 

server: ${OBJ_SERVER} 
    ${CC} -o [email protected] $^ 

我將如何創建一個使用相應的頭文件通配符規則轉換我的源文件編譯成目標文件(在正確的bin /目錄)?另外我的Makefile似乎是可優化的,如果是的話,怎麼樣?

+0

只是爲了澄清,你問的是如何在Makefile中生成規則來說明(例如)foo.c依賴於foo.h? –

+0

你似乎在明確命名想要的文件,這很好。然而,在那種情況下,'wildcard'函數(這是btw,GNU特有的)對你沒有任何幫助。 –

+0

@ChrisTurner我正在尋找一個將'/ src/client/foo.c'編譯爲'/ lib/client/foo.o'的規則,同時依賴於相應的頭文件'$ {HEADERS_CLIENT}'。編輯:規則應該是動態的,所以也適用於服務器。 – Zonko

回答

0

我想你的基礎變量的定義必須實際看上去更像是這樣的:

SOURCES_CLIENT = ${wildcard src/client/*.c} 
SOURCES_SERVER = ${wildcard src/server/*.c} 

HEADERS_CLIENT = ${wildcard lib/client*.h} 
HEADERS_SERVER = ${wildcard lib/server*.h} 

一個你需要的最重要的東西瞭解make是它知道關於構建工具,目錄或文件的什麼都沒有。它只是操縱字符串,並選擇與其一起工作的字符串的子集,並將其作爲shell命令發佈,其時序和順序由規則集對其進行表達。

其中的含義是,如果你想建立一個給定的目標,那麼你必須編寫一個規則正好那個目標。特別是,當您從項目的根目錄下運行make,想要的二進制文件(在你的方案)是clientserver,他們是bin/clientbin/server。類似地,對應於src/client/files.c的想要的目標文件不是files.osrc/client/files.o而是obj/client/files.o

瞭解了之後,下一步的業務就是正確定義目標文件列表。你似乎已經深深地致力於GNU make,這使得事情變得更容易(在可移植性方面需要花費一些代價)。相反,對於OBJ_CLIENTOBJ_SERVER當前的定義,比您需要的提供對象文件在不同的位置,用的東西(GNU專用)這樣的取代的參考會工作:

OBJ_CLIENT = $(SOURCES_CLIENT:src/client/%.c=obj/client/%.o) 
OBJ_SERVER = $(SOURCES_SERVER:src/server/%.c=obj/server/%.o) 

已經這樣做了,但是,您需要編寫明確的規則來構建目標文件; make的默認規則不處理所需的交叉目錄對應。您可以爲此使用GNU模式規則。這也是在那裏你會介紹關於標題的依賴關係:

obj/client/%.o: src/client/%.c $(HEADERS_CLIENT) 
    $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o [email protected] 

再考慮到這個事實,你必須提供創建規則命名你實際上要建立的目標,你可以把所有在一起:

SOURCES_CLIENT = $(wildcard src/client/*.c) 
SOURCES_SERVER = $(wildcard src/server/*.c) 

HEADERS_CLIENT = $(wildcard lib/client*.h) 
HEADERS_SERVER = $(wildcard lib/server*.h) 

OBJ_CLIENT = $(SOURCES_CLIENT:src/client/%.c=obj/client/%.o) 
OBJ_SERVER = $(SOURCES_SERVER:src/server/%.c=obj/server/%.o) 

CC = gcc 
CFLAGS = #not relevant 

all: bin/client bin/server 

bin/client: $(OBJ_CLIENT) 
    $(CC) $(CFLAGS) -o [email protected] $^ 

bin/server: $(OBJ_SERVER) 
    $(CC) $(CFLAGS) -o [email protected] $^ 

obj/client/%.o: src/client/%.c $(HEADERS_CLIENT) 
    $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o [email protected] 

obj/server/%.o: src/server/%.c $(HEADERS_SERVER) 
    $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o [email protected] 
+0

謝謝,詳細的答案。這真的清除了關於Makefiles的事情。 – Zonko

0

這兩個規則應該做你以後

obj/client/%.o: src/client/%.c $(HEADERS_CLIENT) 
     $(CC) -c -o [email protected] $< 

obj/server/%.o: src/server/%.c $(HEADERS_SERVER) 
     $(CC) -c -o [email protected] $< 
+0

謝謝,這有很大的幫助。 – Zonko

相關問題