규칙이있는 메이크 파일이 있다고 가정 해 보겠습니다.
%.o: %.c
gcc -Wall -Iinclude ...
헤더 파일이 변경 될 때마다 * .o가 다시 작성되기를 원합니다. 종속성 목록을 작성하는 대신 헤더 파일이 /include
변경 될 때마다 dir의 모든 개체를 다시 빌드해야합니다.
나는 이것을 수용하기 위해 규칙을 변경하는 좋은 방법을 생각할 수 없다. 나는 제안에 개방적이다. 헤더 목록을 하드 코딩 할 필요가없는 경우 보너스 포인트
답변
GNU 컴파일러를 사용하는 경우 컴파일러가 종속성 목록을 조합 할 수 있습니다. Makefile 조각 :
depend: .depend
.depend: $(SRCS)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^ -MF ./.depend;
include .depend
또는
depend: .depend
.depend: $(SRCS)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^ > ./.depend;
include .depend
여기서는 SRCS
소스 파일의 전체 목록을 가리키는 변수입니다.
도구도 makedepend
있지만 나는 그것을만큼 좋아하지 않았습니다.gcc -MM
답변
대부분의 답변은 놀랍도록 복잡하거나 오류가 있습니다. 그러나 간단하고 강력한 예제는 [ codereview ] 다른 곳에 게시되었습니다 . 확실히 gnu 전처리 기가 제공하는 옵션은 약간 혼란 스럽습니다. 그러나 빌드 대상에서 모든 디렉토리를 제거하는 -MM
것은 문서화되어 있으며 버그 [ gpp ]가 아닙니다 .
기본적으로 CPP는 기본 입력 파일의 이름을 사용하고 모든
디렉토리 구성 요소 및 ‘.c’와 같은 파일 접미사를 삭제 하고 플랫폼의 일반적인 개체 접미사를 추가합니다.
(다소 더 새로운) -MMD
옵션은 아마도 당신이 원하는 것입니다. 완전성을 위해 여러 src 디렉토리를 지원하고 일부 주석으로 디렉토리를 빌드하는 메이크 파일의 예입니다. 빌드 디렉토리가없는 간단한 버전은 [ codereview ]를 참조하십시오 .
CXX = clang++
CXX_FLAGS = -Wfatal-errors -Wall -Wextra -Wpedantic -Wconversion -Wshadow
# Final binary
BIN = mybin
# Put all auto generated stuff to this build dir.
BUILD_DIR = ./build
# List of all .cpp source files.
CPP = main.cpp $(wildcard dir1/*.cpp) $(wildcard dir2/*.cpp)
# All .o files go to build dir.
OBJ = $(CPP:%.cpp=$(BUILD_DIR)/%.o)
# Gcc/Clang will create these .d files containing dependencies.
DEP = $(OBJ:%.o=%.d)
# Default target named after the binary.
$(BIN) : $(BUILD_DIR)/$(BIN)
# Actual target of the binary - depends on all .o files.
$(BUILD_DIR)/$(BIN) : $(OBJ)
# Create build directories - same structure as sources.
mkdir -p $(@D)
# Just link all the object files.
$(CXX) $(CXX_FLAGS) $^ -o $@
# Include all .d files
-include $(DEP)
# Build target for every single object file.
# The potential dependency on header files is covered
# by calling `-include $(DEP)`.
$(BUILD_DIR)/%.o : %.cpp
mkdir -p $(@D)
# The -MMD flags additionaly creates a .d file with
# the same name as the .o file.
$(CXX) $(CXX_FLAGS) -MMD -c $< -o $@
.PHONY : clean
clean :
# This should remove all generated files.
-rm $(BUILD_DIR)/$(BIN) $(OBJ) $(DEP)
이 방법은 단일 대상에 대해 여러 종속성 라인이있는 경우 종속성이 단순히 결합되기 때문에 작동합니다. 예 :
a.o: a.h
a.o: a.c
./cmd
다음과 같습니다.
a.o: a.c a.h
./cmd
언급했듯이 : Makefile 단일 대상에 대한 여러 종속성 줄?
답변
내가 여기에 게시했듯이 gcc는 종속성을 생성하고 동시에 컴파일 할 수 있습니다.
DEPS := $(OBJS:.o=.d)
-include $(DEPS)
%.o: %.c
$(CC) $(CFLAGS) -MM -MF $(patsubst %.o,%.d,$@) -o $@ $<
‘-MF’매개 변수는 종속성을 저장할 파일을 지정합니다.
‘-include’시작 부분의 대시는 Make가 .d 파일이 존재하지 않을 때 (예 : 첫 번째 컴파일시) 계속하도록 지시합니다.
-o 옵션과 관련하여 gcc에 버그가있는 것 같습니다. 객체 파일 이름을 obj / _file__c.o로 설정하면 생성 된 파일 .d에는 여전히 obj / _file__c.o가 아닌 .o 파일 이 포함 됩니다 .
답변
다음과 같은 것은 어떻습니까?
includes = $(wildcard include/*.h)
%.o: %.c ${includes}
gcc -Wall -Iinclude ...
와일드 카드를 직접 사용할 수도 있지만 여러 곳에서 필요한 경우가 많습니다.
이것은 모든 개체 파일이 모든 헤더 파일에 의존한다고 가정하기 때문에 소규모 프로젝트에서만 잘 작동합니다.
답변
위의 Martin의 솔루션은 훌륭하게 작동하지만 하위 디렉토리에있는 .o 파일을 처리하지 않습니다. Godric은 -MT 플래그가 해당 문제를 처리하지만 동시에 .o 파일이 올바르게 작성되는 것을 방지한다고 지적합니다. 다음은 이러한 문제를 모두 처리합니다.
DEPS := $(OBJS:.o=.d)
-include $(DEPS)
%.o: %.c
$(CC) $(CFLAGS) -MM -MT $@ -MF $(patsubst %.o,%.d,$@) $<
$(CC) $(CFLAGS) -o $@ $<
답변
이것은 작업을 잘 수행하고 지정된 하위 디렉토리도 처리합니다.
$(CC) $(CFLAGS) -MD -o $@ $<
gcc 4.8.3으로 테스트했습니다.
답변
다음은 두 줄짜리입니다.
CPPFLAGS = -MMD
-include $(OBJS:.c=.d)
에 모든 개체 파일 목록이있는 한 기본 make 레시피에서 작동합니다 OBJS
.