public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* External kernel modules, second try
@ 2004-03-07  0:44 Andreas Gruenbacher
  2004-03-07 12:53 ` Sam Ravnborg
  0 siblings, 1 reply; 18+ messages in thread
From: Andreas Gruenbacher @ 2004-03-07  0:44 UTC (permalink / raw)
  To: Sam Ravnborg; +Cc: lkml, kbuild-devel@lists.sourceforge.net

[-- Attachment #1: Type: text/plain, Size: 1055 bytes --]

Hello,

here is the patch I posted previously that adds support for modversions
in external kernel modules that are built outside the main kernel tree
(first posting archived here: http://lwn.net/Articles/69148/). Relative
to the original version, the attached version also works when compiling
with O=.

The patch also adds a modules_add target that does the equivalent of
modules_install for one external module. In addition, it makes clean and
mrproper work for external modules. Makefiles of modules that live
outside the main tree currently need to provide their own clean targets
to remove the files kbuild creates; this is pretty messy.

The third change is to remove one instance of temporary file creation
inside the main kernel tree while external modules are built. I think
there are still other cases where temp files in the kernel tree are
used. IMHO they should all go away, so that a ``make -C $KERNEL_SOURCE
modules SUBDIRS=$PWD'' works against a read-only tree.


Thanks,
-- 
Andreas Gruenbacher <agruen@suse.de>
SUSE Labs, SUSE LINUX AG

[-- Attachment #2: kbuild-out-of-tree --]
[-- Type: text/x-patch, Size: 8921 bytes --]

Index: linux-2.6.1/Makefile
===================================================================
--- linux-2.6.1.orig/Makefile
+++ linux-2.6.1/Makefile
@@ -289,7 +289,10 @@ export CPPFLAGS NOSTDINC_FLAGS OBJCOPYFL
 export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE 
 export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
 
-export MODVERDIR := .tmp_versions
+# When compiling out-of-tree modules, put MODVERDIR in the module source
+# tree rather than in the kernel source tree. The kernel source tree might
+# even be read-only.
+export MODVERDIR := $(patsubst %,%/,$(firstword $(filter ../% /%,$(SUBDIRS)))).tmp_versions
 
 # The temporary file to save gcc -MD generated dependencies must not
 # contain a comma
@@ -749,6 +752,9 @@ endif
 _modinst_post: _modinst_
 	if [ -r System.map ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi
 
+modules_add:
+	$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modinst
+
 else # CONFIG_MODULES
 
 # Modules not configured
@@ -820,11 +826,28 @@ clean-dirs += $(addprefix _clean_,$(ALL_
 $(clean-dirs):
 	$(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
 
+.PHONY: _clean _mrproper
+ifeq ($(filter ../% /%,$(SUBDIRS)),)
+
+clean_subdirs := .
+clean: _clean archclean $(clean-dirs)
+	$(call cmd,rmclean)
+mrproper distclean: clean _mrproper archmrproper
+	$(call cmd,mrproper)
+
+else
+
+clean_subdirs := $(filter ../% /%,$(SUBDIRS))
+clean: _clean
+mrproper distclean: _mrproper
+	$(Q)rm -rf $(MODVERDIR)
+
+endif
+
 quiet_cmd_rmclean = RM  $$(CLEAN_FILES)
 cmd_rmclean	  = rm -f $(CLEAN_FILES)
-clean: archclean $(clean-dirs)
-	$(call cmd,rmclean)
-	@find . $(RCS_FIND_IGNORE) \
+_clean:
+	@find $(clean_subdirs) $(RCS_FIND_IGNORE) \
 	 	\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
 		-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \
 		-type f -print | xargs rm -f
@@ -833,15 +856,13 @@ clean: archclean $(clean-dirs)
 #
 quiet_cmd_mrproper = RM  $$(MRPROPER_DIRS) + $$(MRPROPER_FILES)
 cmd_mrproper = rm -rf $(MRPROPER_DIRS) && rm -f $(MRPROPER_FILES)
-mrproper distclean: clean archmrproper
-	@echo '  Making $@ in the srctree'
-	@find . $(RCS_FIND_IGNORE) \
+_mrproper:
+	@find $(clean_subdirs) $(RCS_FIND_IGNORE) \
 	 	\( -name '*.orig' -o -name '*.rej' -o -name '*~' \
 		-o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
 	 	-o -name '.*.rej' -o -size 0 \
 		-o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
 		-type f -print | xargs rm -f
-	$(call cmd,mrproper)
 
 # Generate tags for editors
 # ---------------------------------------------------------------------------
@@ -1045,13 +1066,14 @@ cmd = @$(if $($(quiet)cmd_$(1)),echo '  
 define filechk
 	@set -e;				\
 	echo '  CHK     $@';			\
-	mkdir -p $(dir $@);			\
-	$(filechk_$(1)) < $< > $@.tmp;		\
-	if [ -r $@ ] && cmp -s $@ $@.tmp; then	\
-		rm -f $@.tmp;			\
+	tmp=$$(/bin/mktemp /tmp/kbuild.XXXXXX);	\
+	$(filechk_$(1)) < $< > $$tmp;		\
+	if [ -r $@ ] && cmp -s $@ $$tmp; then	\
+		rm -f $$tmp;			\
 	else					\
 		echo '  UPD     $@';		\
-		mv -f $@.tmp $@;		\
+		mkdir -p $(dir $@);		\
+		mv -f $$tmp $@;			\
 	fi
 endef
 
Index: linux-2.6.1/scripts/modpost.c
===================================================================
--- linux-2.6.1.orig/scripts/modpost.c
+++ linux-2.6.1/scripts/modpost.c
@@ -15,7 +15,7 @@
 
 /* Are we using CONFIG_MODVERSIONS? */
 int modversions = 0;
-/* Do we have vmlinux? */
+/* Warn about undefined symbols? (do so if we have vmlinux) */
 int have_vmlinux = 0;
 
 void
@@ -60,6 +60,17 @@ void *do_nofail(void *ptr, const char *f
 static struct module *modules;
 
 struct module *
+find_module(char *modname)
+{
+	struct module *mod;
+
+	for (mod = modules; mod; mod = mod->next)
+		if (strcmp(mod->name, modname) == 0)
+			break;
+	return mod;
+}
+
+struct module *
 new_module(char *modname)
 {
 	struct module *mod;
@@ -165,7 +176,7 @@ add_exported_symbol(const char *name, st
 	struct symbol *s = find_symbol(name);
 
 	if (!s) {
-		new_symbol(name, modules, crc);
+		new_symbol(name, module, crc);
 		return;
 	}
 	if (crc) {
@@ -346,14 +357,17 @@ read_symbols(char *modname)
 	struct symbol *s;
 	Elf_Sym *sym;
 
-	/* When there's no vmlinux, don't print warnings about
-	 * unresolved symbols (since there'll be too many ;) */
-	have_vmlinux = is_vmlinux(modname);
-
 	parse_elf(&info, modname);
 
 	mod = new_module(modname);
 
+	/* When we have vmlinux, print warnings about unresolved
+	 * symbols. (Otherwise, there might be too many). */
+	if (strcmp(modname, "vmlinux") == 0) {
+		have_vmlinux = 1;
+		mod->skip = 1;
+	}
+
 	for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
 		symname = info.strtab + sym->st_name;
 
@@ -541,19 +555,91 @@ write_if_changed(struct buffer *b, const
 	fclose(file);
 }
 
+void
+read_dump(FILE *file)
+{
+	unsigned int crc;
+	char symname[128], modname[4096];
+
+	while (fscanf(file, "%x %128s %4096s", &crc, symname, modname) == 3) {
+		struct module *mod;
+		if (!(mod = find_module(modname))) {
+			mod = new_module(NOFAIL(strdup(modname)));
+			mod->skip = 1;
+		}
+		add_exported_symbol(symname, mod, &crc);
+	}
+	if (!feof(file)) {
+		fatal("parse error in symbol dump file\n");
+	}
+}
+
+void
+write_dump(FILE *file)
+{
+	struct symbol *symbol;
+	int n;
+
+	for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
+		symbol = symbolhash[n];
+		while (symbol) {
+			symbol = symbol->next;
+		}
+	}
+
+	for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
+		symbol = symbolhash[n];
+		while (symbol) {
+			fprintf(file, "0x%08x\t%s\t%s\n", symbol->crc,
+				symbol->name, symbol->module->name);
+			symbol = symbol->next;
+		}
+	}
+}
+
 int
 main(int argc, char **argv)
 {
 	struct module *mod;
 	struct buffer buf = { };
 	char fname[SZ];
+	char *read_dumpfile = NULL, *write_dumpfile = NULL;
+	int opt;
+
+	while ((opt = getopt(argc, argv, "i:o:")) != -1) {
+		switch(opt) {
+			case 'i':
+				read_dumpfile = optarg;
+				modversions = 1;
+				have_vmlinux = 1;
+				break;
+			case 'o':
+				write_dumpfile = optarg;
+				break;
+			default:
+				exit(1);
+		}
+	}
+
+	if (read_dumpfile) {
+		FILE *file = fopen(read_dumpfile, "r");
+		if (!file) {
+			perror(read_dumpfile);
+			exit(1);
+		}
+		read_dump(file);
+		if (fclose(file) != 0) {
+			perror(read_dumpfile);
+			exit(1);
+		}
+	}
 
-	for (; argv[1]; argv++) {
-		read_symbols(argv[1]);
+	while (optind < argc) {
+		read_symbols(argv[optind++]);
 	}
 
 	for (mod = modules; mod; mod = mod->next) {
-		if (is_vmlinux(mod->name))
+		if (mod->skip)
 			continue;
 
 		buf.pos = 0;
@@ -566,6 +652,20 @@ main(int argc, char **argv)
 		sprintf(fname, "%s.mod.c", mod->name);
 		write_if_changed(&buf, fname);
 	}
+
+	if (write_dumpfile) {
+		FILE *file = fopen(write_dumpfile, "w");
+		if (!file) {
+			perror(write_dumpfile);
+			exit(1);
+		}
+		write_dump(file);
+		if (fclose(file) != 0) {
+			perror(write_dumpfile);
+			exit(1);
+		}
+	}
+
 	return 0;
 }
 
Index: linux-2.6.1/scripts/modpost.h
===================================================================
--- linux-2.6.1.orig/scripts/modpost.h
+++ linux-2.6.1/scripts/modpost.h
@@ -70,6 +70,7 @@ struct module {
 	const char *name;
 	struct symbol *unres;
 	int seen;
+	int skip;
 	struct buffer dev_table_buf;
 };
 
Index: linux-2.6.1/scripts/Makefile.modinst
===================================================================
--- linux-2.6.1.orig/scripts/Makefile.modinst
+++ linux-2.6.1/scripts/Makefile.modinst
@@ -29,11 +29,13 @@ quiet_cmd_modules_install = INSTALL $@
 $(filter-out ../% /%,$(modules)):
 	$(call cmd,modules_install)
 
-# Modules built outside just go into extra
+# Modules built outside go into extra by default
 
-quiet_cmd_modules_install_extra = INSTALL $(obj-m:.o=.ko)
-      cmd_modules_install_extra = mkdir -p $(MODLIB)/extra; \
-			    	  cp $@ $(MODLIB)/extra
+MOD_DIR ?= extra
+
+quiet_cmd_modules_install_extra = INSTALL $(@F)
+      cmd_modules_install_extra = mkdir -p $(MODLIB)/$(MOD_DIR); \
+			    	  cp $@ $(MODLIB)/$(MOD_DIR)
 
 $(filter     ../% /%,$(modules)):
 	$(call cmd,modules_install_extra)
Index: linux-2.6.1/scripts/Makefile.modpost
===================================================================
--- linux-2.6.1.orig/scripts/Makefile.modpost
+++ linux-2.6.1/scripts/Makefile.modpost
@@ -51,11 +51,21 @@ $(modules:.ko=.mod.c): __modpost ;
 
 # Extract all checksums for all exported symbols
 
-quiet_cmd_modpost = MODPOST
-      cmd_modpost = scripts/modpost $(filter-out FORCE,$^)
+# Are we building out-of-tree modules?
 
+ifeq ($(filter ../% /%,$(SUBDIRS)),)
+modver_file := modversions
+quiet_cmd_modpost = MODPOST
+      cmd_modpost = scripts/modpost $(filter-out FORCE,$^) -o $(modver_file)
 __modpost: $(wildcard vmlinux) $(modules:.ko=.o) FORCE
 	$(call if_changed,modpost)
+else
+modver_file := $(wildcard $(srctree)/modversions)
+quiet_cmd_modpost = MODPOST
+      cmd_modpost = scripts/modpost $(if $(modver_file),-i $(modver_file)) $^
+__modpost: $(modules:.ko=.o)
+	$(call cmd,modpost)
+endif
 
 targets += __modpost
 

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2004-03-07 18:40 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-03-07  0:44 External kernel modules, second try Andreas Gruenbacher
2004-03-07 12:53 ` Sam Ravnborg
2004-03-07 13:03   ` Arjan van de Ven
2004-03-07 13:46     ` Andreas Gruenbacher
2004-03-07 14:01       ` Arjan van de Ven
2004-03-07 14:26         ` Andreas Gruenbacher
2004-03-07 15:09           ` GPL 3 mark kandianis
2004-03-07 15:14             ` Måns Rullgård
2004-03-07 16:43               ` John Bradford
2004-03-07 16:05         ` External kernel modules, second try Sam Ravnborg
2004-03-07 16:08           ` Arjan van de Ven
2004-03-07 16:45             ` Andreas Gruenbacher
2004-03-07 16:49               ` Arjan van de Ven
2004-03-07 18:33               ` Sam Ravnborg
2004-03-07 13:32   ` Andreas Gruenbacher
2004-03-07 15:09     ` Sergey Vlasov
2004-03-07 18:37       ` Sam Ravnborg
2004-03-07 16:18     ` Sam Ravnborg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox