[ovs-dev] [PATCH] datapath: Use "make" instead of Autoconf to figure out kernel compat issues.
Ben Pfaff
blp at nicira.com
Mon Mar 5 17:32:12 UTC 2012
This has a few advantages:
* It eliminates the need to infer the kernel source directory based on
the build directory, which has broken several times during Open vSwitch
development.
* It eliminates most of the kernel-related Autoconf code, which should
make it easier to in turn eliminate the openvswitch-datapath-dkms
dependency on libc6-dev. (Currently, openvswitch-datapath-dkms has to
depend on libc6-dev because "configure" fails hard if the C compiler
cannot generate executables, even though the dkms package never does
that.)
* Related to the previous point, it would make it easier to distribute
a tarball that builds only the kernel module and does not contain any
of the userspace code. (This may not be a worthwhile goal, but it
makes sense to only distribute kernel module code in the Debian
packages that build kernel modules.)
* If the kernel headers change (e.g. someone points a symlink to a new
kernel tree), then everything works OK without a new "configure" step.
It has some disadvantages:
* This is a new technique with which I have no experience, and so it
might have new and unexpected pitfalls.
* The makefile syntax that replaces the Autoconf syntax might actually
be harder to read.
Signed-off-by: Ben Pfaff <blp at nicira.com>
---
Something fun for you to look at now that you're back.
Originally posted here, with incomplete changelog:
http://openvswitch.org/pipermail/dev/2012-February/015083.html
acinclude.m4 | 206 +--------------------------------------
datapath/linux/.gitignore | 2 +-
datapath/linux/Kbuild.in | 120 ++++++++++++++++++++++-
datapath/linux/Makefile.main.in | 3 +-
4 files changed, 122 insertions(+), 209 deletions(-)
diff --git a/acinclude.m4 b/acinclude.m4
index 69bb772..d1347ef 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -32,15 +32,9 @@ AC_DEFUN([OVS_CHECK_LINUX], [
AC_ARG_WITH([linux],
[AC_HELP_STRING([--with-linux=/path/to/linux],
[Specify the Linux kernel build directory])])
- AC_ARG_WITH([linux-source],
- [AC_HELP_STRING([--with-linux-source=/path/to/linux-source],
- [Specify the Linux kernel source directory
- (usually figured out automatically from build
- directory)])])
- # Deprecated equivalents to --with-linux, --with-linux-source.
+ # Deprecated equivalent to --with-linux.
AC_ARG_WITH([l26])
- AC_ARG_WITH([l26-source])
if test X"$with_linux" != X; then
KBUILD=$with_linux
@@ -51,19 +45,6 @@ AC_DEFUN([OVS_CHECK_LINUX], [
KBUILD=
fi
- if test X"$KBUILD" != X; then
- if test X"$with_linux_source" != X; then
- KSRC=$with_linux_source
- elif test X"$with_l26_source" != X; then
- KSRC=$with_l26_source
- AC_MSG_WARN([--with-l26-source is deprecated, please use --with-linux-source instead])
- else
- KSRC=
- fi
- elif test X"$with_linux_source" != X || test X"$with_l26_source" != X; then
- AC_MSG_ERROR([Linux source directory may not be specified without Linux build directory])
- fi
-
if test -n "$KBUILD"; then
KBUILD=`eval echo "$KBUILD"`
case $KBUILD in
@@ -82,200 +63,15 @@ AC_DEFUN([OVS_CHECK_LINUX], [
AC_ERROR([source dir $KBUILD doesn't exist])
fi
- # Debian breaks kernel headers into "source" header and "build" headers.
- # We want the source headers, but $KBUILD gives us the "build" headers.
- # Use heuristics to find the source headers.
- AC_MSG_CHECKING([for Linux source directory])
- if test -n "$KSRC"; then
- KSRC=`eval echo "$KSRC"`
- case $KSRC in
- /*) ;;
- *) KSRC=`pwd`/$KSRC ;;
- esac
- if test ! -e $KSRC/include/linux/kernel.h; then
- AC_MSG_ERROR([$KSRC is not a kernel source directory])
- fi
- else
- KSRC=$KBUILD
- if test ! -e $KSRC/include/linux/kernel.h; then
- # Debian kernel build Makefiles tend to include a line of the form:
- # MAKEARGS := -C /usr/src/linux-headers-3.2.0-1-common O=/usr/src/linux-headers-3.2.0-1-486
- # First try to extract the source directory from this line.
- KSRC=`sed -n 's/.*-C \([[^ ]]*\).*/\1/p' "$KBUILD"/Makefile`
- if test ! -e "$KSRC"/include/linux/kernel.h; then
- # Didn't work. Fall back to name-based heuristics that used to work.
- case `echo "$KBUILD" | sed 's,/*$,,'` in # (
- */build)
- KSRC=`echo "$KBUILD" | sed 's,/build/*$,/source,'`
- ;; # (
- *)
- KSRC=`(cd $KBUILD && pwd -P) | sed 's,-[[^-]]*$,-common,'`
- ;;
- esac
- fi
- fi
- if test ! -e "$KSRC"/include/linux/kernel.h; then
- AC_MSG_ERROR([cannot find source directory (please use --with-linux-source)])
- fi
- fi
- AC_MSG_RESULT([$KSRC])
-
- AC_MSG_CHECKING([for kernel version])
- version=`sed -n 's/^VERSION = //p' "$KSRC/Makefile"`
- patchlevel=`sed -n 's/^PATCHLEVEL = //p' "$KSRC/Makefile"`
- sublevel=`sed -n 's/^SUBLEVEL = //p' "$KSRC/Makefile"`
- if test X"$version" = X || test X"$patchlevel" = X; then
- AC_ERROR([cannot determine kernel version])
- elif test X"$sublevel" = X; then
- kversion=$version.$patchlevel
- else
- kversion=$version.$patchlevel.$sublevel
- fi
- AC_MSG_RESULT([$kversion])
-
- if test "$version" -ge 3; then
- : # Linux 3.x
- elif test "$version" = 2 && test "$patchlevel" -ge 6; then
- : # Linux 2.6.x
- else
- if test "$KBUILD" = "$KSRC"; then
- AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version 2.6 or later is required])
- else
- AC_ERROR([Linux kernel in build tree $KBUILD (source tree $KSRC) is version $kversion, but version 2.6 or later is required])
- fi
- fi
if test ! -e "$KBUILD"/include/linux/version.h || \
(test ! -e "$KBUILD"/include/linux/autoconf.h && \
test ! -e "$KBUILD"/include/generated/autoconf.h); then
AC_MSG_ERROR([Linux kernel source in $KBUILD is not configured])
fi
- OVS_CHECK_LINUX_COMPAT
fi
AM_CONDITIONAL(LINUX_ENABLED, test -n "$KBUILD")
])
-dnl OVS_GREP_IFELSE(FILE, REGEX, [IF-MATCH], [IF-NO-MATCH])
-dnl
-dnl Greps FILE for REGEX. If it matches, runs IF-MATCH, otherwise IF-NO-MATCH.
-dnl If IF-MATCH is empty then it defines to OVS_DEFINE(HAVE_<REGEX>), with
-dnl <REGEX> translated to uppercase.
-AC_DEFUN([OVS_GREP_IFELSE], [
- AC_MSG_CHECKING([whether $2 matches in $1])
- if test -f $1; then
- grep '$2' $1 >/dev/null 2>&1
- status=$?
- case $status in
- 0)
- AC_MSG_RESULT([yes])
- m4_if([$3], [], [OVS_DEFINE([HAVE_]m4_toupper([$2]))], [$3])
- ;;
- 1)
- AC_MSG_RESULT([no])
- $4
- ;;
- *)
- AC_MSG_ERROR([grep exited with status $status])
- ;;
- esac
- else
- AC_MSG_RESULT([file not found])
- $4
- fi
-])
-
-dnl OVS_DEFINE(NAME)
-dnl
-dnl Defines NAME to 1 in kcompat.h.
-AC_DEFUN([OVS_DEFINE], [
- echo '#define $1 1' >> datapath/linux/kcompat.h.new
-])
-
-AC_DEFUN([OVS_CHECK_LOG2_H], [
- AC_MSG_CHECKING([for $KSRC/include/linux/log2.h])
- if test -e $KSRC/include/linux/log2.h; then
- AC_MSG_RESULT([yes])
- OVS_DEFINE([HAVE_LOG2_H])
- else
- AC_MSG_RESULT([no])
- fi
-])
-
-dnl OVS_CHECK_LINUX_COMPAT
-dnl
-dnl Runs various Autoconf checks on the Linux 2.6 kernel source in
-dnl the directory in $KBUILD.
-AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
- rm -f datapath/linux/kcompat.h.new
- mkdir -p datapath/linux
- : > datapath/linux/kcompat.h.new
-
- OVS_GREP_IFELSE([$KSRC/arch/x86/include/asm/checksum_32.h], [src_err,],
- [OVS_DEFINE([HAVE_CSUM_COPY_DBG])])
-
- OVS_GREP_IFELSE([$KSRC/include/linux/err.h], [ERR_CAST])
-
- OVS_GREP_IFELSE([$KSRC/include/linux/in.h], [ipv4_is_multicast])
-
- OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [dev_disable_lro])
- OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [dev_get_stats])
- OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [dev_get_by_index_rcu])
-
- OVS_GREP_IFELSE([$KSRC/include/linux/rcupdate.h], [rcu_read_lock_held], [],
- [OVS_GREP_IFELSE([$KSRC/include/linux/rtnetlink.h],
- [rcu_read_lock_held])])
-
- # Check for the proto_data_valid member in struct sk_buff. The [^@]
- # is necessary because some versions of this header remove the
- # member but retain the kerneldoc comment that describes it (which
- # starts with @). The brackets must be doubled because of m4
- # quoting rules.
- OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], [[[^@]]proto_data_valid],
- [OVS_DEFINE([HAVE_PROTO_DATA_VALID])])
- OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], [raw],
- [OVS_DEFINE([HAVE_MAC_RAW])])
- OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], [skb_dst(],
- [OVS_DEFINE([HAVE_SKB_DST_ACCESSOR_FUNCS])])
- OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h],
- [skb_copy_from_linear_data_offset])
- OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h],
- [skb_reset_tail_pointer])
- OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], [skb_cow_head])
- OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], [skb_transport_header],
- [OVS_DEFINE([HAVE_SKBUFF_HEADER_HELPERS])])
- OVS_GREP_IFELSE([$KSRC/include/linux/icmpv6.h], [icmp6_hdr],
- [OVS_DEFINE([HAVE_ICMP6_HDR])])
- OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], [skb_warn_if_lro],
- [OVS_DEFINE([HAVE_SKB_WARN_LRO])])
- OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], [consume_skb])
-
- OVS_GREP_IFELSE([$KSRC/include/linux/string.h], [kmemdup], [],
- [OVS_GREP_IFELSE([$KSRC/include/linux/slab.h], [kmemdup])])
-
- OVS_GREP_IFELSE([$KSRC/include/linux/types.h], [bool],
- [OVS_DEFINE([HAVE_BOOL_TYPE])])
- OVS_GREP_IFELSE([$KSRC/include/linux/types.h], [__wsum],
- [OVS_DEFINE([HAVE_CSUM_TYPES])])
-
- OVS_GREP_IFELSE([$KSRC/include/net/checksum.h], [csum_replace4])
- OVS_GREP_IFELSE([$KSRC/include/net/checksum.h], [csum_unfold])
-
- OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [NLA_NUL_STRING])
- OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_get_be16])
- OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_find_nested])
-
- OVS_GREP_IFELSE([$KSRC/include/linux/if_vlan.h], [ADD_ALL_VLANS_CMD],
- [OVS_DEFINE([HAVE_VLAN_BUG_WORKAROUND])])
-
- OVS_CHECK_LOG2_H
-
- if cmp -s datapath/linux/kcompat.h.new \
- datapath/linux/kcompat.h >/dev/null 2>&1; then
- rm datapath/linux/kcompat.h.new
- else
- mv datapath/linux/kcompat.h.new datapath/linux/kcompat.h
- fi
-])
-
dnl Checks for net/if_packet.h.
AC_DEFUN([OVS_CHECK_IF_PACKET],
[AC_CHECK_HEADER([net/if_packet.h],
diff --git a/datapath/linux/.gitignore b/datapath/linux/.gitignore
index 0aee746..8067279 100644
--- a/datapath/linux/.gitignore
+++ b/datapath/linux/.gitignore
@@ -19,7 +19,7 @@
/genetlink-brcompat.c
/genetlink-openvswitch.c
/ip_output-openvswitch.c
-/kcompat.h
+/kcompat/
/kmemdup.c
/loop_counter.c
/modules.order
diff --git a/datapath/linux/Kbuild.in b/datapath/linux/Kbuild.in
index 07d106d..a451f41 100644
--- a/datapath/linux/Kbuild.in
+++ b/datapath/linux/Kbuild.in
@@ -17,7 +17,7 @@ else
EXTRA_CFLAGS += -DBUILDNR=\"+build$(BUILDNR)\"
endif
EXTRA_CFLAGS += -g
-EXTRA_CFLAGS += -include $(builddir)/kcompat.h
+EXTRA_CFLAGS += -include $(builddir)/kcompat/kcompat.h
# These include directories have to go before -I$(KSRC)/include.
# NOSTDINC_FLAGS just happens to be a variable that goes in the
@@ -28,6 +28,124 @@ obj-m := $(patsubst %,%_mod.o,$(build_modules))
define module_template
$(1)_mod-y = $$(notdir $$(patsubst %.c,%.o,$($(1)_sources)))
+$$(addprefix $$(obj)/,$$(notdir $$(patsubst %.c,%.o,$($(1)_sources)))): $(obj)/kcompat/kcompat.h
endef
+#$(addprefix $(obj)/,$(notdir $(patsubst %.c,%.o,$(brcompat_sources)))): $(obj)/kcompat/kcompat.h
$(foreach module,$(build_modules),$(eval $(call module_template,$(module))))
+
+define GREP
+for file in $^; do \
+ if test -f "$$file"; then \
+ grep '$(1)' $$file >/dev/null 2>&1; \
+ status=$$?; \
+ case $$status in \
+ 0) \
+ $(kecho) " GREP \"$(1)\" found in $$file"; \
+ echo >&3 '#define $(if $(2),$(2),HAVE_$(shell echo $(1) | tr a-z A-Z)) 1'; \
+ break \
+ ;; \
+ 1) \
+ $(kecho) " GREP \"$(1)\" not in $$file"; \
+ ;; \
+ *) \
+ echo "grep exited with status $$status"; \
+ exit $$status \
+ ;; \
+ esac; \
+ else \
+ $(kecho) "file not found"; \
+ fi; \
+done
+endef
+
+$(obj)/datapath.o: $(obj)/kcompat/kcompat.h
+$(obj)/kcompat/kcompat.h: \
+ $(obj)/kcompat/checksum.h \
+ $(obj)/kcompat/err.h \
+ $(obj)/kcompat/icmpv6.h \
+ $(obj)/kcompat/if_vlan.h \
+ $(obj)/kcompat/in.h \
+ $(obj)/kcompat/netdevice.h \
+ $(obj)/kcompat/netlink.h \
+ $(obj)/kcompat/rcupdate.h \
+ $(obj)/kcompat/skbuff.h \
+ $(obj)/kcompat/string.h \
+ $(obj)/kcompat/types.h \
+ $(obj)/kcompat/checksum_32.h \
+ $(obj)/kcompat/log2.h
+ @$(kecho) " GEN $@"
+ @$(O)cat $^ > $@.$$$$ && mv $@.$$$$ $@
+
+$(obj)/kcompat/checksum.h: include/net/checksum.h
+ @($(call GREP,csum_replace4); \
+ $(call GREP,csum_unfold)) 3> $@.tmp$$$$; mv $@.tmp$$$$ $@
+$(obj)/kcompat/err.h: include/linux/err.h
+ @($(call GREP,ERR_CAST)) 3> $@.tmp$$$$; mv $@.tmp$$$$ $@
+$(obj)/kcompat/icmpv6.h: include/linux/icmpv6.h
+ @($(call GREP,icmp6_hdr)) 3> $@.tmp$$$$; mv $@.tmp$$$$ $@
+$(obj)/kcompat/if_vlan.h: include/linux/if_vlan.h
+ @($(call GREP,ADD_ALL_VLANS_CMD,HAVE_VLAN_BUG_WORKAROUND)) \
+ 3> $@.tmp$$$$; mv $@.tmp$$$$ $@
+$(obj)/kcompat/in.h: include/linux/in.h
+ @($(call GREP,ipv4_is_multicast)) 3> $@.tmp$$$$; mv $@.tmp$$$$ $@
+$(obj)/kcompat/netdevice.h: include/linux/netdevice.h
+ @($(call GREP,dev_disable_lro); \
+ $(call GREP,dev_get_stats); \
+ $(call GREP,dev_get_by_index_rcu)) 3> $@.tmp$$$$; mv $@.tmp$$$$ $@
+$(obj)/kcompat/netlink.h: include/net/netlink.h
+ @($(call GREP,NLA_NUL_STRING); \
+ $(call GREP,nla_get_be16); \
+ $(call GREP,nla_find_nested)) 3> $@.tmp$$$$; mv $@.tmp$$$$ $@
+$(obj)/kcompat/rcupdate.h: include/linux/rcupdate.h include/linux/rtnetlink.h
+ @($(call GREP,rcu_read_lock_held)) 3> $@.tmp$$$$; mv $@.tmp$$$$ $@
+$(obj)/kcompat/skbuff.h: include/linux/skbuff.h
+ @($(call GREP,[^@]proto_data_valid,HAVE_PROTO_DATA_VALID); \
+ $(call GREP,raw,HAVE_MAC_RAW); \
+ ${call GREP,skb_dst(,HAVE_SKB_DST_ACCESSOR_FUNCS}; \
+ $(call GREP,skb_copy_from_linear_data_offset); \
+ $(call GREP,skb_reset_tail_pointer); \
+ $(call GREP,skb_cow_head); \
+ $(call GREP,skb_transport_header,HAVE_SKBUFF_HEADER_HELPERS); \
+ $(call GREP,skb_warn_if_lro,HAVE_SKB_WARN_LRO); \
+ $(call GREP,consume_skb)) 3> $@.tmp$$$$; mv $@.tmp$$$$ $@
+$(obj)/kcompat/string.h: include/linux/string.h include/linux/slab.h
+ @($(call GREP,kmemdup)) 3> $@.tmp$$$$; mv $@.tmp$$$$ $@
+$(obj)/kcompat/types.h: include/linux/types.h
+ @($(call GREP,bool,HAVE_BOOL_TYPE); \
+ $(call GREP,__wsum,HAVE_CSUM_TYPES)) 3> $@.tmp$$$$; mv $@.tmp$$$$ $@
+
+ifneq ($(wildcard arch/x86/include/asm/checksum_32.h),)
+# Generate kcompat/checksum_32.h.
+comma := ,
+$(obj)/kcompat/checksum_32.h: arch/x86/include/asm/checksum_32.h
+ @($(call GREP,src_err$(comma),HAVE_CSUM_COPY_DBG)) \
+ 3> $@.tmp$$$$; mv $@.tmp$$$$ $@
+else ifneq ($(shell (test ! -e $(obj)/kcompat/checksum_32.h || test -s $(obj)/kcompat/checksum_32.h) && echo needs-update),)
+# kcompat/checksum_32.h needs to be an empty file but isn't.
+.PHONY: $(obj)/kcompat/checksum_32.h
+$(obj)/kcompat/checksum_32.h:
+ : > $@
+else
+# kcompat/checksum_32.h is empty and that's what we want.
+endif
+
+ifneq ($(wildcard include/linux/log2.h),)
+ifneq ($(shell test -s $(obj)/kcompat/log2.h && echo nonempty),)
+# $(obj)/kcompat/log2.h is nonempty and should be.
+else
+# $(obj)/kcompat/log2.h is empty but should not be.
+.PHONY: $(obj)/kcompat/log2.h
+$(obj)/kcompat/log2.h:
+ @echo '#define HAVE_LOG2_H 1' > $@.tmp$$$$ && mv $@.tmp$$$$ $@
+endif
+else
+ifneq ($(shell test -s $(obj)/kcompat/log2.h && echo nonempty),)
+# $(obj)/kcompat/log2.h is nonempty but should be empty.
+.PHONY: $(obj)/kcompat/log2.h
+$(obj)/kcompat/log2.h:
+ : > $@
+else
+# $(obj)/kcompat/log2.h is empty and should be.
+endif
+endif
diff --git a/datapath/linux/Makefile.main.in b/datapath/linux/Makefile.main.in
index 0302fc6..5d5d29e 100644
--- a/datapath/linux/Makefile.main.in
+++ b/datapath/linux/Makefile.main.in
@@ -29,10 +29,9 @@ check: all
installcheck:
mostlyclean:
clean:
- rm -f *.o *.ko *_mod.* Module.symvers *.cmd kcompat.h.new
+ rm -f *.o *.ko *_mod.* Module.symvers *.cmd kcompat/*.h
for d in $(build_links); do if test -h $$d; then rm $$d; fi; done
distclean: clean
- rm -f kcompat.h
maintainer-clean: distclean
dvi:
pdf:
--
1.7.2.5
More information about the dev
mailing list