0

假设我们有客户端-服务器应用程序,由一个 makefile 编译。服务器使用 libtask 为并行客户端服务。客户端将 ncurses 用于某些图形。目录树如下所示:

./
--bin/
--obj/
--src/
----client/*.c
----server/*.c
--makefile

所以,这里是makefile。我们可以简化它吗?我阅读了一些关于 stackoverflow 的相关问题,我认为它几乎是理想的,除了链接二进制文件,当我们可以看到重复的命令时。一些关于风格/跨平台工作的建议会很有用。谢谢!

.PHONY: all clean

TASKLIB = -ltask
CURSESLIB = -lncurses
CFLAGS = -Wall -Werror -pedantic

bin = server client
obj_dir = obj
bin_dir = bin
ssource := src/server
csource := src/client
search_wildcard s := $(addsuffix /*.c, $(ssource))
search_wildcard c := $(addsuffix /*.c, $(csource))
sobjs = $(addprefix $(obj_dir)/, $(patsubst %.c, %.o, $(notdir $(wildcard $(search_wildcard s)))))
cobjs = $(addprefix $(obj_dir)/, $(patsubst %.c, %.o, $(notdir $(wildcard $(search_wildcard c)))))

all: $(bin)
    @echo "done!"

server: CFLAGS+=$(TASKLIB)
client: CFLAGS+=$(CURSESLIB)

clean:
    rm $(sobjs) $(cobjs) $(obj_dir)/*.d $(bin_dir)/client $(bin_dir)/server

VPATH := $(ssource) $(csource)

server: $(sobjs)
    @test -d $(bin_dir) || mkdir $(bin_dir)
    @echo "Linking $(@F)..."
    @$(CC) $< $(CFLAGS) -o $(bin_dir)/$@

client: $(cobjs)
    @test -d $(bin_dir) || mkdir $(bin_dir)
    @echo "Linking $(@F)..."
    @$(CC) $< $(CFLAGS) -o $(bin_dir)/$@

$(obj_dir)/%.o: %.c
    @test -d $(obj_dir) || mkdir $(obj_dir)
    @echo "Compiling $(@F)..."
    @$(CC) $< $(CFLAGS) -c -MD -o $@

include $(wildcard $(obj_dir)/*.d)
4

3 回答 3

0

我有几点意见:

  • 将 $(obj_dir) 添加到服务器和客户端的配方中。就目前而言,每次运行 make 它都会重建二进制文件。

  • 添加配方以创建目录(bin 和 obj)并将它们从客户端和服务器配方中删除

  • $< 应该是 $^ 服务器和客户端配方

  • 通过删除 bin/ 和 obj/ 进行清理

  • 也许使用 -MMD 而不是 -MD 来排除系统依赖项

  • 向 CFLAGS 添加更多警告

  • 是否应该使用 LDFLAGS 而不是 CFLAGS 进行链接

  • 如果在服务器和客户端目录中使用相同的文件名,则构建将失败。

以下是我更改的行:

all: $(bin_dir) $(obj_dir) $(bin_dir)/server $(bin_dir)/client
    @echo "done!"

clean:
    rm -rf $(obj_dir) $(bin_dir)

$(bin_dir) $(obj_dir) :
    test -d $@ || mkdir $@

$(bin_dir)/server: $(sobjs)
    $(CC) $^ $(CFLAGS) -o $@

$(bin_dir)/client: $(cobjs)
    $(CC) $^ $(CFLAGS) -o $@

$(obj_dir)/%.o: %.c
    $(CC) $< $(CFLAGS) -c -MMD -o $@

正如 Christoph 所示,您还可以将服务器和客户端配方合二为一。我的猜测是专家可以将其缩小,但遗憾的是我不是专家。和看起来$(sobjs)特别$(cobjs)适合还原。

于 2012-04-13T03:46:05.947 回答
0

CMake 是一个跨平台的构建系统生成器。项目使用名称为 CMakeLists.txt 的源代码树的每个目录中包含的与平台无关的 CMake 列表文件来指定其构建过程。用户通过使用 CMake 为他们平台上的原生工具生成构建系统来构建项目。

http://www.cmake.org/cmake/help/cmake2.4docs.html

http://linux.die.net/man/1/cmake

也许这对你有帮助

于 2012-04-12T19:52:34.910 回答
0

您可能比您需要的更一般:例如,我不会使目录可配置 - 这仅对目标的目的地有意义install

无论如何,这就是我编写你的makefile的方式(未经测试):

CFLAGS := -Wall -Werror -pedantic
RM := rm -f
MKDIR := mkdir -p

BINARIES := bin/server bin/client
SERVER_OBJECTS := $(patsubst src/%.c, obj/%.o, $(wildcard src/server/*.c))
CLIENT_OBJECTS := $(patsubst src/%.c, obj/%.o, $(wildcard src/client/*.c))
OBJECTS := $(SERVER_OBJECTS) $(CLIENT_OBJECTS)

.PHONY : build clean realclean

build : $(BINARIES)

clean :
    $(RM) $(OBJECTS) $(OBJECTS:%.o=%.d)

realclean : clean
    $(RM) $(BINARIES)

bin/server : LDLIBS := -ltask
bin/client : LDLIBS := -lncurses

bin/server : $(SERVER_OBJECTS)
bin/client : $(CLIENT_OBJECTS)

$(BINARIES) :
    @$(MKDIR) $(dir $@)
    $(CC) $(CFLAGS) -o $@ $^ $(LDLIBS)

include $(wildcard obj/*.d)

$(OBJECTS) : obj/%.o : src/%.c
    @$(MKDIR) $(dir $@)
    $(CC) $(CFLAGS) -c -MD -o $@ $<
于 2012-04-12T20:55:28.493 回答