diff --git a/.gitignore b/.gitignore index 0302eec4d..6cd1c6d30 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ *.o *.swp *.pcap +Makeconf cscope.* +include-host/ iso/boot/kernel tests/*/*.ukvm tests/*/*.virtio diff --git a/Makefile b/Makefile index ae6b79650..162b8e0f5 100644 --- a/Makefile +++ b/Makefile @@ -15,24 +15,37 @@ # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. +export TOP=$(abspath .) +$(TOP)/Makeconf: + ./configure.sh +include Makefile.common + .PHONY: all all: ukvm virtio +.DEFAULT_GOAL := all .PHONY: virtio virtio: +ifeq ($(BUILD_VIRTIO), yes) $(MAKE) -C kernel virtio $(MAKE) -C tests virtio +endif .PHONY: ukvm ukvm: +ifeq ($(BUILD_UKVM), yes) $(MAKE) -C kernel ukvm $(MAKE) -C tests ukvm +endif +.PHONY: clean clean: $(MAKE) -C kernel clean $(MAKE) -C tests clean $(RM) solo5-kernel-virtio.pc $(RM) solo5-kernel-ukvm.pc + $(RM) -r include-host/ + $(RM) Makeconf PREFIX?=/nonexistent # Fail if not run from OPAM OPAM_BINDIR=$(PREFIX)/bin @@ -43,17 +56,18 @@ OPAM_VIRTIO_INCDIR=$(PREFIX)/include/solo5-kernel-virtio/include # We want the MD CFLAGS and LDFLAGS in the .pc file, where they can be # picked up by the Mirage tool / other downstream consumers. -KERNEL_MD_CFLAGS=$(shell $(MAKE) -sC kernel print-md-cflags) -KERNEL_LDFLAGS=$(shell $(MAKE) -sC kernel print-ldflags) %.pc: %.pc.in sed <$< > $@ \ - -e 's#!CFLAGS!#$(KERNEL_MD_CFLAGS)#g;' \ - -e 's#!LDFLAGS!#$(KERNEL_LDFLAGS)#g;' + -e 's#!CFLAGS!#$(MD_CFLAGS)#g;' \ + -e 's#!LD!#$(LD)#g;' \ + -e 's#!LDFLAGS!#$(LDFLAGS)#g;' .PHONY: opam-virtio-install opam-virtio-install: solo5-kernel-virtio.pc virtio mkdir -p $(OPAM_VIRTIO_INCDIR) $(OPAM_VIRTIO_LIBDIR) cp kernel/solo5.h $(OPAM_VIRTIO_INCDIR)/solo5.h + mkdir -p $(OPAM_VIRTIO_INCDIR)/host + cp -R include-host/. $(OPAM_VIRTIO_INCDIR)/host cp iso/boot/grub/menu.lst $(OPAM_VIRTIO_LIBDIR) cp iso/boot/grub/stage2_eltorito $(OPAM_VIRTIO_LIBDIR) cp kernel/virtio/solo5.o kernel/virtio/solo5.lds $(OPAM_VIRTIO_LIBDIR) @@ -73,6 +87,8 @@ opam-ukvm-install: solo5-kernel-ukvm.pc ukvm mkdir -p $(OPAM_UKVM_INCDIR) $(OPAM_UKVM_LIBDIR) cp kernel/solo5.h $(OPAM_UKVM_INCDIR)/solo5.h cp ukvm/ukvm.h $(OPAM_UKVM_INCDIR)/ukvm.h + mkdir -p $(OPAM_UKVM_INCDIR)/host + cp -R include-host/. $(OPAM_UKVM_INCDIR)/host cp kernel/ukvm/solo5.o kernel/ukvm/solo5.lds $(OPAM_UKVM_LIBDIR) mkdir -p $(OPAM_BINDIR) mkdir -p $(OPAM_UKVM_LIBDIR)/src diff --git a/Makefile.common b/Makefile.common new file mode 100644 index 000000000..0369a22fc --- /dev/null +++ b/Makefile.common @@ -0,0 +1,15 @@ +# This Makefile defines global defaults for building Solo5 (kernel/) and the +# in-tree test programs. These can be overriden either on the command line, or +# via Makeconf generated by configure.sh. +include $(TOP)/Makeconf + +AS?=as +CC?=cc +LD?=ld +OBJCOPY?=objcopy +# Exported to OPAM via pkg-config. +MD_CFLAGS=$(HOST_CFLAGS) -ffreestanding -mno-red-zone -mno-3dnow +# Likewise. +LDFLAGS=-nostdlib -z max-page-size=0x1000 -static +# CFLAGS used for building kernel/ and in-tree tests. +CFLAGS=$(MD_CFLAGS) -isystem $(TOP)/include-host -std=gnu99 -Wall -Wextra -Werror -O2 -g diff --git a/configure.sh b/configure.sh new file mode 100755 index 000000000..8bfaaab72 --- /dev/null +++ b/configure.sh @@ -0,0 +1,84 @@ +#!/bin/sh + +die() +{ + echo "$0: $@" 1>&2 + exit 1 +} + +cc_is_clang() +{ + ${CC:-cc} -v 2>&1 | grep -q "clang version" +} + +cc_is_gcc() +{ + ${CC:-cc} -v 2>&1 | grep -q "^gcc version" +} + +check_ld_version() +{ + type $1 >/dev/null 2>&1 && $1 -v | grep -q 'GNU.*2.2[5-9]' +} + +# Host-provided header files are installed here for in-tree builds. OPAM will +# install these to $(OPAM_INCDIR)/host where they will be picked up by +# pkg-config. +HOST_INCDIR=${PWD}/include-host + +case $(uname -s) in + Linux) + # On Linux/gcc we use -nostdinc and copy all the gcc-provided headers. + cc_is_gcc || die "Only 'gcc' is supported on Linux" + CC_INCDIR=$(${CC:-cc} -print-file-name=include) + [ -d "${CC_INCDIR}" ] || die "Cannot determine gcc include directory" + mkdir -p ${HOST_INCDIR} + cp -R ${CC_INCDIR}/. ${HOST_INCDIR} + + HOST_CFLAGS="-nostdinc" + BUILD_UKVM="yes" + BUILD_VIRTIO="yes" + ;; + FreeBSD) + # On FreeBSD/clang we use -nostdlibinc which gives us access to the + # clang-provided headers for compiler instrinsics. We copy the rest + # (std*.h, float.h and their dependencies) from the host. + cc_is_clang || die "Only 'clang' is supported on FreeBSD" + INCDIR=/usr/include + SRCS_MACH="machine/_stdint.h machine/_types.h machine/endian.h \ + machine/_limits.h" + SRCS_SYS="sys/_null.h sys/_stdint.h sys/_types.h sys/cdefs.h \ + sys/endian.h" + SRCS_X86="x86/float.h x86/_stdint.h x86/stdarg.h x86/endian.h \ + x86/_types.h x86/_limits.h" + SRCS="float.h osreldate.h stddef.h stdint.h stdbool.h stdarg.h" + + mkdir -p ${HOST_INCDIR} + mkdir -p ${HOST_INCDIR}/machine ${HOST_INCDIR}/sys ${HOST_INCDIR}/x86 + for f in ${SRCS_MACH}; do cp -f ${INCDIR}/$f ${HOST_INCDIR}/machine; done + for f in ${SRCS_SYS}; do cp -f ${INCDIR}/$f ${HOST_INCDIR}/sys; done + for f in ${SRCS_X86}; do cp -f ${INCDIR}/$f ${HOST_INCDIR}/x86; done + for f in ${SRCS}; do cp -f ${INCDIR}/$f ${HOST_INCDIR}; done + + HOST_CFLAGS="-nostdlibinc" + BUILD_UKVM= + BUILD_VIRTIO="yes" + # Check that the linker is new enough. Allow the user to explicitly + # override ${LD}; if unset default to looking for the binutils one. + LD=${LD:-/usr/local/bin/ld} + check_ld_version ${LD} || \ + die "Linker '${LD}': Not found or too old (< 2.25)." \ + "Please install ld from 'binutils' or set \$LD explicitly." + EXTRA="LD=${LD}" + ;; + *) + die "Unsupported build OS: $(uname -s)" + ;; +esac + +cat <Makeconf +BUILD_UKVM=${BUILD_UKVM} +BUILD_VIRTIO=${BUILD_VIRTIO} +HOST_CFLAGS=${HOST_CFLAGS} +${EXTRA} +EOM diff --git a/kernel/Makefile b/kernel/Makefile index ecad781e3..a8a7e5dfd 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -15,7 +15,7 @@ # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -include Makefile.common +include $(TOP)/Makefile.common COMMON_COBJS=\ abort.o \ @@ -80,12 +80,3 @@ ukvm/solo5.o: $(UKVM_COBJS) ukvm/solo5.lds .PHONY: clean clean: $(RM) *.o virtio/*.o ukvm/*.o kernel - -# This target is for the top-level opam-install to get MD CFLAGS -.PHONY: print-md-cflags -print-md-cflags: - @echo $(MD_CFLAGS) - -.PHONY: print-ldflags -print-ldflags: - @echo $(LDFLAGS) diff --git a/kernel/Makefile.common b/kernel/Makefile.common deleted file mode 100644 index 3b4ba2180..000000000 --- a/kernel/Makefile.common +++ /dev/null @@ -1,14 +0,0 @@ -AS?=as -CC?=cc -LD?=ld -OBJCOPY?=objcopy -# Ensure no host headers or libraries are used when building, with the -# exception of: -# - Standard C headers required by C89/C99. -nostdinc removes access to these -# so get it back by asking GCC for its installation directory. -GCC_INCLUDE_DIR=$(shell $(CC) -print-file-name=include) -MD_CFLAGS=-nostdinc -isystem $(GCC_INCLUDE_DIR) \ - -ffreestanding -mno-red-zone -mno-3dnow -LDFLAGS=-nostdlib -z max-page-size=0x1000 -static -# Platform-independent CFLAGS -CFLAGS=$(MD_CFLAGS) -std=gnu99 -Wall -Wextra -Werror -O2 -g diff --git a/solo5-kernel-ukvm.pc.in b/solo5-kernel-ukvm.pc.in index 422a90da1..3d6244a96 100644 --- a/solo5-kernel-ukvm.pc.in +++ b/solo5-kernel-ukvm.pc.in @@ -2,9 +2,10 @@ prefix=${pcfiledir}/../.. exec_prefix=${prefix} includedir=${prefix}/include/solo5-kernel-ukvm/include libdir=${exec_prefix}/lib/solo5-kernel-ukvm +ld=!LD! ldflags=!LDFLAGS! -T ${libdir}/solo5.lds ${libdir}/solo5.o Name: solo5-kernel-ukvm Version: 0.1 Description: Solo5 unikernel base (ukvm target) -Cflags: !CFLAGS! -I${includedir} +Cflags: !CFLAGS! -isystem ${includedir}/host -I${includedir} diff --git a/solo5-kernel-virtio.opam b/solo5-kernel-virtio.opam index 1067d0a23..4dbccc3d4 100644 --- a/solo5-kernel-virtio.opam +++ b/solo5-kernel-virtio.opam @@ -18,6 +18,10 @@ conflicts: [ "solo5-kernel-ukvm" ] +depexts: [ + [["freebsd"] ["binutils"]] +] + available: [ ocaml-version >= "4.02.3" & (arch = "x86_64" | arch = "amd64") & os != "darwin" ] diff --git a/solo5-kernel-virtio.pc.in b/solo5-kernel-virtio.pc.in index acc8a6844..81bb54e0b 100644 --- a/solo5-kernel-virtio.pc.in +++ b/solo5-kernel-virtio.pc.in @@ -2,9 +2,10 @@ prefix=${pcfiledir}/../.. exec_prefix=${prefix} includedir=${prefix}/include/solo5-kernel-virtio/include libdir=${exec_prefix}/lib/solo5-kernel-virtio +ld=!LD! ldflags=!LDFLAGS! -T ${libdir}/solo5.lds ${libdir}/solo5.o Name: solo5-kernel-virtio Version: 0.1 Description: Solo5 unikernel base (virtio target) -Cflags: !CFLAGS! -I${includedir} +Cflags: !CFLAGS! -isystem ${includedir}/host -I${includedir} diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 18913e7b5..22a742876 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -1,22 +1,23 @@ +include $(TOP)/Makefile.common + .PHONY: ukvm ukvm: $(UKVM_TARGETS) .PHONY: virtio virtio: $(VIRTIO_TARGETS) -SOLO5_DIR=../../kernel -UKVM_SRC=../../ukvm +SOLO5_DIR=$(TOP)/kernel +UKVM_SRC=$(TOP)/ukvm -include $(SOLO5_DIR)/Makefile.common CFLAGS+=-I$(SOLO5_DIR) %.o: %.c $(HEADERS) $(CC) $(CFLAGS) -c $< -o $@ +ifeq ($(BUILD_UKVM), yes) Makefile.ukvm: $(UKVM_SRC)/ukvm-configure $(UKVM_SRC)/ukvm-configure $(UKVM_SRC) $(UKVM_MODULES) -.PHONY: ukvm-clean -include Makefile.ukvm %.ukvm: %.o $(SOLO5_DIR)/ukvm/solo5.lds $(SOLO5_DIR)/ukvm/solo5.o @@ -25,6 +26,7 @@ Makefile.ukvm: $(UKVM_SRC)/ukvm-configure $(SOLO5_DIR)/ukvm/solo5.o: $(MAKE) -C $(SOLO5_DIR) ukvm +endif %.virtio: %.o $(SOLO5_DIR)/virtio/solo5.lds $(SOLO5_DIR)/virtio/solo5.o $(LD) -T $(SOLO5_DIR)/virtio/solo5.lds \ @@ -33,6 +35,6 @@ $(SOLO5_DIR)/ukvm/solo5.o: $(SOLO5_DIR)/virtio/solo5.o: $(MAKE) -C $(SOLO5_DIR) virtio -.PHONY: clean +.PHONY: clean ukvm-clean clean: ukvm-clean $(RM) *.o $(UKVM_TARGETS) Makefile.ukvm $(VIRTIO_TARGETS)