Как Makefile может использовать отдельные каталоги для исходного кода и двоичных файлов?

Я хочу, чтобы иметь возможность разбить мой bin и мои файлы кода на отдельные каталоги, поскольку в этом текущем состоянии становится трудно управлять.

Я идеально хотел бы иметь

project_dir
|-Makefile
|-run_tests.sh
|
|__source
|  |-program1.cpp
|  |-program2.cpp
|
|__bin
   |-program1
   |-program2

Однако я не могу заставить это работать с моей текущей системой без необходимости вручную выписывать правила для каждой программы (помните, что каждая программа представляет собой отдельную программу, а не ряд связанных между собой объектов)

#Current make system
BIN=./bin/
SOURCE=./source/

LIST=program1 program2...

all: $(LIST)

%:  $(SOURCE)%.cpp
    $(CC) $(INC) $< $(CFLAGS) -o $(BIN)[email protected] $(LIBS)

это работает, за исключением того, что он не может видеть цель в текущем пути, поэтому он считает, что он всегда восстанавливает двоичные файлы, даже если исходные файлы не изменились.

Моя единственная мысль на данный момент - написать программу для создания make файла, но я не хочу этого делать.

Ответы

Ответ 1

Ты был почти там...

#Current make system
BIN=./bin/
SOURCE=./source/

LIST=$(BIN)/program1 $(BIN)/program2...

all: $(LIST)

$(BIN)/%:  $(SOURCE)%.cpp
    $(CC) $(INC) $< $(CFLAGS) -o [email protected] $(LIBS)

Вы также можете сделать LIST проще, используя следующие

PROG=program1 program2
LIST=$(addprefix $(BIN)/, $(PROG))

Ответ 2

Простое решение: используйте automake.

Если вы хотите сделать это вручную, вам понадобится использовать директиву vpath или переменную среды vpath. В руководстве GNU есть раздел о них. Поместите свой Makefile непосредственно в каталог bin, установите vpath в исходный каталог, а неявные правила снова будут работать.

Ответ 3

Вот полная готовая версия Makefile.

Подготовьте свою папку со следующим каталогом

для .o файлов: /build/ для .cpp файлов: /src/ для двоичных файлов: /bin/

Затем используйте следующий Makefile в /

CC          = g++
LD          = g++ 
CFLAG       = -Wall
PROG_NAME   = prog

SRC_DIR     = ./src
BUILD_DIR   = ./build
BIN_DIR     = ./bin
SRC_LIST = $(wildcard $(SRC_DIR)/*.cpp)
OBJ_LIST = $(BUILD_DIR)/$(notdir $(SRC_LIST:.cpp=.o))

.PHONY: all clean $(PROG_NAME) compile

all: $(PROG_NAME)

compile: 
    $(CC) -c $(CFLAG) $(SRC_LIST) -o $(OBJ_LIST)

$(PROG_NAME): compile
    $(LD) $(OBJ_LIST) -o $(BIN_DIR)/[email protected]

clean:
    rm -f $(BIN_DIR)/$(PROG_NAME) $(BUILD_DIR)/*.o

Ваша последняя программа будет называться как prog в /bin/, каждый раз, когда вы скомпилируете код, двоичные файлы будут разделены на /build/, чтобы каталог исходного кода был очень аккуратным и чистым.