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