From 1e2795a1191bb5ff05e80d77feffd51ac875c06d Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 5 Apr 2011 13:24:58 +0300 Subject: kbuild: move KALLSYMS_EXTRA_PASS from Kconfig to Makefile At the moment we have the CONFIG_KALLSYMS_EXTRA_PASS Kconfig switch, which users can enable or disable while configuring the kernel. This option is then used by 'make' to determine whether an extra kallsyms pass is needed or not. However, this approach is not nice and confusing, and this patch moves CONFIG_KALLSYMS_EXTRA_PASS from Kconfig to Makefile instead. The rationale is below. 1. CONFIG_KALLSYMS_EXTRA_PASS is really about the build time, not run-time. There is no real need for it to be in Kconfig. It is just an additional work-around which should be used only in rare cases, when someone breaks kallsyms, so Kbuild/Makefile is much better place for this option. 2. Grepping CONFIG_KALLSYMS_EXTRA_PASS shows that many defconfigs have it enabled, probably not because they try to work-around a kallsyms bug, but just because the Kconfig help text is confusing and does not really make it clear that this option should not be used unless except when kallsyms is broken. 3. And since many people have CONFIG_KALLSYMS_EXTRA_PASS enabled in their Kconfig, we do might fail to notice kallsyms bugs in time. E.g., many testers use "make allyesconfig" to test builds, which will enable CONFIG_KALLSYMS_EXTRA_PASS and kallsyms breakage will not be noticed. To address that, this patch: 1. Kills CONFIG_KALLSYMS_EXTRA_PASS 2. Changes Makefile so that people can use "make KALLSYMS_EXTRA_PASS=1" to enable the extra pass if needed. Additionally, they may define KALLSYMS_EXTRA_PASS as an environment variable. 3. By default KALLSYMS_EXTRA_PASS is disabled and if kallsyms has issues, "make" should print a warning and suggest using KALLSYMS_EXTRA_PASS Signed-off-by: Artem Bityutskiy [mmarek: Removed make help text, is not necessary] Signed-off-by: Michal Marek --- Makefile | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index ba7a55ccd890..c3bd316b16f4 100644 --- a/Makefile +++ b/Makefile @@ -797,15 +797,17 @@ ifdef CONFIG_KALLSYMS # o The correct .tmp_kallsyms2.o is linked into the final vmlinux. # o Verify that the System.map from vmlinux matches the map from # .tmp_vmlinux2, just in case we did not generate kallsyms correctly. -# o If CONFIG_KALLSYMS_EXTRA_PASS is set, do an extra pass using +# o If 'make KALLSYMS_EXTRA_PASS=1" was used, do an extra pass using # .tmp_vmlinux3 and .tmp_kallsyms3.o. This is only meant as a # temporary bypass to allow the kernel to be built while the # maintainers work out what went wrong with kallsyms. -ifdef CONFIG_KALLSYMS_EXTRA_PASS -last_kallsyms := 3 -else last_kallsyms := 2 + +ifdef KALLSYMS_EXTRA_PASS +ifneq ($(KALLSYMS_EXTRA_PASS),0) +last_kallsyms := 3 +endif endif kallsyms.o := .tmp_kallsyms$(last_kallsyms).o @@ -816,7 +818,8 @@ define verify_kallsyms $(cmd_sysmap) .tmp_vmlinux$(last_kallsyms) .tmp_System.map $(Q)cmp -s System.map .tmp_System.map || \ (echo Inconsistent kallsyms data; \ - echo Try setting CONFIG_KALLSYMS_EXTRA_PASS; \ + echo This is a bug - please report about it; \ + echo Try "make KALLSYMS_EXTRA_PASS=1" as a workaround; \ rm .tmp_kallsyms* ; /bin/false ) endef -- cgit v1.2.3-58-ga151 From 40df759e2b9ec945f1a5ddc61b3fdfbb6583257e Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Wed, 20 Apr 2011 13:45:30 +0200 Subject: kbuild: Fix build with binutils <= 2.19 The D option of ar is only available in newer versions. Signed-off-by: Michal Marek --- Documentation/kbuild/makefiles.txt | 5 +++++ Makefile | 4 ++++ scripts/Kbuild.include | 5 +++++ scripts/Makefile.build | 4 ++-- 4 files changed, 16 insertions(+), 2 deletions(-) (limited to 'Makefile') diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index 5d145bb443c0..40e082bb8c52 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt @@ -955,6 +955,11 @@ When kbuild executes, the following steps are followed (roughly): used when linking modules. This is often a linker script. From commandline LDFLAGS_MODULE shall be used (see kbuild.txt). + KBUILD_ARFLAGS Options for $(AR) when creating archives + + $(KBUILD_ARFLAGS) set by the top level Makefile to "D" (deterministic + mode) if this option is supported by $(AR). + --- 6.2 Add prerequisites to archprepare: The archprepare: rule is used to list prerequisites that need to be diff --git a/Makefile b/Makefile index c3bd316b16f4..d7c42319fe1e 100644 --- a/Makefile +++ b/Makefile @@ -382,6 +382,7 @@ export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_GCOV export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL +export KBUILD_ARFLAGS # When compiling out-of-tree modules, put MODVERDIR in the module # tree rather than in the kernel tree. The kernel tree might @@ -612,6 +613,9 @@ KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow) # conserve stack if available KBUILD_CFLAGS += $(call cc-option,-fconserve-stack) +# use the deterministic mode of AR if available +KBUILD_ARFLAGS := $(call ar-option,D) + # check for 'asm goto' ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y) KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index ed2773edfe71..fae2d8d8cb09 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -141,6 +141,11 @@ cc-ldoption = $(call try-run,\ ld-option = $(call try-run,\ $(CC) /dev/null -c -o "$$TMPO" ; $(LD) $(1) "$$TMPO" -o "$$TMP",$(1),$(2)) +# ar-option +# Usage: KBUILD_ARFLAGS := $(call ar-option,D) +# Important: no spaces around options +ar-option = $(call try-run, $(AR) rc$(1) "$$TMP",$(1),$(2)) + ###### ### diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 5f87d3709f9f..e1244ef308ce 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -345,7 +345,7 @@ quiet_cmd_link_o_target = LD $@ cmd_link_o_target = $(if $(strip $(obj-y)),\ $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^) \ $(cmd_secanalysis),\ - rm -f $@; $(AR) rcsD $@) + rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@) $(builtin-target): $(obj-y) FORCE $(call if_changed,link_o_target) @@ -371,7 +371,7 @@ $(modorder-target): $(subdir-ym) FORCE # ifdef lib-target quiet_cmd_link_l_target = AR $@ -cmd_link_l_target = rm -f $@; $(AR) rcsD $@ $(lib-y) +cmd_link_l_target = rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@ $(lib-y) $(lib-target): $(lib-y) FORCE $(call if_changed,link_l_target) -- cgit v1.2.3-58-ga151 From 28bc20dccadc610c56e27255aeef2938141a0cd3 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Wed, 27 Apr 2011 22:15:27 +0200 Subject: kbuild: implement several W= levels Building a kernel with "make W=1" produces far too much noise to be useful. Divide the warning options in three groups: W=1 - warnings that may be relevant and does not occur too often W=2 - warnings that occur quite often but may still be relevant W=3 - the more obscure warnings, can most likely be ignored When building the whole kernel, those levels produce: W=1 - 4859 warnings W=2 - 1394 warnings W=3 - 86666 warnings respectively. Warnings have been counted with Geert's script at http://www.kernel.org/pub/linux/kernel/people/geert/linux-log/linux-log-summary.pl Many warnings occur from .h files so fixing one file may have a nice effect on the total number of warnings. With these changes I am actually tempted to try W=1 now and then. Previously there was just too much noise. Borislav: - make the W= levels exclusive - move very noisy and making little sense for the kernel warnings to W=3 - drop -Woverlength-strings due to useless warning message - copy explanatory text for the different warning levels to 'make help' - recount warnings per level Signed-off-by: Sam Ravnborg Signed-off-by: Borislav Petkov Cc: Dave Jones Cc: Geert Uytterhoeven Signed-off-by: Michal Marek --- Makefile | 8 +++++-- scripts/Makefile.build | 65 +++++++++++++++++++++++++++++--------------------- 2 files changed, 44 insertions(+), 29 deletions(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index d7c42319fe1e..d43429f4ced8 100644 --- a/Makefile +++ b/Makefile @@ -103,7 +103,7 @@ ifeq ("$(origin O)", "command line") endif ifeq ("$(origin W)", "command line") - export KBUILD_ENABLE_EXTRA_GCC_CHECKS := 1 + export KBUILD_ENABLE_EXTRA_GCC_CHECKS := $(W) endif # That's our default target when none is given on the command line @@ -1274,7 +1274,11 @@ help: @echo ' make O=dir [targets] Locate all output files in "dir", including .config' @echo ' make C=1 [targets] Check all c source with $$CHECK (sparse by default)' @echo ' make C=2 [targets] Force check of all c source with $$CHECK' - @echo ' make W=1 [targets] Enable extra gcc checks' + @echo ' make W=n [targets] Enable extra gcc checks, n=1,2,3 where' + @echo ' 1: warnings which may be relevant and do not occur too often' + @echo ' 2: warnings which occur quite often but may still be relevant' + @echo ' 3: more obscure warnings, can most likely be ignored' + @echo '' @echo 'Execute "make" or "make all" to build all targets marked with [*] ' @echo 'For further info see the ./README file' diff --git a/scripts/Makefile.build b/scripts/Makefile.build index e1244ef308ce..9c0c48127946 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -51,36 +51,47 @@ ifeq ($(KBUILD_NOPEDANTIC),) endif # -# make W=1 settings +# make W=... settings # -# $(call cc-option... ) handles gcc -W.. options which +# W=1 - warnings that may be relevant and does not occur too often +# W=2 - warnings that occur quite often but may still be relevant +# W=3 - the more obscure warnings, can most likely be ignored +# +# $(call cc-option, -W...) handles gcc -W.. options which # are not supported by all versions of the compiler ifdef KBUILD_ENABLE_EXTRA_GCC_CHECKS -KBUILD_EXTRA_WARNINGS := -Wextra -KBUILD_EXTRA_WARNINGS += -Wunused -Wno-unused-parameter -KBUILD_EXTRA_WARNINGS += -Waggregate-return -KBUILD_EXTRA_WARNINGS += -Wbad-function-cast -KBUILD_EXTRA_WARNINGS += -Wcast-qual -KBUILD_EXTRA_WARNINGS += -Wcast-align -KBUILD_EXTRA_WARNINGS += -Wconversion -KBUILD_EXTRA_WARNINGS += -Wdisabled-optimization -KBUILD_EXTRA_WARNINGS += -Wlogical-op -KBUILD_EXTRA_WARNINGS += -Wmissing-declarations -KBUILD_EXTRA_WARNINGS += -Wmissing-format-attribute -KBUILD_EXTRA_WARNINGS += $(call cc-option, -Wmissing-include-dirs,) -KBUILD_EXTRA_WARNINGS += -Wmissing-prototypes -KBUILD_EXTRA_WARNINGS += -Wnested-externs -KBUILD_EXTRA_WARNINGS += -Wold-style-definition -KBUILD_EXTRA_WARNINGS += $(call cc-option, -Woverlength-strings,) -KBUILD_EXTRA_WARNINGS += -Wpacked -KBUILD_EXTRA_WARNINGS += -Wpacked-bitfield-compat -KBUILD_EXTRA_WARNINGS += -Wpadded -KBUILD_EXTRA_WARNINGS += -Wpointer-arith -KBUILD_EXTRA_WARNINGS += -Wredundant-decls -KBUILD_EXTRA_WARNINGS += -Wshadow -KBUILD_EXTRA_WARNINGS += -Wswitch-default -KBUILD_EXTRA_WARNINGS += $(call cc-option, -Wvla,) -KBUILD_CFLAGS += $(KBUILD_EXTRA_WARNINGS) +warning-1 := -Wextra -Wunused -Wno-unused-parameter +warning-1 += -Wmissing-declarations +warning-1 += -Wmissing-format-attribute +warning-1 += -Wmissing-prototypes +warning-1 += -Wold-style-definition +warning-1 += $(call cc-option, -Wmissing-include-dirs) + +warning-2 := -Waggregate-return +warning-2 += -Wcast-align +warning-2 += -Wdisabled-optimization +warning-2 += -Wnested-externs +warning-2 += -Wshadow +warning-2 += $(call cc-option, -Wlogical-op) + +warning-3 := -Wbad-function-cast +warning-3 += -Wcast-qual +warning-3 += -Wconversion +warning-3 += -Wpacked +warning-3 += -Wpadded +warning-3 += -Wpointer-arith +warning-3 += -Wredundant-decls +warning-3 += -Wswitch-default +warning-3 += $(call cc-option, -Wpacked-bitfield-compat) +warning-3 += $(call cc-option, -Wvla) + +warning := $(warning-$(KBUILD_ENABLE_EXTRA_GCC_CHECKS)) + +ifeq ("$(warning)","") + $(error W=$(KBUILD_ENABLE_EXTRA_GCC_CHECKS) is unknown) +endif + +KBUILD_CFLAGS += $(warning) endif include scripts/Makefile.lib -- cgit v1.2.3-58-ga151 From d8ecc5cd8e227bc318513b5306ae88a474b8886d Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Wed, 27 Apr 2011 22:29:49 +0200 Subject: kbuild: asm-generic support There is an increasing amount of header files shared between individual architectures in asm-generic. To avoid a lot of dummy wrapper files that just include the corresponding file in asm-generic provide some basic support in kbuild for this. With the following patch an architecture can maintain a list of files in the file arch/$(ARCH)/include/asm/Kbuild To use a generic file just add: generic-y += For each file listed kbuild will generate the necessary wrapper in arch/$(ARCH)/include/generated/asm. When installing userspace headers a wrapper is likewise created. The original inspiration for this came from the unicore32 patchset - although a different method is used. The patch includes several improvements from Arnd Bergmann. Michael Marek contributed Makefile.asm-generic. Remis Baima did an intial implementation along to achive the same - see https://patchwork.kernel.org/patch/13352/ Signed-off-by: Sam Ravnborg Acked-by: Guan Xuetao Tested-by: Guan Xuetao Acked-by: Arnd Bergmann Cc: Remis Lima Baima Signed-off-by: Michal Marek --- .gitignore | 1 + Documentation/kbuild/makefiles.txt | 36 ++++++++++++++++++++++++++++++++++++ Makefile | 16 ++++++++++++---- scripts/Makefile.asm-generic | 23 +++++++++++++++++++++++ scripts/Makefile.headersinst | 10 +++++++++- 5 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 scripts/Makefile.asm-generic (limited to 'Makefile') diff --git a/.gitignore b/.gitignore index 5d56a3fd0de6..9dacde0a4b2d 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,7 @@ modules.builtin include/config include/linux/version.h include/generated +arch/*/include/generated # stgit generated dirs patches-* diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index 40e082bb8c52..835b64acf0b4 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt @@ -40,11 +40,13 @@ This document describes the Linux kernel Makefiles. --- 6.6 Commands useful for building a boot image --- 6.7 Custom kbuild commands --- 6.8 Preprocessing linker scripts + --- 6.9 Generic header files === 7 Kbuild syntax for exported headers --- 7.1 header-y --- 7.2 objhdr-y --- 7.3 destination-y + --- 7.4 generic-y === 8 Kbuild Variables === 9 Makefile language @@ -1214,6 +1216,14 @@ When kbuild executes, the following steps are followed (roughly): The kbuild infrastructure for *lds file are used in several architecture-specific files. +--- 6.9 Generic header files + + The directory include/asm-generic contains the header files + that may be shared between individual architectures. + The recommended approach how to use a generic header file is + to list the file in the Kbuild file. + See "7.4 generic-y" for further info on syntax etc. + === 7 Kbuild syntax for exported headers The kernel include a set of headers that is exported to userspace. @@ -1270,6 +1280,32 @@ See subsequent chapter for the syntax of the Kbuild file. In the example above all exported headers in the Kbuild file will be located in the directory "include/linux" when exported. + --- 7.4 generic-y + + If an architecture uses a verbatim copy of a header from + include/asm-generic then this is listed in the file + arch/$(ARCH)/include/asm/Kbuild like this: + + Example: + #arch/x86/include/asm/Kbuild + generic-y += termios.h + generic-y += rtc.h + + During the prepare phase of the build a wrapper include + file is generated in the directory: + + arch/$(ARCH)/include/generated/asm + + When a header is exported where the architecture uses + the generic header a similar wrapper is generated as part + of the set of exported headers in the directory: + + usr/include/asm + + The generated wrapper will in both cases look like the following: + + Example: termios.h + #include === 8 Kbuild Variables diff --git a/Makefile b/Makefile index d43429f4ced8..e509cc704968 100644 --- a/Makefile +++ b/Makefile @@ -349,7 +349,8 @@ CFLAGS_GCOV = -fprofile-arcs -ftest-coverage # Use LINUXINCLUDE when you must reference the include/ directory. # Needed to be compatible with the O= option -LINUXINCLUDE := -I$(srctree)/arch/$(hdr-arch)/include -Iinclude \ +LINUXINCLUDE := -I$(srctree)/arch/$(hdr-arch)/include \ + -Iarch/$(hdr-arch)/include/generated -Iinclude \ $(if $(KBUILD_SRC), -I$(srctree)/include) \ -include include/generated/autoconf.h @@ -417,6 +418,12 @@ ifneq ($(KBUILD_SRC),) $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL) endif +# Support for using generic headers in asm-generic +PHONY += asm-generic +asm-generic: + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \ + obj=arch/$(SRCARCH)/include/generated/asm + # To make sure we do not include .config for any of the *config targets # catch them early, and hand them over to scripts/kconfig/Makefile # It is allowed to specify more targets when calling make, including @@ -954,7 +961,7 @@ ifneq ($(KBUILD_SRC),) endif # prepare2 creates a makefile if using a separate output directory -prepare2: prepare3 outputmakefile +prepare2: prepare3 outputmakefile asm-generic prepare1: prepare2 include/linux/version.h include/generated/utsrelease.h \ include/config/auto.conf @@ -1028,7 +1035,7 @@ hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm) PHONY += __headers -__headers: include/linux/version.h scripts_basic FORCE +__headers: include/linux/version.h scripts_basic asm-generic FORCE $(Q)$(MAKE) $(build)=scripts build_unifdef PHONY += headers_install_all @@ -1143,7 +1150,8 @@ CLEAN_FILES += vmlinux System.map \ .tmp_kallsyms* .tmp_version .tmp_vmlinux* .tmp_System.map # Directories & files removed with 'make mrproper' -MRPROPER_DIRS += include/config usr/include include/generated +MRPROPER_DIRS += include/config usr/include include/generated \ + arch/*/include/generated MRPROPER_FILES += .config .config.old .version .old_version \ include/linux/version.h \ Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS diff --git a/scripts/Makefile.asm-generic b/scripts/Makefile.asm-generic new file mode 100644 index 000000000000..a687cb697e35 --- /dev/null +++ b/scripts/Makefile.asm-generic @@ -0,0 +1,23 @@ +# include/asm-generic contains a lot of files that are used +# verbatim by several architectures. +# +# This Makefile reads the file arch/$(SRCARCH)/include/asm/Kbuild +# and for each file listed in this file with generic-y creates +# a small wrapper file in $(obj) (arch/$(SRCARCH)/include/generated/asm) + +kbuild-file := $(srctree)/arch/$(SRCARCH)/include/asm/Kbuild +include $(kbuild-file) + +include scripts/Kbuild.include + +# Create output directory if not already present +_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj)) + +quiet_cmd_wrap = WRAP $@ +cmd_wrap = echo "\#include " >$@ + +all: $(patsubst %, $(obj)/%, $(generic-y)) + +$(obj)/%.h: + $(call cmd,wrap) + diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst index f89cb87f5c01..a57f5bd5a13d 100644 --- a/scripts/Makefile.headersinst +++ b/scripts/Makefile.headersinst @@ -27,8 +27,13 @@ header-y := $(filter-out %/, $(header-y)) install-file := $(install)/.install check-file := $(install)/.check +# generic-y list all files an architecture uses from asm-generic +# Use this to build a list of headers which require a wrapper +wrapper-files := $(filter $(header-y), $(generic-y)) + # all headers files for this dir -all-files := $(header-y) $(objhdr-y) +header-y := $(filter-out $(generic-y), $(header-y)) +all-files := $(header-y) $(objhdr-y) $(wrapper-files) input-files := $(addprefix $(srctree)/$(obj)/,$(header-y)) \ $(addprefix $(objtree)/$(obj)/,$(objhdr-y)) output-files := $(addprefix $(install)/, $(all-files)) @@ -47,6 +52,9 @@ quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\ cmd_install = \ $(PERL) $< $(srctree)/$(obj) $(install) $(SRCARCH) $(header-y); \ $(PERL) $< $(objtree)/$(obj) $(install) $(SRCARCH) $(objhdr-y); \ + for F in $(wrapper-files); do \ + echo "\#include " > $(install)/$$F; \ + done; \ touch $@ quiet_cmd_remove = REMOVE $(unwanted) -- cgit v1.2.3-58-ga151 From af0e5d565d2fffcd97d1e2d89669d627cc04e8b8 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 21 Apr 2011 17:28:13 -0400 Subject: kbuild: Disable -Wunused-but-set-variable for gcc 4.6.0 Disable the new -Wunused-but-set-variable that was added in gcc 4.6.0 It produces more false positives than useful warnings. This can still be enabled using W=1 Signed-off-by: Dave Jones Acked-by: Sam Ravnborg Tested-by: Sam Ravnborg Signed-off-by: Michal Marek --- Makefile | 4 ++++ scripts/Makefile.build | 1 + 2 files changed, 5 insertions(+) (limited to 'Makefile') diff --git a/Makefile b/Makefile index e509cc704968..4527dc23a724 100644 --- a/Makefile +++ b/Makefile @@ -567,6 +567,10 @@ ifndef CONFIG_CC_STACKPROTECTOR KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector) endif +# This warning generated too much noise in a regular build. +# Use make W=1 to enable this warning (see scripts/Makefile.build) +KBUILD_CFLAGS += $(call cc-option, -Wno-unused-but-set-variable) + ifdef CONFIG_FRAME_POINTER KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls else diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 9c0c48127946..9fb19c0fbf8c 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -66,6 +66,7 @@ warning-1 += -Wmissing-format-attribute warning-1 += -Wmissing-prototypes warning-1 += -Wold-style-definition warning-1 += $(call cc-option, -Wmissing-include-dirs) +warning-1 += $(call cc-option, -Wunused-but-set-variable) warning-2 := -Waggregate-return warning-2 += -Wcast-align -- cgit v1.2.3-58-ga151 From a6de553da01c2c110c647fbd1c5bad29f5a82487 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Fri, 29 Apr 2011 14:45:31 +0200 Subject: kbuild: Allow to combine multiple W= levels Add support for make W=12, make W=123 and so on, to enable warnings from multiple W= levels. Normally, make W= does not include warnings from the previous level. Signed-off-by: Michal Marek Acked-by: Sam Ravnborg Reviewed-By: Valdis Kletnieks --- Makefile | 2 +- scripts/Makefile.build | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 4527dc23a724..d34250266f47 100644 --- a/Makefile +++ b/Makefile @@ -1290,7 +1290,7 @@ help: @echo ' 1: warnings which may be relevant and do not occur too often' @echo ' 2: warnings which occur quite often but may still be relevant' @echo ' 3: more obscure warnings, can most likely be ignored' - + @echo ' Multiple levels can be combined with W=12 or W=123' @echo '' @echo 'Execute "make" or "make all" to build all targets marked with [*] ' @echo 'For further info see the ./README file' diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 9fb19c0fbf8c..f133641f815a 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -60,6 +60,8 @@ endif # $(call cc-option, -W...) handles gcc -W.. options which # are not supported by all versions of the compiler ifdef KBUILD_ENABLE_EXTRA_GCC_CHECKS +warning- := $(empty) + warning-1 := -Wextra -Wunused -Wno-unused-parameter warning-1 += -Wmissing-declarations warning-1 += -Wmissing-format-attribute @@ -86,9 +88,11 @@ warning-3 += -Wswitch-default warning-3 += $(call cc-option, -Wpacked-bitfield-compat) warning-3 += $(call cc-option, -Wvla) -warning := $(warning-$(KBUILD_ENABLE_EXTRA_GCC_CHECKS)) +warning := $(warning-$(findstring 1, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS))) +warning += $(warning-$(findstring 2, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS))) +warning += $(warning-$(findstring 3, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS))) -ifeq ("$(warning)","") +ifeq ("$(strip $(warning))","") $(error W=$(KBUILD_ENABLE_EXTRA_GCC_CHECKS) is unknown) endif -- cgit v1.2.3-58-ga151 From bffd2020a972a188750e5cf4b9566950dfdf25a2 Mon Sep 17 00:00:00 2001 From: Peter Foley Date: Mon, 2 May 2011 22:48:03 +0200 Subject: kbuild: move scripts/basic/docproc.c to scripts/docproc.c Move docproc from scripts/basic to scripts so it is only built for *doc targets instead of every time the kernel is built. --- Documentation/DocBook/Makefile | 2 +- Makefile | 1 + scripts/.gitignore | 1 + scripts/Makefile | 7 +- scripts/basic/.gitignore | 2 - scripts/basic/Makefile | 3 +- scripts/basic/docproc.c | 583 ----------------------------------------- scripts/docproc.c | 583 +++++++++++++++++++++++++++++++++++++++++ 8 files changed, 592 insertions(+), 590 deletions(-) delete mode 100644 scripts/basic/docproc.c create mode 100644 scripts/docproc.c (limited to 'Makefile') diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 8436b018c289..3cebfa0d1611 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -73,7 +73,7 @@ installmandocs: mandocs ### #External programs used KERNELDOC = $(srctree)/scripts/kernel-doc -DOCPROC = $(objtree)/scripts/basic/docproc +DOCPROC = $(objtree)/scripts/docproc XMLTOFLAGS = -m $(srctree)/Documentation/DocBook/stylesheet.xsl XMLTOFLAGS += --skip-validation diff --git a/Makefile b/Makefile index d34250266f47..bc9eae424af8 100644 --- a/Makefile +++ b/Makefile @@ -1313,6 +1313,7 @@ $(help-board-dirs): help-%: # Documentation targets # --------------------------------------------------------------------------- %docs: scripts_basic FORCE + $(Q)$(MAKE) $(build)=scripts build_docproc $(Q)$(MAKE) $(build)=Documentation/DocBook $@ else # KBUILD_EXTMOD diff --git a/scripts/.gitignore b/scripts/.gitignore index e2741d23bab8..105b21f08185 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -8,3 +8,4 @@ bin2c unifdef ihex2fw recordmcount +docproc diff --git a/scripts/Makefile b/scripts/Makefile index fcea26168bca..df7678febf27 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -6,6 +6,7 @@ # pnmttologo: Convert pnm files to logo files # conmakehash: Create chartable # conmakehash: Create arrays for initializing the kernel console tables +# docproc: Used in Documentation/DocBook hostprogs-$(CONFIG_KALLSYMS) += kallsyms hostprogs-$(CONFIG_LOGO) += pnmtologo @@ -16,12 +17,14 @@ hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount always := $(hostprogs-y) $(hostprogs-m) # The following hostprogs-y programs are only build on demand -hostprogs-y += unifdef +hostprogs-y += unifdef docproc -# This target is used internally to avoid "is up to date" messages +# These targets are used internally to avoid "is up to date" messages PHONY += build_unifdef build_unifdef: scripts/unifdef FORCE @: +build_docproc: scripts/docproc FORCE + @: subdir-$(CONFIG_MODVERSIONS) += genksyms subdir-y += mod diff --git a/scripts/basic/.gitignore b/scripts/basic/.gitignore index bf8b199ec598..a776371a3502 100644 --- a/scripts/basic/.gitignore +++ b/scripts/basic/.gitignore @@ -1,3 +1 @@ -hash fixdep -docproc diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile index 4c324a1f1e0e..4fcef87bb875 100644 --- a/scripts/basic/Makefile +++ b/scripts/basic/Makefile @@ -7,9 +7,8 @@ # .config is included by main Makefile. # --------------------------------------------------------------------------- # fixdep: Used to generate dependency information during build process -# docproc: Used in Documentation/DocBook -hostprogs-y := fixdep docproc +hostprogs-y := fixdep always := $(hostprogs-y) # fixdep is needed to compile other host programs diff --git a/scripts/basic/docproc.c b/scripts/basic/docproc.c deleted file mode 100644 index 98dec87974d0..000000000000 --- a/scripts/basic/docproc.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - * docproc is a simple preprocessor for the template files - * used as placeholders for the kernel internal documentation. - * docproc is used for documentation-frontend and - * dependency-generator. - * The two usages have in common that they require - * some knowledge of the .tmpl syntax, therefore they - * are kept together. - * - * documentation-frontend - * Scans the template file and call kernel-doc for - * all occurrences of ![EIF]file - * Beforehand each referenced file is scanned for - * any symbols that are exported via these macros: - * EXPORT_SYMBOL(), EXPORT_SYMBOL_GPL(), & - * EXPORT_SYMBOL_GPL_FUTURE() - * This is used to create proper -function and - * -nofunction arguments in calls to kernel-doc. - * Usage: docproc doc file.tmpl - * - * dependency-generator: - * Scans the template file and list all files - * referenced in a format recognized by make. - * Usage: docproc depend file.tmpl - * Writes dependency information to stdout - * in the following format: - * file.tmpl src.c src2.c - * The filenames are obtained from the following constructs: - * !Efilename - * !Ifilename - * !Dfilename - * !Ffilename - * !Pfilename - * - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* exitstatus is used to keep track of any failing calls to kernel-doc, - * but execution continues. */ -int exitstatus = 0; - -typedef void DFL(char *); -DFL *defaultline; - -typedef void FILEONLY(char * file); -FILEONLY *internalfunctions; -FILEONLY *externalfunctions; -FILEONLY *symbolsonly; -FILEONLY *findall; - -typedef void FILELINE(char * file, char * line); -FILELINE * singlefunctions; -FILELINE * entity_system; -FILELINE * docsection; - -#define MAXLINESZ 2048 -#define MAXFILES 250 -#define KERNELDOCPATH "scripts/" -#define KERNELDOC "kernel-doc" -#define DOCBOOK "-docbook" -#define LIST "-list" -#define FUNCTION "-function" -#define NOFUNCTION "-nofunction" -#define NODOCSECTIONS "-no-doc-sections" - -static char *srctree, *kernsrctree; - -static char **all_list = NULL; -static int all_list_len = 0; - -static void consume_symbol(const char *sym) -{ - int i; - - for (i = 0; i < all_list_len; i++) { - if (!all_list[i]) - continue; - if (strcmp(sym, all_list[i])) - continue; - all_list[i] = NULL; - break; - } -} - -static void usage (void) -{ - fprintf(stderr, "Usage: docproc {doc|depend} file\n"); - fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n"); - fprintf(stderr, "doc: frontend when generating kernel documentation\n"); - fprintf(stderr, "depend: generate list of files referenced within file\n"); - fprintf(stderr, "Environment variable SRCTREE: absolute path to sources.\n"); - fprintf(stderr, " KBUILD_SRC: absolute path to kernel source tree.\n"); -} - -/* - * Execute kernel-doc with parameters given in svec - */ -static void exec_kernel_doc(char **svec) -{ - pid_t pid; - int ret; - char real_filename[PATH_MAX + 1]; - /* Make sure output generated so far are flushed */ - fflush(stdout); - switch (pid=fork()) { - case -1: - perror("fork"); - exit(1); - case 0: - memset(real_filename, 0, sizeof(real_filename)); - strncat(real_filename, kernsrctree, PATH_MAX); - strncat(real_filename, "/" KERNELDOCPATH KERNELDOC, - PATH_MAX - strlen(real_filename)); - execvp(real_filename, svec); - fprintf(stderr, "exec "); - perror(real_filename); - exit(1); - default: - waitpid(pid, &ret ,0); - } - if (WIFEXITED(ret)) - exitstatus |= WEXITSTATUS(ret); - else - exitstatus = 0xff; -} - -/* Types used to create list of all exported symbols in a number of files */ -struct symbols -{ - char *name; -}; - -struct symfile -{ - char *filename; - struct symbols *symbollist; - int symbolcnt; -}; - -struct symfile symfilelist[MAXFILES]; -int symfilecnt = 0; - -static void add_new_symbol(struct symfile *sym, char * symname) -{ - sym->symbollist = - realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *)); - sym->symbollist[sym->symbolcnt++].name = strdup(symname); -} - -/* Add a filename to the list */ -static struct symfile * add_new_file(char * filename) -{ - symfilelist[symfilecnt++].filename = strdup(filename); - return &symfilelist[symfilecnt - 1]; -} - -/* Check if file already are present in the list */ -static struct symfile * filename_exist(char * filename) -{ - int i; - for (i=0; i < symfilecnt; i++) - if (strcmp(symfilelist[i].filename, filename) == 0) - return &symfilelist[i]; - return NULL; -} - -/* - * List all files referenced within the template file. - * Files are separated by tabs. - */ -static void adddep(char * file) { printf("\t%s", file); } -static void adddep2(char * file, char * line) { line = line; adddep(file); } -static void noaction(char * line) { line = line; } -static void noaction2(char * file, char * line) { file = file; line = line; } - -/* Echo the line without further action */ -static void printline(char * line) { printf("%s", line); } - -/* - * Find all symbols in filename that are exported with EXPORT_SYMBOL & - * EXPORT_SYMBOL_GPL (& EXPORT_SYMBOL_GPL_FUTURE implicitly). - * All symbols located are stored in symfilelist. - */ -static void find_export_symbols(char * filename) -{ - FILE * fp; - struct symfile *sym; - char line[MAXLINESZ]; - if (filename_exist(filename) == NULL) { - char real_filename[PATH_MAX + 1]; - memset(real_filename, 0, sizeof(real_filename)); - strncat(real_filename, srctree, PATH_MAX); - strncat(real_filename, "/", PATH_MAX - strlen(real_filename)); - strncat(real_filename, filename, - PATH_MAX - strlen(real_filename)); - sym = add_new_file(filename); - fp = fopen(real_filename, "r"); - if (fp == NULL) - { - fprintf(stderr, "docproc: "); - perror(real_filename); - exit(1); - } - while (fgets(line, MAXLINESZ, fp)) { - char *p; - char *e; - if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != NULL) || - ((p = strstr(line, "EXPORT_SYMBOL")) != NULL)) { - /* Skip EXPORT_SYMBOL{_GPL} */ - while (isalnum(*p) || *p == '_') - p++; - /* Remove parentheses & additional whitespace */ - while (isspace(*p)) - p++; - if (*p != '(') - continue; /* Syntax error? */ - else - p++; - while (isspace(*p)) - p++; - e = p; - while (isalnum(*e) || *e == '_') - e++; - *e = '\0'; - add_new_symbol(sym, p); - } - } - fclose(fp); - } -} - -/* - * Document all external or internal functions in a file. - * Call kernel-doc with following parameters: - * kernel-doc -docbook -nofunction function_name1 filename - * Function names are obtained from all the src files - * by find_export_symbols. - * intfunc uses -nofunction - * extfunc uses -function - */ -static void docfunctions(char * filename, char * type) -{ - int i,j; - int symcnt = 0; - int idx = 0; - char **vec; - - for (i=0; i <= symfilecnt; i++) - symcnt += symfilelist[i].symbolcnt; - vec = malloc((2 + 2 * symcnt + 3) * sizeof(char *)); - if (vec == NULL) { - perror("docproc: "); - exit(1); - } - vec[idx++] = KERNELDOC; - vec[idx++] = DOCBOOK; - vec[idx++] = NODOCSECTIONS; - for (i=0; i < symfilecnt; i++) { - struct symfile * sym = &symfilelist[i]; - for (j=0; j < sym->symbolcnt; j++) { - vec[idx++] = type; - consume_symbol(sym->symbollist[j].name); - vec[idx++] = sym->symbollist[j].name; - } - } - vec[idx++] = filename; - vec[idx] = NULL; - printf("\n", filename); - exec_kernel_doc(vec); - fflush(stdout); - free(vec); -} -static void intfunc(char * filename) { docfunctions(filename, NOFUNCTION); } -static void extfunc(char * filename) { docfunctions(filename, FUNCTION); } - -/* - * Document specific function(s) in a file. - * Call kernel-doc with the following parameters: - * kernel-doc -docbook -function function1 [-function function2] - */ -static void singfunc(char * filename, char * line) -{ - char *vec[200]; /* Enough for specific functions */ - int i, idx = 0; - int startofsym = 1; - vec[idx++] = KERNELDOC; - vec[idx++] = DOCBOOK; - - /* Split line up in individual parameters preceded by FUNCTION */ - for (i=0; line[i]; i++) { - if (isspace(line[i])) { - line[i] = '\0'; - startofsym = 1; - continue; - } - if (startofsym) { - startofsym = 0; - vec[idx++] = FUNCTION; - vec[idx++] = &line[i]; - } - } - for (i = 0; i < idx; i++) { - if (strcmp(vec[i], FUNCTION)) - continue; - consume_symbol(vec[i + 1]); - } - vec[idx++] = filename; - vec[idx] = NULL; - exec_kernel_doc(vec); -} - -/* - * Insert specific documentation section from a file. - * Call kernel-doc with the following parameters: - * kernel-doc -docbook -function "doc section" filename - */ -static void docsect(char *filename, char *line) -{ - char *vec[6]; /* kerneldoc -docbook -function "section" file NULL */ - char *s; - - for (s = line; *s; s++) - if (*s == '\n') - *s = '\0'; - - if (asprintf(&s, "DOC: %s", line) < 0) { - perror("asprintf"); - exit(1); - } - consume_symbol(s); - free(s); - - vec[0] = KERNELDOC; - vec[1] = DOCBOOK; - vec[2] = FUNCTION; - vec[3] = line; - vec[4] = filename; - vec[5] = NULL; - exec_kernel_doc(vec); -} - -static void find_all_symbols(char *filename) -{ - char *vec[4]; /* kerneldoc -list file NULL */ - pid_t pid; - int ret, i, count, start; - char real_filename[PATH_MAX + 1]; - int pipefd[2]; - char *data, *str; - size_t data_len = 0; - - vec[0] = KERNELDOC; - vec[1] = LIST; - vec[2] = filename; - vec[3] = NULL; - - if (pipe(pipefd)) { - perror("pipe"); - exit(1); - } - - switch (pid=fork()) { - case -1: - perror("fork"); - exit(1); - case 0: - close(pipefd[0]); - dup2(pipefd[1], 1); - memset(real_filename, 0, sizeof(real_filename)); - strncat(real_filename, kernsrctree, PATH_MAX); - strncat(real_filename, "/" KERNELDOCPATH KERNELDOC, - PATH_MAX - strlen(real_filename)); - execvp(real_filename, vec); - fprintf(stderr, "exec "); - perror(real_filename); - exit(1); - default: - close(pipefd[1]); - data = malloc(4096); - do { - while ((ret = read(pipefd[0], - data + data_len, - 4096)) > 0) { - data_len += ret; - data = realloc(data, data_len + 4096); - } - } while (ret == -EAGAIN); - if (ret != 0) { - perror("read"); - exit(1); - } - waitpid(pid, &ret ,0); - } - if (WIFEXITED(ret)) - exitstatus |= WEXITSTATUS(ret); - else - exitstatus = 0xff; - - count = 0; - /* poor man's strtok, but with counting */ - for (i = 0; i < data_len; i++) { - if (data[i] == '\n') { - count++; - data[i] = '\0'; - } - } - start = all_list_len; - all_list_len += count; - all_list = realloc(all_list, sizeof(char *) * all_list_len); - str = data; - for (i = 0; i < data_len && start != all_list_len; i++) { - if (data[i] == '\0') { - all_list[start] = str; - str = data + i + 1; - start++; - } - } -} - -/* - * Parse file, calling action specific functions for: - * 1) Lines containing !E - * 2) Lines containing !I - * 3) Lines containing !D - * 4) Lines containing !F - * 5) Lines containing !P - * 6) Lines containing !C - * 7) Default lines - lines not matching the above - */ -static void parse_file(FILE *infile) -{ - char line[MAXLINESZ]; - char * s; - while (fgets(line, MAXLINESZ, infile)) { - if (line[0] == '!') { - s = line + 2; - switch (line[1]) { - case 'E': - while (*s && !isspace(*s)) s++; - *s = '\0'; - externalfunctions(line+2); - break; - case 'I': - while (*s && !isspace(*s)) s++; - *s = '\0'; - internalfunctions(line+2); - break; - case 'D': - while (*s && !isspace(*s)) s++; - *s = '\0'; - symbolsonly(line+2); - break; - case 'F': - /* filename */ - while (*s && !isspace(*s)) s++; - *s++ = '\0'; - /* function names */ - while (isspace(*s)) - s++; - singlefunctions(line +2, s); - break; - case 'P': - /* filename */ - while (*s && !isspace(*s)) s++; - *s++ = '\0'; - /* DOC: section name */ - while (isspace(*s)) - s++; - docsection(line + 2, s); - break; - case 'C': - while (*s && !isspace(*s)) s++; - *s = '\0'; - if (findall) - findall(line+2); - break; - default: - defaultline(line); - } - } - else { - defaultline(line); - } - } - fflush(stdout); -} - - -int main(int argc, char *argv[]) -{ - FILE * infile; - int i; - - srctree = getenv("SRCTREE"); - if (!srctree) - srctree = getcwd(NULL, 0); - kernsrctree = getenv("KBUILD_SRC"); - if (!kernsrctree || !*kernsrctree) - kernsrctree = srctree; - if (argc != 3) { - usage(); - exit(1); - } - /* Open file, exit on error */ - infile = fopen(argv[2], "r"); - if (infile == NULL) { - fprintf(stderr, "docproc: "); - perror(argv[2]); - exit(2); - } - - if (strcmp("doc", argv[1]) == 0) - { - /* Need to do this in two passes. - * First pass is used to collect all symbols exported - * in the various files; - * Second pass generate the documentation. - * This is required because some functions are declared - * and exported in different files :-(( - */ - /* Collect symbols */ - defaultline = noaction; - internalfunctions = find_export_symbols; - externalfunctions = find_export_symbols; - symbolsonly = find_export_symbols; - singlefunctions = noaction2; - docsection = noaction2; - findall = find_all_symbols; - parse_file(infile); - - /* Rewind to start from beginning of file again */ - fseek(infile, 0, SEEK_SET); - defaultline = printline; - internalfunctions = intfunc; - externalfunctions = extfunc; - symbolsonly = printline; - singlefunctions = singfunc; - docsection = docsect; - findall = NULL; - - parse_file(infile); - - for (i = 0; i < all_list_len; i++) { - if (!all_list[i]) - continue; - fprintf(stderr, "Warning: didn't use docs for %s\n", - all_list[i]); - } - } - else if (strcmp("depend", argv[1]) == 0) - { - /* Create first part of dependency chain - * file.tmpl */ - printf("%s\t", argv[2]); - defaultline = noaction; - internalfunctions = adddep; - externalfunctions = adddep; - symbolsonly = adddep; - singlefunctions = adddep2; - docsection = adddep2; - findall = adddep; - parse_file(infile); - printf("\n"); - } - else - { - fprintf(stderr, "Unknown option: %s\n", argv[1]); - exit(1); - } - fclose(infile); - fflush(stdout); - return exitstatus; -} diff --git a/scripts/docproc.c b/scripts/docproc.c new file mode 100644 index 000000000000..98dec87974d0 --- /dev/null +++ b/scripts/docproc.c @@ -0,0 +1,583 @@ +/* + * docproc is a simple preprocessor for the template files + * used as placeholders for the kernel internal documentation. + * docproc is used for documentation-frontend and + * dependency-generator. + * The two usages have in common that they require + * some knowledge of the .tmpl syntax, therefore they + * are kept together. + * + * documentation-frontend + * Scans the template file and call kernel-doc for + * all occurrences of ![EIF]file + * Beforehand each referenced file is scanned for + * any symbols that are exported via these macros: + * EXPORT_SYMBOL(), EXPORT_SYMBOL_GPL(), & + * EXPORT_SYMBOL_GPL_FUTURE() + * This is used to create proper -function and + * -nofunction arguments in calls to kernel-doc. + * Usage: docproc doc file.tmpl + * + * dependency-generator: + * Scans the template file and list all files + * referenced in a format recognized by make. + * Usage: docproc depend file.tmpl + * Writes dependency information to stdout + * in the following format: + * file.tmpl src.c src2.c + * The filenames are obtained from the following constructs: + * !Efilename + * !Ifilename + * !Dfilename + * !Ffilename + * !Pfilename + * + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* exitstatus is used to keep track of any failing calls to kernel-doc, + * but execution continues. */ +int exitstatus = 0; + +typedef void DFL(char *); +DFL *defaultline; + +typedef void FILEONLY(char * file); +FILEONLY *internalfunctions; +FILEONLY *externalfunctions; +FILEONLY *symbolsonly; +FILEONLY *findall; + +typedef void FILELINE(char * file, char * line); +FILELINE * singlefunctions; +FILELINE * entity_system; +FILELINE * docsection; + +#define MAXLINESZ 2048 +#define MAXFILES 250 +#define KERNELDOCPATH "scripts/" +#define KERNELDOC "kernel-doc" +#define DOCBOOK "-docbook" +#define LIST "-list" +#define FUNCTION "-function" +#define NOFUNCTION "-nofunction" +#define NODOCSECTIONS "-no-doc-sections" + +static char *srctree, *kernsrctree; + +static char **all_list = NULL; +static int all_list_len = 0; + +static void consume_symbol(const char *sym) +{ + int i; + + for (i = 0; i < all_list_len; i++) { + if (!all_list[i]) + continue; + if (strcmp(sym, all_list[i])) + continue; + all_list[i] = NULL; + break; + } +} + +static void usage (void) +{ + fprintf(stderr, "Usage: docproc {doc|depend} file\n"); + fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n"); + fprintf(stderr, "doc: frontend when generating kernel documentation\n"); + fprintf(stderr, "depend: generate list of files referenced within file\n"); + fprintf(stderr, "Environment variable SRCTREE: absolute path to sources.\n"); + fprintf(stderr, " KBUILD_SRC: absolute path to kernel source tree.\n"); +} + +/* + * Execute kernel-doc with parameters given in svec + */ +static void exec_kernel_doc(char **svec) +{ + pid_t pid; + int ret; + char real_filename[PATH_MAX + 1]; + /* Make sure output generated so far are flushed */ + fflush(stdout); + switch (pid=fork()) { + case -1: + perror("fork"); + exit(1); + case 0: + memset(real_filename, 0, sizeof(real_filename)); + strncat(real_filename, kernsrctree, PATH_MAX); + strncat(real_filename, "/" KERNELDOCPATH KERNELDOC, + PATH_MAX - strlen(real_filename)); + execvp(real_filename, svec); + fprintf(stderr, "exec "); + perror(real_filename); + exit(1); + default: + waitpid(pid, &ret ,0); + } + if (WIFEXITED(ret)) + exitstatus |= WEXITSTATUS(ret); + else + exitstatus = 0xff; +} + +/* Types used to create list of all exported symbols in a number of files */ +struct symbols +{ + char *name; +}; + +struct symfile +{ + char *filename; + struct symbols *symbollist; + int symbolcnt; +}; + +struct symfile symfilelist[MAXFILES]; +int symfilecnt = 0; + +static void add_new_symbol(struct symfile *sym, char * symname) +{ + sym->symbollist = + realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *)); + sym->symbollist[sym->symbolcnt++].name = strdup(symname); +} + +/* Add a filename to the list */ +static struct symfile * add_new_file(char * filename) +{ + symfilelist[symfilecnt++].filename = strdup(filename); + return &symfilelist[symfilecnt - 1]; +} + +/* Check if file already are present in the list */ +static struct symfile * filename_exist(char * filename) +{ + int i; + for (i=0; i < symfilecnt; i++) + if (strcmp(symfilelist[i].filename, filename) == 0) + return &symfilelist[i]; + return NULL; +} + +/* + * List all files referenced within the template file. + * Files are separated by tabs. + */ +static void adddep(char * file) { printf("\t%s", file); } +static void adddep2(char * file, char * line) { line = line; adddep(file); } +static void noaction(char * line) { line = line; } +static void noaction2(char * file, char * line) { file = file; line = line; } + +/* Echo the line without further action */ +static void printline(char * line) { printf("%s", line); } + +/* + * Find all symbols in filename that are exported with EXPORT_SYMBOL & + * EXPORT_SYMBOL_GPL (& EXPORT_SYMBOL_GPL_FUTURE implicitly). + * All symbols located are stored in symfilelist. + */ +static void find_export_symbols(char * filename) +{ + FILE * fp; + struct symfile *sym; + char line[MAXLINESZ]; + if (filename_exist(filename) == NULL) { + char real_filename[PATH_MAX + 1]; + memset(real_filename, 0, sizeof(real_filename)); + strncat(real_filename, srctree, PATH_MAX); + strncat(real_filename, "/", PATH_MAX - strlen(real_filename)); + strncat(real_filename, filename, + PATH_MAX - strlen(real_filename)); + sym = add_new_file(filename); + fp = fopen(real_filename, "r"); + if (fp == NULL) + { + fprintf(stderr, "docproc: "); + perror(real_filename); + exit(1); + } + while (fgets(line, MAXLINESZ, fp)) { + char *p; + char *e; + if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != NULL) || + ((p = strstr(line, "EXPORT_SYMBOL")) != NULL)) { + /* Skip EXPORT_SYMBOL{_GPL} */ + while (isalnum(*p) || *p == '_') + p++; + /* Remove parentheses & additional whitespace */ + while (isspace(*p)) + p++; + if (*p != '(') + continue; /* Syntax error? */ + else + p++; + while (isspace(*p)) + p++; + e = p; + while (isalnum(*e) || *e == '_') + e++; + *e = '\0'; + add_new_symbol(sym, p); + } + } + fclose(fp); + } +} + +/* + * Document all external or internal functions in a file. + * Call kernel-doc with following parameters: + * kernel-doc -docbook -nofunction function_name1 filename + * Function names are obtained from all the src files + * by find_export_symbols. + * intfunc uses -nofunction + * extfunc uses -function + */ +static void docfunctions(char * filename, char * type) +{ + int i,j; + int symcnt = 0; + int idx = 0; + char **vec; + + for (i=0; i <= symfilecnt; i++) + symcnt += symfilelist[i].symbolcnt; + vec = malloc((2 + 2 * symcnt + 3) * sizeof(char *)); + if (vec == NULL) { + perror("docproc: "); + exit(1); + } + vec[idx++] = KERNELDOC; + vec[idx++] = DOCBOOK; + vec[idx++] = NODOCSECTIONS; + for (i=0; i < symfilecnt; i++) { + struct symfile * sym = &symfilelist[i]; + for (j=0; j < sym->symbolcnt; j++) { + vec[idx++] = type; + consume_symbol(sym->symbollist[j].name); + vec[idx++] = sym->symbollist[j].name; + } + } + vec[idx++] = filename; + vec[idx] = NULL; + printf("\n", filename); + exec_kernel_doc(vec); + fflush(stdout); + free(vec); +} +static void intfunc(char * filename) { docfunctions(filename, NOFUNCTION); } +static void extfunc(char * filename) { docfunctions(filename, FUNCTION); } + +/* + * Document specific function(s) in a file. + * Call kernel-doc with the following parameters: + * kernel-doc -docbook -function function1 [-function function2] + */ +static void singfunc(char * filename, char * line) +{ + char *vec[200]; /* Enough for specific functions */ + int i, idx = 0; + int startofsym = 1; + vec[idx++] = KERNELDOC; + vec[idx++] = DOCBOOK; + + /* Split line up in individual parameters preceded by FUNCTION */ + for (i=0; line[i]; i++) { + if (isspace(line[i])) { + line[i] = '\0'; + startofsym = 1; + continue; + } + if (startofsym) { + startofsym = 0; + vec[idx++] = FUNCTION; + vec[idx++] = &line[i]; + } + } + for (i = 0; i < idx; i++) { + if (strcmp(vec[i], FUNCTION)) + continue; + consume_symbol(vec[i + 1]); + } + vec[idx++] = filename; + vec[idx] = NULL; + exec_kernel_doc(vec); +} + +/* + * Insert specific documentation section from a file. + * Call kernel-doc with the following parameters: + * kernel-doc -docbook -function "doc section" filename + */ +static void docsect(char *filename, char *line) +{ + char *vec[6]; /* kerneldoc -docbook -function "section" file NULL */ + char *s; + + for (s = line; *s; s++) + if (*s == '\n') + *s = '\0'; + + if (asprintf(&s, "DOC: %s", line) < 0) { + perror("asprintf"); + exit(1); + } + consume_symbol(s); + free(s); + + vec[0] = KERNELDOC; + vec[1] = DOCBOOK; + vec[2] = FUNCTION; + vec[3] = line; + vec[4] = filename; + vec[5] = NULL; + exec_kernel_doc(vec); +} + +static void find_all_symbols(char *filename) +{ + char *vec[4]; /* kerneldoc -list file NULL */ + pid_t pid; + int ret, i, count, start; + char real_filename[PATH_MAX + 1]; + int pipefd[2]; + char *data, *str; + size_t data_len = 0; + + vec[0] = KERNELDOC; + vec[1] = LIST; + vec[2] = filename; + vec[3] = NULL; + + if (pipe(pipefd)) { + perror("pipe"); + exit(1); + } + + switch (pid=fork()) { + case -1: + perror("fork"); + exit(1); + case 0: + close(pipefd[0]); + dup2(pipefd[1], 1); + memset(real_filename, 0, sizeof(real_filename)); + strncat(real_filename, kernsrctree, PATH_MAX); + strncat(real_filename, "/" KERNELDOCPATH KERNELDOC, + PATH_MAX - strlen(real_filename)); + execvp(real_filename, vec); + fprintf(stderr, "exec "); + perror(real_filename); + exit(1); + default: + close(pipefd[1]); + data = malloc(4096); + do { + while ((ret = read(pipefd[0], + data + data_len, + 4096)) > 0) { + data_len += ret; + data = realloc(data, data_len + 4096); + } + } while (ret == -EAGAIN); + if (ret != 0) { + perror("read"); + exit(1); + } + waitpid(pid, &ret ,0); + } + if (WIFEXITED(ret)) + exitstatus |= WEXITSTATUS(ret); + else + exitstatus = 0xff; + + count = 0; + /* poor man's strtok, but with counting */ + for (i = 0; i < data_len; i++) { + if (data[i] == '\n') { + count++; + data[i] = '\0'; + } + } + start = all_list_len; + all_list_len += count; + all_list = realloc(all_list, sizeof(char *) * all_list_len); + str = data; + for (i = 0; i < data_len && start != all_list_len; i++) { + if (data[i] == '\0') { + all_list[start] = str; + str = data + i + 1; + start++; + } + } +} + +/* + * Parse file, calling action specific functions for: + * 1) Lines containing !E + * 2) Lines containing !I + * 3) Lines containing !D + * 4) Lines containing !F + * 5) Lines containing !P + * 6) Lines containing !C + * 7) Default lines - lines not matching the above + */ +static void parse_file(FILE *infile) +{ + char line[MAXLINESZ]; + char * s; + while (fgets(line, MAXLINESZ, infile)) { + if (line[0] == '!') { + s = line + 2; + switch (line[1]) { + case 'E': + while (*s && !isspace(*s)) s++; + *s = '\0'; + externalfunctions(line+2); + break; + case 'I': + while (*s && !isspace(*s)) s++; + *s = '\0'; + internalfunctions(line+2); + break; + case 'D': + while (*s && !isspace(*s)) s++; + *s = '\0'; + symbolsonly(line+2); + break; + case 'F': + /* filename */ + while (*s && !isspace(*s)) s++; + *s++ = '\0'; + /* function names */ + while (isspace(*s)) + s++; + singlefunctions(line +2, s); + break; + case 'P': + /* filename */ + while (*s && !isspace(*s)) s++; + *s++ = '\0'; + /* DOC: section name */ + while (isspace(*s)) + s++; + docsection(line + 2, s); + break; + case 'C': + while (*s && !isspace(*s)) s++; + *s = '\0'; + if (findall) + findall(line+2); + break; + default: + defaultline(line); + } + } + else { + defaultline(line); + } + } + fflush(stdout); +} + + +int main(int argc, char *argv[]) +{ + FILE * infile; + int i; + + srctree = getenv("SRCTREE"); + if (!srctree) + srctree = getcwd(NULL, 0); + kernsrctree = getenv("KBUILD_SRC"); + if (!kernsrctree || !*kernsrctree) + kernsrctree = srctree; + if (argc != 3) { + usage(); + exit(1); + } + /* Open file, exit on error */ + infile = fopen(argv[2], "r"); + if (infile == NULL) { + fprintf(stderr, "docproc: "); + perror(argv[2]); + exit(2); + } + + if (strcmp("doc", argv[1]) == 0) + { + /* Need to do this in two passes. + * First pass is used to collect all symbols exported + * in the various files; + * Second pass generate the documentation. + * This is required because some functions are declared + * and exported in different files :-(( + */ + /* Collect symbols */ + defaultline = noaction; + internalfunctions = find_export_symbols; + externalfunctions = find_export_symbols; + symbolsonly = find_export_symbols; + singlefunctions = noaction2; + docsection = noaction2; + findall = find_all_symbols; + parse_file(infile); + + /* Rewind to start from beginning of file again */ + fseek(infile, 0, SEEK_SET); + defaultline = printline; + internalfunctions = intfunc; + externalfunctions = extfunc; + symbolsonly = printline; + singlefunctions = singfunc; + docsection = docsect; + findall = NULL; + + parse_file(infile); + + for (i = 0; i < all_list_len; i++) { + if (!all_list[i]) + continue; + fprintf(stderr, "Warning: didn't use docs for %s\n", + all_list[i]); + } + } + else if (strcmp("depend", argv[1]) == 0) + { + /* Create first part of dependency chain + * file.tmpl */ + printf("%s\t", argv[2]); + defaultline = noaction; + internalfunctions = adddep; + externalfunctions = adddep; + symbolsonly = adddep; + singlefunctions = adddep2; + docsection = adddep2; + findall = adddep; + parse_file(infile); + printf("\n"); + } + else + { + fprintf(stderr, "Unknown option: %s\n", argv[1]); + exit(1); + } + fclose(infile); + fflush(stdout); + return exitstatus; +} -- cgit v1.2.3-58-ga151 From 8417da6f2128008c431c7d130af6cd3d9079922e Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Mon, 2 May 2011 12:51:15 +0200 Subject: kbuild: Fix passing -Wno-* options to gcc 4.4+ Starting with 4.4, gcc will happily accept -Wno- in the cc-option test and complain later when compiling a file that has some other warning. This rather unexpected behavior is intentional as per http://gcc.gnu.org/PR28322, so work around it by testing for support of the opposite option (without the no-). Introduce a new Makefile function cc-disable-warning that does this and update two uses of cc-option in the toplevel Makefile. Reported-and-tested-by: Stephen Rothwell Signed-off-by: Michal Marek --- Documentation/kbuild/makefiles.txt | 12 ++++++++++++ Makefile | 4 ++-- scripts/Kbuild.include | 5 +++++ 3 files changed, 19 insertions(+), 2 deletions(-) (limited to 'Makefile') diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index 835b64acf0b4..47435e56c5da 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt @@ -501,6 +501,18 @@ more details, with real examples. gcc >= 3.00. For gcc < 3.00, -malign-functions=4 is used. Note: cc-option-align uses KBUILD_CFLAGS for $(CC) options + cc-disable-warning + cc-disable-warning checks if gcc supports a given warning and returns + the commandline switch to disable it. This special function is needed, + because gcc 4.4 and later accept any unknown -Wno-* option and only + warn about it if there is another warning in the source file. + + Example: + KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable) + + In the above example, -Wno-unused-but-set-variable will be added to + KBUILD_CFLAGS only if gcc really accepts it. + cc-version cc-version returns a numerical version of the $(CC) compiler version. The format is where both are two digits. So for example diff --git a/Makefile b/Makefile index bc9eae424af8..5cf4eb03fb3e 100644 --- a/Makefile +++ b/Makefile @@ -569,7 +569,7 @@ endif # This warning generated too much noise in a regular build. # Use make W=1 to enable this warning (see scripts/Makefile.build) -KBUILD_CFLAGS += $(call cc-option, -Wno-unused-but-set-variable) +KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable) ifdef CONFIG_FRAME_POINTER KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls @@ -616,7 +616,7 @@ CHECKFLAGS += $(NOSTDINC_FLAGS) KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) # disable pointer signed / unsigned warnings in gcc 4.0 -KBUILD_CFLAGS += $(call cc-option,-Wno-pointer-sign,) +KBUILD_CFLAGS += $(call cc-disable-warning, pointer-sign) # disable invalid "can't wrap" optimizations for signed / pointers KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow) diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index fae2d8d8cb09..c034dd7161a6 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -118,6 +118,11 @@ cc-option-yn = $(call try-run,\ cc-option-align = $(subst -functions=0,,\ $(call cc-option,-falign-functions=0,-malign-functions=0)) +# cc-disable-warning +# Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable) +cc-disable-warning = $(call try-run,\ + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -xc /dev/null -o "$$TMP",-Wno-$(strip $(1))) + # cc-version # Usage gcc-ver := $(call cc-version) cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC)) -- cgit v1.2.3-58-ga151 From 43f67c98161c65f1b2e3af3a9ce6741850072c06 Mon Sep 17 00:00:00 2001 From: Kevin Cernekee Date: Tue, 10 May 2011 15:47:16 -0700 Subject: kbuild: Fix GNU make v3.80 compatibility According to Documentation/Changes, the kernel should be buildable with GNU make 3.80+. Commit 88d7be031f9f975bb3f50a0b5ef3796a671e7edf (kbuild: Use a single clean rule for kernel and external modules) introduced the "$(or" construct, which requires make 3.81. This causes "make clean" to malfunction when it is used with external modules. Replace "$(or" with an equivalent "$(if" expression, to restore backward compatibility. Signed-off-by: Kevin Cernekee Cc: stable@kernel.org Signed-off-by: Michal Marek --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 5cf4eb03fb3e..d96f56e1bfcd 100644 --- a/Makefile +++ b/Makefile @@ -1398,7 +1398,7 @@ endif # KBUILD_EXTMOD clean: $(clean-dirs) $(call cmd,rmdirs) $(call cmd,rmfiles) - @find $(or $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ + @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ -o -name '*.symtypes' -o -name 'modules.order' \ -- cgit v1.2.3-58-ga151