kbuild: move cc_c_o logic to a shell script
RFC PATCH 1/1 kbuild: move cc_c_o logic to a shell script
From b92cb72f08908a718da05318975545e988bfdaf9 Mon Sep 17 00:00:00 2001
From: Sam Ravnborg <[email protected]>
Date: Mon, 9 Jun 2014 18:03:22 +0200
Subject: [PATCH] kbuild: move cc_c_o logic to a shell script
The amount of makefile magic required when building a .o file from a .c file had grown far too much.
Move all the logic to a shell script where it is much easier to follow the sequence and thus easier to debug/enhance.
This transition has following impact on the current functionality:
- We no longer rebuild the kernel if the source for recordmount is changed The source filehas not changed for a couple of years
- A shortcut to build symtypes files is lost. It was never supported by the top-level Makefile anyway
---
The final link of vmlinux was moved out to a shell script resulting in some much more readable code.
Try to do the same for .c => .o rule.
I would like someone with more shell-foo than me to review the shell script.
Sam
scripts/Makefile.build | 115 ++++-------------------------- scripts/kcc.sh | 187 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 202 insertions(+), 100 deletions(-) create mode 100644 scripts/kcc.sh
scripts/Makefile.build +15 -100
@@ -158,14 +158,9 @@ __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \ @: # Linus' kernel sanity checking tool -ifneq ($(KBUILD_CHECKSRC),0) - ifeq ($(KBUILD_CHECKSRC),2) - quiet_cmd_force_checksrc = CHECK $< - cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ; - else - quiet_cmd_checksrc = CHECK $< - cmd_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ; - endif +ifeq ($(KBUILD_CHECKSRC),2) +quiet_cmd_force_checksrc = CHECK $< + cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ; endif # Do section mismatch analysis for each module/built-in.o
@@ -219,108 +214,28 @@ cmd_cc_i_c = $(CPP) $(c_flags) -o $@ $< $(obj)/%.i: $(src)/%.c FORCE $(call if_changed_dep,cc_i_c) -cmd_gensymtypes = \ - $(CPP) -D__GENKSYMS__ $(c_flags) $< | \ - $(GENKSYMS) $(if $(1), -T $(2)) \ - $(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX)) \ - $(if $(KBUILD_PRESERVE),-p) \ - -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null)) - -quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@ -cmd_cc_symtypes_c = \ - set -e; \ - $(call cmd_gensymtypes,true,$@) >/dev/null; \ - test -s $@ || rm -f $@ - -$(obj)/%.symtypes : $(src)/%.c FORCE - $(call cmd,cc_symtypes_c) - -# C (.c) files -# The C file is compiled and updated dependency information is generated. -# (See cmd_cc_o_c + relevant part of rule_cc_o_c) - -quiet_cmd_cc_o_c = CC $(quiet_modtag) $@ - -ifndef CONFIG_MODVERSIONS -cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< - -else -# When module versioning is enabled the following steps are executed: -# o compile a .tmp_<file>.o from <file>.c -# o if .tmp_<file>.o doesn't contain a __ksymtab version, i.e. does -# not export symbols, we just rename .tmp_<file>.o to <file>.o and -# are done. -# o otherwise, we calculate symbol versions using the good old -# genksyms on the preprocessed source and postprocess them in a way -# that they are usable as a linker script -# o generate <file>.o from .tmp_<file>.o using the linker to -# replace the unresolved symbols __crc_exported_symbol with -# the actual value of the checksum generated by genksyms - -cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $< -cmd_modversions = \ - if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \ - $(call cmd_gensymtypes,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \ - > $(@D)/.tmp_$(@F:.o=.ver); \ - \ - $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \ - -T $(@D)/.tmp_$(@F:.o=.ver); \ - rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \ - else \ - mv -f $(@D)/.tmp_$(@F) $@; \ - fi; -endif - -ifdef CONFIG_FTRACE_MCOUNT_RECORD -ifdef BUILD_C_RECORDMCOUNT -ifeq ("$(origin RECORDMCOUNT_WARN)", "command line") - RECORDMCOUNT_FLAGS = -w -endif -# Due to recursion, we must skip empty.o. -# The empty.o file is created in the make process in order to determine -# the target endianness and word size. It is made before all other C -# files, including recordmcount. -sub_cmd_record_mcount = \ - if [ $(@) != "scripts/mod/empty.o" ]; then \ - $(objtree)/scripts/recordmcount $(RECORDMCOUNT_FLAGS) "$(@)"; \ - fi; -recordmcount_source := $(srctree)/scripts/recordmcount.c \ - $(srctree)/scripts/recordmcount.h -else -sub_cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \ - "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \ - "$(if $(CONFIG_64BIT),64,32)" \ - "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \ - "$(LD)" "$(NM)" "$(RM)" "$(MV)" \ - "$(if $(part-of-module),1,0)" "$(@)"; -recordmcount_source := $(srctree)/scripts/recordmcount.pl -endif -cmd_record_mcount = \ - if [ "$(findstring -pg,$(_c_flags))" = "-pg" ]; then \ - $(sub_cmd_record_mcount) \ - fi; -endif - define rule_cc_o_c - $(call echo-cmd,checksrc) $(cmd_checksrc) \ - $(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \ - $(cmd_modversions) \ - $(call echo-cmd,record_mcount) \ - $(cmd_record_mcount) \ - scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' > \ - $(dot-target).tmp; \ - rm -f $(depfile); \ + $(CONFIG_SHELL) $(srctree)/scripts/kcc.sh \ + $< $@ $(depfile) \ + $(if $(part-of-module),m,b) \ + "$(echo-why)" \ + $(c_flags); \ + scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' > \ + $(dot-target).tmp; \ + rm -f $(depfile); \ mv -f $(dot-target).tmp $(dot-target).cmd endef +# cmd_cc_o_c is required by if_changed_rule to detect changes in options +cmd_cc_o_c = $(CC) $(c_flags) # Built-in and composite module parts -$(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE +$(obj)/%.o: $(src)/%.c FORCE $(call cmd,force_checksrc) $(call if_changed_rule,cc_o_c) # Single-part modules are special since we need to mark them in $(MODVERDIR) -$(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE +$(single-used-m): $(obj)/%.o: $(src)/%.c FORCE $(call cmd,force_checksrc) $(call if_changed_rule,cc_o_c) @{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
scripts/kcc.sh new file +187 -0
187 lines not on this page · raw message
Signature · 1 line
1.9.3
Dne 9.6.2014 18:23, Sam Ravnborg napsal(a):
Quoted 9 lines
From
b92cb72f08908a718da05318975545e988bfdaf9Mon Sep 17 00:00:00 2001
From: Sam Ravnborg <[email protected]>
Date: Mon, 9 Jun 2014 18:03:22 +0200
Subject: [PATCH] kbuild: movecc_c_ologic to a shell scriptThe amount of makefile magic required when building a .o file from a .c file had grown far too much.
Move all the logic to a shell script where it is much easier to follow the sequence and thus easier to debug/enhance.
That's a nice cleanup! Some review below, but I'll have to do one more pass.
Quoted 3 lines
This transition has following impact on the current functionality:
- We no longer rebuild the kernel if the source for recordmount is changed The source filehas not changed for a couple of years
Yeah, that should not be an issue.
Quoted 2 lines
- A shortcut to build symtypes files is lost. It was never supported by the top-level
Makefileanyway
There is a rule for that:
%.symtypes: %.c prepare scripts FORCE
$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
But it could be added to the script, e.g. if $outfile ends in .symtypes, do just the genksyms run.
Quoted 21 lines
scripts/kcc.sh new file +15
-0@@ -0,0 +1,187 @@ +#!/bin/sh +# kernel wrapper for cc +# In the simple case we just call cc with the supplied arguments. +# But we may check the source with sparse before we call cc. +# And we may postprocess the source or the .o file to support +# module versioning and function tracing. + +# Error out on error +set -e + +# Print command and execute +# ${quiet} determine which command to print (if any) +run() +{ + case "${quiet}" in
scripts/kcc.sh line 25
Quoted 10 lines
scripts/kcc.sh new file +10
-0+ "silent_") + shift + ;; + "quiet_") + printf " %s \n" "$1 ${why}" + shift + ;; + *) + shift + echo "$*"
While there is no -n or -e option to gcc, I'd use printf just to be on the safe side:
printf '%s\n' "$*"
Quoted 16 lines
scripts/kcc.sh new file +16
-0+ esac + + # Run the command + $* +} + +# Calculate symbol versions on the preprocessed source +# using genksyms and postprocess the output in a way +# that it is usable as a linker script. +# Then generate the .o file with the __crc_exported_symbol replaced. +gen_sym_types() +{ + if [ "${KBUILD_SYMTYPES}" = "y" ]; then + dump_types="-T $1.symtypes" + fi +
scripts/kcc.sh line 51
Quoted 10 lines
scripts/kcc.sh new file +10
-0+ if [ "${CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX}" = "y" ]; then + mod_prefix="-s _" + fi + + if [ "${KBUILD_PRESERVE}" != "" ]; then + preserve="-p"; + if [ -f $1.symref ]; then + reference="-r $1.symref" + fi + fi
The -r <file>.symref should not depend on KBUILD_PRESERVE
Quoted 18 lines
scripts/kcc.sh new file +18
-0+ + out=$1.ver + shift + + ${CPP} -D__GENKSYMS__ $* ${infile} | \ + ${GENKSYMS} ${dump_types} ${mod_prefix} ${preserve} ${reference} > ${out} + + # Generate <file>.o from .tmp_<file>.o using the linker to + # replace the unresolved symbols __crc_exported_symbol with + # the actual value of the checksum generated by genksyms + ${LD} ${LDFLAGS} -r -o ${outfile} ${tmpfile}.o -T ${out} + rm -f ${tmpfile}.o ${out} +} + +# Create __mcount_loc section with pointers to all calls to mcount +record_mcount() +{ + # Due to recursion, we must skip empty.o.
scripts/kcc.sh line 79
Quoted 10 lines
scripts/kcc.sh new file +10
-0+ # The empty.o file is created in the make process in order to determine + # the target endianness and word size. It is made before all other C + # files, including recordmcount. + + if [ "$(basename ${outfile})" = "empty.o" ]; then + return + fi + + if [ "${BUILD_C_RECORDMCOUNT}" != "" ]; then + if [ "${RECORDMCOUNT_WARN}" != "" ]; then
In the Makefile, there was a check for RECORDMCOUNT_WARN coming from the make command line, but that's not a big deal. Just document it in the changelog.
scripts/kcc.sh line 184
Quoted 3 lines
scripts/kcc.sh new file +3
-0+# Do we have to run record_mcount? +if [ "${CONFIG_FTRACE_MCOUNT_RECORD}" != "" ]; then + if [ $(echo $* | grep -c -e "-pg") -gt 0 ]; then
case " $* " in
" -pg ")
record_mcount
esac
This has the advantage over the Makefile version that it checks a whole word "-pg". Also, it saves some forking.
Michal