QEMU のMakefile 周りを確認

QEMU を拡張するにあたりMakefile を確認する必要がでた。それをまとめる。

- modules ターゲットの依存ファイルは`unnest-vars` で定義されるようだ　

# 関連ファイル
- build-system.txt
    - ここに関連ファイル全体の説明が書いてあった。この記事いらないかも

- Makefile
- Makefile.target
- Makefile.objs
- rules.mak
    - ファイル生成ルールが書いてある
- configure
    - config-all-disas.mak
    - config-host.mak
    - tests/qemu-iotests/common.env

# ソース読み
## Makefile
###はじめは`config-*.mak`の読み込みをしている。

```Makefile
# All following code might depend on configuration variables
ifneq ($(wildcard config-host.mak),)
# Put the all: rule here so that config-host.mak can contain dependencies.
all:
include config-host.mak

# Check that we're not trying to do an out-of-tree build from
# a tree that's been used for an in-tree build.
ifneq ($(realpath $(SRC_PATH)),$(realpath .))
ifneq ($(wildcard $(SRC_PATH)/config-host.mak),)
$(error This is an out of tree build but your source tree ($(SRC_PATH)) \
seems to have been used for an in-tree build. You can fix this by running \
"make distclean && rm -rf *-linux-user *-softmmu" in your source tree)
endif
endif

CONFIG_SOFTMMU := $(if $(filter %-softmmu,$(TARGET_DIRS)),y)
CONFIG_USER_ONLY := $(if $(filter %-user,$(TARGET_DIRS)),y)
CONFIG_ALL=y
-include config-all-devices.mak
-include config-all-disas.mak

## config-host.mak が古くないかを確認
config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/pc-bios
	@echo $@ is out-of-date, running configure
	@# TODO: The next lines include code which supports a smooth
	@# transition from old configurations without config.status.
	@# This code can be removed after QEMU 1.7.
	@if test -x config.status; then \
	    ./config.status; \
        else \
	    sed -n "/.*Configured with/s/[^:]*: //p" $@ | sh; \
	fi
else
## config-host.mak がなければ異常終了
config-host.mak:
ifneq ($(filter-out $(UNCHECKED_GOALS),$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail))
	@echo "Please call configure before running make!"
	@exit 1
endif
endif
```

### 次にルールの読み込みと生成されるヘッダーやソースの登録。`GENERATED_HEADERS`や`GENERATED_SOURCES` はclean ターゲットで使われる。後者はビルド時に自動的に生成されるようルールが作られる。

```Makefile
include $(SRC_PATH)/rules.mak


GENERATED_HEADERS = qemu-version.h config-host.h qemu-options.def
GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h
GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c
GENERATED_HEADERS += qmp-introspect.h
GENERATED_SOURCES += qmp-introspect.c

GENERATED_HEADERS += trace/generated-events.h
GENERATED_SOURCES += trace/generated-events.c

GENERATED_HEADERS += trace/generated-tracers.h
ifeq ($(findstring dtrace,$(TRACE_BACKENDS)),dtrace)
GENERATED_HEADERS += trace/generated-tracers-dtrace.h
endif
GENERATED_SOURCES += trace/generated-tracers.c

GENERATED_HEADERS += trace/generated-tcg-tracers.h

GENERATED_HEADERS += trace/generated-helpers-wrappers.h
GENERATED_HEADERS += trace/generated-helpers.h
GENERATED_SOURCES += trace/generated-helpers.c

ifeq ($(findstring ust,$(TRACE_BACKENDS)),ust)
GENERATED_HEADERS += trace/generated-ust-provider.h
GENERATED_SOURCES += trace/generated-ust.c
endif
```

### メタな設定

```Makefile
# Don't try to regenerate Makefile or configure
# We don't generate any of them
Makefile: ;
configure: ;

.PHONY: all clean cscope distclean dvi html info install install-doc \
	pdf recurse-all speed test dist msi FORCE

$(call set-vpath, $(SRC_PATH))
```

### ライブラリ設定

```Makefile
LIBS+=-lz $(LIBS_TOOLS)
```

### よくわからん

```Makefile
HELPERS-$(CONFIG_LINUX) = qemu-bridge-helper$(EXESUF)
```

### 生成するドキュメントの選択

```Makefile
ifdef BUILD_DOCS
DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 qemu-ga.8
ifdef CONFIG_VIRTFS
DOCS+=fsdev/virtfs-proxy-helper.1
endif
else
DOCS=
endif
```

### Make のフラグ設定

```Makefile
SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory) BUILD_DIR=$(BUILD_DIR)
```

### デバイス周り

```Makefile
SUBDIR_DEVICES_MAK=$(patsubst %, %/config-devices.mak, $(TARGET_DIRS))
SUBDIR_DEVICES_MAK_DEP=$(patsubst %, %-config-devices.mak.d, $(TARGET_DIRS))

ifeq ($(SUBDIR_DEVICES_MAK),)
config-all-devices.mak:
	$(call quiet-command,echo '# no devices' > $@,"  GEN   $@")
else
config-all-devices.mak: $(SUBDIR_DEVICES_MAK)
	$(call quiet-command, sed -n \
             's|^\([^=]*\)=\(.*\)$$|\1:=$$(findstring y,$$(\1)\2)|p' \
             $(SUBDIR_DEVICES_MAK) | sort -u > $@, \
             "  GEN   $@")
endif

-include $(SUBDIR_DEVICES_MAK_DEP)


%/config-devices.mak: default-configs/%.mak $(SRC_PATH)/scripts/make_device_config.sh
	$(call quiet-command, \
            $(SHELL) $(SRC_PATH)/scripts/make_device_config.sh $< $*-config-devices.mak.d $@ > $@.tmp, "  GEN   $@.tmp")
	$(call quiet-command, if test -f $@; then \
	  if cmp -s $@.old $@; then \
	    mv $@.tmp $@; \
	    cp -p $@ $@.old; \
	  else \
	    if test -f $@.old; then \
	      echo "WARNING: $@ (user modified) out of date.";\
	    else \
	      echo "WARNING: $@ out of date.";\
	    fi; \
	    echo "Run \"make defconfig\" to regenerate."; \
	    rm $@.tmp; \
	  fi; \
	 else \
	  mv $@.tmp $@; \
	  cp -p $@ $@.old; \
	 fi, "  GEN   $@");


defconfig:
	rm -f config-all-devices.mak $(SUBDIR_DEVICES_MAK)
```

### `Makefile.objs` の読み込み

```Makefile
ifneq ($(wildcard config-host.mak),)
include $(SRC_PATH)/Makefile.objs
endif
```

### 各変数内のオブジェクトを、ディレクトリを再帰的に辿って確認する。

```Makefile
dummy := $(call unnest-vars,, \
                stub-obj-y \
                util-obj-y \
                qga-obj-y \
                ivshmem-client-obj-y \
                ivshmem-server-obj-y \
                qga-vss-dll-obj-y \
                block-obj-y \
                block-obj-m \
                crypto-obj-y \
                crypto-aes-obj-y \
                qom-obj-y \
                io-obj-y \
                common-obj-y \
                common-obj-m)
```

### テスト用のMakefile を読み込む
 
```Makefile
ifneq ($(wildcard config-host.mak),)
include $(SRC_PATH)/tests/Makefile.include
endif
```

### ここでようやくall を設定
```Makefile
all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all modules
```

### 自動生成ファイルの依存関係設定
ただし、暗黙のルールに沿うわけではないので、依存関係を設定するだけで意味があるのかは不明。

```Makefile

config-host.h: config-host.h-timestamp
config-host.h-timestamp: config-host.mak
qemu-options.def: $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/scripts/hxtool
	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $@")
```

### SUBDIR_RULES の名前, SOFTMMU_SUBDIR_RULES の設定
もっとも、SUBDIR_RULESがどのような変数なのか不明なので、何をしたいのかわからない。
SOFTMMU_SUBDIR_RULES については、softmmu に必要なサブモジュールのビルドを促すもののようである。

```Makefile
SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
SOFTMMU_SUBDIR_RULES=$(filter %-softmmu,$(SUBDIR_RULES))

$(SOFTMMU_SUBDIR_RULES): $(block-obj-y)
$(SOFTMMU_SUBDIR_RULES): $(crypto-obj-y)
$(SOFTMMU_SUBDIR_RULES): $(io-obj-y)
$(SOFTMMU_SUBDIR_RULES): config-all-devices.mak

subdir-%:
	$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $* V="$(V)" TARGET_DIR="$*/" all,)
```


### PIXMAN 周り
```Makefile
subdir-pixman: pixman/Makefile
	$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C pixman V="$(V)" all,)

pixman/Makefile: $(SRC_PATH)/pixman/configure
	(cd pixman; CFLAGS="$(CFLAGS) -fPIC $(extra_cflags) $(extra_ldflags)" $(SRC_PATH)/pixman/configure $(AUTOCONF_HOST) --disable-gtk --disable-shared --enable-static)

$(SRC_PATH)/pixman/configure:
	(cd $(SRC_PATH)/pixman; autoreconf -v --install)
```

### DTC 周り
```Makefile
DTC_MAKE_ARGS=-I$(SRC_PATH)/dtc VPATH=$(SRC_PATH)/dtc -C dtc V="$(V)" LIBFDT_srcdir=$(SRC_PATH)/dtc/libfdt
DTC_CFLAGS=$(CFLAGS) $(QEMU_CFLAGS)
DTC_CPPFLAGS=-I$(BUILD_DIR)/dtc -I$(SRC_PATH)/dtc -I$(SRC_PATH)/dtc/libfdt

subdir-dtc:dtc/libfdt dtc/tests
	$(call quiet-command,$(MAKE) $(DTC_MAKE_ARGS) CPPFLAGS="$(DTC_CPPFLAGS)" CFLAGS="$(DTC_CFLAGS)" LDFLAGS="$(LDFLAGS)" ARFLAGS="$(ARFLAGS)" CC="$(CC)" AR="$(AR)" LD="$(LD)" $(SUBDIR_MAKEFLAGS) libfdt/libfdt.a,)

dtc/%:
	mkdir -p $@
```

### SUBDIR_RULES の依存関係設定
```Makefile
$(SUBDIR_RULES): libqemuutil.a libqemustub.a $(common-obj-y) $(qom-obj-y) $(crypto-aes-obj-$(CONFIG_USER_ONLY))
```

### ROMSUBDIR 周りの設定
```Makefile
ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS))
# Only keep -O and -g cflags
romsubdir-%:
	$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C pc-bios/$* V="$(V)" TARGET_DIR="$*/" CFLAGS="$(filter -O% -g%,$(CFLAGS))",)
```


### ALL_SUBDIRS の設定
clean で使われる。
 
```Makefile
ALL_SUBDIRS=$(TARGET_DIRS) $(patsubst %,pc-bios/%, $(ROMS))
```

### recurse-all の設定
all を呼ぶと呼ばれる。 

```Makefile
recurse-all: $(SUBDIR_RULES) $(ROMSUBDIR_RULES)
```

### version オブジェクト関係
```Makefile

$(BUILD_DIR)/version.o: $(SRC_PATH)/version.rc config-host.h | $(BUILD_DIR)/version.lo
	$(call quiet-command,$(WINDRES) -I$(BUILD_DIR) -o $@ $<,"  RC    version.o")
$(BUILD_DIR)/version.lo: $(SRC_PATH)/version.rc config-host.h
	$(call quiet-command,$(WINDRES) -I$(BUILD_DIR) -o $@ $<,"  RC    version.lo")

Makefile: $(version-obj-y) $(version-lobj-y)
```