From: Mathieu Baudier Date: Sat, 16 Mar 2024 06:49:29 +0000 (+0100) Subject: Merge tag 'v2.3.10' into testing X-Git-Tag: v2.1.6~1 X-Git-Url: https://git.argeo.org/?a=commitdiff_plain;h=5d6d48735e6db0917e5b520e660ab251deb9d442;hp=cabcc3462226b71849ca42301c21e05b63f150c2;p=cc0%2Fargeo-build.git Merge tag 'v2.3.10' into testing --- diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..99f26c0 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 997d664..ee4a902 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -9,9 +9,18 @@ org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable org.eclipse.jdt.core.compiler.annotation.nullable.secondary= org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.APILeak=warning org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.autoboxing=ignore org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning org.eclipse.jdt.core.compiler.problem.deadCode=warning @@ -20,6 +29,8 @@ org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled org.eclipse.jdt.core.compiler.problem.discouragedReference=warning org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled @@ -64,6 +75,7 @@ org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=igno org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled @@ -102,3 +114,5 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/common.mk b/common.mk index bc1bff9..891f8f8 100644 --- a/common.mk +++ b/common.mk @@ -6,8 +6,52 @@ ECJ_MAJOR=3 BNDLIB_BRANCH=5.3 SYSLOGGER_BRANCH=$(build-major).$(build-minor) +# The following variables are found in the sdk.mk file which is generated by the configure script: +# SDK_SRC_BASE the base of the source code, typically the root of the cloned git repository +# SDK_BUILD_BASE the base of the output +# JAVA_HOME the base of the JDK used to build +A2_OUTPUT = $(SDK_BUILD_BASE)/a2 +JVM ?= $(JAVA_HOME)/bin/java +JAVADOC ?= $(JAVA_HOME)/bin/javadoc + # GNU defaults prefix ?= /usr/local datarootdir ?= $(prefix)/share +exec_prefix ?= $(prefix) +libdir ?= $(exec_prefix)/lib + +A2_INSTALL_TARGET ?= $(DESTDIR)$(datarootdir)/a2 +A2_NATIVE_INSTALL_TARGET ?= $(DESTDIR)$(libdir)/a2 + +# The following variables have default values which can be overriden +# A2_BASE the space-separated directories where already built a2 categories can be found +A2_BASE ?=$(A2_OUTPUT) $(A2_INSTALL_TARGET) $(A2_NATIVE_INSTALL_TARGET) /usr/local/share/a2 /usr/local/lib/a2 /usr/share/a2 /usr/lib/a2 + +# OS-speciific +KNOWN_ARCHS ?= x86_64 aarch64 +TARGET_OS ?= linux +TARGET_ARCH ?= $(shell uname -m) + +TARGET_OS_CATEGORY_PREFIX=lib/$(TARGET_OS) +TARGET_ARCH_CATEGORY_PREFIX=$(TARGET_OS_CATEGORY_PREFIX)/$(TARGET_ARCH) +PORTABLE_CATEGORIES=$(filter-out lib/%, $(CATEGORIES)) +ARCH_CATEGORIES=$(filter $(TARGET_ARCH_CATEGORY_PREFIX)/%, $(CATEGORIES)) +OS_CATEGORIES=$(filter-out $(foreach arch, $(KNOWN_ARCHS), $(TARGET_OS_CATEGORY_PREFIX)/$(arch)/%), $(filter $(TARGET_OS_CATEGORY_PREFIX)/%, $(CATEGORIES))) + +## Utilities +# Install to a target directory without executable bit +INSTALL=install -m644 -D --target-directory +# Always try copy-on-write +COPY=--reflink=auto +# Recursively delete directories +RMDIR=$(RM) -r + +# Make variables used to replace spaces by a separator, typically in order to generate classpaths +# for example: CLASSPATH = $(subst $(space),$(pathsep),$(strip $(JARS))) +null := +space := $(null) # +pathsep := : +define LF -A2_INSTALL_TARGET ?= $(DESTDIR)$(datarootdir)/a2 \ No newline at end of file +$(null) +endef diff --git a/jni.mk b/jni.mk new file mode 100644 index 0000000..1892613 --- /dev/null +++ b/jni.mk @@ -0,0 +1,74 @@ +ARGEO_BUILD_BASE := $(dir $(lastword $(MAKEFILE_LIST))) +include $(ARGEO_BUILD_BASE)common.mk + +# The following variables should be declared in the including Makefile: +# NATIVE_PACKAGE this native package name +# A2_CATEGORY the (single) a2 category the bundles will belong to + +# The following variables have default values which can be overriden +# DEP_NATIVE space-separated logical names of named depdencies +# DEP_INCLUDES additional includes +# DEP_LIBS additional native libraries +DEP_NATIVE ?= +DEP_INCLUDES ?= $(foreach dep, $(DEP_NATIVE), /usr/include/$(dep)) +DEP_LIBS ?= $(foreach dep, $(DEP_NATIVE), -l$(dep)) + +A2_NATIVE_CATEGORY=$(A2_OUTPUT)/lib/linux/$(shell uname -m)/$(A2_CATEGORY) +TARGET_EXEC := libJava_$(NATIVE_PACKAGE).$(major).$(minor).so + +LDFLAGS ?= -shared -fPIC -Wl,-soname,$(TARGET_EXEC).$(major).$(minor).$(micro) $(DEP_LIBS) +CFLAGS ?= -O3 -fPIC + +SRC_DIRS := . + +# +# Generic Argeo +# +BUILD_DIR := $(SDK_BUILD_BASE)/jni/$(NATIVE_PACKAGE) + +# Include directories +INC_DIRS := $(shell find $(SRC_DIRS) -type d) $(JAVA_HOME)/include $(JAVA_HOME)/include/linux $(DEP_INCLUDES) + +all: $(A2_NATIVE_CATEGORY)/$(TARGET_EXEC) + +clean: + $(RM) $(BUILD_DIR)/*.o + $(RM) $(A2_NATIVE_CATEGORY)/$(TARGET_EXEC) + +install: + $(INSTALL) $(A2_NATIVE_INSTALL_TARGET)/$(A2_CATEGORY) $(A2_NATIVE_CATEGORY)/$(TARGET_EXEC) + +uninstall: + $(RM) $(A2_NATIVE_INSTALL_TARGET)/$(A2_CATEGORY)/$(TARGET_EXEC) + @if [ -d $(A2_NATIVE_INSTALL_TARGET) ]; then find $(A2_NATIVE_INSTALL_TARGET) -empty -type d -delete; fi + +# Sources +SRCS := $(shell find $(SRC_DIRS) -name '*.cpp' -or -name '*.c' -or -name '*.s') +# Objects (example.cpp to ./org_example_core/example.cpp.o) +OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) +# Dependencies (example.cpp.o to ./org_example_core/example.cpp.d) +DEPS := $(OBJS:.o=.d) +# Add -I prefix to include directories +INC_FLAGS := $(addprefix -I,$(INC_DIRS)) +# Generate dependencies makefiles +CPPFLAGS := $(INC_FLAGS) -MMD -MP + +# Final build step +$(A2_NATIVE_CATEGORY)/$(TARGET_EXEC): $(OBJS) + mkdir -p $(A2_NATIVE_CATEGORY) + $(CC) $(OBJS) -o $@ $(LDFLAGS) + +# Build step for C source +$(BUILD_DIR)/%.c.o: %.c + mkdir -p $(dir $@) + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ + +# Build step for C++ source +$(BUILD_DIR)/%.cpp.o: %.cpp + mkdir -p $(dir $@) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@ + +# Include the .d makefiles. (- pefix suppress errors if not found) +-include $(DEPS) + +.PHONY: clean all install uninstall diff --git a/osgi.mk b/osgi.mk index ca17cbe..334714b 100644 --- a/osgi.mk +++ b/osgi.mk @@ -1,37 +1,27 @@ ARGEO_BUILD_BASE := $(dir $(lastword $(MAKEFILE_LIST))) include $(ARGEO_BUILD_BASE)common.mk -# -# Common build routines to be included in Makefiles -# -# The following variables are found in the sdk.mk file which is generated by the configure script: -# SDK_SRC_BASE the base of the source code, typically the root of the cloned git repository -# SDK_BUILD_BASE the base of the output -# JAVA_HOME the base of the JDK used to build -A2_OUTPUT = $(SDK_BUILD_BASE)/a2 -JVM ?= $(JAVA_HOME)/bin/java -JAVADOC ?= $(JAVA_HOME)/bin/javadoc # The following variables should be declared in the including Makefile: -# BUNDLES the space-separated list of bundles to build -# A2_CATEGORY the (single) a2 category the bundles will belong to +# BUNDLES the space-separated list of bundles to build +# A2_CATEGORY the (single) a2 category the bundles will belong to # The following environment variables can change the behaviour of the build -# SOURCE_BUNDLES sources will be packaged separately in Eclipse-compatible source bundles -# NO_MANIFEST_COPY generated MANIFESTs won't be copied to the source tree +# SOURCE_BUNDLES sources will be packaged separately in Eclipse-compatible source bundles +# NO_MANIFEST_COPY generated MANIFESTs won't be copied to the source tree # The following variables have default values which can be overriden -# DEP_CATEGORIES the a2 categories the compilation depends on -# JAVADOC_PACKAGES the space-separated list of packages for which javadoc will be generated -# A2_BASE the space-separated directories where already built a2 categories can be found +# DEP_CATEGORIES the a2 categories the compilation depends on +# JAVADOC_PACKAGES the space-separated list of packages for which javadoc will be generated +# NATIVE_PACKAGES the space-separated list of JNI packages (directories) DEP_CATEGORIES ?= JAVADOC_PACKAGES ?= -A2_BASE ?=/usr/share/a2 /usr/local/share/a2 $(A2_OUTPUT) +NATIVE_PACKAGES ?= # We always use the latest version of the ECJ compiler -ECJ_JAR ?= $(lastword $(foreach base, $(A2_BASE), $(sort $(wildcard $(base)/org.argeo.tp.build/org.eclipse.jdt.core.compiler.batch.$(ECJ_MAJOR).*.jar)))) +ECJ_JAR ?= $(firstword $(foreach base, $(A2_BASE), $(sort $(wildcard $(base)/org.argeo.tp.build/org.eclipse.jdt.core.compiler.batch.$(ECJ_MAJOR).*.jar)))) # Third-party libraries -LOGGER_JAR ?= $(lastword $(foreach base, $(A2_BASE), $(wildcard $(base)/log/syslogger/org.argeo.tp/org.argeo.tp.syslogger.$(SYSLOGGER_BRANCH).jar))) -BNDLIB_JAR ?= $(lastword $(foreach base, $(A2_BASE), $(wildcard $(base)/org.argeo.tp.build/biz.aQute.bndlib.$(BNDLIB_BRANCH).jar))) +LOGGER_JAR ?= $(firstword $(foreach base, $(A2_BASE), $(wildcard $(base)/log/syslogger/org.argeo.tp/org.argeo.tp.syslogger.$(SYSLOGGER_BRANCH).jar))) +BNDLIB_JAR ?= $(firstword $(foreach base, $(A2_BASE), $(wildcard $(base)/org.argeo.tp.build/biz.aQute.bndlib.$(BNDLIB_BRANCH).jar))) # Internal variables ARGEO_MAKE = $(JVM) -cp $(LOGGER_JAR):$(ECJ_JAR):$(BNDLIB_JAR) $(ARGEO_BUILD_BASE)src/org/argeo/build/Make.java @@ -42,10 +32,11 @@ endif BUILD_BASE = $(SDK_BUILD_BASE)/$(shell basename $(SDK_SRC_BASE)) TARGET_BUNDLES = $(abspath $(foreach bundle, $(BUNDLES),$(A2_OUTPUT)/$(shell dirname $(bundle))/$(A2_CATEGORY)/$(shell basename $(bundle)).$(major).$(minor).jar)) TODOS = $(foreach bundle, $(BUNDLES),$(BUILD_BASE)/$(bundle)/to-build) +# Native +JNIDIRS=$(foreach package, $(NATIVE_PACKAGES), jni/$(package)) # Needed in order to be able to expand $$ variables .SECONDEXPANSION: -.PHONY: osgi manifests javadoc osgi: $(BUILD_BASE)/built $(MANIFESTS) @@ -81,22 +72,37 @@ endif clean-manifests : @rm -rf $(foreach bundle, $(BUNDLES), $(bundle)/META-INF/MANIFEST.MF); -osgi-install: +osgi-all: osgi jni-all + +osgi-clean: jni-clean + rm -rf $(BUILD_BASE) + +osgi-install: jni-install $(ARGEO_MAKE) \ install --category $(A2_CATEGORY) --bundles $(BUNDLES) \ - --target $(A2_INSTALL_TARGET) + --target $(A2_INSTALL_TARGET) \ + --os $(TARGET_OS) --target-native $(A2_NATIVE_INSTALL_TARGET) -osgi-uninstall: +osgi-uninstall: jni-uninstall $(ARGEO_MAKE) \ uninstall --category $(A2_CATEGORY) --bundles $(BUNDLES) \ - --target $(A2_INSTALL_TARGET) + --target $(A2_INSTALL_TARGET) \ + --os $(TARGET_OS) --target-native $(A2_NATIVE_INSTALL_TARGET) + +jni-all: + $(foreach dir, $(JNIDIRS), $(MAKE) -C $(dir) all;) + +jni-clean: + $(foreach dir, $(JNIDIRS), $(MAKE) -C $(dir) clean;) + +jni-install: + $(foreach dir, $(JNIDIRS), $(MAKE) -C $(dir) install;) + +jni-uninstall: + $(foreach dir, $(JNIDIRS), $(MAKE) -C $(dir) uninstall;) # Javadoc generation javadoc: $(BUILD_BASE)/built $(JAVADOC) -noindex -quiet -Xmaxwarns 1 -d $(BUILD_BASE)/api --source-path $(subst $(space),$(pathsep),$(strip $(JAVADOC_SRCS))) -subpackages $(JAVADOC_PACKAGES) -# Make variables used to replace spaces by a separator, typically in order to generate classpaths -# for example: CLASSPATH = $(subst $(space),$(pathsep),$(strip $(JARS))) -null := -space := $(null) # -pathsep := : \ No newline at end of file +.PHONY: osgi manifests javadoc osgi-all osgi-clean osgi-install osgi-uninstall jni-all jni-clean jni-install jni-uninstall diff --git a/repackage.mk b/repackage.mk index 5a14bb7..87ce907 100644 --- a/repackage.mk +++ b/repackage.mk @@ -1,25 +1,14 @@ ARGEO_BUILD_BASE := $(dir $(lastword $(MAKEFILE_LIST))) include $(ARGEO_BUILD_BASE)common.mk -# -# Common repackage routines to be included in Makefiles -# -# The following variables are found in the sdk.mk file which is generated by the configure script: -# SDK_SRC_BASE the base of the source code, typically the root of the cloned git repository -# SDK_BUILD_BASE the base of the output -# JAVA_HOME the base of the JDK used to build -A2_OUTPUT = $(SDK_BUILD_BASE)/a2 -JVM ?= $(JAVA_HOME)/bin/java # The following variables should be declared in the including Makefile: -# CATEGORIES the space-separated list of categories to repackage +# CATEGORIES the space-separated list of categories to repackage -# The following variables have default values which can be overriden -# A2_BASE the space-separated directories where already built a2 categories can be found A2_BASE ?=/usr/share/a2 /usr/local/share/a2 $(A2_OUTPUT) # Third-party libraries -LOGGER_JAR ?= $(lastword $(foreach base, $(A2_BASE), $(wildcard $(base)/log/syslogger/org.argeo.tp/org.argeo.tp.syslogger.$(SYSLOGGER_BRANCH).jar))) -BNDLIB_JAR ?= $(lastword $(foreach base, $(A2_BASE), $(wildcard $(base)/org.argeo.tp.build/biz.aQute.bndlib.$(BNDLIB_BRANCH).jar))) +LOGGER_JAR ?= $(firstword $(foreach base, $(A2_BASE), $(wildcard $(base)/log/syslogger/org.argeo.tp/org.argeo.tp.syslogger.$(SYSLOGGER_BRANCH).jar))) +BNDLIB_JAR ?= $(firstword $(foreach base, $(A2_BASE), $(wildcard $(base)/org.argeo.tp.build/biz.aQute.bndlib.$(BNDLIB_BRANCH).jar))) # Internal variables ARGEO_REPACKAGE = $(JVM) -cp $(LOGGER_JAR):$(BNDLIB_JAR) $(ARGEO_BUILD_BASE)src/org/argeo/build/Repackage.java @@ -30,13 +19,28 @@ REPACKAGED_CATEGORIES = $(foreach category, $(CATEGORIES),$(A2_OUTPUT)/$(categor all: $(BUILD_BASE)/repackaged install: - @$(foreach category, $(CATEGORIES), mkdir -p $(A2_INSTALL_TARGET)/$(category); cp $(A2_OUTPUT)/$(category)/*.jar $(A2_INSTALL_TARGET)/$(category);) - @echo Installed $(CATEGORIES) to $(A2_INSTALL_TARGET) + @$(foreach category, $(PORTABLE_CATEGORIES), $(INSTALL) $(A2_INSTALL_TARGET)/$(category) $(wildcard $(A2_OUTPUT)/$(category)/*.jar);$(LF)) + @echo Installed portable jars \'$(PORTABLE_CATEGORIES)\' to $(A2_INSTALL_TARGET) + @$(foreach category, $(OS_CATEGORIES), $(INSTALL) $(A2_INSTALL_TARGET)/$(category:$(TARGET_OS_CATEGORY_PREFIX)/%=%) $(wildcard $(A2_OUTPUT)/$(category)/*.jar);$(LF)) + @echo Installed OS-dependent jars \'$(OS_CATEGORIES)\' to $(A2_INSTALL_TARGET) + @$(foreach category, $(ARCH_CATEGORIES), $(INSTALL) $(A2_NATIVE_INSTALL_TARGET)/$(category:$(TARGET_ARCH_CATEGORY_PREFIX)/%=%) $(wildcard $(A2_OUTPUT)/$(category)/*.jar);$(LF)) + @echo Installed arch-dependent jars \'$(ARCH_CATEGORIES)\' to $(A2_NATIVE_INSTALL_TARGET) + @$(foreach category, $(ARCH_CATEGORIES), $(INSTALL) $(A2_NATIVE_INSTALL_TARGET)/$(category:$(TARGET_ARCH_CATEGORY_PREFIX)/%=%) $(wildcard $(A2_OUTPUT)/$(category)/*.so);$(LF)) + @echo Installed arch binaries \'$(ARCH_CATEGORIES)\' to $(A2_NATIVE_INSTALL_TARGET) uninstall: - @$(foreach category, $(CATEGORIES), rm -rf $(A2_INSTALL_TARGET)/$(category);) - @find $(A2_INSTALL_TARGET) -empty -type d -delete - @echo Uninstalled $(CATEGORIES) from $(A2_INSTALL_TARGET) + @$(foreach category, $(PORTABLE_CATEGORIES), $(RMDIR) $(A2_INSTALL_TARGET)/$(category);$(LF)) + @echo Uninstalled portable jars \'$(PORTABLE_CATEGORIES)\' to $(A2_INSTALL_TARGET) + @$(foreach category, $(OS_CATEGORIES), $(RMDIR) $(A2_INSTALL_TARGET)/$(category:$(TARGET_OS_CATEGORY_PREFIX)/%=%);$(LF)) + @echo Uninstalled OS-dependent jars \'$(OS_CATEGORIES)\' to $(A2_INSTALL_TARGET) + @$(foreach category, $(ARCH_CATEGORIES), $(RMDIR) $(A2_NATIVE_INSTALL_TARGET)/$(category:$(TARGET_ARCH_CATEGORY_PREFIX)/%=%);$(LF)) + @echo Uninstalled arch-dependent jars and binaries \'$(ARCH_CATEGORIES)\' to $(A2_NATIVE_INSTALL_TARGET) +# @$(foreach category, $(ARCH_CATEGORIES), \ +# $(foreach libfile, $(wildcard $(A2_OUTPUT)/$(category)/*.so), $(RMDIR) $(A2_NATIVE_INSTALL_TARGET)/$(notdir $(libfile));$(LF)) \ +# ) +# @echo Uninstalled arch binaries \'$(ARCH_CATEGORIES)\' to $(A2_NATIVE_INSTALL_TARGET) + @if [ -d $(A2_INSTALL_TARGET) ]; then find $(A2_INSTALL_TARGET) -empty -type d -delete; fi + @if [ -d $(A2_NATIVE_INSTALL_TARGET) ]; then find $(A2_NATIVE_INSTALL_TARGET) -empty -type d -delete; fi .SECONDEXPANSION: # We use .SECONDEXPANSION and CATEGORIES_TO_REPACKAGE instead of directly CATEGORIES diff --git a/sdk/branches/testing.bnd b/sdk/branches/testing.bnd index a8ddda3..e8a57b2 100644 --- a/sdk/branches/testing.bnd +++ b/sdk/branches/testing.bnd @@ -1,6 +1,6 @@ major=2 minor=1 micro=5 -qualifier= +qualifier=.next SPDX-License-Identifier=CC0-1.0 \ No newline at end of file diff --git a/sdk/branches/unstable.bnd b/sdk/branches/unstable.bnd index 9ba0e10..6f41334 100644 --- a/sdk/branches/unstable.bnd +++ b/sdk/branches/unstable.bnd @@ -1,6 +1,6 @@ major=2 minor=3 -micro=9 +micro=10 qualifier= SPDX-License-Identifier=CC0-1.0 \ No newline at end of file diff --git a/src/org/argeo/build/Make.java b/src/org/argeo/build/Make.java index 34477cf..b0066ac 100644 --- a/src/org/argeo/build/Make.java +++ b/src/org/argeo/build/Make.java @@ -38,6 +38,7 @@ import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; +import java.util.stream.Collectors; import java.util.zip.Deflater; import org.eclipse.jdt.core.compiler.CompilationProgress; @@ -175,7 +176,8 @@ public class Make { List a2Categories = options.getOrDefault("--dep-categories", new ArrayList<>()); List a2Bases = options.getOrDefault("--a2-bases", new ArrayList<>()); - if (a2Bases.isEmpty() || !a2Bases.contains(a2Output.toString())) { + a2Bases = a2Bases.stream().distinct().collect(Collectors.toList());// remove duplicates + if (a2Bases.isEmpty() || !a2Bases.contains(a2Output.toString())) {// make sure a2 output is available a2Bases.add(a2Output.toString()); } @@ -204,10 +206,9 @@ public class Make { A2Jar current = a2Jars.get(a2Jar.name); if (a2Jar.major > current.major) a2Jars.put(a2Jar.name, a2Jar); - else if (a2Jar.major == current.major // - // if minor equals, we take the last one - && a2Jar.minor >= current.minor) + else if (a2Jar.major == current.major && a2Jar.minor > current.minor) a2Jars.put(a2Jar.name, a2Jar); + // keep if minor equals } else { a2Jars.put(a2Jar.name, a2Jar); } @@ -312,26 +313,21 @@ public class Make { logger.log(DEBUG, "Packaging took " + duration + " ms"); } - /** Install the bundles. */ + /** Install or uninstall bundles and native output. */ void install(Map> options, boolean uninstall) throws IOException { + final String LIB_ = "lib/"; + final String NATIVE_ = "native/"; + // check arguments - List bundles = options.get("--bundles"); - Objects.requireNonNull(bundles, "--bundles argument must be set"); + List bundles = multiArg(options, "--bundles", true); if (bundles.isEmpty()) return; - - List categories = options.get("--category"); - Objects.requireNonNull(categories, "--category argument must be set"); - if (categories.size() != 1) - throw new IllegalArgumentException("One and only one --category must be specified"); - String category = categories.get(0); - - List targetDirs = options.get("--target"); - Objects.requireNonNull(targetDirs, "--target argument must be set"); - if (targetDirs.size() != 1) - throw new IllegalArgumentException("One and only one --target must be specified"); - Path targetA2 = Paths.get(targetDirs.get(0)); - logger.log(INFO, (uninstall ? "Uninstalling from " : "Installing to ") + targetA2); + String category = singleArg(options, "--category", true); + Path targetA2 = Paths.get(singleArg(options, "--target", true)); + String nativeTargetArg = singleArg(options, "--target-native", false); + Path nativeTargetA2 = nativeTargetArg != null ? Paths.get(nativeTargetArg) : null; + String targetOs = singleArg(options, "--os", nativeTargetArg != null); + logger.log(INFO, (uninstall ? "Uninstalling bundles from " : "Installing bundles to ") + targetA2); final String branch; Path branchMk = sdkSrcBase.resolve(BRANCH_MK); @@ -354,14 +350,28 @@ public class Make { Objects.requireNonNull(minor, "'minor' must be set"); int count = 0; - for (String bundle : bundles) { + bundles: for (String bundle : bundles) { Path bundlePath = Paths.get(bundle); Path bundleParent = bundlePath.getParent(); Path a2JarDirectory = bundleParent != null ? a2Output.resolve(bundleParent).resolve(category) : a2Output.resolve(category); Path jarP = a2JarDirectory.resolve(bundlePath.getFileName() + "." + major + "." + minor + ".jar"); - Path targetJarP = targetA2.resolve(a2Output.relativize(jarP)); + Path targetJarP; + if (bundle.startsWith(LIB_)) {// OS-specific + Objects.requireNonNull(nativeTargetA2); + if (bundle.startsWith(LIB_ + NATIVE_) // portable native + || bundle.startsWith(LIB_ + targetOs + "/" + NATIVE_)) {// OS-specific native + targetJarP = nativeTargetA2.resolve(category).resolve(jarP.getFileName()); + } else if (bundle.startsWith(LIB_ + targetOs)) {// OS-specific portable + targetJarP = targetA2.resolve(category).resolve(jarP.getFileName()); + } else { // ignore other OS + continue bundles; + } + } else { + targetJarP = targetA2.resolve(a2Output.relativize(jarP)); + } + if (uninstall) { // uninstall if (Files.exists(targetJarP)) { Files.delete(targetJarP); @@ -369,7 +379,10 @@ public class Make { count++; } Path targetParent = targetJarP.getParent(); - deleteEmptyParents(targetA2, targetParent); + if (targetParent.startsWith(targetA2)) + deleteEmptyParents(targetA2, targetParent); + if (nativeTargetA2 != null && targetParent.startsWith(nativeTargetA2)) + deleteEmptyParents(nativeTargetA2, targetParent); } else { // install Files.createDirectories(targetJarP.getParent()); boolean update = Files.exists(targetJarP); @@ -381,16 +394,45 @@ public class Make { logger.log(INFO, uninstall ? count + " bundles removed" : count + " bundles installed or updated"); } - /** Delete empty parent directory up to the A2 target (included). */ - void deleteEmptyParents(Path targetA2, Path targetParent) throws IOException { + /** Extracts an argument which must be unique. */ + String singleArg(Map> options, String arg, boolean mandatory) { + List values = options.get(arg); + if (values == null || values.size() == 0) + if (mandatory) + throw new IllegalArgumentException(arg + " argument must be set"); + else + return null; + if (values.size() != 1) + throw new IllegalArgumentException("One and only one " + arg + " arguments must be specified"); + return values.get(0); + } + + /** Extracts an argument which can have multiple values. */ + List multiArg(Map> options, String arg, boolean mandatory) { + List values = options.get(arg); + if (mandatory && values == null) + throw new IllegalArgumentException(arg + " argument must be set"); + return values != null ? values : new ArrayList<>(); + } + + /** Delete empty parent directory up to the base directory (included). */ + void deleteEmptyParents(Path baseDir, Path targetParent) throws IOException { + if (!targetParent.startsWith(baseDir)) + throw new IllegalArgumentException(targetParent + " does not start with " + baseDir); + if (!Files.exists(baseDir)) + return; + if (!Files.exists(targetParent)) { + deleteEmptyParents(baseDir, targetParent.getParent()); + return; + } if (!Files.isDirectory(targetParent)) throw new IllegalArgumentException(targetParent + " must be a directory"); - boolean isA2target = Files.isSameFile(targetA2, targetParent); + boolean isA2target = Files.isSameFile(baseDir, targetParent); if (!Files.list(targetParent).iterator().hasNext()) { Files.delete(targetParent); if (isA2target) return;// stop after deleting A2 base - deleteEmptyParents(targetA2, targetParent.getParent()); + deleteEmptyParents(baseDir, targetParent.getParent()); } } diff --git a/src/org/argeo/build/Repackage.java b/src/org/argeo/build/Repackage.java index 5b5247b..2a9331d 100644 --- a/src/org/argeo/build/Repackage.java +++ b/src/org/argeo/build/Repackage.java @@ -23,6 +23,7 @@ import static org.argeo.build.Repackage.ManifestHeader.BUNDLE_VERSION; import static org.argeo.build.Repackage.ManifestHeader.ECLIPSE_SOURCE_BUNDLE; import static org.argeo.build.Repackage.ManifestHeader.EXPORT_PACKAGE; import static org.argeo.build.Repackage.ManifestHeader.IMPORT_PACKAGE; +import static org.argeo.build.Repackage.ManifestHeader.REQUIRE_BUNDLE; import static org.argeo.build.Repackage.ManifestHeader.SPDX_LICENSE_IDENTIFIER; import java.io.BufferedWriter; @@ -32,8 +33,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.System.Logger; -import java.net.MalformedURLException; -import java.net.URL; +import java.net.URI; +import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.nio.file.DirectoryStream; import java.nio.file.FileSystem; @@ -148,6 +149,8 @@ public class Repackage { EXPORT_PACKAGE("Export-Package"), // /** OSGi imported packages list. */ IMPORT_PACKAGE("Import-Package"), // + /** OSGi required bundles. */ + REQUIRE_BUNDLE("Require-Bundle"), // /** OSGi path to embedded jar. */ BUNDLE_CLASSPATH("Bundle-Classpath"), // // Java @@ -174,7 +177,7 @@ public class Repackage { /** Maven repository, if not the default one. */ ARGEO_ORIGIN_M2_REPO("Argeo-Origin-M2-Repo"), // /** - * Do not perform BND analysis of the origin component. Typically Import_package + * Do not perform BND analysis of the origin component. Typically Import-Package * and Export-Package will be kept untouched. */ ARGEO_ORIGIN_NO_METADATA_GENERATION("Argeo-Origin-NoMetadataGeneration"), // @@ -773,7 +776,7 @@ public class Repackage { : null; String alternateUri = props.getProperty(ARGEO_ORIGIN_SOURCES_URI.toString()); M2Artifact sourcesArtifact = new M2Artifact(artifact.toM2Coordinates(), "sources"); - URL sourcesUrl = alternateUri != null ? new URL(alternateUri) + URI sourcesUrl = alternateUri != null ? new URI(alternateUri) : M2ConventionsUtils.mavenRepoUrl(repoStr, sourcesArtifact); Path sourcesDownloaded = downloadMaven(sourcesUrl, sourcesArtifact); processM2SourceJar(sourcesDownloaded, targetBundleDir, merging ? artifact : null, unmodified); @@ -847,13 +850,17 @@ public class Repackage { ? props.getProperty(ARGEO_ORIGIN_M2_REPO.toString()) : null; String alternateUri = props.getProperty(ARGEO_ORIGIN_URI.toString()); - URL url = alternateUri != null ? new URL(alternateUri) : M2ConventionsUtils.mavenRepoUrl(repoStr, artifact); - return downloadMaven(url, artifact); + try { + URI uri = alternateUri != null ? new URI(alternateUri) : M2ConventionsUtils.mavenRepoUrl(repoStr, artifact); + return downloadMaven(uri, artifact); + } catch (URISyntaxException e) { + throw new IllegalArgumentException("Wrong aritfact URI", e); + } } /** Download a Maven artifact. */ - Path downloadMaven(URL url, M2Artifact artifact) throws IOException { - return download(url, mavenBase, M2ConventionsUtils.artifactPath("", artifact)); + Path downloadMaven(URI uri, M2Artifact artifact) throws IOException { + return download(uri, mavenBase, M2ConventionsUtils.artifactPath("", artifact)); } /* @@ -1122,8 +1129,9 @@ public class Repackage { Files.copy(jarIn, target); // native libraries + boolean removeDllFromJar = true; if (isNative && (entry.getName().endsWith(".so") || entry.getName().endsWith(".dll") - || entry.getName().endsWith(".jnilib"))) { + || entry.getName().endsWith(".jnilib") || entry.getName().endsWith(".a"))) { Path categoryDir = bundleDir.getParent(); boolean copyDll = false; Path targetDll = categoryDir.resolve(bundleDir.relativize(target)); @@ -1145,8 +1153,11 @@ public class Repackage { Files.delete(targetDll); Files.copy(target, targetDll); } - Files.delete(target); - origin.deleted.add(bundleDir.relativize(target).toString()); + + if (removeDllFromJar) { + Files.delete(target); + origin.deleted.add(bundleDir.relativize(target).toString()); + } } logger.log(TRACE, () -> "Copied " + target); } @@ -1208,7 +1219,11 @@ public class Repackage { for (Iterator> manifestEntries = manifest.getMainAttributes().entrySet() .iterator(); manifestEntries.hasNext();) { Map.Entry manifestEntry = manifestEntries.next(); - switch (manifestEntry.getKey().toString()) { + String key = manifestEntry.getKey().toString(); + // TODO make it more generic + if (key.equals(REQUIRE_BUNDLE.toString()) && nameVersion.getName().equals("com.sun.jna.platform")) + manifestEntries.remove(); + switch (key) { case "Archiver-Version": case "Build-By": case "Created-By": @@ -1309,12 +1324,12 @@ public class Repackage { } /** Try to download from an URI. */ - Path tryDownloadArchive(String uri, Path dir) throws IOException { + Path tryDownloadArchive(String uriStr, Path dir) throws IOException { // find mirror List urlBases = null; String uriPrefix = null; uriPrefixes: for (String uriPref : mirrors.keySet()) { - if (uri.startsWith(uriPref)) { + if (uriStr.startsWith(uriPref)) { if (mirrors.get(uriPref).size() > 0) { urlBases = mirrors.get(uriPref); uriPrefix = uriPref; @@ -1324,56 +1339,56 @@ public class Repackage { } if (urlBases == null) try { - return downloadArchive(new URL(uri), dir); - } catch (FileNotFoundException e) { - throw new FileNotFoundException("Cannot find " + uri); + return downloadArchive(new URI(uriStr), dir); + } catch (FileNotFoundException | URISyntaxException e) { + throw new FileNotFoundException("Cannot find " + uriStr); } // try to download for (String urlBase : urlBases) { - String relativePath = uri.substring(uriPrefix.length()); - URL url = new URL(urlBase + relativePath); + String relativePath = uriStr.substring(uriPrefix.length()); + String uStr = urlBase + relativePath; try { - return downloadArchive(url, dir); - } catch (FileNotFoundException e) { - logger.log(WARNING, "Cannot download " + url + ", trying another mirror"); + return downloadArchive(new URI(uStr), dir); + } catch (FileNotFoundException | URISyntaxException e) { + logger.log(WARNING, "Cannot download " + uStr + ", trying another mirror"); } } - throw new FileNotFoundException("Cannot find " + uri); + throw new FileNotFoundException("Cannot find " + uriStr); } /** * Effectively download an archive. */ - Path downloadArchive(URL url, Path dir) throws IOException { - return download(url, dir, (String) null); + Path downloadArchive(URI uri, Path dir) throws IOException { + return download(uri, dir, (String) null); } /** * Effectively download. Synchronised in order to avoid downloading twice in * parallel. */ - synchronized Path download(URL url, Path dir, String name) throws IOException { + synchronized Path download(URI uri, Path dir, String name) throws IOException { Path dest; if (name == null) { // We use also use parent directory in case the archive itself has a fixed name - String[] segments = url.getPath().split("/"); + String[] segments = uri.getPath().split("/"); name = segments.length > 1 ? segments[segments.length - 2] + '-' + segments[segments.length - 1] : segments[segments.length - 1]; } dest = dir.resolve(name); if (Files.exists(dest)) { - logger.log(TRACE, () -> "File " + dest + " already exists for " + url + ", not downloading again"); + logger.log(TRACE, () -> "File " + dest + " already exists for " + uri + ", not downloading again"); return dest; } else { Files.createDirectories(dest.getParent()); } - try (InputStream in = url.openStream()) { + try (InputStream in = uri.toURL().openStream()) { Files.copy(in, dest); - logger.log(DEBUG, () -> "Downloaded " + dest + " from " + url); + logger.log(DEBUG, () -> "Downloaded " + dest + " from " + uri); } return dest; } @@ -1633,14 +1648,9 @@ class M2ConventionsUtils { } /** Absolute path to the file */ - static URL mavenRepoUrl(String repoBase, M2Artifact artifact) { - String url = artifactUrl(repoBase == null ? MAVEN_CENTRAL_BASE_URL : repoBase, artifact); - try { - return new URL(url); - } catch (MalformedURLException e) { - // it should not happen - throw new IllegalStateException(e); - } + static URI mavenRepoUrl(String repoBase, M2Artifact artifact) throws URISyntaxException { + String uri = artifactUrl(repoBase == null ? MAVEN_CENTRAL_BASE_URL : repoBase, artifact); + return new URI(uri); } /** Absolute path to the directories where the files will be stored */