# # Copyright (C) 2019,2022 Michael Zucchi # # This is the copyright for java.make # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # General purpose modular java makefile that supports native library # compilation directly. Non-recrusve implementation. # # Uses metamake programming with some file conventions to implement # auto-make-like features. # Define modules # -------------- # java_MODULES list of java modules to compile. The sources must # exist in src//classes. Resource files are # stored in src//classes. Source-code # generators must exist in src//gen. Native # libraries must exist in src//jni. # native_MODULES list of native-only "modules". # Global variables # JAVA_HOME location of jdk. # JAVAC java compiler to use. Default is 'javac' on the path. # JAVACFLAGS javac flags applied to all invocations. # JAR jar command. # JARFLAGS jar flags # JMOD jmod command. # JMODFLAGS jmod flags. # JAVAFLAGS java flags for run targets # Module specific variables # _JDEPMOD Lists modules which this one depends on. # _JAVACFLAGS Extra module-specific flags for each command. # _JARFLAGS # _JMODFLAGS # _JAVA Java sources. If not set it is found from src//classes/(*.java) # _RESOURCES .jar resources. If not set it is found from src//classes/(not *.java) # _JAVA_GENERATED Java generated sources. These must be relative to the package name. # Variables for use in fragments # gen.make and jni.make can additionally make use of these variables # _gendir Location for files used in Java generation process (per project). # _genjavadir Location where _JAVA_GENERATED .java files will be created (per project). # _objdir Location for c objects (per target). # _incdir Location for output includes, .jmod staging. # _libdir Location for output libraries, .jmod staging. May point to _bindir. # _bindir Location for output commands, .jmod staging. # Define libraries # ---------------- # Each module can define one or more native libraries. # These are compiled after the java sources have been compiled as that # process also generates any native binding headers. # _NATIVE_LIBRARIES list of libraries to build. # library names match System.loadLibrary(). # Global variables # _LDFLAGS # _LDLIBS # _CPPFLAGS # _CFLAGS # _CC # _CXXFLAGS # _CXX # SO shared library suffix # LIB shared library prefix # Utility functions # # $(call library-path,,) will resolve to the library file name. # Per library variables. # _SOURCES .c source files for library. Paths are relative to src//native. # _CXXSOURCES .c source files for library. Paths are relative to src//native. # _HEADERS header files for install/jmod # _COMMANDS commands/bin/scripts for install/jmod # _LDFLAGS link flags # _LIBADD extra objects to add to link line # _LDLIBS link libraries # _CPPFLAGS c and c++ pre-processor flags. "-Isrc//jni -Ibin/include/" is implicit. # _CCFLAGS c compiler flags # _CXXFLAGS c++ compiler flags # _DEPENDENCIES A list of other objects on which this library depends before linking. # .c and .cc files have dependencies automatically generated # Targets # ------- # make gen only generate java sources # make clean rm -rf bin # make dist create dist tar in bin/ # make | make jar make all jars and jmods # Outputs # ------- # All intermediate and output files are written to bin/ # This layout is enforced by javac # bin/include// .h files from javac -h # bin/modules// .class files from javac # This layout is convenient for netbeans # bin/gen//gen/ .c, exe files for generator free use # bin/gen//classes/ .java files from generator _JAVA_GENERATED # Working files # bin/status/ marker files for makefile # bin///lib .so librareies for jmod _LIBRARIES = libname # bin///obj .o, .d files for library _SOURCES # bin///include .h files for jmod _HEADERS # bin///.jmod .jmod module # Output files # bin//lib/ modular jar files and shared libraries for GNU/linux dev # bin//include/ header files for exported shared libraries # bin//bin/ shared libraries for microsoft dev # bin//jmods/ jmod files for 'jlink' use. # ###################################################################### E:= S:=$(E) $(E) # All modules with native code java_JMODS=$(foreach module,$(java_MODULES),$(if $(wildcard src/$(module)/jni/jni.make),$(module))) # Only modules with no native code java_JARS=$(foreach module,$(java_MODULES),$(if $(wildcard src/$(module)/jni/jni.make),,$(module))) # Modules with generated java source java_JGEN=$(foreach module,$(java_MODULES),$(if $(wildcard src/$(module)/gen/gen.make),$(module))) # Define some useful variables before including fragments define common_variables= $(1)_gendir:=bin/gen/$(1)/gen $(1)_genjavadir:=bin/gen/$(1)/classes $(1)_objdir:=bin/$(1)/$(TARGET)/obj $(1)_incdir:=bin/$(1)/$(TARGET)/include $(1)_libdir:=$$(if $$(filter windows-%,$(TARGET)),bin/$(1)/$(TARGET)/bin,bin/$(1)/$(TARGET)/lib) $(1)_bindir:=bin/$(1)/$(TARGET)/bin ifndef $(1)_SCRIPTS $(1)_SCRIPTS := $$(shell find src/$(1)/bin src/$(1)/$(TARGET)/bin -type f 2>/dev/null) endif ifndef $(1)_DATA $(1)_DATA := $$(shell find src/$(1)/lib src/$(1)/$(TARGET)/lib -type f 2>/dev/null) endif endef define java_variables= ifndef $(1)_JAVA $(1)_JAVA := $$(shell find src/$(1)/classes -type f -name '*.java') endif ifndef $(1)_RESOURCES $(1)_RESOURCES := $$(shell find src/$(1)/classes -type f \! -name '*.java') endif endef java_libdir:=$(if $(filter windows-%,$(TARGET)),bin/$(TARGET)/bin,bin/$(TARGET)/lib) java_bindir:=bin/$(TARGET)/bin java_jardir:=bin/$(TARGET)/lib java_incdir:=bin/$(TARGET)/include java_jmoddir:=bin/$(TARGET)/jmods $(foreach module,$(java_MODULES),$(eval $(call java_variables,$(module)))) $(foreach module,$(java_MODULES) $(native_MODULES),$(eval $(call common_variables,$(module)))) # ###################################################################### all: jar gen: native: .PHONY: all clean jar gen $(java_MODULES) clean: rm -rf bin include $(foreach module,$(java_MODULES),$(wildcard src/$(module)/gen/gen.make)) include $(foreach module,$(java_MODULES) $(native_MODULES),$(wildcard src/$(module)/native/native.make)) # staging only, not for modules, not sure here? define bin_files_targets= bin/status/$1.classes: $(patsubst src/$1/bin/%,bin/$(TARGET)/bin/%,$($1_SCRIPTS)) bin/$(TARGET)/bin/%: src/$1/bin/% install -vD -m 0755 $$< $$@ endef define lib_files_targets= bin/status/$1.classes: $(patsubst src/$1/lib/%,bin/$(TARGET)/lib/%,$($1_DATA)) bin/$(TARGET)/lib/%: src/$1/lib/% install -vD -m 0644 $$< $$@ endef #$(foreach module,$(java_MODULES),$(if $($(module)_SCRIPTS),$(info $(call bin_files_targets,$(module))))) #$(foreach module,$(java_MODULES),$(if $($(module)_DATA),$(info $(call lib_files_targets,$(module))))) $(foreach module,$(java_MODULES),$(if $($(module)_SCRIPTS),$(eval $(call bin_files_targets,$(module))))) $(foreach module,$(java_MODULES),$(if $($(module)_DATA),$(eval $(call lib_files_targets,$(module))))) $(error) # ###################################################################### # Java # ###################################################################### # Targets used to manage dependencies: # bin/status/.classes Source compilation target. Depends on dependent jars, sources, generated sources. # $(java_jardir)/.jar Binary compilation target. Depends on compiled classes and resources. # $(java_jardir)/.jmod Binary compilation target. Depends on compiled classes, resources, and native libraries. define java_targets= # Rules for module $(1) $(1)_JAVA_generated = $$(addprefix $$($1_genjavadir)/,$$($1_JAVA_GENERATED)) #$(java_jardir)/$1.jar: $(patsubst %,$(java_jardir)/%.jar,$(filter $($1_JDEPMOD), $(java_MODULES))) $(java_jardir)/$1.jar: $(patsubst %,$(java_jardir)/%.jar,$($1_JDEPMOD)) #bin/status/$1.classes: $(patsubst %,bin/status/%.classes,$(filter $($1_JDEPMOD), $(java_MODULES))) $$($1_JAVA) $$($1_JAVA_generated) bin/status/$1.classes: $(patsubst %,$(java_jardir)/%.jar,$(filter $($1_JDEPMOD), $(java_MODULES))) $$($1_JAVA) $$($1_JAVA_generated) jar $1: $(java_jardir)/$1.jar $(java_jmoddir)/$1.jmod $1: $(filter $($1_JDEPMOD), $(native_MODULES)) sources: $(java_jardir)/$(1)-sources.zip gen: $$($(1)_JAVA_generated) $(java_jardir)/$1.jar $(java_jmoddir)/$1.jmod: bin/status/$1.classes $(patsubst src/$1/classes/%,%,$($1_RESOURCES)) # Create modular jar $(java_jardir)/$1.jar: @install -d $$(@D) $(JAR) cf $$@ \ $(JARFLAGS) $$($(1)_JARFLAGS) \ -C bin/modules/$(1) . # Create a jmod $(java_jmoddir)/$1.jmod: rm -f $$@ @install -d $$(@D) $$(JMOD) create \ $$(JMODFLAGS) $$($(1)_JMODFLAGS) \ --target-platform $(TARGET) \ --class-path bin/modules/$(1) \ $$(if $$(wildcard bin/$(1)/$(TARGET)/include),--header-files bin/$(1)/$(TARGET)/include) \ $$(if $$(wildcard src/$(1)/legal),--legal-notices src/$(1)/legal) \ $$(if $$(wildcard bin/$(1)/$(TARGET)/bin),--cmds bin/$(1)/$(TARGET)/bin) \ $$(if $$(wildcard bin/$(1)/$(TARGET)/lib),--libs bin/$(1)/$(TARGET)/lib) \ $$@ # Create an IDE source zip, paths have to match --module-source-path $(java_jardir)/$1-sources.zip: bin/status/$1.classes @install -d $$(@D) jar -c -f $$@ -M \ $$(patsubst src/$1/classes/%,-C src/$1/classes %,$$(filter src/$1/classes/%,$$($1_JAVA))) \ $$(patsubst bin/gen/$1/classes/%,-C bin/gen/$1/classes %,$$(filter bin/gen/$1/classes/%,$$($1_JAVA))) # resources bin/modules/$1/%: src/$1/classes/% install -vDC $$< $$@ # Compile module. bin/status/$1.classes: @install -d $$(@D) $(JAVAC) \ --module-source-path "src/*/classes:bin/gen/*/classes" \ $(if $(JAVAMODPATH),--module-path $(subst $(S),:,$(JAVAMODPATH))) \ $(JAVACFLAGS) $($1_JAVACFLAGS) \ -d bin/modules \ -m $1 \ $($1_JAVA) $($1_JAVA_generated) touch $$@ endef #$(foreach module,$(java_MODULES),$(info $(call java_targets,$(module)))) $(foreach module,$(java_MODULES),$(eval $(call java_targets,$(module)))) # setup run-* targets define run_targets= run-$1/$2: $(java_jardir)/$1.jar LD_LIBRARY_PATH=$(FFMPEG_HOME)/lib \ $(JAVA) \ $(if $(JAVAMODPATH) $($1_JAVAMODPATH),--module-path $(subst $(S),:,$(JAVAMODPATH) $($1_JAVAMODPATH))) \ $(JMAINFLAGS) $($1_JMAINFLAGS) \ -m $1/$2 \ $(ARGV) .PHONY: run-$1/$2 endef #$(foreach module,$(java_MODULES),$(foreach main,$($(module)_JMAIN),$(info $(call run_targets,$(module),$(main))))) $(foreach module,$(java_MODULES),$(foreach main,$($(module)_JMAIN),$(eval $(call run_targets,$(module),$(main))))) # ###################################################################### # notzed.nativez jdk.foreign export tool via _API variables # ###################################################################### # _API List of api's to include # _APIFLAGS Extra flags to pass to export-api for every api in module # __APIFLAGS Extra flags to pass to export-api for each api define export_targets= bin/status/$2.export: $(NATIVEZ_HOME)/lib/notzed.nativez.jar # hack for in-tree notzed.nativez? bin/status/$1.classes: bin/status/$2.export bin/status/$2.export: mkdir -p bin/gen/$1/gen bin/status $(NATIVEZ_HOME)/bin/export-api \ -w bin/gen/$1/gen -d bin/gen/$1/classes $($1_APIFLAGS) $($1_$2_APIFLAGS) src/$1/gen/$2.api touch $$@ bin/status/$2.export.d: @$(NATIVEZ_HOME)/bin/export-api -M -MT "$$(@:.d=) $$@" -MF $$@ \ -w bin/gen/$1/gen -d bin/gen/$1/classes $($1_APIFLAGS) $($1_$2_APIFLAGS) src/$1/gen/$2.api 2>/dev/null $(if $(filter clean dist gen,$(MAKECMDGOALS)),,-include bin/status/$2.export.d) endef #$(foreach module,$(java_MODULES),$(if $($(module)_API),$(foreach api,$($(module)_API),$(info $(call export_targets,$(module),$(api)))))) $(foreach module,$(java_MODULES),$(foreach api,$($(module)_API),$(eval $(call export_targets,$(module),$(api))))) # ###################################################################### # C and c++ native library support # ###################################################################### SUFFIXES=.c .C .cc SO=$($(TARGET)_SO) LIB=$($(TARGET)_LIB) # functions to find cross-module stuff $(call library-path,modname,libname) library-path=$($(1)_libdir)/$(LIB)$(2)$(SO) library-dir=$($(1)_libdir)/ define native_library= # Rule for library $(2) in module $(1) $(2)_OBJS = $(patsubst %.c, $($(1)_objdir)/%.o, $($(2)_SOURCES)) \ $(patsubst %.cc, $($(1)_objdir)/%.o, $($(2)_CXXSOURCES)) $(2)_SRCS = $(addprefix src/$(1)/native/,$($(2)_SOURCES)) $(2)_SO = $($(1)_libdir)/$(LIB)$(2)$(SO) $($(1)_libdir)/$(LIB)$(2)$(SO): $$($(2)_OBJS) $($(2)_LIBADD) $($(2)_DEPENDENCIES) @install -d $$(@D) $($(TARGET)_CC) -o $$@ -shared \ $($(TARGET)_LDFLAGS) $($(2)_LDFLAGS) $$($(2)_OBJS) $($(2)_LIBADD) $($(TARGET)_LDLIBS) $($(2)_LDLIBS) $(java_libdir)/%: $($(1)_libdir)/% install -DC $$< $$@ $(java_bindir)/%: $($(1)_bindir)/% install -DC $$< $$@ $(java_incdir)/%: $($(1)_incdir)/% install -DC $$< $$@ $($(1)_objdir)/%.o: src/$(1)/native/%.c @install -d $$(@D) $($(TARGET)_CC) -Isrc/$(1)/native -Ibin/include/$(1) \ $($(TARGET)_CPPFLAGS) $($(2)_CPPFLAGS) \ $($(TARGET)_CFLAGS) $($(2)_CFLAGS) -c -o $$@ $$< $($(1)_objdir)/%.o: src/$(1)/native/%.cc @install -d $$(@D) $($(TARGET)_CXX) -Isrc/$(1)/native -Ibin/include/$(1) \ $($(TARGET)_CPPFLAGS) $($(2)_CPPFLAGS) \ $($(TARGET)_CXXFLAGS) $($(2)_CXXFLAGS) -c -o $$@ $$< $($(1)_incdir)/%: src/$(1)/native/% install -DC $$< $$@ $($(1)_libdir)/%: src/$(1)/native/% install -DC $$< $$@ # auto-dependencies for c files $($(1)_objdir)/%.d: src/$(1)/native/%.c @install -d $$(@D) @rm -f $$@ @$($(TARGET)_CC) -MM -MT "$$(@:.d=.o) $$@" -Isrc/$(1)/jni -Ibin/include/$(1) \ $($(TARGET)_CPPFLAGS) $($(2)_CPPFLAGS) $$< -o $$@ 2>/dev/null # auto-dependencies for c++ files $($(1)_objdir)/%.d: src/$(1)/native/%.cc @install -d $$(@D) @rm -f $$@ @$($(TARGET)_CXX) -MM -MT "$$(@:.d=.o) $$@" -Isrc/$(1)/jni -Ibin/include/$(1) \ $($(TARGET)_CPPFLAGS) $($(2)_CPPFLAGS) $$< -o $$@ 2>/dev/null $(java_jardir)/$(1).jar: \ $($(1)_libdir)/$(LIB)$(2)$(SO) \ $(java_libdir)/$(LIB)$(2)$(SO) \ $(addprefix $($(1)_incdir)/,$($(2)_HEADERS)) \ $(addprefix $(java_incdir)/,$($(2)_HEADERS)) \ $(addprefix $($(1)_bindir)/,$($(2)_COMMANDS)) \ $(addprefix $(java_bindir)/,$($(2)_COMMANDS)) \ $(addprefix $($(1)_libdir)/,$($(2)_LIBRARIES)) $(if $(filter clean dist gen,$(MAKECMDGOALS)),,-include $$($(2)_OBJS:.o=.d)) endef #$(foreach module,$(java_MODULES) $(native_MODULES),$(foreach library,$($(module)_NATIVE_LIBRARIES),$(info $(call native_library,$(module),$(library))))) $(foreach module,$(java_MODULES) $(native_MODULES),$(foreach library,$($(module)_NATIVE_LIBRARIES),$(eval $(call native_library,$(module),$(library))))) # small hack: native-only modules have a phony jar target define native_targets= .PHONY: $(java_jardir)/$(1).jar $1 jar: $(java_jardir)/$(1).jar endef #$(foreach module,$(native_MODULES),$(info $(call native_targets,$(module)))) $(foreach module,$(native_MODULES),$(eval $(call native_targets,$(module)))) # ###################################################################### dist: @install -d bin tar cfz bin/$(dist_NAME)-$(dist_VERSION).tar.gz \ --transform=s,^,$(dist_NAME)-$(dist_VERSION)/, \ config.make.in java.make Makefile src \ $(dist_EXTRA)