X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=src%2Forg%2Fargeo%2Fbuild%2FMake.java;h=78310597c15a4982f03dccbaa2b2ecf35965adb2;hb=1d38b1c8155f35271cf20217167eb6901df25272;hp=4d9caf93145e8bc717bf90c415519896a9cf174b;hpb=3bf6a139f456ff71bec3bc61d8cd14a1d058133a;p=cc0%2Fargeo-build.git diff --git a/src/org/argeo/build/Make.java b/src/org/argeo/build/Make.java index 4d9caf9..7831059 100644 --- a/src/org/argeo/build/Make.java +++ b/src/org/argeo/build/Make.java @@ -1,7 +1,9 @@ package org.argeo.build; +import static java.lang.System.Logger.Level.DEBUG; import static java.lang.System.Logger.Level.ERROR; import static java.lang.System.Logger.Level.INFO; +import static java.lang.System.Logger.Level.WARNING; import java.io.File; import java.io.IOException; @@ -21,12 +23,14 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Properties; import java.util.StringJoiner; import java.util.StringTokenizer; +import java.util.TreeMap; import java.util.concurrent.CompletableFuture; import java.util.jar.Attributes; import java.util.jar.JarEntry; @@ -52,10 +56,17 @@ public class Make { private final static Logger logger = System.getLogger(Make.class.getName()); /** - * Environment properties on whether sources should be packaged separately or + * Environment variable on whether sources should be packaged separately or * integrated in the bundles. */ - private final static String ENV_BUILD_SOURCE_BUNDLES = "BUILD_SOURCE_BUNDLES"; + private final static String ENV_SOURCE_BUNDLES = "SOURCE_BUNDLES"; + + /** + * Environment variable to override the default location for the Argeo Build + * configuration files. Typically used if Argeo Build has been compiled and + * packaged separately. + */ + private final static String ENV_ARGEO_BUILD_CONFIG = "ARGEO_BUILD_CONFIG"; /** Name of the local-specific Makefile (sdk.mk). */ final static String SDK_MK = "sdk.mk"; @@ -77,19 +88,17 @@ public class Make { final Path buildBase; /** The base of the a2 output for all layers. */ final Path a2Output; + /** The base of the a2 sources when packages separately. */ + final Path a2srcOutput; /** Whether sources should be packaged separately */ final boolean sourceBundles; /** Constructor initialises the base directories. */ public Make() throws IOException { - if (System.getenv(ENV_BUILD_SOURCE_BUNDLES) != null) { - sourceBundles = Boolean.parseBoolean(System.getenv(ENV_BUILD_SOURCE_BUNDLES)); - if (sourceBundles) - logger.log(Level.INFO, "Sources will be packaged separately"); - } else { - sourceBundles = true; - } + sourceBundles = Boolean.parseBoolean(System.getenv(ENV_SOURCE_BUNDLES)); + if (sourceBundles) + logger.log(Level.INFO, "Sources will be packaged separately"); execDirectory = Paths.get(System.getProperty("user.dir")); Path sdkMkP = findSdkMk(execDirectory); @@ -99,13 +108,26 @@ public class Make { sdkSrcBase = Paths.get(context.computeIfAbsent("SDK_SRC_BASE", (key) -> { throw new IllegalStateException(key + " not found"); })).toAbsolutePath(); - argeoBuildBase = sdkSrcBase.resolve("sdk/argeo-build"); + + Path argeoBuildBaseT = sdkSrcBase.resolve("sdk/argeo-build"); + if (!Files.exists(argeoBuildBaseT)) { + String fromEnv = System.getenv(ENV_ARGEO_BUILD_CONFIG); + if (fromEnv != null) + argeoBuildBaseT = Paths.get(fromEnv); + if (fromEnv == null || !Files.exists(argeoBuildBaseT)) { + throw new IllegalStateException( + "Argeo Build not found. Did you initialise the git submodules or set the " + + ENV_ARGEO_BUILD_CONFIG + " environment variable?"); + } + } + argeoBuildBase = argeoBuildBaseT; sdkBuildBase = Paths.get(context.computeIfAbsent("SDK_BUILD_BASE", (key) -> { throw new IllegalStateException(key + " not found"); })).toAbsolutePath(); buildBase = sdkBuildBase.resolve(sdkSrcBase.getFileName()); a2Output = sdkBuildBase.resolve("a2"); + a2srcOutput = sdkBuildBase.resolve("a2.src"); } /* @@ -127,7 +149,7 @@ public class Make { List a2Categories = options.getOrDefault("--dep-categories", new ArrayList<>()); List a2Bases = options.getOrDefault("--a2-bases", new ArrayList<>()); - if (a2Bases.isEmpty()) { + if (a2Bases.isEmpty() || !a2Bases.contains(a2Output.toString())) { a2Bases.add(a2Output.toString()); } @@ -138,20 +160,39 @@ public class Make { // classpath if (!a2Categories.isEmpty()) { - StringJoiner classPath = new StringJoiner(File.pathSeparator); - StringJoiner modulePath = new StringJoiner(File.pathSeparator); + // We will keep only the highest major.minor + // and order by bundle name, for predictability + Map a2Jars = new TreeMap<>(); + +// StringJoiner modulePath = new StringJoiner(File.pathSeparator); for (String a2Base : a2Bases) { - for (String a2Category : a2Categories) { + categories: for (String a2Category : a2Categories) { Path a2Dir = Paths.get(a2Base).resolve(a2Category); if (!Files.exists(a2Dir)) - Files.createDirectories(a2Dir); - modulePath.add(a2Dir.toString()); + continue categories; +// modulePath.add(a2Dir.toString()); for (Path jarP : Files.newDirectoryStream(a2Dir, (p) -> p.getFileName().toString().endsWith(".jar"))) { - classPath.add(jarP.toString()); + A2Jar a2Jar = new A2Jar(jarP); + if (a2Jars.containsKey(a2Jar.name)) { + 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) + a2Jars.put(a2Jar.name, a2Jar); + } else { + a2Jars.put(a2Jar.name, a2Jar); + } } } } + + StringJoiner classPath = new StringJoiner(File.pathSeparator); + for (Iterator it = a2Jars.values().iterator(); it.hasNext();) + classPath.add(it.next().path.toString()); + compilerArgs.add("-cp"); compilerArgs.add(classPath.toString()); // compilerArgs.add("--module-path"); @@ -162,8 +203,14 @@ public class Make { for (String bundle : bundles) { StringBuilder sb = new StringBuilder(); Path bundlePath = execDirectory.resolve(bundle); - if (!Files.exists(bundlePath)) - throw new IllegalArgumentException("Bundle " + bundle + " not found in " + execDirectory); + if (!Files.exists(bundlePath)) { + if (bundles.size() == 1) { + logger.log(WARNING, "Bundle " + bundle + " not found in " + execDirectory + + ", assuming this is this directory, as only one bundle was requested."); + bundlePath = execDirectory; + } else + throw new IllegalArgumentException("Bundle " + bundle + " not found in " + execDirectory); + } sb.append(bundlePath.resolve("src")); sb.append("[-d"); compilerArgs.add(sb.toString()); @@ -176,8 +223,11 @@ public class Make { if (logger.isLoggable(INFO)) compilerArgs.add("-time"); -// for (String arg : compilerArgs) -// System.out.println(arg); + if (logger.isLoggable(DEBUG)) { + logger.log(DEBUG, "Compiler arguments:"); + for (String arg : compilerArgs) + logger.log(DEBUG, arg); + } boolean success = org.eclipse.jdt.core.compiler.batch.BatchCompiler.compile( compilerArgs.toArray(new String[compilerArgs.size()]), new PrintWriter(System.out), @@ -226,12 +276,17 @@ public class Make { logger.log(INFO, "Packaging took " + duration + " ms"); } - /* - * UTILITIES - */ /** Package a single bundle. */ void createBundle(String branch, String bundle, String category) throws IOException { - Path source = execDirectory.resolve(bundle); + final Path source; + if (!Files.exists(execDirectory.resolve(bundle))) { + logger.log(WARNING, + "Bundle " + bundle + " not found in " + execDirectory + ", assuming this is this directory."); + source = execDirectory; + } else { + source = execDirectory.resolve(bundle); + } + Path compiled = buildBase.resolve(bundle); String bundleSymbolicName = source.getFileName().toString(); @@ -356,7 +411,11 @@ public class Make { // TODO add effective BND, Eclipse project file, etc., in order to be able to // repackage if (sourceBundles) { - Path srcJarP = a2JarDirectory.resolve(compiled.getFileName() + "." + major + "." + minor + ".src.jar"); + Path a2srcJarDirectory = bundleParent != null ? a2srcOutput.resolve(bundleParent).resolve(category) + : a2srcOutput.resolve(category); + Files.createDirectories(a2srcJarDirectory); + Path srcJarP = a2srcJarDirectory + .resolve(compiled.getFileName() + "." + major + "." + minor + ".src.jar"); Manifest srcManifest = new Manifest(); srcManifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); srcManifest.getMainAttributes().putValue("Bundle-SymbolicName", bundleSymbolicName + ".src"); @@ -374,6 +433,10 @@ public class Make { } } + /* + * UTILITIES + */ + /** Add sources to a jar file */ void copySourcesToJar(Path srcP, JarOutputStream srcJarOut, String prefix) throws IOException { Files.walkFileTree(srcP, new SimpleFileVisitor() { @Override @@ -466,6 +529,23 @@ public class Make { } } + static class A2Jar { + final Path path; + final String name; + final int major; + final int minor; + + A2Jar(Path path) { + this.path = path; + String fileName = path.getFileName().toString(); + fileName = fileName.substring(0, fileName.lastIndexOf('.')); + minor = Integer.parseInt(fileName.substring(fileName.lastIndexOf('.') + 1)); + fileName = fileName.substring(0, fileName.lastIndexOf('.')); + major = Integer.parseInt(fileName.substring(fileName.lastIndexOf('.') + 1)); + name = fileName.substring(0, fileName.lastIndexOf('.')); + } + } + /** * An ECJ {@link CompilationProgress} printing a progress bar while compiling. */