BUILD: WEB: Supported hybrid multi app 43/11843/3
authorTaeyoung Son <taeyoung2.son@samsung.com>
Mon, 7 Oct 2013 06:14:49 +0000 (15:14 +0900)
committerTaeyoung Son <taeyoung2.son@samsung.com>
Thu, 14 Nov 2013 10:41:51 +0000 (19:41 +0900)
Supported building hybrid multi app.
Modified web-build cli's option.
Added NativeMultiPackager class.
Added build/install dependency for using native multi packager

Signed-off-by: Taeyoung Son <taeyoung2.son@samsung.com>
Conflicts:

package/pkginfo.manifest

Change-Id: I795968f7f3478239a3012c9dc1c2f6ea2579316c

org.tizen.cli/src/org/tizen/cli/exec/pack/CLIMultiPackager.java
org.tizen.cli/src/org/tizen/cli/exec/web/build/Main.java
org.tizen.cli/src/org/tizen/cli/exec/web/build/NativeMultiPackager.java [new file with mode: 0644]
package/build.linux
package/pkginfo.manifest

index f105f6e..67ed20b 100644 (file)
@@ -37,15 +37,19 @@ import org.tizen.nativecpp.misc.core.NewAppXmlStore;
 public class CLIMultiPackager extends AbstractMultiPackager{
 
     public static final String BIN_FOLDER_NAME = "CommandLineBuild";
-    private String rootPrjPath;
-    private String[] refPrjPath;
-    
-    CLIMultiPackager(String rootPrjPath, String[] refPrjPath, Executor executor) {
-        super(executor);
+    protected String rootPrjPath;
+    protected String[] refPrjPath;
+
+    public CLIMultiPackager(String outputPath, String rootPrjPath, String[] refPrjPath, Executor executor) {
+        super(executor, outputPath);
         this.rootPrjPath = rootPrjPath;
         this.refPrjPath = refPrjPath;
     }
-    
+
+    public CLIMultiPackager(String rootPrjPath, String[] refPrjPath, Executor executor) {
+        this(null, rootPrjPath, refPrjPath, executor);
+    }
+
     @Override
     protected String getBinaryFolder() {
         return BIN_FOLDER_NAME;
index dd2118e..c5afc84 100755 (executable)
@@ -36,12 +36,14 @@ import org.apache.commons.cli.Options;
 import org.apache.tools.ant.BuildException;
 import org.tizen.cli.exec.AbstractLauncher;
 import org.tizen.cli.exec.Help;
+import org.tizen.cli.exec.pack.CLIMultiPackager;
 import org.tizen.common.FactoryWithArgument;
 import org.tizen.common.builder.BuildProcess;
 import org.tizen.common.builder.Builder;
 import org.tizen.common.builder.Resource;
 import org.tizen.common.builder.ResourceLayer;
 import org.tizen.common.builder.core.CopyBuilder;
+import org.tizen.common.core.command.CommandCancelException;
 import org.tizen.common.file.FileHandler;
 import org.tizen.common.file.FileHandler.Attribute;
 import org.tizen.common.file.Filter;
@@ -72,7 +74,9 @@ extends AbstractLauncher
     private static final String SUCCEED_MSG = "Build completed. In sequence you can sign on your build output folder(default:{0}) using the web-signing command.";
     
     private String cwd = ".";
-    private String output = ".buildResult"; //default output directory
+
+    private String BUILD_DEFAULT_OUTPUT =  ".buildResult";
+    private String output = BUILD_DEFAULT_OUTPUT; //default output directory
 
     private SimpleFileFilter filter = new SimpleFileFilter(true);
     private FactoryWithArgument<Filter, String> filterFactory = new WildCardFilterFactory();
@@ -109,15 +113,18 @@ extends AbstractLauncher
     protected static final String RESOURCE_LAYER_END = "end";
 
     // file filter. If you want to exclude a directory, append '/*'
-    private static final String[] DEFAULT_EXCLUDES = {".build"+File.separator+"*"
+    private static final String[] DEFAULT_EXCLUDES = {".build/*"
                                                     , ".project"
-                                                    , ".settings" + File.separator + "*"
+                                                    , ".settings/*"
                                                     , ".sdk_delta.info"
-                                                    , "*.wgt"};
+                                                    , "*.wgt"
+                                                    , ".buildResult/*"};
 
     // excluding file list
     private List<String> excludes = new ArrayList<String>();
 
+    private String[] referenceProjects = null;
+
     /**
      * Entry point for cli main
      * 
@@ -160,7 +167,6 @@ extends AbstractLauncher
      * @see org.tizen.cli.exec.AbstractLauncher#execute(org.apache.commons.cli.CommandLine)
      */
     @Override
-    @SuppressWarnings("unchecked")
     protected
     void
     execute(
@@ -168,13 +174,59 @@ extends AbstractLauncher
             )
                     throws Exception
                     {
+        init(cmdLine);
+
+        CLIMultiPackager nativePackager = null;
+
+        nativePackager = createNativeMultiAppStructure(output,  getReferenceProjects());
+
+        BuildProcess buildProcess = new BuildProcess();
+
+        // Set start layer
+        FileHandler fh = new StandardFileHandler();
+        fh.setCurrentWorkingDirectory(cwd);
+        ResourceLayer startLayer = new ResourceLayer(RESOURCE_LAYER_START, fh);
+
+        // Get resource list for build
+        Resource[] resources = getBuildResources(cmdLine
+                                                , startLayer
+                                                , null
+                                                , excludes.toArray(new String[excludes.size()]));
+
+        // Generate web builders to build process
+        generateAllBuilders(cmdLine, buildProcess, startLayer);
+
+        if (buildProcess.getLastBuilder() != null) {
+            logger.debug("start build process");
+            try {
+                buildProcess.build(resources);
+            } catch (MinifyException e) {
+                StringBuffer msg = new StringBuffer();
+                msg.append("Optimization failed.\n");
+                msg.append("Error: "+ e.getPath()+"("+e.getLineNumber()+"): "+e.getLineSource()+"\n");
+                msg.append("Cause: "+e.getMessage()+"\n");
+                getPrompter().notify(msg.toString());
+                return;
+            }
+
+            if (nativePackager != null) {
+                nativePackager.removeMutilAppResources();
+            }
+
+            // check succeeding status.
+            checkProcessComplete( buildProcess );
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private void init(CommandLine cmdLine) throws Exception{
         final List<String> args = cmdLine.getArgList();
         logger.trace( "arguments :{}", args );
 
         // input path's argument will be set.
         if (args.size() < 1) {
             printHelp();
-            return;
+            throw new BuildException("Could not find project path.");
         }
 
         // set absolute path
@@ -197,40 +249,70 @@ extends AbstractLauncher
             logger.info( "{} directory deleted", output);
         }
 
+        if (!FileUtil.createDirectory(output)) {
+            throw new BuildException("Could not create "+output+" directory...");
+        }
+
         // Set exclude file list
         initExcludes(cmdLine);
+        setReferenceProjects(cmdLine);
+    }
 
-        BuildProcess buildProcess = new BuildProcess();
+    /**
+     * Create native multi application structure.
+     * @param output output path
+     * @param refProjectPaths array's first value is root reference project.
+     * @return If <code>refProjectPaths</code>'s length is 1, it return null. or, it return {@link CLIMultiPackager}.
+     * @throws Exception
+     */
+    private CLIMultiPackager createNativeMultiAppStructure(String output, String ... refProjectPaths) throws Exception {
+        if ((refProjectPaths == null)
+                || (refProjectPaths.length <= 1)) {
+            return null;
+        }
 
-        // Set start layer
-        FileHandler fh = new StandardFileHandler();
-        fh.setCurrentWorkingDirectory(cwd);
-        ResourceLayer startLayer = new ResourceLayer(RESOURCE_LAYER_START, fh);
-        
-        // Get resource list for build
-        Resource[] resources = getBuildResources(cmdLine
-                                                , startLayer
-                                                , null
-                                                , excludes.toArray(new String[excludes.size()]));
+        String rootRefProjectPath = refProjectPaths[0];
 
-        // Generate web builders to build process
-        generateAllBuilders(cmdLine, buildProcess, startLayer);
-        if (buildProcess.getLastBuilder() != null) {
-            logger.debug("start build process");
-            try {
-                buildProcess.build(resources);
-            } catch (MinifyException e) {
-                StringBuffer msg = new StringBuffer();
-                msg.append("Optimization failed.\n");
-                msg.append("Error: "+ e.getPath()+"("+e.getLineNumber()+"): "+e.getLineSource()+"\n");
-                msg.append("Cause: "+e.getMessage()+"\n");
-                getPrompter().notify(msg.toString());
-                return;
-            }
+        List<String> subRefProjectPaths = new ArrayList<String>();
+        for (int i=1;i<refProjectPaths.length;i++) {
+            subRefProjectPaths.add(refProjectPaths[i]);
+        }
 
-            // check succeeding status.
-            checkProcessComplete( buildProcess );
+        CLIMultiPackager packager = new NativeMultiPackager(output, rootRefProjectPath, subRefProjectPaths.toArray(new String[0]), getExecutor());
+        try {
+            packager.doMultiPreProcess();
         }
+        catch (CommandCancelException e) {
+            packager.removeMutilAppResources();
+            throw new BuildException(e);
+        }
+        return packager;
+    }
+
+    /**
+     * Set reference project path list
+     * @param cmdLine
+     * @throws IOException
+     */
+    private void setReferenceProjects(CommandLine cmdLine) throws IOException {
+        if (cmdLine.hasOption(OPT_NAME_REFERENCE_PROJECT)) {
+            String refPathValue = cmdLine.getOptionValue(OPT_NAME_REFERENCE_PROJECT);
+            String[] refPaths = refPathValue.split("\\s*,\\s*");
+            for (int i=0; i<refPaths.length; i++) {
+                refPaths[i] = convertPath(refPaths[i]);
+            }
+            referenceProjects = refPaths;
+        } else {
+            referenceProjects = new String[]{};
+        }
+    }
+
+    /**
+     * Get reference project path list
+     * @return reference project path list.
+     */
+    private String[] getReferenceProjects() {
+        return this.referenceProjects;
     }
 
     /**
@@ -343,9 +425,15 @@ extends AbstractLauncher
         ResourceLayer layer = new ResourceLayer(HybridAppCLIBuilder.RESOURCE_LAYER_NAME
                                                     , lastLayer
                                                     , fh);
-        
-        String refPath = convertPath(cmdLine.getOptionValue(OPT_NAME_REFERENCE_PROJECT));
-        
+        String refPath = null;
+        String[] refProjects = getReferenceProjects();
+        if ((refProjects != null)
+                && (refProjects.length > 1)) {
+            refPath = FileUtil.appendPath(output, NativeMultiPackager.FOLDER_MULTIAPP_TEMP);
+        } else {
+            refPath = convertPath(cmdLine.getOptionValue(OPT_NAME_REFERENCE_PROJECT));
+        }
+
         HybridAppCLIBuilder hybridAppBuilder = new HybridAppCLIBuilder( layer, refPath );
         buildProcess.addBuilder(hybridAppBuilder);
     }
@@ -427,11 +515,18 @@ extends AbstractLauncher
             ResourceLayer referenceLayer = new ResourceLayer(HybridAppCLIBuilder.RESOURCE_LAYER_REFERENCE_NAME
                                                                 , refFh);
             layer.setParent(referenceLayer);
-            String refPath = convertPath(cmdLine.getOptionValue(OPT_NAME_REFERENCE_PROJECT));
-            refFh.setCurrentWorkingDirectory(refPath);
+            String refRootPath = null;
+            String[] refProjects = getReferenceProjects();
+            if ((refProjects != null)
+                    && refProjects.length > 1) {
+                refRootPath = FileUtil.appendPath(output, NativeMultiPackager.FOLDER_MULTIAPP_TEMP);
+            } else {
+                refRootPath = convertPath(cmdLine.getOptionValue(OPT_NAME_REFERENCE_PROJECT));
+            }
+            refFh.setCurrentWorkingDirectory(refRootPath);
 
-            resources.addAll(getResources(refPath
-                                            , FilenameUtil.getRelativePath(refPath, refPath)
+            resources.addAll(getResources(refRootPath
+                                            , FilenameUtil.getRelativePath(refRootPath, refRootPath)
                                             , referenceLayer));
         }
 
diff --git a/org.tizen.cli/src/org/tizen/cli/exec/web/build/NativeMultiPackager.java b/org.tizen.cli/src/org/tizen/cli/exec/web/build/NativeMultiPackager.java
new file mode 100644 (file)
index 0000000..c2e78f5
--- /dev/null
@@ -0,0 +1,154 @@
+package org.tizen.cli.exec.web.build;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.tools.ant.BuildException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.tizen.cli.exec.pack.CLIMultiPackager;
+import org.tizen.common.TizenPlatformConstants;
+import org.tizen.common.core.command.CommandCancelException;
+import org.tizen.common.core.command.Executor;
+import org.tizen.common.util.FileUtil;
+import org.tizen.nativecpp.misc.core.NewAppXmlStore;
+import org.tizen.web.builder.HybridAppCLIBuilder;
+
+public class NativeMultiPackager extends CLIMultiPackager {
+    Logger logger = LoggerFactory.getLogger(getClass());
+
+    public static final String FILE_NAME_MANIFEST = TizenPlatformConstants.MANIFEST_XML_FILE_NAME;
+
+    public NativeMultiPackager(String outputPath, String rootPrjPath, String[] refPrjPath,
+            Executor executor) {
+        super(outputPath, rootPrjPath, refPrjPath, executor);
+    }
+    
+    @Override
+    protected void mergeApplicationXML() throws Exception{
+        super.mergeApplicationXML();
+
+        //Rename multi manifest file
+        String srcPath = FileUtil.appendPath(getOutputPath(), FILE_NAME_MULTI_MANIFEST);
+        String destPath = FileUtil.appendPath(getOutputPath(), FOLDER_MULTIAPP_TEMP);
+        File destDir = new File(destPath);
+        destDir.mkdir();
+
+        destPath = FileUtil.appendPath(destPath, FILE_NAME_MANIFEST);
+
+        File srcFile = new File(srcPath);
+        srcFile.renameTo(new File(destPath));
+    }
+    
+    @Override
+    protected void copyBinaries() throws IOException {
+        super.copyBinaries();
+
+        // copy root reference project's binaries.
+        String tempMultiPath = FileUtil.appendPath(getOutputPath(), FOLDER_MULTIAPP_TEMP);
+        String tempBinPath = FileUtil.appendPath(tempMultiPath, FOLDER_MULTIAPP_TEMP_BIN);
+        
+        File tempBinDir = new File(tempBinPath);
+        tempBinDir.mkdirs();
+
+        String rootPrjPath = getRootPrjPath();
+        List<String> binaryList = getExecutableBinaries(rootPrjPath);
+
+        String binaryFolder = getBinaryFolder(rootPrjPath);
+        String rootPrjBinaryFolder = FileUtil.appendPath(rootPrjPath, binaryFolder);
+
+        for(String binary: binaryList) {
+            String binaryName = binary + EXT_BINARY_EXECUTABLE;
+            String binaryPath = FileUtil.appendPath(rootPrjBinaryFolder, binaryName);
+            File binaryFile = new File(binaryPath);
+            if(!binaryFile.exists()) {
+                String message = String.format("binary file '%s' does not exist", binaryPath);
+                logger.error(message);
+                throw new CommandCancelException(message);
+            }
+            FileUtil.copyTo(binaryFile.getAbsolutePath(), FileUtil.appendPath(tempBinPath, binaryName));
+        }
+    }
+
+    /**
+     * Get executable binary list from manifest file
+     * @param rootPrjPath
+     * @return executable binary list
+     */
+    private List<String> getExecutableBinaries(String rootPrjPath) {
+        NewAppXmlStore store = new NewAppXmlStore();
+
+        String manifestPath = FileUtil.appendPath(rootPrjPath, FILE_NAME_MANIFEST);
+        store.setManifestFile(manifestPath);
+        store.loadXml();
+        return store.getExecutableNames();
+    }
+
+    @Override
+    public void doMultiPreProcess() throws Exception {
+        super.doMultiPreProcess();
+
+        //Rename folder
+        String tempOutputPath = FileUtil.appendPath(getOutputPath(), FOLDER_MULTIAPP_TEMP);
+
+        String srcPath = FileUtil.appendPath(tempOutputPath, FOLDER_MULTIAPP_TEMP_BIN);
+        String destPath = FileUtil.appendPath(tempOutputPath, FOLDER_BIN);
+        renameTo(srcPath, destPath);
+
+        srcPath = FileUtil.appendPath(tempOutputPath, FOLDER_MULTIAPP_TEMP_RES);
+        destPath = FileUtil.appendPath(tempOutputPath, FOLDER_RES);
+        renameTo(srcPath, destPath);
+
+        srcPath = FileUtil.appendPath(tempOutputPath, FOLDER_MULTIAPP_TEMP_DATA);
+        destPath = FileUtil.appendPath(tempOutputPath, FOLDER_DATA);
+        renameTo(srcPath, destPath);
+
+        srcPath = FileUtil.appendPath(tempOutputPath, FOLDER_MULTIAPP_TEMP_SHARE);
+        destPath = FileUtil.appendPath(tempOutputPath, FOLDER_SHARE);
+        renameTo(srcPath, destPath);
+    }
+
+    /**
+     * rename directory or file
+     * @param srcPath
+     * @param destPath
+     */
+    private void renameTo(String srcPath, String destPath) {
+        if ((srcPath==null)
+                || (destPath==null)) {
+            throw new BuildException("Could not rename path");
+        }
+
+        File srcFile = new File(srcPath);
+        if (srcFile.exists() && (!srcFile.renameTo(new File(destPath)))) {
+            throw new BuildException("Could not rename path");
+        }
+    }
+
+    /**
+     * Get binary folder
+     * @param prjPath project's root path
+     * @return binary folder what have latest binary file.
+     *          If the project does not have binary file, it return default binary folder.
+     */
+    @Override
+    protected String getBinaryFolder(String prjPath) {
+        List<String> binaryList = getExecutableBinaries(prjPath);
+        String result = BIN_FOLDER_NAME; 
+        long tmpDate = 0;
+
+        for (String tmpBin : HybridAppCLIBuilder.NATIVE_BINARY_FOLDER) {
+            String binaryDir = FileUtil.appendPath(prjPath, tmpBin);
+            for (int i=0; i<binaryList.size(); i++) {
+                String binaryFullPath = FileUtil.appendPath(binaryDir, binaryList.get(i)+EXT_BINARY_EXECUTABLE);
+                File f = new File(binaryFullPath);
+                if (f.exists() && (f.lastModified()>tmpDate)) {
+                    tmpDate = f.lastModified();
+                    result = tmpBin;
+                }
+            }
+        }
+        return result;
+    }
+}
index 10fd8a7..9126836 100755 (executable)
@@ -81,6 +81,8 @@ build()
     org.tizen.common.verrari_*
     org.tizen.common.verrari.realm_*
     org.tizen.common.sdblib_*
+    org.tizen.nativecommon_*
+    org.tizen.nativecpp.misc_*
     org.tizen.web.builder_*
     org.tizen.web.compressor.minifier.core_*
     org.tizen.web.zimlaunch_*
index aa36c5e..ba49448 100644 (file)
@@ -4,36 +4,36 @@ Maintainer: Bon-Yong Lee<bonyong.lee@samsung.com>, gyeongseok seo <gyeongseok.se
 Package: web-cli
 OS: ubuntu-32
 Build-host-os: ubuntu-32
-Build-dependency: webapp-eplugin [ubuntu-32], base-ide-product [ubuntu-32], common-eplugin [ubuntu-32]
-Install-dependency: sdb [ubuntu-32]
+Build-dependency: webapp-eplugin [ubuntu-32], base-ide-product [ubuntu-32], common-eplugin [ubuntu-32], nativecommon-eplugin [ubuntu-32], nativecpp-ext-eplugin [ubuntu-32]
+Install-dependency: sdb [ubuntu-32], web-ui-fw [ubuntu-32]
 Description: Tizen IDE Command Line Interface
 
 Package: web-cli
 OS: ubuntu-64
 Build-host-os: ubuntu-64
-Build-dependency: webapp-eplugin [ubuntu-64], base-ide-product [ubuntu-64], common-eplugin [ubuntu-64]
-Install-dependency: sdb [ubuntu-64]
+Build-dependency: webapp-eplugin [ubuntu-64], base-ide-product [ubuntu-64], common-eplugin [ubuntu-64], nativecommon-eplugin [ubuntu-64], nativecpp-ext-eplugin [ubuntu-64]
+Install-dependency: sdb [ubuntu-64], web-ui-fw [ubuntu-64]
 Description: Tizen IDE Command Line Interface
 
 Package: web-cli
 OS: windows-32
 Build-host-os: ubuntu-32
-Build-dependency: webapp-eplugin [windows-32], base-ide-product [windows-32], common-eplugin [windows-32]
-Install-dependency: sdb [windows-32]
+Build-dependency: webapp-eplugin [windows-32], base-ide-product [windows-32], common-eplugin [windows-32], nativecommon-eplugin [windows-32], nativecpp-ext-eplugin [windows-32]
+Install-dependency: sdb [windows-32], web-ui-fw [windows-32]
 Description: Tizen IDE Command Line Interface
 
 Package: web-cli
 OS: windows-64
 Build-host-os: ubuntu-64
-Build-dependency: webapp-eplugin [windows-64], base-ide-product [windows-64], common-eplugin [windows-64]
-Install-dependency: sdb [windows-64]
+Build-dependency: webapp-eplugin [windows-64], base-ide-product [windows-64], common-eplugin [windows-64], nativecommon-eplugin [windows-64], nativecpp-ext-eplugin [windows-64]
+Install-dependency: sdb [windows-64], web-ui-fw [windows-64]
 Description: Tizen IDE Command Line Interface
 
 Package: web-cli
 OS: macos-64
 Build-host-os: ubuntu-64
-Build-dependency: webapp-eplugin [macos-64], base-ide-product [macos-64], common-eplugin [macos-64]
-Install-dependency: sdb [macos-64]
+Build-dependency: webapp-eplugin [macos-64], base-ide-product [macos-64], common-eplugin [macos-64], nativecommon-eplugin [macos-64], nativecpp-ext-eplugin [macos-64]
+Install-dependency: sdb [macos-64], web-ui-fw [macos-64]
 Description: Tizen IDE Command Line Interface
 
 Package: native-cli