Moved to modular java build system.
[panamaz] / java.make
1 #
2 # Copyright (C) 2019,2022 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 # native_MODULES list of native-only "modules".
35
36
37 # Global variables
38
39 # JAVA_HOME             location of jdk.
40 # JAVAC                 java compiler to use.  Default is 'javac' on the path.
41 # JAVACFLAGS            javac flags applied to all invocations.
42 # JAR                   jar command.
43 # JARFLAGS              jar flags
44 # JMOD                  jmod command.
45 # JMODFLAGS             jmod flags.
46 # JAVAFLAGS             java flags for run targets
47
48 # Module specific variables
49
50 # <module>_JDEPMOD      Lists modules which this one depends on.
51
52 # <module>_JAVACFLAGS   Extra module-specific flags for each command.
53 # <module>_JARFLAGS
54 # <module>_JMODFLAGS
55
56 # <module>_JAVA                 Java sources.  If not set it is found from src/<module>/classes/(*.java)
57 # <module>_RESOURCES            .jar resources.  If not set it is found from src/<module>/classes/(not *.java)
58 # <module>_JAVA_GENERATED       Java generated sources.  These must be relative to the package name.
59
60 # Variables for use in fragments
61
62 # gen.make and jni.make can additionally make use of these variables
63
64 # <module>_gendir       Location for files used in Java generation process (per project).
65 # <module>_genjavadir   Location where _JAVA_GENERATED .java files will be created (per project).
66 # <module>_objdir       Location for c objects (per target).
67 # <module>_incdir       Location for output includes, .jmod staging.
68 # <module>_libdir       Location for output libraries, .jmod staging.  May point to _bindir.
69 # <module>_bindir       Location for output commands, .jmod staging.
70
71 # Define libraries
72 # ----------------
73
74 # Each module can define one or more native libraries.
75
76 # These are compiled after the java sources have been compiled as that
77 # process also generates any native binding headers.
78
79 # <module>_NATIVE_LIBRARIES     list of libraries to build.
80 # library names match System.loadLibrary().
81
82 # Global variables
83
84 # <target>_LDFLAGS
85 # <target>_LDLIBS
86 # <target>_CPPFLAGS
87 # <target>_CFLAGS
88 # <target>_CC
89 # <target>_CXXFLAGS
90 # <target>_CXX
91 # SO            shared library suffix
92 # LIB           shared library prefix
93
94 # Utility functions
95 #
96 # $(call library-path,<module>,<libname>) will resolve to the library file name.
97
98 # Per library variables.
99
100 # <library>_SOURCES     .c source files for library.  Paths are relative to src/<module>/native.
101 # <library>_CXXSOURCES  .c source files for library.  Paths are relative to src/<module>/native.
102 # <library>_HEADERS     header files for install/jmod
103 # <library>_COMMANDS    commands/bin/scripts for install/jmod
104
105 # <library>_LDFLAGS     link flags
106 # <library>_LIBADD      extra objects to add to link line
107 # <library>_LDLIBS      link libraries
108 # <library>_CPPFLAGS    c and c++ pre-processor flags.  "-Isrc/<module>/jni -Ibin/include/<module>" is implicit.
109 # <library>_CCFLAGS     c compiler flags
110 # <library>_CXXFLAGS    c++ compiler flags
111
112 # <library>_DEPENDENCIES        A list of other objects on which this library depends before linking.
113
114 # .c and .cc files have dependencies automatically generated
115
116 # Targets
117 # -------
118
119 # make gen              only generate java sources
120 # make clean            rm -rf bin
121 # make dist             create dist tar in bin/
122 # make | make jar       make all jars and jmods
123 # make bin              make everything but jars and mods
124
125 # Outputs
126 # -------
127
128 # All intermediate and output files are written to bin/
129
130 # This layout is enforced by javac
131 #  bin/include/<module>/        .h files from javac -h
132 #  bin/modules/<module>/        .class files from javac
133
134 # This layout is convenient for netbeans
135 #  bin/gen/<module>/gen/        .c, exe files for generator     free use
136 #  bin/gen/<module>/classes/    .java files from generator      <module>_JAVA_GENERATED
137
138 # Working files
139 #  bin/status/                  marker files for makefile
140
141 #  bin/<module>/<target>/lib    .so librareies for jmod         <module>_LIBRARIES = libname
142 #  bin/<module>/<target>/obj    .o, .d files for library        <libname>_SOURCES
143 #  bin/<module>/<target>/include .h files for jmod              <libname>_HEADERS
144 #  bin/<module>/<target>/<module>.jmod  .jmod module
145
146 # Output files
147 #  bin/<target>/lib/            modular jar files and shared libraries for GNU/linux dev
148 #  bin/<target>/include/        header files for exported shared libraries
149 #  bin/<target>/bin/            shared libraries for microsoft dev
150 #  bin/<target>/jmods/          jmod files for 'jlink' use.
151
152 # ######################################################################
153
154 E:=
155 S:=$(E) $(E)
156
157 # All modules with native code
158 java_JMODS=$(foreach module,$(java_MODULES),$(if $(wildcard src/$(module)/jni/jni.make),$(module)))
159 # Only modules with no native code
160 java_JARS=$(foreach module,$(java_MODULES),$(if $(wildcard src/$(module)/jni/jni.make),,$(module)))
161 # Modules with generated java source
162 java_JGEN=$(foreach module,$(java_MODULES),$(if $(wildcard src/$(module)/gen/gen.make),$(module)))
163
164 # Define some useful variables before including fragments
165 define common_variables=
166 $(1)_gendir:=bin/gen/$(1)/gen
167 $(1)_genjavadir:=bin/gen/$(1)/classes
168 $(1)_objdir:=bin/$(1)/$(TARGET)/obj
169 $(1)_incdir:=bin/$(1)/$(TARGET)/include
170 $(1)_libdir:=$$(if $$(filter windows-%,$(TARGET)),bin/$(1)/$(TARGET)/bin,bin/$(1)/$(TARGET)/lib)
171 $(1)_bindir:=bin/$(1)/$(TARGET)/bin
172 ifndef $(1)_SCRIPTS
173 $(1)_SCRIPTS := $$(shell find src/$(1)/bin src/$(1)/$(TARGET)/bin -type f 2>/dev/null)
174 endif
175 ifndef $(1)_DATA
176 $(1)_DATA := $$(shell find src/$(1)/lib src/$(1)/$(TARGET)/lib -type f 2>/dev/null)
177 endif
178 endef
179
180 define java_variables=
181 ifndef $(1)_JAVA
182 $(1)_JAVA := $$(shell find src/$(1)/classes -type f -name '*.java')
183 endif
184 ifndef $(1)_RESOURCES
185 $(1)_RESOURCES := $$(shell find src/$(1)/classes -type f \! -name '*.java')
186 endif
187 endef
188
189 java_libdir:=$(if $(filter windows-%,$(TARGET)),bin/$(TARGET)/bin,bin/$(TARGET)/lib)
190 java_bindir:=bin/$(TARGET)/bin
191 java_jardir:=bin/$(TARGET)/lib
192 java_incdir:=bin/$(TARGET)/include
193 java_jmoddir:=bin/$(TARGET)/jmods
194
195 $(foreach module,$(java_MODULES),$(eval $(call java_variables,$(module))))
196 $(foreach module,$(java_MODULES) $(native_MODULES),$(eval $(call common_variables,$(module))))
197
198 # ######################################################################
199
200 all: jar
201 bin:
202 gen:
203 native:
204
205 .PHONY: all clean jar bin gen $(java_MODULES)
206 clean:
207         rm -rf bin
208
209 include $(foreach module,$(java_MODULES),$(wildcard src/$(module)/gen/gen.make))
210 include $(foreach module,$(java_MODULES) $(native_MODULES),$(wildcard src/$(module)/native/native.make))
211
212 # ######################################################################
213 # Java
214 # ######################################################################
215
216 define java_targets=
217 # Rules for module $(1)
218 $(1)_JAVA_generated = $$(addprefix $$($(1)_genjavadir)/,$$($(1)_JAVA_GENERATED))
219
220 bin/status/$(1).data: $$($(1)_RESOURCES)
221 bin/status/$(1).classes: $(patsubst %,bin/status/%.classes,$(filter $($(1)_JDEPMOD), $(java_MODULES))) $$($(1)_JAVA) $$($(1)_JAVA_generated)
222 bin/status/$(1).scripts: $$($(1)_DATA) $$($(1)_SCRIPTS)
223 jar $(1): $(java_jardir)/$(1).jar $(java_jmoddir)/$(1).jmod bin/status/$(1).scripts $($(1)_JDEPMOD)
224 bin: bin/status/$(1).classes bin/status/$(1).data bin/status/$(1).scripts
225 sources: $(java_jardir)/$(1)-sources.zip
226 gen: $$($(1)_JAVA_generated)
227
228 # Create modular jar
229 $(java_jardir)/$(1).jar: bin/status/$(1).classes bin/status/$(1).data
230         @install -d $$(@D)
231         $(JAR) cf $$@ \
232           $(JARFLAGS) $$($(1)_JARFLAGS) \
233           -C bin/modules/$(1) .
234
235 # Create a jmod
236 $(java_jmoddir)/$(1).jmod: bin/status/$(1).classes bin/status/$(1).data
237         rm -f $$@
238         @install -d $$(@D)
239         $$(JMOD) create \
240           $$(JMODFLAGS) $$($(1)_JMODFLAGS) \
241           --target-platform $(TARGET) \
242           --class-path bin/modules/$(1) \
243           $$(if $$(wildcard bin/$(1)/$(TARGET)/include),--header-files bin/$(1)/$(TARGET)/include) \
244           $$(if $$(wildcard src/$(1)/legal),--legal-notices src/$(1)/legal) \
245           $$(if $$(wildcard bin/$(1)/$(TARGET)/bin),--cmds bin/$(1)/$(TARGET)/bin) \
246           $$(if $$(wildcard bin/$(1)/$(TARGET)/lib),--libs bin/$(1)/$(TARGET)/lib) \
247           $$@
248
249 # Create an IDE source zip, paths have to match --module-source-path
250 $(java_jardir)/$(1)-sources.zip: bin/status/$(1).classes
251         @install -d $$(@D)
252         jar -c -f $$@ -M \
253                 $$(patsubst src/$(1)/classes/%,-C src/$(1)/classes %,$$(filter src/$(1)/classes/%,$$($(1)_JAVA))) \
254                 $$(patsubst bin/gen/$(1)/classes/%,-C bin/gen/$(1)/classes %,$$(filter bin/gen/$(1)/classes/%,$$($(1)_JAVA)))
255
256 endef
257
258 #$(foreach module,$(java_MODULES),$(info $(call java_targets,$(module))))
259 $(foreach module,$(java_MODULES),$(eval $(call java_targets,$(module))))
260
261 # ######################################################################
262 # Global pattern rules
263
264 # Stage resources
265 bin/status/%.data:
266         @install -d $(@D)
267         for data in $(patsubst src/$*/classes/%,"%",$($*_RESOURCES)) ; do \
268                 install -vDC "src/$*/classes/$$data" "bin/modules/$*/$$data" || exit 1 ; \
269         done
270         touch $@
271
272 # Stage scripts and data
273 bin/status/%.scripts:
274         @install -d $(@D)
275         for data in $(patsubst src/$*/lib/%,"%",$($*_DATA)) ; do \
276                 install -vDC -m 0644 "src/$*/lib/$$data" "bin/$(TARGET)/lib/$$data" || exit 1 ; \
277         done
278         for data in $(patsubst src/$*/bin/%,"%",$($*_SCRIPTS)) ; do \
279                 install -vDC -m 0755 "src/$*/bin/$$data" "bin/$(TARGET)/bin/$$data" || exit 1 ; \
280         done
281         touch $@
282
283 # Compile one module.
284 bin/status/%.classes:
285         @install -d $(@D)
286         $(JAVAC) \
287                 --module-source-path "src/*/classes:bin/gen/*/classes" \
288                 $(if $(JAVAMODPATH),--module-path $(subst $(S),:,$(JAVAMODPATH))) \
289                 $(JAVACFLAGS) $($*_JAVACFLAGS) \
290                 -d bin/modules \
291                 -m $* \
292                 $($*_JAVA) $($*_JAVA_generated)
293         touch $@
294
295 # setup run-* targets
296 define run_targets=
297 run-$1/$2: $1
298         LD_LIBRARY_PATH=$(FFMPEG_HOME)/lib \
299         $(JAVA) \
300                 $(if $(JAVAMODPATH) $($1_JAVAMODPATH),--module-path $(subst $(S),:,$(JAVAMODPATH) $($1_JAVAMODPATH))) \
301                 $(JMAINFLAGS) $($1_JMAINFLAGS) \
302                 -m $1/$2 \
303                 $(ARGV)
304 .PHONY: run-$1/$2
305 endef
306
307 #$(foreach module,$(java_MODULES),$(foreach main,$($(module)_JMAIN),$(info $(call run_targets,$(module),$(main)))))
308 $(foreach module,$(java_MODULES),$(foreach main,$($(module)_JMAIN),$(eval $(call run_targets,$(module),$(main)))))
309
310 # ######################################################################
311 # nativez jdk.foreign export tool via _API variables
312 # ######################################################################
313
314 # <module>_API                  List of api's to include
315 # <module>_APIFLAGS             Extra flags to pass to export-api for every api in module
316 # <module>_<api>_APIFLAGS       Extra flags to pass to export-api for each api
317
318 define export_targets=
319 gen: bin/status/$2.export
320 bin/status/$1.classes: bin/status/$2.export
321 bin/status/$2.export: src/$1/gen/$2.api src/$1/gen/$2.h $(NATIVEZ_HOME)/bin/export-api
322         mkdir -p bin/gen/$1/gen bin/status
323         $(NATIVEZ_HOME)/bin/export-api -w bin/gen/$1/gen -d bin/gen/$1/classes $($1_APIFLAGS) $($1_$2_APIFLAGS) $$<
324         touch $$@
325 endef
326
327 #$(foreach module,$(java_MODULES),$(if $($(module)_API),$(foreach api,$($(module)_API),$(info $(call export_targets,$(module),$(api))))))
328 $(foreach module,$(java_MODULES),$(foreach api,$($(module)_API),$(eval $(call export_targets,$(module),$(api)))))
329
330 # ######################################################################
331 # C and c++ native library support
332 # ######################################################################
333
334 SUFFIXES=.c .C .cc
335 SO=$($(TARGET)_SO)
336 LIB=$($(TARGET)_LIB)
337
338 # functions to find cross-module stuff $(call library-path,modname,libname)
339 library-path=$($(1)_libdir)/$(LIB)$(2)$(SO)
340 library-dir=$($(1)_libdir)/
341
342 define native_library=
343 # Rule for library $(2) in module $(1)
344 $(2)_OBJS = $(patsubst %.c, $($(1)_objdir)/%.o, $($(2)_SOURCES)) \
345         $(patsubst %.cc, $($(1)_objdir)/%.o, $($(2)_CXXSOURCES))
346 $(2)_SRCS = $(addprefix src/$(1)/native/,$($(2)_SOURCES))
347 $(2)_SO = $($(1)_libdir)/$(LIB)$(2)$(SO)
348
349 $($(1)_libdir)/$(LIB)$(2)$(SO): $$($(2)_OBJS) $($(2)_LIBADD) $($(2)_DEPENDENCIES)
350         @install -d $$(@D)
351         $($(TARGET)_CC) -o $$@ -shared \
352                 $($(TARGET)_LDFLAGS) $($(2)_LDFLAGS) $$($(2)_OBJS) $($(2)_LIBADD) $($(TARGET)_LDLIBS) $($(2)_LDLIBS)
353
354 $(java_libdir)/%: $($(1)_libdir)/%
355         install -DC $$< $$@
356 $(java_bindir)/%: $($(1)_bindir)/%
357         install -DC $$< $$@
358 $(java_incdir)/%: $($(1)_incdir)/%
359         install -DC $$< $$@
360
361 $($(1)_objdir)/%.o: src/$(1)/native/%.c
362         @install -d $$(@D)
363         $($(TARGET)_CC) -Isrc/$(1)/native -Ibin/include/$(1) \
364                 $($(TARGET)_CPPFLAGS) $($(2)_CPPFLAGS) \
365                 $($(TARGET)_CFLAGS) $($(2)_CFLAGS) -c -o $$@ $$<
366
367 $($(1)_objdir)/%.o: src/$(1)/native/%.cc
368         @install -d $$(@D)
369         $($(TARGET)_CXX) -Isrc/$(1)/native -Ibin/include/$(1) \
370                 $($(TARGET)_CPPFLAGS) $($(2)_CPPFLAGS) \
371                 $($(TARGET)_CXXFLAGS) $($(2)_CXXFLAGS) -c -o $$@ $$<
372
373 $($(1)_incdir)/%: src/$(1)/native/%
374         install -DC $$< $$@
375 $($(1)_libdir)/%: src/$(1)/native/%
376         install -DC $$< $$@
377
378 # auto-dependencies for c files
379 $($(1)_objdir)/%.d: src/$(1)/native/%.c
380         @install -d $$(@D)
381         @rm -f $$@
382         @$($(TARGET)_CC) -MM -MT "bin/$(1)/$(TARGET)/obj/$$*.o" -Isrc/$(1)/jni -Ibin/include/$(1) \
383                 $($(TARGET)_CPPFLAGS) $($(2)_CPPFLAGS) $$< -o $$@.d 2>/dev/null
384         @sed 's,\($$*\.o\) *:,\1 $$@ : ,g' $$@.d > $$@ ; rm $$@.d
385
386 # auto-dependencies for c++ files
387 $($(1)_objdir)/%.d: src/$(1)/native/%.cc
388         @install -d $$(@D)
389         @rm -f $$@
390         @$($(TARGET)_CXX) -MM -MT "bin/$(1)/$(TARGET)/obj/$$*.o" -Isrc/$(1)/jni -Ibin/include/$(1) \
391                 $($(TARGET)_CPPFLAGS) $($(2)_CPPFLAGS) $$< -o $$@.d
392         @sed 's,\($$*\.o\) *:,\1 $$@ : ,g' $$@.d > $$@ ; rm $$@.d
393
394 bin native $(1) $(java_jmoddir)/$(1).jmod: \
395         $($(1)_libdir)/$(LIB)$(2)$(SO) \
396         $(java_libdir)/$(LIB)$(2)$(SO) \
397         $(addprefix $($(1)_incdir)/,$($(2)_HEADERS)) \
398         $(addprefix $(java_incdir)/,$($(2)_HEADERS)) \
399         $(addprefix $($(1)_bindir)/,$($(2)_COMMANDS)) \
400         $(addprefix $(java_bindir)/,$($(2)_COMMANDS)) \
401         $(addprefix $($(1)_libdir)/,$($(2)_LIBRARIES))
402
403 $(if $(filter clean dist gen,$(MAKECMDGOALS)),,-include $$($(2)_OBJS:.o=.d))
404 endef
405
406 #$(foreach module,$(java_MODULES) $(native_MODULES),$(foreach library,$($(module)_NATIVE_LIBRARIES),$(info $(call native_library,$(module),$(library)))))
407 $(foreach module,$(java_MODULES) $(native_MODULES),$(foreach library,$($(module)_NATIVE_LIBRARIES),$(eval $(call native_library,$(module),$(library)))))
408
409 # ######################################################################
410
411 dist:
412         @install -d bin
413         tar cfz bin/$(dist_NAME)-$(dist_VERSION).tar.gz \
414          --transform=s,^,$(dist_NAME)-$(dist_VERSION)/, \
415          config.make.in java.make Makefile src          \
416          $(dist_EXTRA)