Получение make для создания объектных файлов в определенном каталоге - программирование

Получение make для создания объектных файлов в определенном каталоге

GNU Make 3.82
gcc 4.7.2
c89

У меня есть следующий файл make:

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 [email protected] $(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

Я получаю эту ошибку:

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

Я использовал это, чтобы получить все исходные файлы:

SOURCES=$(wildcard src/*.c)

И объектные файлы:

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

Однако make, кажется, создает объектный файл в корневой папке проекта, где находится Makefile. Должен ли он не помещать его в каталог src?

4b9b3361

Ответ 1

У вас есть две проблемы в этом правиле (ну, три):

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

Вы еще не заметили, но правило делает каждый объект зависимым от всех источников и пытается построить этот путь. Не проблема, если у вас есть только один источник. Легко исправить с помощью правила статического шаблона и автоматическая переменная:

$(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 [email protected]

Ответ 2

Используйте параметр gcc -o для записи выходного файла в определенное место. Например, вы могли бы сказать:

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

К сожалению, есть проблема с этой строкой: если в $(SOURCES) имеется более одного исходного файла, это не сработает, поскольку $(OBJECTS) также будет содержать несколько имен файлов, а -o привязывается только к первому аргументу.

Способ компиляции каждого файла в списке файлов исходного кода заключается в использовании неявных правил. В gmake вы должны написать:

$(EXECUTABLE):  $(OBJECTS)
        $(CC) $(CFLAGS) -o [email protected] $(RUNTIME_PATH) $(OBJECTS) $(LIB_PATH) $(LIBS)

%.o : %.c
        $(CC) $(CFLAGS) -c $< -o [email protected]

где $< заменяется именем входного файла, а [email protected] заменяется именем выходного файла.