34
GNU Make 3.82
gcc 4.7.2
c89

次のメイクファイルがあります。

INC_PATH=-I/home/dev_tools/apr/include/apr-1
LIB_PATH=-L/home/dev_tools/apr/lib
LIBS=-lapr-1 -laprutil-1
RUNTIME_PATH=-Wl,-rpath,/home/dev_tools/apr/lib
CC=gcc
CFLAGS=-Wall -Wextra -g -m32 -O2 -D_DEBUG -D_THREAD_SAFE -D_REENTRANT -D_LARGEFILE64_SOURCE $(INC_PATH)
SOURCES=$(wildcard src/*.c)
OBJECTS=$(patsubst %.c, %.o, $(SOURCES))

EXECUTABLE=bin/to

all:    build $(EXECUTABLE)

$(EXECUTABLE):  $(OBJECTS)
    $(CC) $(CFLAGS) -o $@ $(RUNTIME_PATH) $(OBJECTS) $(LIB_PATH) $(LIBS)

$(OBJECTS): $(SOURCES)
    $(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS)

build:
    @mkdir -p bin

clean:
    rm -rf $(EXECUTABLE) $(OBJECTS) bin
    find . -name "*~" -exec rm {} \;
    find . -name "*.o" -exec rm {} \;

私のディレクトリ構造はこのようなものproject/src project/binです。Makefile はproject (root)フォルダーにあり、*.h と *.c はすべて src ディレクトリにあります。現在、timeout.c というソース ファイルが 1 つしかありません。

次のエラーが表示されます。

gcc: error: src/timeout.o: No such file or directory

これを使用して、すべてのソース ファイルを取得しました。

SOURCES=$(wildcard src/*.c)

そしてオブジェクトファイル:

OBJECTS=$(patsubst %.c, %.o, $(SOURCES))

ただし、make は、Makefile があるプロジェクト ルート フォルダーにオブジェクト ファイルを作成するようです。src ディレクトリに置くべきではありませんか?

4

3 に答える 3

29

このルールには2つの問題があります(まあ、3つ):

$(OBJECTS): $(SOURCES)
    $(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS)

まだ気づいていませんが、ルールは各オブジェクトをすべてのソースに依存させ、そのように構築しようとします。ソースが1つしかない限り、問題はありません。静的パターンルール自動変数で簡単に修正できます:

$(OBJECTS): src/%.o : src/%.c
    $(CC) $(CFLAGS) -c $< $(LIB_PATH) $(LIBS)

また、コマンド( "$(CC)...")は出力ファイル名を指定しないため、gccはソースファイル名からそれを推測します。あなたがそれを与えるならばsrc/timeout.c、それはtimeout.o(作業ディレクトリでproject/)を生成します。したがって、出力ファイルへの目的のパスを指定する必要があります。別の自動変数で簡単に実行できます。

$(OBJECTS): src/%.o : src/%.c
    $(CC) $(CFLAGS) -c $< $(LIB_PATH) $(LIBS) -o $@
于 2013-02-01T07:03:56.453 に答える
7

gcc-oオプションを使用して、出力ファイルを特定の場所に書き込みます。たとえば、次のように言えます。

$(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS) -o $(OBJECTS)

残念ながら、この行には問題があります。 に複数のソース ファイルがある場合、複数のファイル名も含まれ、-oオプションは最初の引数にのみバインドされるため、機能し$(SOURCES)ません。$(OBJECTS)

ソース コード ファイルのリスト内の各ファイルをコンパイルする方法は、暗黙の規則を使用することです。ではgmake、次のように記述します。

$(EXECUTABLE):  $(OBJECTS)
        $(CC) $(CFLAGS) -o $@ $(RUNTIME_PATH) $(OBJECTS) $(LIB_PATH) $(LIBS)

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

ここで、$<は入力ファイルの名前に置き換えられ、$@は出力ファイルの名前に置き換えられます。

于 2013-02-01T05:54:42.323 に答える