QEMU

QEMU のMakefile 周りを確認

More than 1 year has passed since last update.

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の読み込みをしている。

# 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_HEADERSGENERATED_SOURCES はclean ターゲットで使われる。後者はビルド時に自動的に生成されるようルールが作られる。

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

メタな設定

# 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))

ライブラリ設定

LIBS+=-lz $(LIBS_TOOLS)

よくわからん

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

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

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 のフラグ設定

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

デバイス周り

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 の読み込み

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

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

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 を読み込む

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

ここでようやくall を設定

all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all modules

自動生成ファイルの依存関係設定

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

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 に必要なサブモジュールのビルドを促すもののようである。

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 周り

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 周り

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 の依存関係設定

$(SUBDIR_RULES): libqemuutil.a libqemustub.a $(common-obj-y) $(qom-obj-y) $(crypto-aes-obj-$(CONFIG_USER_ONLY))

ROMSUBDIR 周りの設定

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 で使われる。

ALL_SUBDIRS=$(TARGET_DIRS) $(patsubst %,pc-bios/%, $(ROMS))

recurse-all の設定

all を呼ぶと呼ばれる。

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

version オブジェクト関係

$(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)