c7074abb81385e1adc795ecc74f4c62eb47ffe55
[nativez] / java.make
1 #
2 # Copyright (C) 2019 Michael Zucchi
3 #
4 # This is the copyright for java.make
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 #
19
20 # General purpose modular java makefile that supports native library
21 # compilation directly.  Non-recrusve implementation.
22 #
23 # Uses metamake programming with some file conventions to implement
24 # auto-make-like features.
25
26 # Define modules
27 # --------------
28 # java_MODULES list of java modules to compile.  The sources must
29 #               exist in src/<module>/classes.  Resource files are
30 #               stored in src/<module>/classes.  Source-code
31 #               generators must exist in src/<module>/gen.  Native
32 #               libraries must exist in src/<module>/jni.
33
34 # Global variables
35
36 # JAVA_HOME             location of jdk.
37 # JAVAC                 java compiler to use.  Default is 'javac' on the path.
38 # JAVACFLAGS            javac flags applied to all invocations.
39 # JAR                   jar command.
40 # JARFLAGS              jar flags
41 # JMOD                  jmod command.
42 # JMODFLAGS             jmod flags.
43
44 # Module specific variables
45
46 # <module>_JDEPMOD      Lists modules which this one depends on.
47
48 # <module>_JAVACFLAGS   Extra module-specific flags for each command.
49 # <module>_JARFLAGS
50 # <module>_JMODFLAGS
51
52
53 # <module>_JAVA         Java sources.  This is set internally.
54 # <module>_RESOURCES    .jar resources.  This is set internally.
55
56 # Define libraries
57 # ----------------
58
59 # Each module can define one or more native libraries.
60
61 # These are compiled after the java sources have been compiled as that
62 # process also generates any native binding headers.
63
64 # <module>_JNI_LIBRARIES        list of libraries to build.
65 # library names match System.loadLibrary().
66
67 # Global variables
68
69 # <target>_LDFLAGS
70 # <target>_LDLIBS
71 # <target>_CPPFLAGS
72 # <target>_CFLAGS
73 # SO            shared library suffix
74 # LIB           shared library prefix
75
76 # Utility functions
77 #
78 # $(call library-path,<module>,<libname>) will resolve to the library file name.
79
80 # Per library variables.
81
82 # <library>_SOURCES     .c, .cc, .C - source files for library.  Paths are relative to src/<module>/jni.
83 # <library>_HEADERS     header files for jmod
84
85 # <library>_LDFLAGS     link flags
86 # <library>_LIBADD      extra objects to add to link line
87 # <library>_LDLIBS      link libraries
88 # <library>_CPPFLAGS    c pre-processor flags.  "-Isrc/<module>/jni -Ibin/include/<module>" is implicit.
89 # <library>_CCFLAGS     c compiler flags
90
91 # <library>_DEPENDENCIES        A list of other objects on which this library depends before linking.
92
93 # .c files have dependencies automatically generated
94
95
96 # Outputs
97 # -------
98
99 # All intermediate and output files are written to bin/
100
101 # This layout is enforced by javac
102 #  bin/include/<module>/        .h files from javac -h
103 #  bin/modules/<module>/        .class files from javac
104
105 # This layout is convenient for netbeans
106 #  bin/gen/<module>/gen/        .c, exe files for generator     free use
107 #  bin/gen/<module>/classes/    .java files from generator      <module>_JAVA_GENERATED
108
109 #  bin/status/                  marker files for makefile
110
111 #  bin/<module>/<module>.jar    .jar modular
112
113 # Native code
114
115 #  bin/<module>/<target>/lib    .so librareies for jmod         <module>_LIBRARIES = libname
116 #  bin/<module>/<target>/obj    .o, .d files for library        <libname>_SOURCES
117 #  bin/<module>/<target>/include .h files for jmod              <libname>_HEADERS
118 #  bin/<module>/<target>/<module>.jmod  .jmod module
119
120 # ######################################################################
121
122 E:=
123 S:=$(E) $(E)
124
125 # All modules with native code
126 java_JMODS=$(foreach module,$(java_MODULES),$(if $(wildcard src/$(module)/jni/jni.make),$(module)))
127 # Only modules with no native code
128 java_JARS=$(foreach module,$(java_MODULES),$(if $(wildcard src/$(module)/jni/jni.make),,$(module)))
129 # Modules with generated java source
130 java_JGEN=$(foreach module,$(java_MODULES),$(if $(wildcard src/$(module)/gen/gen.make),$(module)))
131
132 # Define per-module source and resource variables
133 $(foreach module,$(java_MODULES),$(eval $(module)_JAVA := $(shell find src/$(module)/classes -type f -name '*.java')))
134 $(foreach module,$(java_MODULES),$(eval $(module)_RESOURCES := $(shell find src/$(module)/classes -type f \! -name '*.java')))
135
136 # external jni deps
137 $(foreach mod,$(java_MODULES),$(eval $(mod)_JDEPMOD_JNI=$(foreach jdep,$($(mod)_JDEPMOD),$(if $(wildcard src/$(mod)/jni),$(jdep)))))
138
139 # Make some of the setup dirs (should it be a target?)
140 $(shell install -d bin/status bin/modules)
141
142 # ######################################################################
143
144 all: jar
145 bin:
146 jni:
147 sources:
148
149 .PHONY: all clean jar jni bin sources
150 clean:
151         rm -rf bin
152
153 include $(patsubst %,src/%/gen/gen.make,$(java_JGEN))
154 include $(patsubst %,src/%/jni/jni.make,$(java_JMODS))
155
156 # ######################################################################
157 # Java
158 # ######################################################################
159
160 define java_targets=
161 # Rules for module $(1)
162 bin/status/$(1).data: $$($(1)_RESOURCES)
163 bin/status/$(1).classes: $(patsubst %,bin/status/%.classes,$($(1)_JDEPMOD)) $$($(1)_JAVA)
164 jar $(1): bin/$(1)/$(1).jar $(if $(wildcard src/$(1)/jni/jni.make),bin/$(1)/$(TARGET)/$(1).jmod)
165 bin: bin/status/$(1).classes bin/status/$(1).data
166 sources: bin/$(1)/$(1)-sources.zip
167
168 # Create modular jar
169 bin/$(1)/$(1).jar: bin/status/$(1).classes bin/status/$(1).data
170         @install -d $$(@D)
171         $(JAR) cf $$@ \
172           $(JARFLAGS) $$($(1)_JARFLAGS) \
173           -C bin/modules/$(1) .
174
175 # Create a jmod
176 bin/$(1)/$(TARGET)/$(1).jmod: bin/status/$(1).classes bin/status/$(1).data
177         rm -f $$@
178         @install -d $$(@D)
179         $$(JMOD) create \
180           $$(JMODFLAGS) $$($(1)_JMODFLAGS) \
181           --target-platform $(TARGET) \
182           --class-path bin/modules/$(1) \
183           $$(if $$(wildcard bin/$(1)/$(TARGET)/include),--header-files bin/$(1)/$(TARGET)/include) \
184           $$(if $$(wildcard src/$(1)/legal),--legal-notices src/$(1)/legal) \
185           $$($(TARGET)_JMOD_LIBS) bin/$(1)/$(TARGET)/lib \
186           $$@
187
188 # Create an IDE source zip, paths have to match --module-source-path
189 bin/$(1)/$(1)-sources.zip: bin/status/$(1).classes
190         jar -c -f $$@ -M \
191                 $$(patsubst src/$(1)/classes/%,-C src/$(1)/classes %,$$(filter src/$(1)/classes/%,$$($(1)_JAVA))) \
192                 $$(patsubst bin/gen/$(1)/classes/%,-C bin/gen/$(1)/classes %,$$(filter bin/gen/$(1)/classes/%,$$($(1)_JAVA)))
193
194 endef
195
196 #$(foreach module,$(java_MODULES),$(info $(call java_targets,$(module))))
197 $(foreach module,$(java_MODULES),$(eval $(call java_targets,$(module))))
198
199 # ######################################################################
200 # Global pattern rules
201
202 # Stage resources
203 bin/status/%.data:
204         for data in $(patsubst src/$*/classes/%,"%",$($*_RESOURCES)) ; do \
205                 install -vDC "src/$*/classes/$$data" "bin/modules/$*/$$data" || exit 1 ; \
206         done
207         touch $@
208
209 # Compile one module.  This only updates (javac -h) headers if they changed.
210 bin/status/%.classes:
211         $(JAVAC) \
212                 --module-source-path "src/*/classes:bin/gen/*/classes" \
213                 $(JAVACFLAGS) $($*_JAVACFLAGS) \
214                 -h bin/inc \
215                 -d bin/modules \
216                 -m $* \
217                 $($*_JAVA)
218         if [ -d bin/inc/$* ] ; then \
219                 install -DC -t bin/include/$* bin/inc/$*/*.h ; \
220         fi
221         touch $@
222
223 # ######################################################################
224 # C stuff
225 # ######################################################################
226
227 SUFFIXES=.c .C .cc
228 SO=$($(TARGET)_SO)
229 LIB=$($(TARGET)_LIB)
230
231 library-path=bin/$(1)/$(TARGET)/lib/$(LIB)$(2)$(SO)
232 library-dir=bin/$(1)/$(TARGET)/lib/
233
234 define jni_library=
235 # Rule for library $(2) in module $(1)
236 $(2)_OBJS = $(foreach sx,$(SUFFIXES),$(patsubst %$(sx), bin/$(1)/$(TARGET)/obj/%.o, $(filter %$(sx),$($(2)_SOURCES))))
237 $(2)_SRCS = $(addprefix src/$(1)/jni/,$($(2)_SOURCES))
238
239 bin/$(1)/$(TARGET)/lib/$(LIB)$(2)$(SO): $$($(2)_OBJS) $($(2)_LIBADD) $($(2)_DEPENDENCIES)
240         @install -d $$(@D)
241         $($(TARGET)_CC) -o $$@ -shared \
242                 $($(TARGET)_LDFLAGS) $($(2)_LDFLAGS) $$($(2)_OBJS) $($(2)_LIBADD) $($(TARGET)_LDLIBS) $($(2)_LDLIBS)
243
244 bin/$(1)/$(TARGET)/obj/%.o: src/$(1)/jni/%.c bin/status/$(1).classes
245         @install -d $$(@D)
246         $($(TARGET)_CC) -Isrc/$(1)/jni -Ibin/include/$(1) $($(TARGET)_CPPFLAGS) $($(2)_CPPFLAGS) \
247                 $($(TARGET)_CFLAGS) $($(2)_CFLAGS) -c -o $$@ $$<
248
249 bin/$(1)/$(TARGET)/include/%.h: src/$(1)/jni/%.h
250         install -D $$< $$@
251
252 bin/$(1)/$(TARGET)/obj/%.d: src/$(1)/jni/%.c bin/status/$(1).classes
253         @install -d $$(@D)
254         @rm -f $$@
255         @$($(TARGET)_CC) -MM -MT "bin/$(1)/$(TARGET)/obj/$$*.o" -Isrc/$(1)/jni -Ibin/include/$(1) \
256                 $($(TARGET)_CPPFLAGS) $($(2)_CPPFLAGS) $$< -o $$@.d 2>/dev/null
257         @sed 's,\($$*\.o\) *:,\1 $$@ : ,g' $$@.d > $$@ ; rm $$@.d
258
259 bin jni $(1) bin/$(1)/$(TARGET)/$(1).jmod: bin/$(1)/$(TARGET)/lib/$(LIB)$(2)$(SO) $(addprefix bin/$(1)/$(TARGET)/include/,$($(2)_HEADERS))
260
261 $(if $(filter clean dist,$(MAKECMDGOALS)),,-include $$($(2)_OBJS:.o=.d))
262 endef
263
264 #$(foreach module,$(java_JMODS),$(foreach library,$($(module)_JNI_LIBRARIES),$(info $(call jni_library,$(module),$(library)))))
265 $(foreach module,$(java_JMODS),$(foreach library,$($(module)_JNI_LIBRARIES),$(eval $(call jni_library,$(module),$(library)))))
266
267 # ######################################################################
268
269 dist:
270         tar cfz bin/$(dist_NAME)-$(dist_VERSION).tar.gz \
271          --transform=s,^,$(dist_NAME)-$(dist_VERSION)/, \
272          config.make java.make Makefile src             \
273          $(dist_EXTRA)
274