작업중인 프로그램 (실제로 커널)을 빌드하는 데 사용하는 다음 메이크 파일이 있습니다. 처음부터 프로세스에 대해 배우고 있으므로 완벽하지는 않지만이 시점에서 메이크 파일 작성 경험 수준에 비해 충분히 강력하다고 생각합니다.
AS = nasm
CC = gcc
LD = ld
TARGET = core
BUILD = build
SOURCES = source
INCLUDE = include
ASM = assembly
VPATH = $(SOURCES)
CFLAGS = -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions \
-nostdinc -fno-builtin -I $(INCLUDE)
ASFLAGS = -f elf
#CFILES = core.c consoleio.c system.c
CFILES = $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
SFILES = assembly/start.asm
SOBJS = $(SFILES:.asm=.o)
COBJS = $(CFILES:.c=.o)
OBJS = $(SOBJS) $(COBJS)
build : $(TARGET).img
$(TARGET).img : $(TARGET).elf
c:/python26/python.exe concat.py stage1 stage2 pad.bin core.elf floppy.img
$(TARGET).elf : $(OBJS)
$(LD) -T link.ld -o $@ $^
$(SOBJS) : $(SFILES)
$(AS) $(ASFLAGS) $< -o $@
%.o: %.c
@echo Compiling $<...
$(CC) $(CFLAGS) -c -o $@ $<
#Clean Script - Should clear out all .o files everywhere and all that.
clean:
-del *.img
-del *.o
-del assembly\*.o
-del core.elf
이 메이크 파일의 주요 문제는 하나 이상의 C 파일이 포함 된 헤더 파일을 수정할 때 C 파일이 다시 빌드되지 않는다는 것입니다. 내 모든 헤더 파일이 내 모든 C 파일에 대한 종속성이되도록함으로써이 문제를 아주 쉽게 해결할 수 있지만, 헤더 파일을 변경 / 추가 할 때마다 프로젝트를 완전히 재 빌드 할 수 있습니다.
내가 원하는 것은 내가 변경 한 헤더 파일 을 포함 하는 C 파일 만 다시 빌드하고 전체 프로젝트를 다시 링크하는 것입니다. 모든 헤더 파일을 대상의 종속성으로 설정하여 연결을 수행 할 수 있지만 포함 된 헤더 파일이 더 최신 일 때 C 파일을 무효화하는 방법을 알 수 없습니다.
GCC에이를 가능하게하는 몇 가지 명령이 있다고 들었지만 (메이크 파일이 어떤 파일을 재 빌드해야하는지 알아낼 수 있음) 실제 구현 예제를 볼 수는 없습니다. 누군가 메이크 파일에서이 동작을 가능하게하는 솔루션을 게시 할 수 있습니까?
편집 : 명확해야합니다. 개별 대상을 넣고 각 target.o에 헤더 파일이 필요하다는 개념에 익숙합니다. 어딘가에 헤더 파일을 포함 할 때마다 makefile을 편집해야하는데, 이는 약간의 고통입니다. 헤더 파일 종속성을 자체적으로 파생 할 수있는 솔루션을 찾고 있는데, 다른 프로젝트에서 본 것이 상당히 확실합니다.
답변
이 사이트의 다른 곳에서 이미 지적했듯이 다음 페이지를 참조하십시오.
자동 종속성 생성
간단히 말해 gcc는 컴파일 한 .c 파일의 종속성을 포함하는 미니 메이크 파일 조각 인 .d 종속성 파일을 자동으로 생성 할 수 있습니다. .c 파일을 변경하고 컴파일 할 때마다 .d 파일이 업데이트됩니다.
-M 플래그를 gcc에 추가하는 것 외에도 메이크 파일에 .d 파일을 포함해야합니다 (위에서 Chris가 작성한 것처럼). 페이지에는 sed를 사용하여 해결되는 좀 더 복잡한 문제가 있지만 더 이상 존재하지 않는 헤더 파일을 빌드 할 수 없다는 불만이있을 때마다이를 무시하고 “make clean”을 수행하여 .d 파일을 지울 수 있습니다. .
답변
다른 사람들이 언급 한대로 ‘make dependent’명령을 추가 할 수 있지만 gcc를 사용하여 종속성을 만들고 동시에 컴파일하지 않는 이유는 무엇입니까?
DEPS := $(COBJS:.o=.d)
-include $(DEPS)
%.o: %.c
$(CC) -c $(CFLAGS) -MM -MF $(patsubst %.o,%.d,$@) -o $@ $<
‘-MF’매개 변수는 종속성을 저장할 파일을 지정합니다.
‘-include’시작 부분의 대시는 Make가 .d 파일이 존재하지 않을 때 (예 : 첫 번째 컴파일시) 계속하도록 지시합니다.
-o 옵션과 관련하여 gcc에 버그가있는 것 같습니다. 당신은 말을 오브젝트 파일 이름을 설정하면 obj/_file__c.o
다음 생성 _file_.d
아직 포함 _file_.o
하지 obj/_file_c.o
.
답변
이것은 Chris Dodd의 대답 과 동일하지만 다른 명명 규칙을 사용합니다 (우연히 sed
마법이 필요하지 않습니다 . 나중에 복제 된 .
GNU 컴파일러를 사용하는 경우 컴파일러가 종속성 목록을 조합 할 수 있습니다. Makefile 조각 :
depend: .depend
.depend: $(SOURCES)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^>>./.depend;
include .depend
도구도 makedepend
있지만 나는 그것을만큼 좋아하지 않았습니다.gcc -MM
답변
각 C 파일에 대해 개별 대상을 만든 다음 헤더 파일을 종속성으로 나열해야합니다. 일반 대상을 계속 사용할 수 있으며 .h
다음과 같이 나중에 종속성을 배치 할 수 있습니다 .
%.o: %.c
@echo Compiling $<...
$(CC) $(CFLAGS) -c -o $@ $<
foo.c: bar.h
# And so on...
답변
기본적으로 헤더 파일이 변경 될 때 개체 파일을 다시 빌드하려면 makefile 규칙을 동적으로 만들어야합니다. gcc와 gnumake를 사용한다면 이것은 매우 쉽습니다. 다음과 같이 입력하십시오.
$(OBJDIR)/%.d: %.c
$(CC) -MM -MG $(CPPFLAGS) $< | sed -e 's,^\([^:]*\)\.o[ ]*:,$(@D)/\1.o $(@D)/\1.d:,' >$@
ifneq ($(MAKECMDGOALS),clean)
include $(SRCS:%.c=$(OBJDIR)/%.d)
endif
당신의 makefile에.
답변
@mipadi가 말한 것 이상으로 ‘ -M
‘옵션을 사용하여 종속성 레코드를 생성하는 방법을 탐색 할 수도 있습니다 . 이를 별도의 파일 (예 : ‘depend.mk’)로 생성 한 다음 makefile에 포함 할 수도 있습니다. 또는 make depend
올바른 종속성으로 메이크 파일을 편집 하는 ‘ ‘규칙을 찾을 수 있습니다 (Google 용어 : “이 줄을 제거하지 마십시오”및 종속성).
답변
어떤 답변도 나를 위해 일하지 않았습니다. 예를 들어 Martin Fido의 대답은 gcc가 종속성 파일을 만들 수 있다고 제안하지만 경고 나 오류없이 빈 (0 바이트) 개체 파일을 생성하려고 시도했습니다. gcc 버그 일 수 있습니다. 나는
$ gcc –version gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)
그래서 여기 저에게 맞는 완전한 Makefile이 있습니다. 솔루션 + 다른 사람이 언급하지 않은 것의 조합입니다 (예 : .cc.o :로 지정된 “접미사 대체 규칙”) :
CC = g++
CFLAGS = -Wall -g -std=c++0x
INCLUDES = -I./includes/
# LFLAGS = -L../lib
# LIBS = -lmylib -lm
# List of all source files
SRCS = main.cc cache.cc
# Object files defined from source files
OBJS = $(SRCS:.cc=.o)
# # define the executable file
MAIN = cache_test
#List of non-file based targets:
.PHONY: depend clean all
## .DEFAULT_GOAL := all
# List of dependencies defined from list of object files
DEPS := $(OBJS:.o=.d)
all: $(MAIN)
-include $(DEPS)
$(MAIN): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS)
#suffix replacement rule for building .o's from .cc's
#build dependency files first, second line actually compiles into .o
.cc.o:
$(CC) $(CFLAGS) $(INCLUDES) -c -MM -MF $(patsubst %.o,%.d,$@) $<
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
clean:
$(RM) *.o *~ $(MAIN) *.d
.cc ..를 사용했습니다. 위의 Makefile은 .c 파일에 대해 쉽게 조정할 수 있습니다.
또한 다음 두 줄의 중요성에 유의하십시오.
$(CC) $(CFLAGS) $(INCLUDES) -c -MM -MF $(patsubst %.o,%.d,$@) $<
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
따라서 gcc를 한 번 호출하여 먼저 종속성 파일을 빌드 한 다음 실제로 .cc 파일을 컴파일합니다. 각 소스 파일에 대해 등등.