ПОСМОТРЕТЬ ОБНОВЛЕНИЯ НИЖЕ
Исследование завершено: Мне трудно научиться превращать Make-файлы из одной ситуации в другую.Существует множество вопросов и ответов, но немногие из них на самом деле показывают, как Makefile может развиваться по мере изменения вашего проекта.Кажется, все они также используют различные техники и идиомы Makefiles, поэтому перевод с одного вопроса на другой может быть сложным, когда вы впервые изучаете Makefiles, как и я.
Проблема: Моя проблема в том, что у меня есть проект, который начинался как плоская структура каталогов, но затем мигрировал в структуру с подкаталогами.Что я не могу сделать, так это взять с собой мой Makefile для поездки.
Сначала я покажу, что я создал, что работает, а затем я покажу, как я хочу, чтобы он развивался и как это не работало.
Плоская структура каталогов, рабочий Makefile
У меня есть каталог проекта, в котором есть все мои C-файлы и один заголовочный файл плюс мой Makefile:
project
Makefile
c8_asm.c
c8_dasm.c
c8_terp.c
chip8.h
Вот мой Makefile (который прекрасно работает):
CC = gcc
CFLAGS += -c -Wall -std=c99
CFLAGS += -D_POSIX_C_SOURCE=200809L
LDLIBS += -lm
# Targets
all: c8_dasm c8_asm c8_terp
c8_dasm: c8_dasm.o
$(CC) $(LDLIBS) c8_dasm.o -o $@
c8_asm: c8_asm.o
$(CC) $(LDLIBS) c8_asm.o -o $@
c8_terp: c8_terp.o
$(CC) $(LDLIBS) c8_terp.o -o $@
# Using implicit rules for updating an '.o' file from a correspondingly
# named '.c' file.
c8_dasm.o: chip8.h
c8_asm.o: chip8.h
c8_terp.o: chip8.h
.PHONY: clean
clean:
rm c8_dasm c8_asm c8_terp c8_dasm.o c8_asm.o c8_terp.o
Я получаю все мои .o файлы и мои исполняемые файлы создаются в каталоге проекта.
Развитие проекта
Но я хотел, чтобы мои исходные файлы (все .c и .h) были в каталоге src.Я хотел встроить в каталог obj и сделать так, чтобы исполняемые файлы помещались в каталог bin.Поэтому мой проект будет выглядеть следующим образом:
project
src
c8_asm.c
c8_dasm.c
c8_terp.c
chip8.h
Makefile
Структура подкаталога, Makefile НЕ работает
Чтобы учесть вышеизложенное, я изменил свой Makefile соответствующим образом:
CC = gcc
CFLAGS += -c -Wall -std=c99
CFLAGS += -D_POSIX_C_SOURCE=200809L
LDLIBS += -lm
SRC_DIR = src
OBJ_DIR = obj
BIN_DIR = bin
SOURCES := $(wildcard $(SRC_DIR)/*.c)
OBJECTS := $(SOURCES:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
MKDIR_P ?= mkdir -p
# Targets
all: $(BIN_DIR)/c8_dasm $(BIN_DIR)/c8_asm $(BIN_DIR)/c8_terp
$(BIN_DIR)/c8_dasm: $(OBJ_DIR)/c8_dasm.o
$(CC) $(LDLIBS) $(OBJ_DIR)/c8_dasm.o -o $@
$(BIN_DIR)/c8_asm: $(OBJ_DIR)/c8_asm.o
$(CC) $(LDLIBS) $(OBJ_DIR)/c8_asm.o -o $@
$(BIN_DIR)/c8_terp: $(OBJ_DIR)/c8_terp.o
$(MKDIR_P) $(dir $@)
$(CC) $(LDLIBS) $(OBJ_DIR)/c8_terp.o -o $@
$(OBJECTS): $(OBJ_DIR)/%.o : $(SRC_DIR)/%.c
$(MKDIR_P) $(dir $@)
$(CC) $< -o $(OBJ_DIR)/$@
# Using implicit rules for updating an '.o' file from a correspondingly
# named '.c' file.
$(OBJ_DIR)/c8_dasm.o: $(SRC_DIR)/chip8.h
$(OBJ_DIR)/c8_asm.o: $(SRC_DIR)/chip8.h
$(OBJ_DIR)/c8_terp.o: $(SRC_DIR)/chip8.h
.PHONY: clean
clean:
rm -r $(BUILD_DIR)
rm $(OBJECTS)
После запуска этого я получаю следующее:
mkdir -p obj/obj/
gcc src/c8_dasm.c -o obj/c8_dasm.o
gcc -lm obj/c8_dasm.o -o bin/c8_dasm
ld: can't link with a main executable file 'obj/c8_dasm.o' for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [bin/c8_dasm] Error 1
Я хотел остановиться здесь и получить некоторую помощь, потому что я боюсь, что делаю этот Makefile сложнее, чем нужно, и яЯ пытаюсь избежать вредных привычек.
Я надеюсь услышать мнения о том, что я не правильно концептуализирую здесь.
ПЕРВОЕ ОБНОВЛЕНИЕ
Мне удалось взять это понемногу и заставить его работать в основном.Вот что я закончил:
CC = gcc
CFLAGS += -c -Wall -std=c99
CFLAGS += -D_POSIX_C_SOURCE=200809L
LDLIBS += -lm
# Directories.
SRC_DIR = src
BIN_DIR = bin
$(shell mkdir -p $(BIN_DIR))
# Patterns for files.
SOURCES := $(wildcard $(SRC_DIR)/*.c)
OBJECTS := $(SOURCES:$(SRC_DIR)/%.c=$(SRC_DIR)/%.o)
EXECUTABLES := c8_dasm c8_asm c8_terp
# Targets
all: $(EXECUTABLES)
c8_dasm: $(SRC_DIR)/c8_dasm.o
$(CC) $^ $(LDLIBS) -o $(BIN_DIR)/$@
@echo "C8 Disassembler Built"
c8_asm: $(SRC_DIR)/c8_asm.o
$(CC) $^ $(LDLIBS) -o $(BIN_DIR)/$@
@echo "C8 Assembler Built"
c8_terp: $(SRC_DIR)/c8_terp.o
$(CC) $^ $(LDLIBS) -o $(BIN_DIR)/$@
@echo "C8 Interpreter Built"
# Using implicit rules for updating an '.o' file from a correspondingly
# named '.c' file.
c8_dasm.o: $(SRC_DIR)/chip8.h
c8_asm.o: $(SRC_DIR)/chip8.h
c8_terp.o: $(SRC_DIR)/chip8.h
.PHONY: clean
clean:
rm $(OBJECTS)
rm -r $(BIN_DIR)
Конечно, поскольку я нахожу с Make, это приводит к другим неясным проблемам.Например, сделав это:
make
make clean
работает нормально.Это означает, что все файлы сгенерированы, и файлы очищены, включая каталог bin
.
Однако, если я сделаю это:
make c8_dasm
make clean
Это прекрасно работает.Но очистка не удаляет каталог bin
(хотя она и удаляет объектные файлы).Это происходит независимо от того, какой отдельный исполняемый файл я пытаюсь создать.
Никакие поиски не помогают мне выяснить, почему это так.
ВТОРОЕ ОБНОВЛЕНИЕ
Я обнаружил, что проблема также была решена.Просто потребовалось использовать "-f" для операторов rm в чистой цели.
ТРЕТЬЕ ОБНОВЛЕНИЕ
Чтобы заставить работать часть каталога объектных файлов, я попытался (из этого: путь include и make-файл каталога src ) для создания моего Makefile следующим образом:
CC = gcc
CFLAGS += -c -Wall -std=c99
CFLAGS += -D_POSIX_C_SOURCE=200809L
LDLIBS += -lm
SRC_DIR = src
OBJ_DIR = obj
BIN_DIR = bin
$(shell mkdir -p $(BIN_DIR))
$(shell mkdir -p $(OBJ_DIR))
SOURCES := $(wildcard $(SRC_DIR)/*.c)
OBJECTS := $(SOURCES:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
EXECUTABLES := c8_dasm c8_asm c8_terp
all: $(EXECUTABLES)
c8_dasm: $(SRC_DIR)/c8_dasm.o
$(CC) $^ $(LDLIBS) -o $(BIN_DIR)/$@
@echo "C8 Disassembler Built"
c8_asm: $(SRC_DIR)/c8_asm.o
$(CC) $^ $(LDLIBS) -o $(BIN_DIR)/$@
@echo "C8 Assembler Built"
c8_terp: $(SRC_DIR)/c8_terp.o
$(CC) $^ $(LDLIBS) -o $(BIN_DIR)/$@
@echo "C8 Interpreter Built"
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) -c $< -o $(BIN_DIR)/$@
.PHONY: clean
clean:
rm -rf $(BIN_DIR)
rm -f $(OBJECTS)
Мне удалось сжать три исходные строки, используя chip8.h
, в одну цель, но яне знаю, правильно ли это.Это компилирует по крайней мере.Я также изменил строку OBJECTS
, чтобы отразить новую созданную мной OBJ_DIR
.
Однако, это не помещает объектные файлы в правильное место.Он по-прежнему помещает их в каталог src
, а не в каталог obj
.