2017-04-06 40 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

相关问题