0

1つの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/を削除してクリーンアップします

  • おそらく、システムの依存関係を除外するために、-MDの代わりに-MMDを使用してください

  • CFLAGSに警告を追加する

  • CFLAGSの代わりにLDFLAGSをリンクに使用する必要があります

  • サーバーディレクトリとクライアントディレクトリの両方で同じファイル名が使用されている場合、ビルドは失敗します。

これが私が変更した行です:

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が示すように、サーバーとクライアントのレシピを1つに結合することもできます。私の推測では、専門家がそれを小さくすることができますが、残念ながら私は1人ではありません。$(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 に答える