diff options
Diffstat (limited to 'Makefile')
-rw-r--r-- | Makefile | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..33e8c140 --- /dev/null +++ b/Makefile @@ -0,0 +1,333 @@ +SHELL := /bin/sh + +MAKEFLAGS += -rR +MAKEFLAGS += --no-print-directory + +.PHONY: all +all: x15 docs + +VERSION = 0.1 +export VERSION + +ifndef V +V := 0 +endif + +# Use callable variables so that commands can be split into multiple +# lines, but produce a single line when echoed. This makes copying +# commands easy. It also makes them somewhat self-describing. + +ifeq ($(V),0) +Q := @ + +# $(call xbuild_action_print,<action_short_name>,<target>) +define xbuild_action_print +@printf " %-7s %s\n" $(1) $(2) +@ +endef +else ifneq ($(V),1) +$(error invalid value for V) +endif + +export Q + +# $(call xbuild_action_mkdir,<target>) +define xbuild_action_mkdir + $(Q)mkdir -p $(dir $(1)) +endef + +# $(call xbuild_action,<action>,<target>) +define xbuild_action + $(call xbuild_action_mkdir,$(2)) + $(call xbuild_action_print,$(1),$(2)) +endef + +define xbuild_kconfig_invoke + $(Q)$(MAKE) -f $(SRCDIR)/$(KCONFIG_PATH)/Makefile $@ +endef + +define xbuild_gen_autoconf_h + $(call xbuild_action,GEN,$@)cat $< \ + | sed -e 's/^\([^#]\)/#define CONFIG_\1/g' \ + -e 's/=/ /' \ + | grep '^#define' > $@ +endef + +define xbuild_gen_autoconf_mk + $(call xbuild_action,GEN,$@)cat $< \ + | sed -e 's/^\([^#]\)/CONFIG_\1/g' > $@ +endef + +# $(call xbuild_check_cc_option,<option>) +define xbuild_check_cc_option +$(shell printf "int main(void){ return 0; }\n" \ + | $(CC) -Wall -Werror -x c $(1) -c - -o /dev/null 2> /dev/null \ + && printf -- "%s" $(1)) +endef + +# $(call xbuild_replace_source_suffix,<suffix>,<file_names>) +define xbuild_replace_source_suffix +$(sort $(patsubst %.c,%.$(1),$(filter %.c,$(2))) \ + $(patsubst %.S,%.$(1),$(filter %.S,$(2)))) +endef + +define xbuild_compile + $(call xbuild_action,CC,$@) \ + $(COMPILE) -MMD -MP -c -o $@ $< +endef + +define xbuild_gen_linker_script + $(call xbuild_action,LDS,$@) \ + $(CPP) $(XBUILD_CPPFLAGS) -P -o $@ $< +endef + +# $(call xbuild_link,<objects>) +define xbuild_link + $(call xbuild_action,LD,$@) \ + $(COMPILE) -o $@ $(1) $(XBUILD_LDFLAGS) +endef + +define xbuild_clean + $(Q)rm -f x15 \ + $(x15_OBJDEPS) \ + $(x15_OBJECTS) \ + $(x15_LDS) +endef + +define xbuild_distclean + $(clean) + $(Q)rm -f .config \ + .config.old \ + include/generated/autoconf.h \ + include/generated/autoconf.mk +endef + +ARCH ?= $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ ) +export ARCH + +SRCDIR := $(realpath $(dir $(realpath $(firstword $(MAKEFILE_LIST))))) +VPATH := $(SRCDIR) +export SRCDIR VPATH + +PREFIX ?= /usr/local +DATAROOTDIR ?= share + +# Do not use MAKEFILE_LIST as its value is updated only on inclusion, +# which makes it unsuitable as a rule dependency in most of the file. +# +# These additional Makefiles are included in order. +MAKEFILE_INCLUDES := \ + $(SRCDIR)/arch/$(ARCH)/Makefile \ + $(SRCDIR)/doc/Makefile \ + $(SRCDIR)/kern/Makefile \ + $(SRCDIR)/test/Makefile \ + $(SRCDIR)/vm/Makefile +ALL_MAKEFILES := $(MAKEFILE_LIST) $(MAKEFILE_INCLUDES) + +ifeq ($(words $(MAKECMDGOALS)),0) +else ifeq ($(words $(MAKECMDGOALS)),1) +else +$(error up to one target may be given) +endif + +KCONFIG_PATH := tools/kconfig + +# Export to Kconfig +export KCONFIG_PATH + +HOSTCC := $(if $(shell type gcc 2>/dev/null),gcc,cc) +HOSTCXX = g++ +HOSTCFLAGS := -g +HOSTCXXFLAGS := -g + +# Export to Kconfig +export HOSTCC HOSTCXX HOSTCFLAGS HOSTCXXFLAGS + +BOARDS := $(wildcard $(SRCDIR)/arch/$(ARCH)/configs/*_defconfig) +BOARDS := $(sort $(notdir $(BOARDS))) + +.PHONY: help +help: + @printf 'Configuration targets:\n' + @$(Q)$(MAKE) -f $(SRCDIR)/$(KCONFIG_PATH)/Makefile $@ + @printf '\n' + @printf 'Cleaning targets:\n' + @printf ' clean - Remove most generated files but keep configuration\n' + @printf ' distclean - Remove all generated files\n' + @printf '\n' + @printf 'Build targets:\n' + @printf ' all - Build all targets marked with [*]\n' + @printf '* x15 - Build the kernel ELF image\n' + @printf '\n' + $(DOC_HELP) + @printf 'Installation targets:\n' + @printf ' install - Install the kernel and documentation\n' + @printf ' install-strip - Same as install but also strip the kernel\n' + @printf '\n' + @printf 'Architecture specific targets ($(ARCH)):\n' + @$(if $(BOARDS), \ + $(foreach b, $(BOARDS), \ + printf " %-24s - Build for %s\\n" $(b) $(subst _defconfig,,$(b));)) + @printf '\n' + @printf 'Options:\n' + @printf ' make V=0 - Quiet build\n' + @printf ' make V=1 - Verbose build\n' + @printf '\n' + @printf 'Notes:\n' + @printf '- One target at most may be specified.\n' + @printf '- The compiler program and flags may be given at configuration time\n' + @printf ' through the CC and CFLAGS variables respectively.\n' + @printf '- Out-of-tree builds are performed with the following command:\n' + @printf ' make -f path/to/src/Makefile [options] [target]\n' + @printf '- The source directory must be completely clean for reliable out-of-tree builds.\n' + @printf '- Use the DESTDIR and PREFIX variables to control installation, e.g.:\n' + @printf ' make DESTDIR=/stagingroot PREFIX=/usr install\n' + @printf '\n' + @printf 'See README for more information.\n' + +# Don't create a %config pattern rule as it would conflict with .config +KCONFIG_TARGETS := config nconfig menuconfig xconfig gconfig \ + allnoconfig allyesconfig alldefconfig randconfig \ + oldconfig defconfig savedefconfig listnewconfig + +.PHONY: $(KCONFIG_TARGETS) +$(KCONFIG_TARGETS): + $(call xbuild_kconfig_invoke) + +%_defconfig: + $(call xbuild_kconfig_invoke) + +include/generated/autoconf.h: .config $(ALL_MAKEFILES) + $(call xbuild_gen_autoconf_h) + +include/generated/autoconf.mk: .config $(ALL_MAKEFILES) + $(call xbuild_gen_autoconf_mk) + +ifneq ($(MAKECMDGOALS),help) +-include include/generated/autoconf.mk +endif + +ifdef CONFIG_CC_EXE +# Use printf to remove quotes +CC := $(shell printf -- $(CONFIG_CC_EXE)) +else +CC := gcc +endif + +# Export to CONFIG_CC +export CC + +CPP = $(CC) -E + +CFLAGS ?= -O2 -g + +# Export to CONFIG_CFLAGS +export CFLAGS + +XBUILD_CPPFLAGS := +XBUILD_CFLAGS := + +XBUILD_CPPFLAGS += -pipe + +# Do not include headers from the hosted environment, but +# do include headers from the compiler. +XBUILD_CPPFLAGS += -nostdinc +XBUILD_CPPFLAGS += -isystem $(shell $(CC) -print-file-name=include) + +XBUILD_CPPFLAGS += -std=gnu11 +XBUILD_CPPFLAGS += -ffreestanding +XBUILD_CPPFLAGS += -include $(SRCDIR)/kern/config.h +XBUILD_CPPFLAGS += -include include/generated/autoconf.h +XBUILD_CPPFLAGS += -I$(SRCDIR) +XBUILD_CPPFLAGS += -I$(SRCDIR)/include +XBUILD_CPPFLAGS += -I$(SRCDIR)/arch/$(ARCH) + +ifndef CONFIG_ASSERT +XBUILD_CPPFLAGS += -DNDEBUG +endif + +XBUILD_CFLAGS += -fsigned-char +XBUILD_CFLAGS += -fno-common + +XBUILD_CFLAGS += -Wall +XBUILD_CFLAGS += -Wextra +XBUILD_CFLAGS += -Wshadow +XBUILD_CFLAGS += -Wmissing-prototypes +XBUILD_CFLAGS += -Wstrict-prototypes + +XBUILD_CFLAGS += $(call xbuild_check_cc_option,-fno-PIE) +XBUILD_CFLAGS += $(call xbuild_check_cc_option,-Qunused-arguments) + +XBUILD_LDFLAGS += -static -nostdlib -lgcc + +x15_SOURCES-y := +x15_LDS_S := arch/$(ARCH)/x15.lds.S + +# Include the additional Makefiles here, as they may augment the build +# variables. +include $(MAKEFILE_INCLUDES) + +# Export to Kconfig. +# Must be defined by the architecture-specific Makefile. +export KCONFIG_DEFCONFIG + +ifdef CONFIG_CC_OPTIONS +# Use printf to remove quotes +XBUILD_CFLAGS += $(shell printf -- $(CONFIG_CC_OPTIONS)) +endif + +COMPILE := $(CC) $(XBUILD_CPPFLAGS) $(XBUILD_CFLAGS) + +# Don't change preprocessor and compiler flags from this point + +x15_SOURCES := $(x15_SOURCES-y) +x15_OBJDEPS := $(call xbuild_replace_source_suffix,d,$(x15_SOURCES)) +x15_OBJECTS := $(call xbuild_replace_source_suffix,o,$(x15_SOURCES)) +x15_LDS := $(basename $(x15_LDS_S)) + +XBUILD_LDFLAGS += -Xlinker -T $(x15_LDS) + +define gen_sorted_init_ops + $(call xbuild_action,GEN,$@) \ + $(SRCDIR)/tools/tsort_init_ops.sh "$(COMPILE)" "$@" $^ +endef + +.INTERMEDIATE: .x15.sorted_init_ops +.x15.sorted_init_ops: $(filter %.c,$(x15_SOURCES)) + $(call gen_sorted_init_ops) + +x15_DEPS := $(x15_LDS) .x15.sorted_init_ops + +# Compiling produces dependency rules as a side-effect. When the dependency +# rules file doesn't exist, the main source file is enough to trigger a +# rebuild. Afterwards, the dependency rules file is included here and the +# rules provide correct incremental compilation. +-include $(x15_OBJDEPS) + +%.o: %.c include/generated/autoconf.h + $(xbuild_compile) + +%.o: %.S include/generated/autoconf.h + $(xbuild_compile) + +%.lds: %.lds.S include/generated/autoconf.h + $(xbuild_gen_linker_script) + +x15: $(x15_OBJECTS) $(x15_DEPS) + $(call xbuild_link,$(x15_OBJECTS)) + +.PHONY: install install-strip +install: docs_install + install -D -m 644 x15 $(DESTDIR)/boot/x15 + +install-strip: docs_install + install -s -D -m 644 x15 $(DESTDIR)/boot/x15 + +.PHONY: clean distclean +clean: docs_clean + $(Q)$(MAKE) -f $(SRCDIR)/$(KCONFIG_PATH)/Makefile $@ + $(call xbuild_clean) + +distclean: clean docs_distclean + $(Q)$(MAKE) -f $(SRCDIR)/$(KCONFIG_PATH)/Makefile $@ + $(call xbuild_distclean) |