KBUILD_CHECKSRC = 0
endif
+# Use make M=dir to specify direcotry of external module to build
+# Old syntax make ... SUBDIRS=$PWD is still supported
+# Setting the environment variable KBUILD_EXTMOD take precedence
+ifdef SUBDIRS
+ KBUILD_EXTMOD ?= $(SUBDIRS)
+endif
+ifdef M
+ ifeq ("$(origin M)", "command line")
+ KBUILD_EXTMOD := $(M)
+ endif
+endif
+
+
# kbuild supports saving output files in a separate directory.
# To locate output files in a separate directory two syntax'es are supported.
# In both cases the working directory must be the root of the kernel src.
endif
# That's our default target when none is given on the command line
-.PHONY: all
-all:
-
+.PHONY: _all
+_all:
+
ifneq ($(KBUILD_OUTPUT),)
# Invoke a second make in the output directory, passing relevant variables
# check that the output directory actually exists
.PHONY: $(MAKECMDGOALS)
-$(filter-out all,$(MAKECMDGOALS)) all:
+$(filter-out _all,$(MAKECMDGOALS)) _all:
$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
- KBUILD_SRC=$(CURDIR) KBUILD_VERBOSE=$(KBUILD_VERBOSE) \
- KBUILD_CHECK=$(KBUILD_CHECK) -f $(CURDIR)/Makefile $@
+ KBUILD_SRC=$(CURDIR) KBUILD_VERBOSE=$(KBUILD_VERBOSE) \
+ KBUILD_CHECK=$(KBUILD_CHECK) KBUILD_EXTMOD=$(KBUILD_EXTMOD) \
+ -f $(CURDIR)/Makefile $@
# Leave processing to above invocation of make
skip-makefile := 1
# We process the rest of the Makefile if this is the final invocation of make
ifeq ($(skip-makefile),)
+# If building an external module we do not care about the all: rule
+# but instead _all depend on modules
+.PHONY: all
+ifeq ($(KBUILD_EXTMOD),)
+_all: all
+else
+_all: modules
+endif
+
# Make sure we're not wasting cpu-cycles doing locale handling, yet do make
# sure error messages appear in the user-desired language
ifdef LC_ALL
# in addition to whatever we do anyway.
# Just "make" or "make all" shall build modules as well
-ifneq ($(filter all modules,$(MAKECMDGOALS)),)
+ifneq ($(filter all _all modules,$(MAKECMDGOALS)),)
KBUILD_MODULES := 1
endif
endif
export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE
-export KBUILD_CHECKSRC KBUILD_SRC
+export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
# Beautify output
# ---------------------------------------------------------------------------
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
+# tree rather than in the kernel tree. The kernel tree might
+# even be read-only.
+export MODVERDIR := $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/).tmp_versions
# The temporary file to save gcc -MD generated dependencies must not
# contain a comma
endif
endif
-ifneq ($(filter config %config,$(MAKECMDGOALS)),)
- config-targets := 1
- ifneq ($(filter-out config %config,$(MAKECMDGOALS)),)
- mixed-targets := 1
- endif
+ifeq ($(KBUILD_EXTMOD),)
+ ifneq ($(filter config %config,$(MAKECMDGOALS)),)
+ config-targets := 1
+ ifneq ($(filter-out config %config,$(MAKECMDGOALS)),)
+ mixed-targets := 1
+ endif
+ endif
endif
ifeq ($(mixed-targets),1)
# Build targets only - this includes vmlinux, arch specific targets, clean
# targets and others. In general all targets except *config targets.
+ifeq ($(KBUILD_EXTMOD),)
# Additional helpers built in scripts/
# Carefully list dependencies so we do not try to build scripts twice
# in parrallel
net-y := net/
libs-y := lib/
core-y := usr/
-SUBDIRS :=
+endif # KBUILD_EXTMOD
ifeq ($(dot-config),1)
# In this section, we need .config
include $(srctree)/arch/$(ARCH)/Makefile
-# Let architecture Makefiles change CPPFLAGS if needed
-CFLAGS := $(CPPFLAGS) $(CFLAGS)
-AFLAGS := $(CPPFLAGS) $(AFLAGS)
-
-core-y += kernel/ mm/ fs/ ipc/ security/ crypto/
-
-SUBDIRS += $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
- $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
- $(net-y) $(net-m) $(libs-y) $(libs-m)))
-
-ALL_SUBDIRS := $(sort $(SUBDIRS) $(patsubst %/,%,$(filter %/, \
- $(init-n) $(init-) \
- $(core-n) $(core-) $(drivers-n) $(drivers-) \
- $(net-n) $(net-) $(libs-n) $(libs-))))
-
-init-y := $(patsubst %/, %/built-in.o, $(init-y))
-core-y := $(patsubst %/, %/built-in.o, $(core-y))
-drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
-net-y := $(patsubst %/, %/built-in.o, $(net-y))
-libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
-libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
-libs-y := $(libs-y1) $(libs-y2)
-
-# Here goes the main Makefile
-# ---------------------------------------------------------------------------
-
-
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
CFLAGS += -Os
else
MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
export MODLIB
+
+ifeq ($(KBUILD_EXTMOD),)
+core-y += kernel/ mm/ fs/ ipc/ security/ crypto/
+
+vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
+ $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
+ $(net-y) $(net-m) $(libs-y) $(libs-m)))
+
+vmlinux-alldirs := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \
+ $(init-n) $(init-) \
+ $(core-n) $(core-) $(drivers-n) $(drivers-) \
+ $(net-n) $(net-) $(libs-n) $(libs-))))
+
+init-y := $(patsubst %/, %/built-in.o, $(init-y))
+core-y := $(patsubst %/, %/built-in.o, $(core-y))
+drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
+net-y := $(patsubst %/, %/built-in.o, $(net-y))
+libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
+libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
+libs-y := $(libs-y1) $(libs-y2)
+
# Build vmlinux
# ---------------------------------------------------------------------------
# The actual objects are generated when descending,
# make sure no implicit rule kicks in
-$(sort $(vmlinux-objs)) arch/$(ARCH)/kernel/vmlinux.lds.s: $(SUBDIRS) ;
+$(sort $(vmlinux-objs)) arch/$(ARCH)/kernel/vmlinux.lds.s: $(vmlinux-dirs) ;
-# Handle descending into subdirectories listed in $(SUBDIRS)
+# Handle descending into subdirectories listed in $(vmlinux-dirs)
-.PHONY: $(SUBDIRS)
-$(SUBDIRS): prepare-all scripts
+.PHONY: $(vmlinux-dirs)
+$(vmlinux-dirs): prepare-all scripts
$(Q)$(MAKE) $(build)=$@
# Things we need to do before we recursively start building the kernel
endif
prepare0: prepare1 include/linux/version.h include/asm include/config/MARKER
-ifdef KBUILD_MODULES
-ifeq ($(origin SUBDIRS),file)
$(Q)rm -rf $(MODVERDIR)
-else
- @echo '*** Warning: Overriding SUBDIRS on the command line can cause'
- @echo '*** inconsistencies'
-endif
-endif
$(if $(CONFIG_MODULES),$(Q)mkdir -p $(MODVERDIR))
# All the preparing..
# Build modules
.PHONY: modules
-modules: $(SUBDIRS) $(if $(KBUILD_BUILTIN),vmlinux)
+modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
@echo ' Building modules, stage 2.';
$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
MRPROPER_DIRS += include/config include2
MRPROPER_FILES += .config .config.old include/asm .version \
include/linux/autoconf.h include/linux/version.h \
- include/linux/modversions.h \
- tags TAGS cscope*
+ Module.symvers tags TAGS cscope*
# clean - Delete most, but leave enough to build external modules
#
clean: rm-dirs := $(CLEAN_DIRS)
clean: rm-files := $(CLEAN_FILES)
-clean-dirs := $(addprefix _clean_,$(ALL_SUBDIRS))
+clean-dirs := $(addprefix _clean_,$(vmlinux-alldirs))
.PHONY: $(clean-dirs) clean archclean
$(clean-dirs):
-o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
-type f -print | xargs rm -f
-# Generate tags for editors
-# ---------------------------------------------------------------------------
-
-define all-sources
- ( find . $(RCS_FIND_IGNORE) \
- \( -name include -o -name arch \) -prune -o \
- -name '*.[chS]' -print; \
- find arch/$(ARCH) $(RCS_FIND_IGNORE) \
- -name '*.[chS]' -print; \
- find include $(RCS_FIND_IGNORE) \
- \( -name config -o -name 'asm-*' \) -prune \
- -o -name '*.[chS]' -print; \
- find include/asm-$(ARCH) $(RCS_FIND_IGNORE) \
- -name '*.[chS]' -print; \
- find include/asm-generic $(RCS_FIND_IGNORE) \
- -name '*.[chS]' -print )
-endef
-
-quiet_cmd_cscope-file = FILELST cscope.files
- cmd_cscope-file = $(all-sources) > cscope.files
-
-quiet_cmd_cscope = MAKE cscope.out
- cmd_cscope = cscope -k -b -q
-
-cscope: FORCE
- $(call cmd,cscope-file)
- $(call cmd,cscope)
-
-quiet_cmd_TAGS = MAKE $@
-cmd_TAGS = $(all-sources) | etags -
-
-# Exuberant ctags works better with -I
-
-quiet_cmd_tags = MAKE $@
-define cmd_tags
- rm -f $@; \
- CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_NOVERS"`; \
- $(all-sources) | xargs ctags $$CTAGSF -a
-endef
-
-TAGS: FORCE
- $(call cmd,TAGS)
-
-tags: FORCE
- $(call cmd,tags)
-
# RPM target
# ---------------------------------------------------------------------------
%docs: scripts_basic FORCE
$(Q)$(MAKE) $(build)=Documentation/DocBook $@
+else # KBUILD_EXTMOD
+
+###
+# External module support.
+# When building external modules the kernel used as basis is considered
+# read-only, and no consistency checks are made and the make
+# system is not used on the basis kernel. If updates are required
+# in the basis kernel ordinary make commands (without M=...) must
+# be used.
+#
+# The following are the only valid targets when building external
+# modules.
+# make M=dir clean Delete all automatically generated files
+# make M=dir modules Make all modules in specified dir
+# make M=dir Same as 'make M=dir modules'
+# make M=dir modules_install
+# Install the modules build in the module directory
+# Assumes install directory is already created
+
+# We are always building modules
+KBUILD_MODULES := 1
+
+.PHONY: $(KBUILD_EXTMOD)
+$(KBUILD_EXTMOD): FORCE
+ $(Q)$(MAKE) $(build)=$@
+
+.PHONY: modules
+modules: $(KBUILD_EXTMOD)
+ @echo ' Building modules, stage 2.';
+ $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
+
+.PHONY: modules_install
+modules_install:
+ $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modinst
+
+clean-dirs := _clean_$(KBUILD_EXTMOD)
+
+.PHONY: $(clean-dirs) clean
+$(clean-dirs):
+ $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
+
+clean: $(clean-dirs)
+ @find $(KBUILD_EXTMOD) $(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
+
+help:
+ @echo ' Building external modules.'
+ @echo ' Syntax: make -C path/to/kernel/src M=$$PWD target'
+ @echo ''
+ @echo ' modules - default target, build the module(s)'
+ @echo ' modules_install - install the module'
+ @echo ' clean - remove generated files in module directory only'
+ @echo ''
+endif # KBUILD_EXTMOD
+
+# Generate tags for editors
+# ---------------------------------------------------------------------------
+
+define all-sources
+ ( find . $(RCS_FIND_IGNORE) \
+ \( -name include -o -name arch \) -prune -o \
+ -name '*.[chS]' -print; \
+ find arch/$(ARCH) $(RCS_FIND_IGNORE) \
+ -name '*.[chS]' -print; \
+ find include $(RCS_FIND_IGNORE) \
+ \( -name config -o -name 'asm-*' \) -prune \
+ -o -name '*.[chS]' -print; \
+ find include/asm-$(ARCH) $(RCS_FIND_IGNORE) \
+ -name '*.[chS]' -print; \
+ find include/asm-generic $(RCS_FIND_IGNORE) \
+ -name '*.[chS]' -print )
+endef
+
+quiet_cmd_cscope-file = FILELST cscope.files
+ cmd_cscope-file = $(all-sources) > cscope.files
+
+quiet_cmd_cscope = MAKE cscope.out
+ cmd_cscope = cscope -k -b -q
+
+cscope: FORCE
+ $(call cmd,cscope-file)
+ $(call cmd,cscope)
+
+quiet_cmd_TAGS = MAKE $@
+cmd_TAGS = $(all-sources) | etags -
+
+# Exuberant ctags works better with -I
+
+quiet_cmd_tags = MAKE $@
+define cmd_tags
+ rm -f $@; \
+ CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_NOVERS"`; \
+ $(all-sources) | xargs ctags $$CTAGSF -a
+endef
+
+TAGS: FORCE
+ $(call cmd,TAGS)
+
+tags: FORCE
+ $(call cmd,tags)
+
+
# Scripts to check various things for consistency
# ---------------------------------------------------------------------------
/* 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
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)
{
int fd;
fd = open(filename, O_RDONLY);
- if (fstat(fd, &st) != 0)
+ if (fd < 0 || fstat(fd, &st) != 0)
return NULL;
*size = st.st_size;
/* May not have this if !CONFIG_MODULE_UNLOAD: fake it.
If it appears, we'll get the real CRC. */
add_exported_symbol("cleanup_module", mod, &fake_crc);
+ add_exported_symbol("struct_module", mod, &fake_crc);
+ mod->skip = 1;
}
for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
fclose(file);
}
+void
+read_dump(const char *fname)
+{
+ unsigned long size, pos = 0;
+ void *file = grab_file(fname, &size);
+ char *line;
+
+ if (!file) {
+ perror(fname);
+ abort();
+ }
+
+ while ((line = get_next_line(&pos, file, size))) {
+ char *symname, *modname, *d;
+ unsigned int crc;
+ struct module *mod;
+
+ if (!(symname = strchr(line, '\t')))
+ goto fail;
+ *symname++ = '\0';
+ if (!(modname = strchr(symname, '\t')))
+ goto fail;
+ *modname++ = '\0';
+ if (strchr(modname, '\t'))
+ goto fail;
+ crc = strtoul(line, &d, 16);
+ if (*symname == '\0' || *modname == '\0' || *d != '\0')
+ goto fail;
+
+ if (!(mod = find_module(modname))) {
+ if (is_vmlinux(modname)) {
+ modversions = 1;
+ have_vmlinux = 1;
+ }
+ mod = new_module(NOFAIL(strdup(modname)));
+ mod->skip = 1;
+ }
+ add_exported_symbol(symname, mod, &crc);
+ }
+ return;
+fail:
+ fatal("parse error in symbol dump file\n");
+}
+
+void
+write_dump(const char *fname)
+{
+ struct buffer buf = { };
+ 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) {
+ buf_printf(&buf, "0x%08x\t%s\t%s\n", symbol->crc,
+ symbol->name, symbol->module->name);
+ symbol = symbol->next;
+ }
+ }
+ write_if_changed(&buf, fname);
+}
+
int
main(int argc, char **argv)
{
struct module *mod;
struct buffer buf = { };
char fname[SZ];
+ char *dump_read = NULL, *dump_write = NULL;
+ int opt;
- for (; argv[1]; argv++) {
- read_symbols(argv[1]);
+ while ((opt = getopt(argc, argv, "i:o:")) != -1) {
+ switch(opt) {
+ case 'i':
+ dump_read = optarg;
+ break;
+ case 'o':
+ dump_write = optarg;
+ break;
+ default:
+ exit(1);
+ }
+ }
+
+ if (dump_read)
+ read_dump(dump_read);
+
+ 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;
sprintf(fname, "%s.mod.c", mod->name);
write_if_changed(&buf, fname);
}
+
+ if (dump_write)
+ write_dump(dump_write);
+
return 0;
}