| 1 |
# Makefile rules for modules. |
| 2 |
# |
| 3 |
# IRC Services is copyright (c) 1996-2009 Andrew Church. |
| 4 |
# E-mail: <achurch@achurch.org> |
| 5 |
# Parts written by Andrew Kempe and others. |
| 6 |
# This program is free but copyrighted software; see the file GPL.txt for |
| 7 |
# details. |
| 8 |
|
| 9 |
########################################################################### |
| 10 |
|
| 11 |
# The following variables must be set by the caller (the Makefile which |
| 12 |
# includes this file). See operserv/Makefile for examples of using all the |
| 13 |
# variables listed below. |
| 14 |
# |
| 15 |
# MODULES List of modules, each with the extension ".so". Each |
| 16 |
# module is compiled from a source file of the same name |
| 17 |
# name ending in ".c" which must contain the required |
| 18 |
# module symbol definitions (init_module, etc.), and |
| 19 |
# possibly other files as defined by the appropriate |
| 20 |
# OBJECTS variable. |
| 21 |
# OBJECTS-... List of additional objects for a particular module. The |
| 22 |
# "..." is replaced by the name of the module; for |
| 23 |
# example, if the module name is "main.so", the OBJECTS |
| 24 |
# variable name is "OBJECTS-main.so". |
| 25 |
# INCLUDES List of include files every source file in the directory |
| 26 |
# depends on. |
| 27 |
# INCLUDES-... List of include files a particular source file depends on. |
| 28 |
# The "..." is replaced by the _object_ file name of the |
| 29 |
# source file; for example, if the filename is "main.c", |
| 30 |
# then the INCLUDES variable name is "INCLUDES-main.o". |
| 31 |
# |
| 32 |
# The following variables are set by this file: |
| 33 |
# |
| 34 |
# DIRNAME Name of this directory (set by modules/Makefile). |
| 35 |
# TOPDIR Top Services directory. |
| 36 |
# DEPS Files which every source file should depend on. |
| 37 |
|
| 38 |
# This makefile is complex because there's no way to say something like |
| 39 |
# "%.so: %.o $(OBJECTS-%)". Instead, we recursively call ourselves for |
| 40 |
# each module, settings OBJECTS to the appropriate target-dependent value. |
| 41 |
# We then recursively call ourselves _again_ for each source file, defining |
| 42 |
# INCLUDES to the appropriate value. |
| 43 |
|
| 44 |
########################################################################### |
| 45 |
|
| 46 |
TOPDIR=../.. |
| 47 |
DEPS = Makefile ../Makerules $(TOPDIR)/Makefile.inc $(TOPDIR)/Makefile \ |
| 48 |
$(TOPDIR)/services.h $(TOPDIR)/modules.h $(TOPDIR)/conffile.h \ |
| 49 |
$(INCLUDES) |
| 50 |
.PHONY: all-dynamic all-static install clean spotless |
| 51 |
|
| 52 |
all-dynamic: $(MODULES) |
| 53 |
all-static: $(MODULES:.so=.a) |
| 54 |
@set -e ; \ |
| 55 |
if $(TEST_NT) ! -f $(DIRNAME).o -o .stamp -nt $(DIRNAME).o ; then \ |
| 56 |
rm -f .$(DIRNAME).lst2 ; \ |
| 57 |
sort -u .$(DIRNAME).lst >.$(DIRNAME).lst2 ; \ |
| 58 |
mv -f .$(DIRNAME).lst2 .$(DIRNAME).lst ; \ |
| 59 |
echo 'ld -r -o $(DIRNAME).o' `cat .$(DIRNAME).lst` ; \ |
| 60 |
ld -r -o $(DIRNAME).o `cat .$(DIRNAME).lst` ; \ |
| 61 |
echo 'ar -cr ../modules.a $(DIRNAME).o' ; \ |
| 62 |
ar -cr ../modules.a $(DIRNAME).o ; \ |
| 63 |
echo 'touch .stamp' ; \ |
| 64 |
touch .stamp ; \ |
| 65 |
fi |
| 66 |
|
| 67 |
ifeq ($(MODULES),) |
| 68 |
install: |
| 69 |
$(MKDIR) "$(INSTALL_PREFIX)$(DATDEST)/modules/$(DIRNAME)" |
| 70 |
clean: |
| 71 |
else |
| 72 |
install: |
| 73 |
$(MKDIR) "$(INSTALL_PREFIX)$(DATDEST)/modules/$(DIRNAME)" |
| 74 |
$(INSTALL_DAT) $(MODULES) "$(INSTALL_PREFIX)$(DATDEST)/modules/$(DIRNAME)" |
| 75 |
clean: |
| 76 |
rm -f $(MODULES) $(MODULES:.so=.a) .$(DIRNAME).lst* *.o .mod* .compiled* |
| 77 |
endif |
| 78 |
|
| 79 |
spotless: clean |
| 80 |
|
| 81 |
########################################################################### |
| 82 |
|
| 83 |
.PHONY: FRC |
| 84 |
FRC: |
| 85 |
|
| 86 |
ifeq ($(REALLY_COMPILE),) |
| 87 |
|
| 88 |
%_static.so %_static.a: |
| 89 |
@echo >&2 '*** Module names must not end in "_static". Compile aborted.' |
| 90 |
@false |
| 91 |
.%.so .%.a: |
| 92 |
@echo >&2 '*** Module names must not begin with ".". Compile aborted.' |
| 93 |
@false |
| 94 |
|
| 95 |
# We include FRC as a prerequisite here since we can't check the real |
| 96 |
# prerequisites until the sub-make, which won't get executed if the target |
| 97 |
# exists and there are no prerequisites listed. |
| 98 |
%.so: FRC |
| 99 |
@$(MAKE) --no-print-directory $@ TARGET=$(@:.so=) OBJECTS="$(OBJECTS-$@)" REALLY_COMPILE=1 |
| 100 |
%.a: FRC |
| 101 |
@$(MAKE) --no-print-directory $@ TARGET=$(@:.a=) OBJECTS="$(OBJECTS-$(@:.a=.so))" REALLY_COMPILE=1 |
| 102 |
|
| 103 |
else |
| 104 |
|
| 105 |
# Compile one or more objects into a dynamic module. |
| 106 |
$(TARGET).so: $(TARGET).o $(OBJECTS) |
| 107 |
$(CC_SHARED) $^ -o $@ |
| 108 |
|
| 109 |
# Compile one or more objects into a static module and generate a symbol |
| 110 |
# list. The .a file we create here is just a placeholder to show that |
| 111 |
# we've compiled the module; the objects themselves go into ../modules.a |
| 112 |
# (via $(DIRNAME).o). |
| 113 |
$(TARGET).a: $(TARGET)_static.o $(OBJECTS) |
| 114 |
@for i in $^ ; do echo $$i >>.$(DIRNAME).lst ; done |
| 115 |
@set -e ; \ |
| 116 |
FILENAME=$(@:.a=) ; \ |
| 117 |
MODNAME=`echo $(DIRNAME)_$$FILENAME | sed -e 'y/-/_/' -e 's/_$$//'` ; \ |
| 118 |
rm -f .modext-$$FILENAME.h .modlist-$$FILENAME.c .modsyms-$$FILENAME.c ; \ |
| 119 |
echo >>.modext-$$FILENAME.h 'extern void *_this_module_ptr_'$$MODNAME';' ; \ |
| 120 |
echo >>.modext-$$FILENAME.h 'extern uint32 module_version_'$$MODNAME';' ; \ |
| 121 |
echo >>.modext-$$FILENAME.h 'extern char module_config_'$$MODNAME'[];' ; \ |
| 122 |
echo >>.modext-$$FILENAME.h 'extern int init_module_'$$MODNAME'();' ; \ |
| 123 |
echo >>.modext-$$FILENAME.h 'extern int exit_module_'$$MODNAME'();' ; \ |
| 124 |
echo >>.modlist-$$FILENAME.c '{ "$(DIRNAME)/'$$FILENAME'", modsyms_'$$MODNAME' },' ; \ |
| 125 |
echo >>.modsyms-$$FILENAME.c 'struct {const char *name; void *value; } modsyms_'$$MODNAME'[] = {' ; \ |
| 126 |
echo >>.modsyms-$$FILENAME.c '{"_this_module_ptr",&_this_module_ptr_'$$MODNAME'},' ; \ |
| 127 |
echo >>.modsyms-$$FILENAME.c '{"module_version",&module_version_'$$MODNAME'},' ; \ |
| 128 |
echo >>.modsyms-$$FILENAME.c '{"module_config",module_config_'$$MODNAME'},' ; \ |
| 129 |
echo >>.modsyms-$$FILENAME.c '{"init_module",init_module_'$$MODNAME'},' ; \ |
| 130 |
echo >>.modsyms-$$FILENAME.c '{"exit_module",exit_module_'$$MODNAME'},' ; \ |
| 131 |
rm -f .modsyms-$$FILENAME.tmp ; \ |
| 132 |
for file in $(@:.a=.c) $(OBJECTS-$(@:.a=.so):.o=.c) ; do \ |
| 133 |
grep '^EXPORT_' $$file \ |
| 134 |
| sed -e 's/^EXPORT_VAR[ ]*([ ]*\([^,]*\),[ ]*\([A-Za-z0-9_]*\)[ ]*)[ ]*$$/\&\2:\1 \2/' \ |
| 135 |
-e 's/^EXPORT_ARRAY[ ]*([ ]*\([A-Za-z0-9_]*\)[ ]*)[ ]*$$/ \1:char \1[]/' \ |
| 136 |
-e 's/^EXPORT_FUNC[ ]*([ ]*\([A-Za-z0-9_]*\)[ ]*)[ ]*$$/ \1:void \1()/' ; \ |
| 137 |
done >.modsyms-$$FILENAME.tmp ; \ |
| 138 |
if grep >/dev/null 2>&1 '^EXPORT_' .modsyms-$$FILENAME.tmp ; then \ |
| 139 |
echo >&2 "$$file: invalid use of EXPORT_xxx" ; \ |
| 140 |
exit 1 ; \ |
| 141 |
fi ; \ |
| 142 |
sed 's/\(.\)\([^:]*\):.*/{"\2",\1\2},/' <.modsyms-$$FILENAME.tmp >>.modsyms-$$FILENAME.c ; \ |
| 143 |
sed 's/[^:]*:\(.*\)/extern \1;/' <.modsyms-$$FILENAME.tmp >>.modext-$$FILENAME.h;\ |
| 144 |
rm -f .modsyms-$$FILENAME.tmp ; \ |
| 145 |
echo '{0}};' >>.modsyms-$$FILENAME.c |
| 146 |
@touch $@ |
| 147 |
|
| 148 |
|
| 149 |
ifneq ($(REALLY_COMPILE),2) |
| 150 |
|
| 151 |
MODULE_ID = $(shell echo $(DIRNAME)_$(TARGET) | sed -e 'y/-/_/' -e 's/_$$//') |
| 152 |
MODULE_CFLAGS = -DMODULE -DMODULE_ID=$(MODULE_ID) |
| 153 |
$(TARGET).o $(TARGET)_static.o: MODULE_CFLAGS += -DMODULE_MAIN_FILE |
| 154 |
$(TARGET)_static.o: MODULE_CFLAGS += -D_this_module_ptr=_this_module_ptr_$(MODULE_ID) -Dmodule_version=module_version_$(MODULE_ID) -Dmodule_config=module_config_$(MODULE_ID) -Dinit_module=init_module_$(MODULE_ID) -Dexit_module=exit_module_$(MODULE_ID) |
| 155 |
$(TARGET)_static.o: FRC |
| 156 |
@$(MAKE) --no-print-directory $@ TARGET=$(@:_static.o=) INCLUDES2="$(INCLUDES-$(@:_static.o=.o))" CFLAGS="$(CFLAGS) $(MODULE_CFLAGS)" REALLY_COMPILE=2 |
| 157 |
@if $(TEST_NT) ! -f .stamp -o "$@" -nt .stamp ; then \ |
| 158 |
echo "touch .stamp" ; \ |
| 159 |
touch .stamp ; \ |
| 160 |
fi |
| 161 |
$(TARGET).o $(OBJECTS): FRC |
| 162 |
@$(MAKE) --no-print-directory $@ TARGET=$(@:.o=) INCLUDES2="$(INCLUDES-$@)" CFLAGS="$(CFLAGS) $(MODULE_CFLAGS)" REALLY_COMPILE=2 |
| 163 |
@if $(TEST_NT) ! -f .stamp -o "$@" -nt .stamp ; then \ |
| 164 |
echo "touch .stamp" ; \ |
| 165 |
touch .stamp ; \ |
| 166 |
fi |
| 167 |
|
| 168 |
else |
| 169 |
|
| 170 |
# Compile a source file into an object file. This construct is used to |
| 171 |
# suppress the "target is up to date" message that would otherwise appear. |
| 172 |
$(TARGET).o: .compiled-$(TARGET).o FRC |
| 173 |
@echo >/dev/null |
| 174 |
.compiled-$(TARGET).o: $(TARGET).c $(DEPS) $(INCLUDES2) |
| 175 |
cd $(TOPDIR) && $(CC) $(CFLAGS) -I. -c modules/$(DIRNAME)/$< -o modules/$(DIRNAME)/$(TARGET).o |
| 176 |
@rm -f $@ |
| 177 |
@ln -s $(TARGET).o $@ |
| 178 |
|
| 179 |
# Compile a source file into an object file suitable for use in a static |
| 180 |
# module. This is used with the main object file of a module to generate |
| 181 |
# unique names for exported module symbols (init_module and the like). |
| 182 |
$(TARGET)_static.o: .compiled-$(TARGET)_static.o FRC |
| 183 |
@echo >/dev/null |
| 184 |
.compiled-$(TARGET)_static.o: $(TARGET).c $(DEPS) $(INCLUDES2) |
| 185 |
cd $(TOPDIR) && $(CC) $(CFLAGS) -I. -c modules/$(DIRNAME)/$< -o modules/$(DIRNAME)/$(TARGET)_static.o |
| 186 |
@touch $@ |
| 187 |
|
| 188 |
endif # REALLY_COMPILE == 2 |
| 189 |
|
| 190 |
endif # REALLY_COMPILE != "" |