]> git.argeo.org Git - cc0/argeo-build.git/blobdiff - src/org/argeo/build/Make.java
Store source bundles separately
[cc0/argeo-build.git] / src / org / argeo / build / Make.java
index d9e61d6d1faa8f38087170adab71dcd59b86c820..97318ab610d5abc44caa4e7df77c9ad7d37d6b31 100644 (file)
@@ -28,9 +28,11 @@ import java.util.Properties;
 import java.util.StringJoiner;
 import java.util.StringTokenizer;
 import java.util.concurrent.CompletableFuture;
+import java.util.jar.Attributes;
 import java.util.jar.JarEntry;
 import java.util.jar.JarOutputStream;
 import java.util.jar.Manifest;
+import java.util.zip.Deflater;
 
 import org.eclipse.jdt.core.compiler.CompilationProgress;
 
@@ -49,6 +51,12 @@ import aQute.bnd.osgi.Jar;
 public class Make {
        private final static Logger logger = System.getLogger(Make.class.getName());
 
+       /**
+        * Environment properties on whether sources should be packaged separately or
+        * integrated in the bundles.
+        */
+       private final static String ENV_BUILD_SOURCE_BUNDLES = "BUILD_SOURCE_BUNDLES";
+
        /** Name of the local-specific Makefile (sdk.mk). */
        final static String SDK_MK = "sdk.mk";
        /** Name of the branch definition Makefile (branch.mk). */
@@ -69,9 +77,18 @@ 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 {
+               sourceBundles = Boolean.parseBoolean(System.getenv(ENV_BUILD_SOURCE_BUNDLES));
+               if (sourceBundles)
+                       logger.log(Level.INFO, "Sources will be packaged separately");
+
                execDirectory = Paths.get(System.getProperty("user.dir"));
                Path sdkMkP = findSdkMk(execDirectory);
                Objects.requireNonNull(sdkMkP, "No " + SDK_MK + " found under " + execDirectory);
@@ -87,6 +104,7 @@ public class Make {
                })).toAbsolutePath();
                buildBase = sdkBuildBase.resolve(sdkSrcBase.getFileName());
                a2Output = sdkBuildBase.resolve("a2");
+               a2srcOutput = sdkBuildBase.resolve("a2.src");
        }
 
        /*
@@ -181,12 +199,14 @@ public class Make {
                        throw new IllegalArgumentException("One and only one --category must be specified");
                String category = categories.get(0);
 
+               final String branch;
                Path branchMk = sdkSrcBase.resolve(BRANCH_MK);
-               if (!Files.exists(branchMk))
-                       throw new IllegalStateException("No " + branchMk + " file available");
-               Map<String, String> branchVariables = readeMakefileVariables(branchMk);
-
-               String branch = branchVariables.get("BRANCH");
+               if (Files.exists(branchMk)) {
+                       Map<String, String> branchVariables = readeMakefileVariables(branchMk);
+                       branch = branchVariables.get("BRANCH");
+               } else {
+                       branch = null;
+               }
 
                long begin = System.currentTimeMillis();
                // create jars in parallel
@@ -221,18 +241,23 @@ public class Make {
                        properties.load(in);
                }
 
-               Path branchBnd = sdkSrcBase.resolve("sdk/branches/" + branch + ".bnd");
-               try (InputStream in = Files.newInputStream(branchBnd)) {
-                       properties.load(in);
+               if (branch != null) {
+                       Path branchBnd = sdkSrcBase.resolve("sdk/branches/" + branch + ".bnd");
+                       if (Files.exists(branchBnd))
+                               try (InputStream in = Files.newInputStream(branchBnd)) {
+                                       properties.load(in);
+                               }
                }
 
                Path bndBnd = source.resolve("bnd.bnd");
-               try (InputStream in = Files.newInputStream(bndBnd)) {
-                       properties.load(in);
-               }
+               if (Files.exists(bndBnd))
+                       try (InputStream in = Files.newInputStream(bndBnd)) {
+                               properties.load(in);
+                       }
 
                // Normalise
-               properties.put("Bundle-SymbolicName", bundleSymbolicName);
+               if (!properties.containsKey("Bundle-SymbolicName"))
+                       properties.put("Bundle-SymbolicName", bundleSymbolicName);
 
                // Calculate MANIFEST
                Path binP = compiled.resolve("bin");
@@ -275,6 +300,7 @@ public class Make {
                Files.createDirectories(jarP.getParent());
 
                try (JarOutputStream jarOut = new JarOutputStream(Files.newOutputStream(jarP), manifest)) {
+                       jarOut.setLevel(Deflater.DEFAULT_COMPRESSION);
                        // add all classes first
                        Files.walkFileTree(binP, new SimpleFileVisitor<Path>() {
                                @Override
@@ -328,19 +354,41 @@ public class Make {
                        // add sources
                        // TODO add effective BND, Eclipse project file, etc., in order to be able to
                        // repackage
-                       Files.walkFileTree(srcP, new SimpleFileVisitor<Path>() {
-                               @Override
-                               public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
-                                       jarOut.putNextEntry(new JarEntry("OSGI-OPT/src/" + srcP.relativize(file).toString()));
-                                       if (!Files.isDirectory(file))
-                                               Files.copy(file, jarOut);
-                                       return FileVisitResult.CONTINUE;
+                       if (sourceBundles) {
+                               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");
+                               srcManifest.getMainAttributes().putValue("Bundle-Version",
+                                               manifest.getMainAttributes().getValue("Bundle-Version").toString());
+                               srcManifest.getMainAttributes().putValue("Eclipse-SourceBundle",
+                                               bundleSymbolicName + ";version=\"" + manifest.getMainAttributes().getValue("Bundle-Version"));
+
+                               try (JarOutputStream srcJarOut = new JarOutputStream(Files.newOutputStream(srcJarP), srcManifest)) {
+                                       copySourcesToJar(srcP, srcJarOut, "");
                                }
-                       });
-
+                       } else {
+                               copySourcesToJar(srcP, jarOut, "OSGI-OPT/src/");
+                       }
                }
        }
 
+       void copySourcesToJar(Path srcP, JarOutputStream srcJarOut, String prefix) throws IOException {
+               Files.walkFileTree(srcP, new SimpleFileVisitor<Path>() {
+                       @Override
+                       public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                               srcJarOut.putNextEntry(new JarEntry(prefix + srcP.relativize(file).toString()));
+                               if (!Files.isDirectory(file))
+                                       Files.copy(file, srcJarOut);
+                               return FileVisitResult.CONTINUE;
+                       }
+               });
+       }
+
        /**
         * Recursively find the base source directory (which contains the
         * <code>{@value #SDK_MK}</code> file).