web-dev-qa-db-ja.com

修正されたヘッダーファイルを含むソースファイルをMakefileで自動的に再構築するにはどうすればよいですか? (C / C ++の場合)

私が取り組んでいるプログラム(実際にはカーネル)をビルドするために使用する次のメイクファイルがあります。ゼロから作成しているため、プロセスについて学習しているため、完璧ではありませんが、この時点では、メイクファイルを作成した経験のレベルに十分な力があると思います。

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

このメイクファイルの主な問題は、1つまたは複数のCファイルに含まれるヘッダーファイルを変更しても、Cファイルが再構築されないことです。すべてのヘッダーファイルをすべてのCファイルの依存関係にすることで、これを非常に簡単に修正できますが、ヘッダーファイルを変更/追加するとプロジェクトが完全に再構築されることになり、あまり優雅ではありません。

私が欲しいのは、includeが変更されるヘッダーファイルであるCファイルのみであり、プロジェクト全体が再度リンクされることです。すべてのヘッダーファイルをターゲットの依存関係にすることでリンクを作成できますが、含まれているヘッダーファイルが新しい場合にCファイルを無効にする方法はわかりません。

GCCにはこれを可能にするいくつかのコマンドがあると聞きました(したがって、メイクファイルはどのファイルを再構築する必要があるのか​​を何らかの方法で把握できます)が、実際の実装例を見ることはできません。誰かがメイクファイルでこの動作を有効にするソリューションを投稿できますか?

編集:私は明確にする必要があります、私は個々のターゲットを配置し、各target.oがヘッダーファイルを必要とするという概念に精通しています。そのため、ヘッダーファイルをどこかにインクルードするたびにメイクファイルを編集する必要がありますが、これは少し苦痛です。ヘッダーファイルの依存関係を独自に導出できるソリューションを探しています。これは、他のプロジェクトで見たことがあると確信しています。

86
Nicholas Flynt

このサイトの他の場所で既に指摘したように、このページを参照してください: Auto-Dependency Generation

つまり、gccは自動的に.d依存ファイルを作成できます。これは、コンパイルした.cファイルの依存関係を含むミニメイクファイルフラグメントです。 .cファイルを変更してコンパイルするたびに、.dファイルが更新されます。

-Mフラグをgccに追加する以外に、メイクファイルに.dファイルを含める必要があります(Chrisが上記で書いたように)。ページにはさらに複雑な問題があり、sedを使用して解決されますが、makeが存在しないヘッダーファイルを構築できないという苦情があった場合は、それらを無視して「make clean」を実行して.dファイルを削除できます。 。

30
Udi Meiri

他の人が述べたように「make depend」コマンドを追加することもできますが、なぜgccに依存関係を作成させて同時にコンパイルしないのですか:

DEPS := $(COBJS:.o=.d)

-include $(DEPS)

%.o: %.c
    $(CC) -c $(CFLAGS) -MM -MF $(patsubst %.o,%.d,$@) -o $@ $<

'-MF'パラメーターは、依存関係を保存するファイルを指定します。

'-include'の先頭にあるダッシュは、.dファイルが存在しない場合(最初のコンパイル時など)に続行するようにMakeに指示します。

-oオプションに関するgccのバグがあるようです。オブジェクトのファイル名をobj/_file__c.oに設定すると、生成される_file_.dには_file_.oではなくobj/_file_c.oが含まれます。

20
Martin Fido

これは Chris Doddの答え と同等ですが、異なる命名規則を使用します(そして、偶然sedマジックを必要としません。 後の複製 からコピーされます。


GNUコンパイラを使用している場合、コンパイラは依存関係のリストを作成できます。Makefileフラグメント:

depend: .depend

.depend: $(SOURCES)
        rm -f ./.depend
        $(CC) $(CFLAGS) -MM $^>>./.depend;

include .depend

ツールmakedependもありますが、gcc -MM

17
dmckee

Cファイルごとに個別のターゲットを作成し、ヘッダーファイルを依存関係としてリストする必要があります。汎用ターゲットを引き続き使用でき、.h依存関係、その後:

%.o: %.c
        @echo Compiling $<...
        $(CC) $(CFLAGS) -c -o $@ $<

foo.c: bar.h
# And so on...
7
mipadi

基本的に、ヘッダーファイルが変更されたときにオブジェクトファイルを再構築するために、メイクファイルルールを動的に作成する必要があります。 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

メイクファイルで。

4
Chris Dodd

@mipadiが言ったことに加えて、 '-M '依存関係の記録を生成するオプション。それらを別のファイル(おそらく 'depend.mk')に生成し、それをメイクファイルに含めることもできます。または、「make depend '正しい依存関係でメイクファイルを編集するルール(Googleの用語:「この行を削除しないでください」に依存)。

3

より簡単なソリューション:Makefileを使用して、.cから.oへのコンパイルルールをヘッダーファイルと、プロジェクトに依存関係として関係する他のものに依存させます。

たとえば、Makefileのどこかに:

DEPENDENCIES=mydefs.h yourdefs.h Makefile GameOfThrones.S07E01.mkv

::: (your other Makefile statements like rules 
:::  for constructing executables or libraries)

# Compile any .c to the corresponding .o file:
%.o: %.c $(DEPENDENCIES)
        $(CC) $(CFLAGS) -c -o $@ $<
0
Richard Elkins

答えはどれも私には役に立たなかった。例えば。 Martin Fidoの答えは、gccが依存関係ファイルを作成できることを示唆していますが、警告またはエラーなしで空の(ゼロバイトの)オブジェクトファイルを生成しようとしたとき。 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ファイル用に簡単に調整できます。

これら2行の重要性に注意することも重要です。

$(CC) $(CFLAGS) $(INCLUDES) -c -MM -MF $(patsubst %.o,%.d,$@) $<
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<

そのため、gccは一度呼び出されて最初に依存関係ファイルを構築し、次に実際に.ccファイルをコンパイルします。各ソースファイルについてなど。

0
Tagar