-1

コンパイルに Makefile を使用するソフトウェアを作成しています。元々、各ファイルにルールを設定していましたが、新しいファイルを追加するたびに面倒であることがわかりました。プロセスを自動化するために、いくつかの調査を行い、GCC/G++ が -M フラグを使用して Makefile ルールを自動的に構築できることを知りました。

単純なディレクトリ構造でこれを行う例はたくさんありますが、私の理想的なディレクトリ構造は次のようになります。

src/ 
    kernel.hpp kernel.cpp
    Types/
          String.cpp
          String.hpp
    Drivers/IO-Ports/
          CMOS.cpp
          CMOS.hpp
    ...

build/
    DEPS/
        kernel.d
        Types/String.d
        ...
    OBJ/
        kernel.o
        Types/String.o
        ...

私の現在のメイクファイル:

CCHOME=/home/dan/opt/cross/bin
CC=@$(CCHOME)/i586-elf-g++
CFLAGS=-ffreestanding -O2 -Wextra -Wall -fno-exceptions -fno-rtti

KernelName=CPlusKern
QEMU=qemu-system-x86_64 -monitor stdio

SrcDIR=src
SourceDIRS:=$(shell find $(SrcDIR) -type d)
SrcFILES=$(shell find $(SrcDIR) -type f -name *.cpp)
HdrFILES=$(shell find $(SrcDIR) -type f -name *.hpp)

DepDIR=$(BuildDIR)/DEPS
DepFILES0=$(subst $(SrcDIR), $(DepDIR),$(SrcFILES))
DepFILES=$(subst .cpp,.d,$(DepFILES0))

ObjDIR=$(BuildDIR)/OBJ
ObjDIRS=$(subst $(SrcDIR),$(ObjDIR),$(SourceDIRS))
ObjFILES0=$(subst $(SrcDIR), $(ObjDIR),$(SrcFILES))
ObjFILES=$(subst .cpp,.o,$(ObjFILES0))

BuildDIR=build
BuildDIRS=$(BuildDIR) $(ObjDIR) $(DepDIR)


all: assemble compile run
image: assemble compile build-image run-image

debug:
    @echo "BuildDIRS: " $(BuildDIRS)
    @echo "DepFiles: " $(DepFILES)
    @echo "SrcFiles: " $(SrcFILES)
    @echo "ObjFiles: " $(ObjFILES)

./src/kernel.o: ./src/kernel.cpp
    @echo $(CC) $(CFLAGS) -MMD -MP -MF $< -o $(subst $(SrcDIR), $(ObjDIR),$@)

./src/kernel.cpp:

dir:
    @echo "Making Build Dirs..."
    @-mkdir -p $(BuildDIRS)

compile: dir $(ObjFILES)
#   @echo "Compiling Source Files: " $(SrcFILES)

assemble: dir boot.o
    @echo "Assembling Core Files..."

boot.o: $(SrcDIR)/boot.s
    @$(CCHOME)/i586-elf-as $(SrcDIR)/boot.s -o $(ObjDIR)/boot.o

build: %.o
    echo "Building Kernel Binary..."
    @$(CC) -T linker.ld -o $(KernelName).bin -ffreestanding -O2 -nostdlib $(SrcFILES)-lgcc

build-image: build
    @echo "Building Kernel Image..."
    @cp $(KernelName).bin isodir/boot/$(KernelName).bin
    @Scripts/MakeGrub.sh $(KernelName) isodir/boot/grub
    grub-mkrescue -o $(KernelName).iso isodir

%.o: %.cpp Makefile
    @echo "Building Object $@"
    $(CC) $(CFLAGS) -MMD -MP -MF $(subst $(SrcDIR),$(DepDIR),$@) -o $(subst $(SrcDIR), $(ObjDIR),$@)

run:
    @echo "Starting QEMU"
    @$(QEMU) -kernel $(KernelName).bin

run-image:
    @echo "Starting QEMU"
    @$(QEMU) -bios OVMF.fd -cdrom $(KernelName).iso

clean:
    @echo "Cleaning Build Directories..."
    -@rm -R $(BuildDIR) ./isodir
    -@$(RM) $(KernelName).bin $(KernelName).iso

私はこれがトリックを行うかもしれないと思ったが、makeはエラーをスローする:

make: *** No rule to make target `build/OBJ/VGA.o', needed by `compile'. Stop.

ルールの作成方法がわかりません:

%.o: %.cpp Makefile
    $(CC) $(CFLAGS) -MMD -MP -MF $(subst $(SrcDIR),$(DepDIR),$@) -o $(subst $(SrcDIR), $(ObjDIR),$@)

すべての .cpp ファイルに適用されます。私の知る限り、ワイルドカードはルール定義では使用できません。

これが役立つかどうかはわかりませんが、各ソース ファイルのパス/名前は $(SrcFILES) 変数に格納されています。

明確にするために、上記のルールの拡張版を次に示します。

/home/dan/opt/cross/bin/i586-elf-g++ -ffreestanding -O2 -Wextra -Wall -fno-exceptions -fno-rtti -MMD -MP -MF src/kernel.cpp -o build/OBJ/kernel.o

そして、このインスタンス用に生成された依存関係ファイル:

kernel.o: src/kernel.cpp src/kernel.hpp src/Globals.hpp \
 src/VGATerminal.hpp src/Types/String.hpp src/Types/../Globals.hpp \
 src/VGA.hpp src/IO/Read.hpp src/IO/Write.hpp \
 src/Drivers/IO-Ports/CMOS.hpp src/Drivers/IO-Ports/../../IO/Read.hpp \
 src/Drivers/IO-Ports/../../IO/Write.hpp

これは私の最初の投稿なので、私の質問に対するフィードバックをお待ちしております:)

うまくいけば、これを解決して、コードの開発に戻ることができます。

編集: @Beta が提供するルールは問題なく機能しました。すべてのオブジェクト ファイルが正常にビルドされ、適切な場所に出力されます。このルールは、build/OBJ/Drivers/IO-Ports/CMOS.obuild/OBJ/Drivers/PS2.o.

したがって、ファイル名を渡せばすべてのオブジェクトを個別にビルドできますが、ファイルごとにルールを作成する必要がないように依存関係の解決が必要だと思います。

4

1 に答える 1

0

これには数回の反復が必要な場合があります。

最初の問題は、ターゲットがbuild/OBJ/VGA.oあり、対応するルールがないことです。ルール

%.o: %.cpp Makefile
    ...

合わない; build/OBJ/VGA.oからビルドできますbuild/OBJ/VGA.cppが、そのようなソース ファイルはありません。

したがって、最初のステップとして、ソース ファイルが の場合は、次のsrc/whatever/VGA.cppルールを試してください。

build/OBJ/%.o: src/whatever/%.cpp
    ...

そして結果を教えてください。

編集:

よし、これを試してみてください:

build/OBJ/%.o: src/%.cpp
    ...
于 2013-06-07T00:20:56.687 に答える