OSDN Git Service

Support for aidl files in library project in the Ant build system.
authorXavier Ducrohet <xav@android.com>
Fri, 25 Jun 2010 22:11:17 +0000 (15:11 -0700)
committerXavier Ducrohet <xav@android.com>
Mon, 28 Jun 2010 19:18:41 +0000 (12:18 -0700)
Change-Id: I3e36e6f4db60d3d979b24c2b88d496f453394127

anttasks/src/com/android/ant/AaptExecLoopTask.java
anttasks/src/com/android/ant/AidlExecTask.java [new file with mode: 0644]
anttasks/src/com/android/ant/TaskHelper.java
files/ant/ant_lib_rules_r3.xml
files/ant/ant_rules_r3.xml

index f93a208..3e24295 100644 (file)
@@ -26,9 +26,12 @@ import java.io.File;
 import java.util.ArrayList;
 
 /**
- * Task able to run an Exec task on aapt several times.
+ * Task to execute aapt.
+ *
  * <p>It does not follow the exec task format, instead it has its own parameters, which maps
  * directly to aapt.</p>
+ * <p>It is able to run aapt several times if library setup requires generating several
+ * R.java files.
  * <p>The following map shows how to use the task for each supported aapt command line
  * parameter.</p>
  *
diff --git a/anttasks/src/com/android/ant/AidlExecTask.java b/anttasks/src/com/android/ant/AidlExecTask.java
new file mode 100644 (file)
index 0000000..862d745
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ant;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.ExecTask;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.PatternSet.NameEntry;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * Task to execute aidl.
+ * <p>
+ * It expects 3 attributes:<br>
+ * 'executable' ({@link Path} with a single path) for the location of the aidl executable<br>
+ * 'framework' ({@link Path} with a single path) for the "preprocessed" file containing all the
+ *     parcelables exported by the framework<br>
+ * 'genFolder' ({@link Path} with a single path) for the location of the gen folder.
+ *
+ * It also expects one or more inner elements called "source" which are identical to {@link Path}
+ * elements.
+ */
+public class AidlExecTask extends Task {
+
+    private String mExecutable;
+    private String mFramework;
+    private String mGenFolder;
+    private final ArrayList<Path> mPaths = new ArrayList<Path>();
+
+    /**
+     * Sets the value of the "executable" attribute.
+     * @param executable the value.
+     */
+    public void setExecutable(Path executable) {
+        mExecutable = TaskHelper.checkSinglePath("executable", executable);
+    }
+
+    public void setFramework(Path value) {
+        mFramework = TaskHelper.checkSinglePath("framework", value);
+    }
+
+    public void setGenFolder(Path value) {
+        mGenFolder = TaskHelper.checkSinglePath("genFolder", value);
+    }
+
+    public Path createSource() {
+        Path p = new Path(getProject());
+        mPaths.add(p);
+        return p;
+    }
+
+    @Override
+    public void execute() throws BuildException {
+        if (mFramework == null) {
+            throw new BuildException("AidlExecTask's framework is required.");
+        }
+        if (mGenFolder == null) {
+            throw new BuildException("AidlExecTask's genFolder is required.");
+        }
+
+        Project taskProject = getProject();
+
+        // build a list of all the source folders
+        ArrayList<String> sourceFolders = new ArrayList<String>();
+        for (Path p : mPaths) {
+            String[] values = p.list();
+            if (values != null) {
+                sourceFolders.addAll(Arrays.asList(values));
+            }
+        }
+
+        // now loop on all the source folders to find all the aidl to compile
+        // and compile them
+        for (String sourceFolder : sourceFolders) {
+            // create a fileset to find all the aidl files in the current source folder
+            FileSet fs = new FileSet();
+            fs.setProject(taskProject);
+            fs.setDir(new File(sourceFolder));
+            NameEntry include = fs.createInclude();
+            include.setName("**/*.aidl");
+
+            // loop through the results of the file set
+            Iterator<?> iter = fs.iterator();
+            while (iter.hasNext()) {
+                Object next = iter.next();
+
+                ExecTask task = new ExecTask();
+                task.setProject(taskProject);
+                task.setOwningTarget(getOwningTarget());
+                task.setExecutable(mExecutable);
+                task.setFailonerror(true);
+
+                task.createArg().setValue("-p" + mFramework);
+                task.createArg().setValue("-o" + mGenFolder);
+                // add all the source folders as import in case an aidl file in a source folder
+                // imports a parcelable from another source folder.
+                for (String importFolder : sourceFolders) {
+                    task.createArg().setValue("-I" + importFolder);
+                }
+
+                task.createArg().setValue(next.toString());
+
+                // execute it.
+                task.execute();
+            }
+        }
+    }
+}
index b79d274..22cfb30 100644 (file)
@@ -84,7 +84,8 @@ final class TaskHelper {
     static String checkSinglePath(String attribute, Path path) {
         String[] paths = path.list();
         if (paths.length != 1) {
-            throw new BuildException(String.format("Path value for '%1$s' is not valid.", attribute));
+            throw new BuildException(String.format(
+                    "Value for '%1$s' is not valid. It must resolve to a single path", attribute));
         }
 
         return paths[0];
index c207308..f4816fc 100644 (file)
     -->
 
     <!-- Custom tasks -->
-    <taskdef name="aaptexec"
+    <taskdef name="aapt"
         classname="com.android.ant.AaptExecLoopTask"
         classpathref="android.antlibs" />
 
+    <taskdef name="aidl"
+        classname="com.android.ant.AidlExecTask"
+        classpathref="android.antlibs" />
+
     <taskdef name="xpath"
         classname="com.android.ant.XPathTask"
         classpathref="android.antlibs" />
 
+    <taskdef name="if"
+        classname="com.android.ant.IfElseTask"
+        classpathref="android.antlibs" />
+
     <!-- Properties -->
 
     <!-- Tells adb which device to target. You can change this from the command line
@@ -33,6 +41,8 @@
     <!-- Name of the application package extracted from manifest file -->
     <xpath input="AndroidManifest.xml" expression="/manifest/@package"
                 output="manifest.package" />
+    <xpath input="AndroidManifest.xml" expression="/manifest/application/@android:hasCode"
+                output="manifest.hasCode" default="true"/>
 
     <!-- Input directories -->
     <property name="source.dir" value="src" />
         <mkdir dir="${out.classes.absolute.dir}" />
     </target>
 
+    <!-- empty default pre-build target. Create a similar target in
+         your build.xml and it'll be called instead of this one. -->
+    <target name="-pre-build"/>
+
     <!-- Generates the R.java file for this project's resources. -->
-    <target name="-resource-src" depends="-dirs">
+    <target name="-resource-src" depends="-dirs, -pre-build">
         <echo>Generating R.java / Manifest.java from the resources...</echo>
-        <aaptexec executable="${aapt}"
+        <aapt executable="${aapt}"
                 command="package"
                 verbose="${verbose}"
                 manifest="AndroidManifest.xml"
                 androidjar="${android.jar}"
                 rfolder="${gen.absolute.dir}">
             <res path="${resource.absolute.dir}" />
-        </aaptexec>
+        </aapt>
+    </target>
+
+    <!-- Generates java classes from .aidl files. -->
+    <target name="-aidl" depends="-dirs">
+        <if condition="${manifest.hasCode}">
+            <then>
+                <echo>Compiling aidl files into Java classes...</echo>
+                <aidl executable="${aidl}" framework="${android.aidl}"
+                        genFolder="${gen.absolute.dir}">
+                    <source path="${source.absolute.dir}"/>
+                    <source refid="android.libraries.src"/>
+                </aidl>
+            </then>
+            <else>
+                <echo>hasCode = false. Skipping...</echo>
+            </else>
+        </if>
     </target>
 
+    <!-- empty default pre-compile target. Create a similar target in
+         your build.xml and it'll be called instead of this one. -->
+    <target name="-pre-compile"/>
+
     <!-- Compiles this project's .java files into .class files. -->
-    <target name="compile" depends="-resource-src"
+    <target name="compile" depends="-resource-src, -aidl, -pre-compile"
                 description="Compiles project's .java files into .class files">
         <!-- If android rules are used for a test project, its classpath should include
              tested project's location -->
index 2277136..8876c7d 100644 (file)
     -->
 
     <!-- Custom tasks -->
-    <taskdef name="aaptexec"
+    <taskdef name="aapt"
         classname="com.android.ant.AaptExecLoopTask"
         classpathref="android.antlibs" />
 
+    <taskdef name="aidl"
+        classname="com.android.ant.AidlExecTask"
+        classpathref="android.antlibs" />
+
     <taskdef name="apkbuilder"
         classname="com.android.ant.ApkBuilderTask"
         classpathref="android.antlibs" />
         <if condition="${manifest.hasCode}">
             <then>
                 <echo>Generating R.java / Manifest.java from the resources...</echo>
-                <aaptexec executable="${aapt}"
+                <aapt executable="${aapt}"
                         command="package"
                         verbose="${verbose}"
                         manifest="AndroidManifest.xml"
                         androidjar="${android.jar}"
                         rfolder="${gen.absolute.dir}">
                     <res path="${resource.absolute.dir}" />
-                </aaptexec>
+                </aapt>
             </then>
             <else>
                 <echo>hasCode = false. Skipping...</echo>
         <if condition="${manifest.hasCode}">
             <then>
                 <echo>Compiling aidl files into Java classes...</echo>
-                <apply executable="${aidl}" failonerror="true">
-                    <arg value="-p${android.aidl}" />
-                    <arg value="-I${source.absolute.dir}" />
-                    <arg value="-o${gen.absolute.dir}" />
-                    <fileset dir="${source.absolute.dir}">
-                        <include name="**/*.aidl" />
-                    </fileset>
-                </apply>
+                <aidl executable="${aidl}" framework="${android.aidl}"
+                        genFolder="${gen.absolute.dir}">
+                    <source path="${source.absolute.dir}"/>
+                    <source refid="android.libraries.src"/>
+                </aidl>
             </then>
             <else>
                 <echo>hasCode = false. Skipping...</echo>
          -->
     <target name="-package-resources">
         <echo>Packaging resources</echo>
-        <aaptexec executable="${aapt}"
+        <aapt executable="${aapt}"
                 command="package"
                 versioncode="${version.code}"
                 manifest="AndroidManifest.xml"
             <res path="${resource.absolute.dir}" />
             <!-- <nocompress /> forces no compression on any files in assets or res/raw -->
             <!-- <nocompress extension="xml" /> forces no compression on specific file extensions in assets and res/raw -->
-        </aaptexec>
+        </aapt>
     </target>
 
     <!-- Packages the application and sign it with a debug key. -->