X-Git-Url: http://akaros.cs.berkeley.edu/gitweb/?p=akaros.git;a=blobdiff_plain;f=Makefile;h=5f7681f3dde6e074dd872bef8b875834a5aa1df2;hp=9897db00a48e74851be711d16c574d6b78170274;hb=f195b3f1e068302e5ce7459fd1a5aba68503f0bf;hpb=758d2e8950e46aeb583b33b4b89a154fccf035f5 diff --git a/Makefile b/Makefile index 9897db0..5f7681f 100644 --- a/Makefile +++ b/Makefile @@ -16,25 +16,18 @@ # of the default settings that silentoldconfig uses, but I'll leave it as-is # for now, and just symlink that into kern/include. It'll be easier for us, # and also potentially easier if we ever move kern/ up a level. Similarly, -# there are default Kconfigs in arch/, not in kern/arch. I might change -# that, if we want to support defconfig, or just symlink it. +# there are default Kconfigs in arch/, not in kern/arch. I just symlinked +# arch->kern/arch to keep everything simple. # # TODO: -# - Connect to kconfig, have it generate our CONFIGS, instead of makelocal. -# - what about userspace / tests? -# the only one is SYSCALL_TRAP. the others control building -# - keep them using the old style -# - might need to symlink arch -> kern/arch/ too -# - though def config is hardcoded to arch/$ARCH, instead of k/a/ -# # - Consider merging the two target-detection bits (Linux's config, mixed, or -# dot target, and the symlink handling). -# -# - Do we want some sort of default config? Or the ability to change arches -# and keep common vars? +# dot target, and the symlink handling). Also, could consider moving around +# the KFS and EXT2 targets. Clean doesn't need to know about them, for +# instance. # # - Review, with an eye for being better about $(srctree). It might only be -# necessary in this file, if we every do the KBUILD_OUTPUT option +# necessary in this file, if we every do the KBUILD_OUTPUT option. But we +# don't always want it (like for the implicit rule for Makefile) # # - It's a bit crazy that we build symlinks for parlib, instead of it # managing its own links based on $(ARCH) @@ -54,6 +47,14 @@ MAKEFLAGS += -rR --no-print-directory PHONY := all all: akaros-kernel +# Export the location of this top level directory +AKAROS_ROOT = $(CURDIR) +export AKAROS_ROOT + +# Setup dumping ground for object files and any temporary files we need to +# generate for non-kbuild targets +OBJDIR ?= obj + # Symlinks # ========================================================================= # We have a few symlinks so that code can include . This @@ -78,8 +79,8 @@ goals-has-build-targets := 1 endif PHONY += symlinks clean_symlinks -clean_symlinks: - @-rm -f kern/include/arch kern/boot user/parlib/include/arch +clean_symlinks: objclean + @rm -f kern/include/arch kern/boot user/parlib/include/arch arch-link := $(notdir $(shell readlink kern/include/arch)) valid-arches := $(notdir $(wildcard kern/arch/*)) @@ -119,7 +120,8 @@ symlinks: endif # ifneq ($(arch-link),) endif # ifeq ($(ARCH),) -export ARCH +SRCARCH := $(ARCH) +export ARCH SRCARCH # Generic Kbuild Environment # ========================================================================= @@ -187,68 +189,6 @@ export quiet Q KBUILD_VERBOSE $(srctree)/scripts/Kbuild.include: ; include $(srctree)/scripts/Kbuild.include -# Akaros Build Environment -# ========================================================================= -AKAROSINCLUDE := \ - -I$(srctree)/kern/arch/ \ - -I$(srctree)/kern/include/ - -CROSS_COMPILE := $(ARCH)-ros- - -CC := $(CROSS_COMPILE)gcc -CPP := $(CROSS_COMPILE)g++ -AS := $(CROSS_COMPILE)as -AR := $(CROSS_COMPILE)ar -LD := $(CROSS_COMPILE)ld -OBJCOPY := $(CROSS_COMPILE)objcopy -OBJDUMP := $(CROSS_COMPILE)objdump -NM := $(CROSS_COMPILE)nm -STRIP := $(CROSS_COMPILE)strip - -ifeq ($(goals-has-build-targets),1) -ifeq ($(shell which $(CROSS_COMPILE)gcc 2>/dev/null ),) -$(error Could not find a $(CROSS_COMPILE) version of GCC/binutils. \ - Be sure to build the cross-compiler and update your PATH) -endif -# Computing these without a cross compiler complains loudly -gcc-lib := $(shell $(CC) -print-libgcc-file-name) -NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include) -# Note: calling this GCC_ROOT interferes with the host tools -XCC_ROOT := $(dir $(shell which $(CC)))../ -endif - -CFLAGS_KERNEL += -O2 -pipe -MD -gstabs -CFLAGS_KERNEL += -std=gnu99 -fgnu89-inline -CFLAGS_KERNEL += -fno-strict-aliasing -fno-omit-frame-pointer -CFLAGS_KERNEL += -fno-stack-protector -CFLAGS_KERNEL += -Wall -Wno-format -Wno-unused -CFLAGS_KERNEL += -DROS_KERNEL -CFLAGS_KERNEL += -include include/generated/autoconf.h - -# TODO: do we need this, or can we rely on the compiler's defines? -CFLAGS_KERNEL += -D$(ARCH) - -# TODO: this requires our own strchr (kern/src/stdio.c), which is a potential -# source of bugs/problems. -# note we still pull in stdbool and stddef from the compiler -CFLAGS_KERNEL += -fno-builtin - -AFLAGS_KERNEL := $(CFLAGS_KERNEL) - -KBUILD_BUILTIN := 1 -KBUILD_CHECKSRC := 0 - -export AKAROSINCLUDE CROSS_COMPILE -export CC CPP AS AR LD OBJCOPY OBJDUMP NM STRIP -export CFLAGS_KERNEL AFLAGS_KERNEL -export NOSTDINC_FLAGS XCC_ROOT -export KBUILD_BUILTIN KBUILD_CHECKSRC - -CFLAGS_USER += -O2 -std=gnu99 -fno-stack-protector -fgnu89-inline -CXXFLAGS_USER += -O2 - -export CFLAGS_USER CXXFLAGS_USER - # Kbuild Target/Goals Parsing # ========================================================================= # Need to figure out if we're a config or not, and whether or not to include @@ -297,6 +237,13 @@ ifeq ($(config-targets),1) # =========================================================================== # *config targets only - make sure prerequisites are updated, and descend # in scripts/kconfig to make the *config target + +# Default config file, per arch. This path will resolve to +# arch/$ARCH/configs/defconfig (arch -> kern/arch). Each arch can override +# this if they want, or just symlink to one in the main root directory. +KBUILD_DEFCONFIG := defconfig +export KBUILD_DEFCONFIG + config: scripts_basic symlinks FORCE $(Q)mkdir -p include/config $(Q)$(MAKE) $(build)=scripts/kconfig $@ @@ -336,28 +283,103 @@ else include/config/auto.conf: ; endif # $(dot-config) +# Akaros Build Environment +# ========================================================================= +AKAROSINCLUDE := -I$(srctree)/kern/include/ + +# CROSS_COMPILE is defined per-arch. Each arch can set other makeflags, kbuild +# directories, etc. +-include $(srctree)/kern/arch/$(ARCH)/Makefile + +CC := $(CROSS_COMPILE)gcc +CPP := $(CROSS_COMPILE)g++ +AS := $(CROSS_COMPILE)as +AR := $(CROSS_COMPILE)ar +LD := $(CROSS_COMPILE)ld +OBJCOPY := $(CROSS_COMPILE)objcopy +OBJDUMP := $(CROSS_COMPILE)objdump +NM := $(CROSS_COMPILE)nm +STRIP := $(CROSS_COMPILE)strip +KERNEL_LD ?= kernel.ld + +# These may have bogus values if there is no compiler. The kernel and user +# build targets will check cc-exists. Hopefully no cleaning targets rely on +# these. Note that if you change configs, these will get computed once, before +# silentoldconfig kicks in to regenerate auto.conf, and these values will +# temporarily be stale. +gcc-lib := $(shell $(CC) -print-libgcc-file-name 2>/dev/null) +NOSTDINC_FLAGS += -nostdinc -isystem \ + $(shell $(CC) -print-file-name=include 2>/dev/null) +XCC_TARGET_ROOT := $(dir $(shell which $(CC) 2> /dev/null))../$(patsubst %-,%,\ + $(CROSS_COMPILE)) + +CFLAGS_KERNEL += -O2 -pipe -MD +CFLAGS_KERNEL += -std=gnu99 -fgnu89-inline +CFLAGS_KERNEL += -fno-strict-aliasing -fno-omit-frame-pointer +CFLAGS_KERNEL += -fno-stack-protector +CFLAGS_KERNEL += -Wall -Wno-format -Wno-unused +CFLAGS_KERNEL += -DROS_KERNEL +CFLAGS_KERNEL += -include include/generated/autoconf.h -include include/common.h +CFLAGS_KERNEL += -fplan9-extensions +ifeq ($(CONFIG_64BIT),y) +CFLAGS_KERNEL += -m64 -g +else +CFLAGS_KERNEL += -m32 -gstabs +endif + +# TODO: do we need this, or can we rely on the compiler's defines? +CFLAGS_KERNEL += -D$(ARCH) + +# TODO: this requires our own strchr (kern/src/stdio.c), which is a potential +# source of bugs/problems. +# note we still pull in stdbool and stddef from the compiler +CFLAGS_KERNEL += -fno-builtin + +AFLAGS_KERNEL := $(CFLAGS_KERNEL) + +KBUILD_BUILTIN := 1 +KBUILD_CHECKSRC := 0 + +export AKAROSINCLUDE CROSS_COMPILE +export CC CPP AS AR LD OBJCOPY OBJDUMP NM STRIP +export CFLAGS_KERNEL AFLAGS_KERNEL +export NOSTDINC_FLAGS XCC_TARGET_ROOT +export KBUILD_BUILTIN KBUILD_CHECKSRC + +CFLAGS_USER += -O2 -std=gnu99 -fno-stack-protector -fgnu89-inline +CXXFLAGS_USER += -O2 + +export CFLAGS_USER CXXFLAGS_USER + # Akaros include stuff (includes custom make targets and user overrides) # ========================================================================= # The user can override this, though it won't apply for any of the in-tree # kernel build output. Right now, it's only passed down to tests/ -OBJDIR ?= obj dummy-1 := $(shell mkdir -p $(OBJDIR)/kern/) # Don't need to export these, since the Makelocal is included. KERNEL_OBJ := $(OBJDIR)/kern/akaros-kernel CMP_KERNEL_OBJ := $(KERNEL_OBJ).gz -# TODO: have the KFS paths be determined in .config -# Give it a reasonable default path for initramfs to avoid build breakage -INITRAMFS_PATHS = kern/kfs -FIRST_INITRAMFS_PATH = $(firstword $(INITRAMFS_PATHS)) +# Since we're doing this outside of the dot-config part, some targets, such as +# clean, won't read in our .config/auto.conf, and won't know about the +# KFS_PATH. Future rules related to KFS will have issues (mkdir with no +# argument, or a find of the entire pwd). It's also possible someone provided +# an empty path. To deal with both, we'll just have a sensible default. +kfs-paths := $(subst $\",,$(CONFIG_KFS_PATHS)) +ifeq ($(kfs-paths),) +kfs-paths := kern/kfs +endif + +FIRST_KFS_PATH = $(firstword $(kfs-paths)) -export OBJDIR INITRAMFS_PATHS FIRST_INITRAMFS_PATH +export OBJDIR FIRST_KFS_PATH # Avoiding implicit rules -$(srctree)/Makeconfig $(srctree)/Makelocal: ; -include $(srctree)/Makeconfig +$(srctree)/Makelocal: ; +# TODO: one issue is that we import all types of targets: build, clean, etc. +# That makes it a bit tougher to reorganize with ifeqs. -include $(srctree)/Makelocal # Akaros Kernel Build @@ -372,7 +394,7 @@ include $(srctree)/Makeconfig # We have all-arch-dirs and all-dirs, so that we can still clean even without # an arch symlink. -core-y += kern/src/ +core-y += kern/src/ kern/drivers/ $(AKAROS_EXTERNAL_DIRS) arch-y += kern/arch/$(ARCH)/ akaros-dirs := $(patsubst %/,%,$(filter %/, $(core-y) $(arch-y))) @@ -384,48 +406,98 @@ core-y := $(patsubst %/, %/built-in.o, $(core-y)) arch-y := $(patsubst %/, %/built-in.o, $(arch-y)) kbuild_akaros_main := $(core-y) $(arch-y) -akaros-deps := $(kbuild_akaros_main) kern/arch/$(ARCH)/kernel.ld +akaros-deps := $(kbuild_akaros_main) kern/arch/$(ARCH)/$(KERNEL_LD) kern_cpio := $(OBJDIR)/kern/initramfs.cpio kern_cpio_obj := $(kern_cpio).o -ifneq ($(EXT2_BDEV),) -ext2_bdev_obj := $(OBJDIR)/kern/$(shell basename $(EXT2_BDEV)).o + +# ext2 will crash at runtime if we don't have a block device. try to catch the +# errors now. if it is a bad one, you're just out of luck. +ifneq ($(CONFIG_EXT2FS),) +ext2-bdev := $(patsubst "%",%,$(CONFIG_EXT2_BDEV)) +ifeq ($(ext2-bdev),) +$(error EXT2 selected with no block device [$(ext2-bdev)], fix your .config) +endif +ext2_bdev_obj = $(OBJDIR)/kern/$(shell basename $(ext2-bdev)).o +endif + +# a bit hacky: we want to make sure the directories exist, and error out +# otherwise. we also want to error out before the initramfs target, otherwise +# we might not get the error (if initramfs files are all up to date). the +# trickiest thing here is that kfs-paths-check could be stale and require an +# oldconfig. running make twice should suffice. +kfs-paths-check := $(shell for i in $(kfs-paths); do \ + if [ ! -d "$$i" ]; then \ + echo "Can't find KFS directory $$i"; \ + $(MAKE) -f $(srctree)/Makefile \ + silentoldconfig > /dev/null; \ + exit -1; \ + fi; \ + done; echo "ok") + +ifneq (ok,$(kfs-paths-check)) +$(error $(kfs-paths-check), try make one more time in case of stale configs) endif -kern_initramfs_files := $(shell mkdir -p $(INITRAMFS_PATHS); \ - find $(INITRAMFS_PATHS)) +kern_initramfs_files := $(shell find $(kfs-paths)) +# Need to make an empty cpio, then append each kfs-path's contents $(kern_cpio) initramfs: $(kern_initramfs_files) @echo " Building initramfs:" - @if [ "$(INITRAMFS_BIN)" != "" ]; then \ - sh $(INITRAMFS_BIN); \ + @if [ "$(CONFIG_KFS_CPIO_BIN)" != "" ]; then \ + sh $(CONFIG_KFS_CPIO_BIN); \ fi - $(Q)for i in $(INITRAMFS_PATHS); do cd $$i; \ + @cat /dev/null | cpio --quiet -oH newc -O $(kern_cpio) + $(Q)for i in $(kfs-paths); do cd $$i; \ echo " Adding $$i to initramfs..."; \ - find -L . | cpio --quiet -oH newc > \ - $(CURDIR)/$(kern_cpio); \ + find -L . | cpio --quiet -oAH newc -O $(CURDIR)/$(kern_cpio); \ cd $$OLDPWD; \ done; ld_emulation = $(shell $(OBJDUMP) -i | grep -v BFD | grep ^[a-z] |head -n1) ld_arch = $(shell $(OBJDUMP) -i | grep -v BFD | grep "^ [a-z]" | head -n1) +# Our makefile doesn't detect a change in subarch, and old binary objects that +# don't need to be updated won't get rebuilt, but they also can't link with the +# new subarch (32 bit vs 64 bit). If we detect the wrong type, we'll force a +# rebuild. +existing-cpio-emul := $(shell objdump -f $(kern_cpio_obj) 2> /dev/null | \ + grep format | sed 's/.*format //g') +ifneq ($(existing-cpio-emul),) +ifneq ($(existing-cpio-emul),$(ld_emulation)) +$(kern_cpio_obj): cpio-rebuild +cpio-rebuild: + $(Q)rm $(kern_cpio_obj) +endif +endif + $(kern_cpio_obj): $(kern_cpio) - $(Q)$(OBJCOPY) -I binary -B $(ld_arch) -O $(ld_emulation) $^ $@ + $(Q)$(OBJCOPY) -I binary -B $(ld_arch) -O $(ld_emulation) $< $@ + +existing-ext2b-emul := $(shell objdump -f $(kern_cpio_obj) 2> /dev/null | \ + grep format | sed 's/.*format //g') +ifneq ($(existing-ext2b-emul),) +ifneq ($(existing-ext2b-emul),$(ld_emulation)) +$(ext2_bdev_obj): ext2b-rebuild +ext2b-rebuild: + $(Q)rm $(ext2_bdev_obj) +endif +endif -$(ext2_bdev_obj): $(EXT2_BDEV) - $(Q)$(OBJCOPY) -I binary -B $(ld_arch) -O $(ld_emulation) $^ $@ +$(ext2_bdev_obj): $(ext2-bdev) + $(Q)$(OBJCOPY) -I binary -B $(ld_arch) -O $(ld_emulation) $< $@ -# TODO super-bugged objdump! Passing -S (intermix source) and having auto.conf -# be regenerated while the Makefile is running causes a segfault. This would -# happen after touching .config and remaking. For now, just pass -d... +# Not the worlds most elegant link command. link-kernel takes the obj output +# name, then the linker script, then everything else you'd dump on the ld +# command line, including linker options and objects to link together. +# +# After the script is done, we run the arch-specific command directly. quiet_cmd_link-akaros = LINK $@ - cmd_link-akaros = $(LD) -T kern/arch/$(ARCH)/kernel.ld -o $@ \ - $(akaros-deps) \ - $(gcc-lib) \ - $(kern_cpio_obj) \ - $(ext2_bdev_obj) ; \ - $(OBJDUMP) -d $@ > $@.asm + cmd_link-akaros = $(CONFIG_SHELL) scripts/link-kernel.sh $@ \ + kern/arch/$(ARCH)/$(KERNEL_LD) $(LDFLAGS_KERNEL) \ + $(akaros-deps) $(gcc-lib) $(kern_cpio_obj) \ + $(ext2_bdev_obj); \ + $(ARCH_POST_LINK_CMD) # For some reason, the if_changed doesn't work with FORCE (like it does in # Linux). It looks like it can't find the .cmd file or something (also @@ -439,10 +511,15 @@ $(sort $(akaros-deps)): $(akaros-dirs) ; # Recursively Kbuild all of our directories. If we're changing arches # mid-make, we might have issues ( := on akaros-dirs, etc). -PHONY += $(akaros-dirs) -$(akaros-dirs): scripts symlinks +PHONY += $(akaros-dirs) cc_exists +$(akaros-dirs): scripts symlinks cc-exists $(Q)$(MAKE) $(build)=$@ +cc-exists: + @if [ "`which $(CROSS_COMPILE)gcc`" = "" ]; then echo \ + Could not find a $(CROSS_COMPILE) version of GCC/binutils. \ + Be sure to build the cross-compiler and update your PATH; exit 1; fi + $(CMP_KERNEL_OBJ): $(KERNEL_OBJ) @echo "Compressing kernel image" $(Q)gzip -c $^ > $@ @@ -463,16 +540,15 @@ endif #ifeq ($(mixed-targets),1) # List all userspace directories here, and state any dependencies between them, # such as how pthread depends on parlib. -user-dirs = parlib pthread benchutil -pthread: parlib - -ifeq ($(ARCH),i686) -user-dirs += c3po -c3po: parlib -endif +user-dirs = parlib pthread benchutil iplib ndblib bsd +benchutil: parlib +pthread: parlib benchutil +iplib: parlib +ndblib: iplib +bsd: parlib iplib PHONY += install-libs $(user-dirs) -install-libs: $(user-dirs) symlinks +install-libs: $(user-dirs) symlinks cc-exists $(user-dirs): @cd user/$@ && $(MAKE) && $(MAKE) install @@ -480,7 +556,7 @@ $(user-dirs): PHONY += userclean $(clean-user-dirs) clean-user-dirs := $(addprefix _clean_user_,$(user-dirs)) -userclean: $(clean-user-dirs) testclean +userclean: $(clean-user-dirs) testclean utestclean $(clean-user-dirs): @cd user/$(patsubst _clean_user_%,%,$@) && $(MAKE) clean @@ -489,19 +565,37 @@ tests/: tests tests: install-libs @$(MAKE) -f tests/Makefile +PHONY += utest +utest: $(user-dirs) + @cd user/$@ && $(MAKE) + testclean: @$(MAKE) -f tests/Makefile clean -install-tests: +utestclean: + @cd user/utest && $(MAKE) clean + +# KFS related stuff +PHONY += fill-kfs unfill-kfs +XCC_SO_FILES = $(addprefix $(XCC_TARGET_ROOT)/lib/, *.so*) + +$(OBJDIR)/.dont-force-fill-kfs: + $(Q)rm -rf $(addprefix $(FIRST_KFS_PATH)/lib/, $(notdir $(XCC_SO_FILES))) + @echo "Cross Compiler 'so' files removed from KFS" + @$(MAKE) -f tests/Makefile uninstall + @echo "Apps from /test removed from KFS" + @cd user/utest && $(MAKE) uninstall + @echo "User space tests removed from KFS" + @touch $(OBJDIR)/.dont-force-fill-kfs + +fill-kfs: $(OBJDIR)/.dont-force-fill-kfs install-libs + @mkdir -p $(FIRST_KFS_PATH)/lib + $(Q)cp -uP $(XCC_SO_FILES) $(FIRST_KFS_PATH)/lib + @echo "Cross Compiler 'so' files installed to KFS" @$(MAKE) -f tests/Makefile install - -# TODO: cp -u all of the .sos, but flush it on an arch change (same with tests) -fill-kfs: install-libs install-tests - @mkdir -p $(FIRST_INITRAMFS_PATH)/lib - @cp $(addprefix $(XCC_ROOT)/$(ARCH)-ros/lib/, \ - libc.so.6 ld.so.1 libm.so libgcc_s.so.1) $(FIRST_INITRAMFS_PATH)/lib - $(Q)$(STRIP) --strip-debug $(addprefix $(FIRST_INITRAMFS_PATH)/lib/, \ - libc.so.6 ld.so.1) + @echo "Apps from /test installed to KFS" + @cd user/utest && $(MAKE) install + @echo "User space tests installed to KFS" # Use doxygen to make documentation for ROS (Untested since 2010 or so) doxygen-dir := $(CUR_DIR)/Documentation/doxygen @@ -519,7 +613,7 @@ doxyclean: objclean: @echo + clean [OBJDIR] - @rm -rf $(OBJDIR)/* + @rm -rf $(OBJDIR) realclean: userclean mrproper doxyclean objclean @@ -582,6 +676,10 @@ mrproper: $(mrproper-dirs) clean clean_symlinks PHONY += FORCE FORCE: +# Don't put the srctree on this, make is looking for Makefile, not +# /full/path/to/Makefile. +Makefile: ; # avoid implicit rule on Makefile + # Declare the contents of the .PHONY variable as phony. We keep that # information in a variable so we can use it in if_changed and friends. .PHONY: $(PHONY)