From nobody Tue Feb 10 04:17:06 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=reject dis=none) header.from=citrix.com ARC-Seal: i=1; a=rsa-sha256; t=1629802927; cv=none; d=zohomail.com; s=zohoarc; b=ba3YFIn54qaELgHMItezi54dnC877zWV+TjNhYJV7Kg68tvVFGoWHFmWpeOcQ9Rz2sKZlUWAV91szIlH4OP/rShE8ORoCa6jKa0zu7F36fUCdE12+JZy/ydztF75rfTiCKBEHkcaMUpt4Q1SvVI+UfCUZNSNSJTXxsuQBX91AbQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1629802927; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=DyjD1B1HXFVsW0RlAXEvLkG0/h9YAsm8+NK++l80aEI=; b=Ilh+TDsBb4CP3TTy/ERXDD3KkPFP3KENVzc9p7UbJ3+nYcj98yKWc7gRzjiJrtR/xBTEP685EsLruyH6cuZxoLxmYBWmjfEtKICPDsMashneJrV5WzwSq8q11A/wuG93Rjqi7Jrikq7ye2/JhzY9Lx1ZwMm+0npZVMv05gOy3Cg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1629802927056195.8767171017522; Tue, 24 Aug 2021 04:02:07 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.170996.312208 (Exim 4.92) (envelope-from ) id 1mIUBd-00087e-5W; Tue, 24 Aug 2021 11:01:45 +0000 Received: by outflank-mailman (output) from mailman id 170996.312208; Tue, 24 Aug 2021 11:01:44 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1mIUBc-00083I-9S; Tue, 24 Aug 2021 11:01:44 +0000 Received: by outflank-mailman (input) for mailman id 170996; Tue, 24 Aug 2021 11:01:41 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1mIU2R-0003Ux-AZ for xen-devel@lists.xenproject.org; Tue, 24 Aug 2021 10:52:15 +0000 Received: from esa6.hc3370-68.iphmx.com (unknown [216.71.155.175]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 46e059c8-04c9-11ec-a8c5-12813bfff9fa; Tue, 24 Aug 2021 10:51:47 +0000 (UTC) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 46e059c8-04c9-11ec-a8c5-12813bfff9fa DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1629802306; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=aX8fbbOJrw/glho2e/gRuUJr0uXwqlhwJqAv5f/9XQw=; b=SY9vzKbecohOr5v5XVXkVj1lr0wAvSbHYIFy5YyNWMcJ30Nv7bz3HTdt JA+8/BBiracH11Dvj/7lj5n6cRoFelvcZuQVnhNN/ufDJug2OoxORwaIJ xfphc5ZnzZUMSnFuPXDctKAmXDmGdvj6N7UHVbQc9ZXQKrgilnempfepr U=; Authentication-Results: esa6.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none IronPort-SDR: HFlbiZv665B8YfXjtD/xz/Bcsmgo//L/+dFt6uhkZhnBznxmOw2oogNSBxClYV42C5YRhG2Qw4 m6UTjzqWx+7eP+4XxMjPATBg4fSdQSr03lo+RF2/CZD6ZDeoNeC0ct9AhF8QctvnUV00el83UI hMwOom4shQBykew5TkVFTXNSlDL70tu1n3uQ9eBHapoEKjjYlwxth4lutsqrZS2npJaFvinbU0 QEoXpgCCSzsOODMevMDogSeM57ociXkFmMmr3uQUtATF4K0lzLsWWc24a9G57S1mWRsJ1HOtSH SxncRTP+otznwF3qV3H0bq1X X-SBRS: 5.1 X-MesageID: 51166374 X-Ironport-Server: esa6.hc3370-68.iphmx.com X-Remote-IP: 162.221.156.83 X-Policy: $RELAYED IronPort-HdrOrdr: A9a23:mTumcqtNN+NVHS6FZPJt7vfa7skDTtV00zEX/kB9WHVpmszxra 6TdZMgpHnJYVcqKQkdcL+7WJVoLUmxyXcx2/h1AV7AZniAhILLFvAA0WKK+VSJcEeSygce79 YFT0EXMqyIMbEQt6fHCWeDfOrIuOP3kpyVuQ== X-IronPort-AV: E=Sophos;i="5.84,347,1620705600"; d="scan'208";a="51166374" From: Anthony PERARD To: CC: Anthony PERARD , Andrew Cooper , George Dunlap , "Ian Jackson" , Jan Beulich , Julien Grall , Stefano Stabellini , Wei Liu , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= Subject: [XEN PATCH v7 27/51] build: introduce if_changed_deps Date: Tue, 24 Aug 2021 11:50:14 +0100 Message-ID: <20210824105038.1257926-28-anthony.perard@citrix.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210824105038.1257926-1-anthony.perard@citrix.com> References: <20210824105038.1257926-1-anthony.perard@citrix.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @citrix.com) X-ZM-MESSAGEID: 1629802931685100001 Content-Type: text/plain; charset="utf-8" This macro does compare command line like if_changed, but it also rewrite the dependencies generated by $(CC) in order to depend on a CONFIG_* as generated by kconfig instead of depending on autoconf.h. This allow to make a change in kconfig options and only rebuild the object that uses that CONFIG_* option. cmd_and_record isn't needed anymore as it is replace by cmd_and_fixdep. There's only one .*.d dependency file left which is explicitly included as a workound, all the other are been absorb into the .*.cmd dependency files via `fixdep`. So including .*.d can be removed from the makefile. This imports fixdep.c and if_changed_deps macro from Linux v5.12. Signed-off-by: Anthony PERARD Reviewed-by: Jan Beulich --- .gitignore | 1 + xen/Makefile | 15 +- xen/Rules.mk | 17 +- xen/arch/x86/Makefile | 8 +- xen/build.mk | 1 + xen/scripts/Kbuild.include | 17 +- xen/tools/Makefile | 7 +- xen/tools/fixdep.c | 404 +++++++++++++++++++++++++++++++++++++ 8 files changed, 441 insertions(+), 29 deletions(-) create mode 100644 xen/tools/fixdep.c diff --git a/.gitignore b/.gitignore index 59a22d1685e2..550b38b9fa3c 100644 --- a/.gitignore +++ b/.gitignore @@ -338,6 +338,7 @@ xen/include/xen/lib/x86/cpuid-autogen.h xen/test/livepatch/config.h xen/test/livepatch/expect_config.h xen/test/livepatch/*.livepatch +xen/tools/fixdep xen/tools/kconfig/.tmp_gtkcheck xen/tools/kconfig/.tmp_qtcheck xen/tools/symbols diff --git a/xen/Makefile b/xen/Makefile index eb9ea70aaa29..1b5517b02a8c 100644 --- a/xen/Makefile +++ b/xen/Makefile @@ -187,6 +187,13 @@ endif export root-make-done :=3D y endif # root-make-done =20 +# =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D +# Rules shared between *config targets and build targets + +PHONY +=3D tools_fixdep +tools_fixdep: + $(MAKE) -C tools fixdep + # Shorthand for kconfig kconfig =3D -f $(BASEDIR)/tools/kconfig/Makefile.kconfig ARCH=3D$(ARCH) SR= CARCH=3D$(SRCARCH) HOSTCC=3D"$(HOSTCC)" HOSTCXX=3D"$(HOSTCXX)" =20 @@ -400,7 +407,7 @@ $(TARGET).gz: $(TARGET) gzip -n -f -9 < $< > $@.new mv $@.new $@ =20 -$(TARGET): FORCE +$(TARGET): tools_fixdep FORCE $(MAKE) -C tools $(MAKE) $(build)=3D. include/xen/compile.h [ -e arch/$(TARGET_ARCH)/efi ] && for f in $$(cd common/efi; echo *.[ch])= ; \ @@ -457,13 +464,13 @@ cscope: _MAP: $(NM) -n $(TARGET)-syms | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|= \(\.\.ng$$\)\|\(LASH[RL]DI\)' > System.map =20 -%.o %.i %.s: %.c FORCE +%.o %.i %.s: %.c tools_fixdep FORCE $(MAKE) $(build)=3D$(*D) $(*D)/$(@F) =20 -%.o %.s: %.S FORCE +%.o %.s: %.S tools_fixdep FORCE $(MAKE) $(build)=3D$(*D) $(*D)/$(@F) =20 -%/: FORCE +%/: tools_fixdep FORCE $(MAKE) $(build)=3D$* need-builtin=3D1 =20 .PHONY: cloc diff --git a/xen/Rules.mk b/xen/Rules.mk index 2e1435ff4ada..9b8415160649 100644 --- a/xen/Rules.mk +++ b/xen/Rules.mk @@ -148,8 +148,8 @@ cpp_flags =3D $(filter-out -Wa$(comma)% -flto,$(1)) # Calculation of flags, first the generic flags, then the arch specific fl= ags, # and last the flags modified for a target or a directory. =20 -c_flags =3D -MMD -MP -MF $(@D)/.$(@F).d $(XEN_CFLAGS) -a_flags =3D -MMD -MP -MF $(@D)/.$(@F).d $(XEN_AFLAGS) +c_flags =3D -MMD -MP -MF $(depfile) $(XEN_CFLAGS) +a_flags =3D -MMD -MP -MF $(depfile) $(XEN_AFLAGS) =20 include $(BASEDIR)/arch/$(TARGET_ARCH)/Rules.mk =20 @@ -206,7 +206,7 @@ else endif =20 define rule_cc_o_c - $(call cmd_and_record,cc_o_c) + $(call cmd_and_fixdep,cc_o_c) $(call cmd,objcopy_fix_sym) endef =20 @@ -217,7 +217,7 @@ quiet_cmd_cc_o_S =3D CC $@ cmd_cc_o_S =3D $(CC) $(a_flags) -c $< -o $@ =20 $(obj)/%.o: $(src)/%.S FORCE - $(call if_changed,cc_o_S) + $(call if_changed_dep,cc_o_S) =20 =20 quiet_cmd_obj_init_o =3D INIT_O $@ @@ -247,13 +247,13 @@ quiet_cmd_cpp_s_S =3D CPP $@ cmd_cpp_s_S =3D $(CPP) $(call cpp_flags,$(a_flags)) -MQ $@ -o $@ $< =20 $(obj)/%.i: $(src)/%.c FORCE - $(call if_changed,cpp_i_c) + $(call if_changed_dep,cpp_i_c) =20 $(obj)/%.s: $(src)/%.c FORCE - $(call if_changed,cc_s_c) + $(call if_changed_dep,cc_s_c) =20 $(obj)/%.s: $(src)/%.S FORCE - $(call if_changed,cpp_s_S) + $(call if_changed_dep,cpp_s_S) =20 # Linker scripts, .lds.S -> .lds quiet_cmd_cpp_lds_S =3D LDS $@ @@ -292,9 +292,6 @@ existing-targets :=3D $(wildcard $(sort $(targets))) =20 -include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd) =20 -DEPS:=3D $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).d) --include $(DEPS_INCLUDE) - # Declare the contents of the PHONY variable as phony. We keep that # information in a variable so we can use it in if_changed and friends. .PHONY: $(PHONY) diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index f60084eb73e7..05f1d12065a0 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -248,7 +248,7 @@ $(BASEDIR)/arch/x86/include/asm/asm-macros.h: $(obj)/as= m-macros.i $(src)/Makefil =20 $(obj)/efi.lds: AFLAGS-y +=3D -DEFI $(obj)/xen.lds $(obj)/efi.lds: $(src)/xen.lds.S FORCE - $(call if_changed,cpp_lds_S) + $(call if_changed_dep,cpp_lds_S) =20 $(obj)/boot/mkelf32: $(src)/boot/mkelf32.c $(HOSTCC) $(HOSTCFLAGS) -o $@ $< @@ -264,9 +264,3 @@ clean:: rm -f $(BASEDIR)/.xen.efi.[0-9]* efi/*.efi efi/mkreloc rm -f boot/cmdline.S boot/reloc.S boot/*.lnk boot/*.bin rm -f note.o - -# Suppress loading of DEPS files for internal, temporary target files. Th= is -# then also suppresses re-generation of the respective .*.d2 files. -ifeq ($(filter-out .xen%.o,$(notdir $(MAKECMDGOALS))),) -DEPS_INCLUDE:=3D -endif diff --git a/xen/build.mk b/xen/build.mk index c6c06d9f17f5..537c32f42d25 100644 --- a/xen/build.mk +++ b/xen/build.mk @@ -37,6 +37,7 @@ include/xen/compile.h: include/xen/compile.h.in .banner F= ORCE $(call if_changed,compile.h) targets +=3D include/xen/compile.h =20 +-include $(wildcard .asm-offsets.s.d) asm-offsets.s: arch/$(TARGET_ARCH)/$(TARGET_SUBARCH)/asm-offsets.c $(CC) $(call cpp_flags,$(c_flags)) -S -g0 -o $@.new -MQ $@ $< $(call move-if-changed,$@.new,$@) diff --git a/xen/scripts/Kbuild.include b/xen/scripts/Kbuild.include index 62c7caeba1d1..aa3a8a1bd9e7 100644 --- a/xen/scripts/Kbuild.include +++ b/xen/scripts/Kbuild.include @@ -15,8 +15,7 @@ dot-target =3D $(@D)/.$(@F) =20 ### # dependencies -DEPS =3D .*.d -DEPS_INCLUDE =3D $(addsuffix .d2, $(basename $(wildcard $(DEPS)))) +depfile =3D $(dot-target).d =20 ### # real prerequisites without phony targets @@ -81,6 +80,8 @@ cmd =3D @set -e; $(echo-cmd) $(cmd_$(1)) ### # if_changed - execute command if any prerequisite is newer than # target, or command line has changed +# if_changed_dep - as if_changed, but uses fixdep to reveal dependencies +# including used config symbols # if_changed_rule - as if_changed but execute rule instead =20 ifneq ($(KBUILD_NOCMDDEP),1) @@ -109,15 +110,19 @@ if_changed =3D $(if $(any-prereq)$(cmd-check), = \ $(cmd); = \ printf '%s\n' 'cmd_$@ :=3D $(make-cmd)' > $(dot-target).cmd, @:) =20 +# Execute the command and also postprocess generated .d dependencies file. +if_changed_dep =3D $(if $(any-prereq)$(cmd-check),$(cmd_and_fixdep),@:) + +cmd_and_fixdep =3D = \ + $(cmd); = \ + tools/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).cmd; = \ + rm -f $(depfile) + # Usage: $(call if_changed_rule,foo) # Will check if $(cmd_foo) or any of the prerequisites changed, # and if so will execute $(rule_foo). if_changed_rule =3D $(if $(any-prereq)$(cmd-check),$(rule_$(1)),@:) =20 -cmd_and_record =3D = \ - $(cmd); = \ - printf '%s\n' 'cmd_$@ :=3D $(make-cmd)' > $(dot-target).cmd - ### # why - tell why a target got built # enabled by make V=3D2 diff --git a/xen/tools/Makefile b/xen/tools/Makefile index 4e42163f981c..722f3664549d 100644 --- a/xen/tools/Makefile +++ b/xen/tools/Makefile @@ -2,11 +2,14 @@ include $(XEN_ROOT)/Config.mk =20 .PHONY: default -default: symbols +default: symbols fixdep =20 .PHONY: clean clean: - rm -f *.o symbols + rm -f *.o symbols fixdep =20 symbols: symbols.c $(HOSTCC) $(HOSTCFLAGS) -o $@ $< + +fixdep: fixdep.c + $(HOSTCC) $(HOSTCFLAGS) -o $@ $< diff --git a/xen/tools/fixdep.c b/xen/tools/fixdep.c new file mode 100644 index 000000000000..d98540552941 --- /dev/null +++ b/xen/tools/fixdep.c @@ -0,0 +1,404 @@ +/* + * "Optimize" a list of dependencies as spit out by gcc -MD + * for the kernel build + * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D + * + * Author Kai Germaschewski + * Copyright 2002 by Kai Germaschewski + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + * + * Introduction: + * + * gcc produces a very nice and correct list of dependencies which + * tells make when to remake a file. + * + * To use this list as-is however has the drawback that virtually + * every file in the kernel includes autoconf.h. + * + * If the user re-runs make *config, autoconf.h will be + * regenerated. make notices that and will rebuild every file which + * includes autoconf.h, i.e. basically all files. This is extremely + * annoying if the user just changed CONFIG_HIS_DRIVER from n to m. + * + * So we play the same trick that "mkdep" played before. We replace + * the dependency on autoconf.h by a dependency on every config + * option which is mentioned in any of the listed prerequisites. + * + * kconfig populates a tree in include/config/ with an empty file + * for each config symbol and when the configuration is updated + * the files representing changed config options are touched + * which then let make pick up the changes and the files that use + * the config symbols are rebuilt. + * + * So if the user changes his CONFIG_HIS_DRIVER option, only the objects + * which depend on "include/config/his/driver.h" will be rebuilt, + * so most likely only his driver ;-) + * + * The idea above dates, by the way, back to Michael E Chastain, AFAIK. + * + * So to get dependencies right, there are two issues: + * o if any of the files the compiler read changed, we need to rebuild + * o if the command line given to the compile the file changed, we + * better rebuild as well. + * + * The former is handled by using the -MD output, the later by saving + * the command line used to compile the old object and comparing it + * to the one we would now use. + * + * Again, also this idea is pretty old and has been discussed on + * kbuild-devel a long time ago. I don't have a sensibly working + * internet connection right now, so I rather don't mention names + * without double checking. + * + * This code here has been based partially based on mkdep.c, which + * says the following about its history: + * + * Copyright abandoned, Michael Chastain, . + * This is a C version of syncdep.pl by Werner Almesberger. + * + * + * It is invoked as + * + * fixdep + * + * and will read the dependency file + * + * The transformed dependency snipped is written to stdout. + * + * It first generates a line + * + * cmd_ =3D + * + * and then basically copies the ..d file to stdout, in the + * process filtering out the dependency on autoconf.h and adding + * dependencies on include/config/my/option.h for every + * CONFIG_MY_OPTION encountered in any of the prerequisites. + * + * We don't even try to really parse the header files, but + * merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will + * be picked up as well. It's not a problem with respect to + * correctness, since that can only give too many dependencies, thus + * we cannot miss a rebuild. Since people tend to not mention totally + * unrelated CONFIG_ options all over the place, it's not an + * efficiency problem either. + * + * (Note: it'd be easy to port over the complete mkdep state machine, + * but I don't think the added complexity is worth it) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void usage(void) +{ + fprintf(stderr, "Usage: fixdep \n"); + exit(1); +} + +/* + * In the intended usage of this program, the stdout is redirected to .*.c= md + * files. The return value of printf() and putchar() must be checked to ca= tch + * any error, e.g. "No space left on device". + */ +static void xprintf(const char *format, ...) +{ + va_list ap; + int ret; + + va_start(ap, format); + ret =3D vprintf(format, ap); + if (ret < 0) { + perror("fixdep"); + exit(1); + } + va_end(ap); +} + +static void xputchar(int c) +{ + int ret; + + ret =3D putchar(c); + if (ret =3D=3D EOF) { + perror("fixdep"); + exit(1); + } +} + +/* + * Print out a dependency path from a symbol name + */ +static void print_dep(const char *m, int slen, const char *dir) +{ + int c, prev_c =3D '/', i; + + xprintf(" $(wildcard %s/", dir); + for (i =3D 0; i < slen; i++) { + c =3D m[i]; + if (c =3D=3D '_') + c =3D '/'; + else + c =3D tolower(c); + if (c !=3D '/' || prev_c !=3D '/') + xputchar(c); + prev_c =3D c; + } + xprintf(".h) \\\n"); +} + +struct item { + struct item *next; + unsigned int len; + unsigned int hash; + char name[]; +}; + +#define HASHSZ 256 +static struct item *hashtab[HASHSZ]; + +static unsigned int strhash(const char *str, unsigned int sz) +{ + /* fnv32 hash */ + unsigned int i, hash =3D 2166136261U; + + for (i =3D 0; i < sz; i++) + hash =3D (hash ^ str[i]) * 0x01000193; + return hash; +} + +/* + * Lookup a value in the configuration string. + */ +static int is_defined_config(const char *name, int len, unsigned int hash) +{ + struct item *aux; + + for (aux =3D hashtab[hash % HASHSZ]; aux; aux =3D aux->next) { + if (aux->hash =3D=3D hash && aux->len =3D=3D len && + memcmp(aux->name, name, len) =3D=3D 0) + return 1; + } + return 0; +} + +/* + * Add a new value to the configuration string. + */ +static void define_config(const char *name, int len, unsigned int hash) +{ + struct item *aux =3D malloc(sizeof(*aux) + len); + + if (!aux) { + perror("fixdep:malloc"); + exit(1); + } + memcpy(aux->name, name, len); + aux->len =3D len; + aux->hash =3D hash; + aux->next =3D hashtab[hash % HASHSZ]; + hashtab[hash % HASHSZ] =3D aux; +} + +/* + * Record the use of a CONFIG_* word. + */ +static void use_config(const char *m, int slen) +{ + unsigned int hash =3D strhash(m, slen); + + if (is_defined_config(m, slen, hash)) + return; + + define_config(m, slen, hash); + print_dep(m, slen, "include/config"); +} + +/* test if s ends in sub */ +static int str_ends_with(const char *s, int slen, const char *sub) +{ + int sublen =3D strlen(sub); + + if (sublen > slen) + return 0; + + return !memcmp(s + slen - sublen, sub, sublen); +} + +static void parse_config_file(const char *p) +{ + const char *q, *r; + const char *start =3D p; + + while ((p =3D strstr(p, "CONFIG_"))) { + if (p > start && (isalnum(p[-1]) || p[-1] =3D=3D '_')) { + p +=3D 7; + continue; + } + p +=3D 7; + q =3D p; + while (isalnum(*q) || *q =3D=3D '_') + q++; + if (str_ends_with(p, q - p, "_MODULE")) + r =3D q - 7; + else + r =3D q; + if (r > p) + use_config(p, r - p); + p =3D q; + } +} + +static void *read_file(const char *filename) +{ + struct stat st; + int fd; + char *buf; + + fd =3D open(filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "fixdep: error opening file: "); + perror(filename); + exit(2); + } + if (fstat(fd, &st) < 0) { + fprintf(stderr, "fixdep: error fstat'ing file: "); + perror(filename); + exit(2); + } + buf =3D malloc(st.st_size + 1); + if (!buf) { + perror("fixdep: malloc"); + exit(2); + } + if (read(fd, buf, st.st_size) !=3D st.st_size) { + perror("fixdep: read"); + exit(2); + } + buf[st.st_size] =3D '\0'; + close(fd); + + return buf; +} + +/* Ignore certain dependencies */ +static int is_ignored_file(const char *s, int len) +{ + return str_ends_with(s, len, "include/generated/autoconf.h") || + str_ends_with(s, len, "include/generated/autoksyms.h"); +} + +/* + * Important: The below generated source_foo.o and deps_foo.o variable + * assignments are parsed not only by make, but also by the rather simple + * parser in scripts/mod/sumversion.c. + */ +static void parse_dep_file(char *m, const char *target) +{ + char *p; + int is_last, is_target; + int saw_any_target =3D 0; + int is_first_dep =3D 0; + void *buf; + + while (1) { + /* Skip any "white space" */ + while (*m =3D=3D ' ' || *m =3D=3D '\\' || *m =3D=3D '\n') + m++; + + if (!*m) + break; + + /* Find next "white space" */ + p =3D m; + while (*p && *p !=3D ' ' && *p !=3D '\\' && *p !=3D '\n') + p++; + is_last =3D (*p =3D=3D '\0'); + /* Is the token we found a target name? */ + is_target =3D (*(p-1) =3D=3D ':'); + /* Don't write any target names into the dependency file */ + if (is_target) { + /* The /next/ file is the first dependency */ + is_first_dep =3D 1; + } else if (!is_ignored_file(m, p - m)) { + *p =3D '\0'; + + /* + * Do not list the source file as dependency, so that + * kbuild is not confused if a .c file is rewritten + * into .S or vice versa. Storing it in source_* is + * needed for modpost to compute srcversions. + */ + if (is_first_dep) { + /* + * If processing the concatenation of multiple + * dependency files, only process the first + * target name, which will be the original + * source name, and ignore any other target + * names, which will be intermediate temporary + * files. + */ + if (!saw_any_target) { + saw_any_target =3D 1; + xprintf("source_%s :=3D %s\n\n", + target, m); + xprintf("deps_%s :=3D \\\n", target); + } + is_first_dep =3D 0; + } else { + xprintf(" %s \\\n", m); + } + + buf =3D read_file(m); + parse_config_file(buf); + free(buf); + } + + if (is_last) + break; + + /* + * Start searching for next token immediately after the first + * "whitespace" character that follows this token. + */ + m =3D p + 1; + } + + if (!saw_any_target) { + fprintf(stderr, "fixdep: parse error; no targets found\n"); + exit(1); + } + + xprintf("\n%s: $(deps_%s)\n\n", target, target); + xprintf("$(deps_%s):\n", target); +} + +int main(int argc, char *argv[]) +{ + const char *depfile, *target, *cmdline; + void *buf; + + if (argc !=3D 4) + usage(); + + depfile =3D argv[1]; + target =3D argv[2]; + cmdline =3D argv[3]; + + xprintf("cmd_%s :=3D %s\n\n", target, cmdline); + + buf =3D read_file(depfile); + parse_dep_file(buf, target); + free(buf); + + return 0; +} --=20 Anthony PERARD