--- /dev/null
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
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
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
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
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
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
--- /dev/null
+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
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
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)
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
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
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
major=2
minor=1
micro=5
-qualifier=
+qualifier=.next
SPDX-License-Identifier=CC0-1.0
\ No newline at end of file
major=2
minor=3
-micro=9
+micro=10
qualifier=
SPDX-License-Identifier=CC0-1.0
\ No newline at end of file
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;
List<String> a2Categories = options.getOrDefault("--dep-categories", new ArrayList<>());
List<String> 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());
}
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);
}
logger.log(DEBUG, "Packaging took " + duration + " ms");
}
- /** Install the bundles. */
+ /** Install or uninstall bundles and native output. */
void install(Map<String, List<String>> options, boolean uninstall) throws IOException {
+ final String LIB_ = "lib/";
+ final String NATIVE_ = "native/";
+
// check arguments
- List<String> bundles = options.get("--bundles");
- Objects.requireNonNull(bundles, "--bundles argument must be set");
+ List<String> bundles = multiArg(options, "--bundles", true);
if (bundles.isEmpty())
return;
-
- List<String> 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<String> 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);
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);
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);
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<String, List<String>> options, String arg, boolean mandatory) {
+ List<String> 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<String> multiArg(Map<String, List<String>> options, String arg, boolean mandatory) {
+ List<String> 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());
}
}
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;
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;
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
/** 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"), //
: 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);
? 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));
}
/*
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));
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);
}
for (Iterator<Map.Entry<Object, Object>> manifestEntries = manifest.getMainAttributes().entrySet()
.iterator(); manifestEntries.hasNext();) {
Map.Entry<Object, Object> 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":
}
/** 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<String> 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;
}
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;
}
}
/** 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 */