SDK support improvements.
Xavier Ducrohet [Wed, 30 Jan 2013 21:24:03 +0000 (13:24 -0800)]
Move figuring out the path to aidl/aapt/dx/llvm-rs-cc from IAndroidTarget
to SdkParser (in preparation of the build-tools).

Also change android.target to android.compileSdkVersion to make it
less confusing with regards to min/targetSdkVersion and also change it
to take either an int or a string.

Change-Id: I8642cb84f67cf75b49abe905b2a65f4d26668e98

55 files changed:
builder/src/main/java/com/android/builder/AndroidBuilder.java
builder/src/main/java/com/android/builder/DefaultSdkParser.java
builder/src/main/java/com/android/builder/PlatformSdkParser.java [new file with mode: 0644]
builder/src/main/java/com/android/builder/SdkParser.java
builder/src/main/java/com/android/builder/internal/FakeAndroidTarget.java [new file with mode: 0644]
changelog.txt
gradle/src/main/groovy/com/android/build/gradle/AppPlugin.groovy
gradle/src/main/groovy/com/android/build/gradle/BaseExtension.groovy
gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy
gradle/src/main/groovy/com/android/build/gradle/LibraryPlugin.groovy
gradle/src/main/groovy/com/android/build/gradle/internal/tasks/InstallTask.groovy
gradle/src/main/groovy/com/android/build/gradle/internal/tasks/TestFlavorTask.groovy
gradle/src/main/groovy/com/android/build/gradle/internal/tasks/UninstallTask.groovy
gradle/src/main/groovy/com/android/build/gradle/tasks/ZipAlign.groovy
gradle/src/test/groovy/com/android/build/gradle/AppPluginDslTest.groovy
gradle/src/test/groovy/com/android/build/gradle/AppPluginInternalTest.groovy
gradle/src/test/groovy/com/android/build/gradle/LibraryPluginDslTest.groovy
gradle/src/test/groovy/com/android/build/gradle/internal/dsl/BuildTypeDslTest.groovy
tests/aidl/build.gradle
tests/api/app/build.gradle
tests/api/lib/build.gradle
tests/applibtest/app/build.gradle
tests/applibtest/lib/build.gradle
tests/basic/build.gradle
tests/dependencies/build.gradle
tests/flavored/build.gradle
tests/flavorlib/app/build.gradle
tests/flavorlib/lib1/build.gradle
tests/flavorlib/lib2/build.gradle
tests/flavorlibWithFailedTests/app/build.gradle
tests/flavorlibWithFailedTests/lib1/build.gradle
tests/flavorlibWithFailedTests/lib2/build.gradle
tests/flavors/build.gradle
tests/libsTest/app/build.gradle
tests/libsTest/lib1/build.gradle
tests/libsTest/lib2/build.gradle
tests/libsTest/lib2b/build.gradle
tests/libsTest/libapp/build.gradle
tests/migrated/build.gradle
tests/multiproject/app/build.gradle
tests/multiproject/baseLibrary/build.gradle
tests/multiproject/library/build.gradle
tests/multires/build.gradle
tests/overlay1/build.gradle
tests/overlay2/build.gradle
tests/renderscript/build.gradle
tests/renderscriptInLib/app/build.gradle
tests/renderscriptInLib/lib/build.gradle
tests/renderscriptMultiSrc/build.gradle
tests/repo/app/build.gradle
tests/repo/app/src/main/java/com/example/android/multiproject/MainActivity.java
tests/repo/baseLibrary/build.gradle
tests/repo/library/build.gradle
tests/tictactoe/app/build.gradle
tests/tictactoe/lib/build.gradle

index 6499a31..880f591 100644 (file)
@@ -525,7 +525,7 @@ public class AndroidBuilder {
 
         File aapt = mSdkParser.getAapt();
         if (aapt == null || !aapt.isFile()) {
-            throw new IllegalStateException(String.valueOf("aapt is missing"));
+            throw new IllegalStateException("aapt is missing");
         }
 
         command.add(aapt.getAbsolutePath());
@@ -698,7 +698,7 @@ public class AndroidBuilder {
 
         File aidl = mSdkParser.getAidlCompiler();
         if (aidl == null || !aidl.isFile()) {
-            throw new IllegalStateException(String.valueOf("aidl is missing"));
+            throw new IllegalStateException("aidl is missing");
         }
 
         List<File> fullImportList = Lists.newArrayListWithCapacity(
@@ -743,7 +743,7 @@ public class AndroidBuilder {
 
         File aidl = mSdkParser.getAidlCompiler();
         if (aidl == null || !aidl.isFile()) {
-            throw new IllegalStateException(String.valueOf("aidl is missing"));
+            throw new IllegalStateException("aidl is missing");
         }
 
         AidlProcessor processor = new AidlProcessor(
@@ -792,7 +792,7 @@ public class AndroidBuilder {
 
         File renderscript = mSdkParser.getRenderscriptCompiler();
         if (renderscript == null || !renderscript.isFile()) {
-            throw new IllegalStateException(String.valueOf("llvm-rs-cc is missing"));
+            throw new IllegalStateException("llvm-rs-cc is missing");
         }
 
         // gather the files to compile
@@ -927,9 +927,12 @@ public class AndroidBuilder {
         // launch dx: create the command line
         ArrayList<String> command = Lists.newArrayList();
 
-        @SuppressWarnings("deprecation")
-        String dxPath = mTarget.getPath(IAndroidTarget.DX);
-        command.add(dxPath);
+        File dx = mSdkParser.getDx();
+        if (dx == null || !dx.isFile()) {
+            throw new IllegalStateException("dx is missing");
+        }
+
+        command.add(dx.getAbsolutePath());
 
         command.add("--dex");
 
index ac3041f..8fb0830 100644 (file)
@@ -24,6 +24,7 @@ import com.android.sdklib.internal.repository.packages.FullRevision;
 import com.android.sdklib.repository.PkgProps;
 import com.android.utils.ILogger;
 import com.google.common.base.Charsets;
+import com.google.common.collect.Maps;
 import com.google.common.io.Closeables;
 
 import java.io.File;
@@ -32,6 +33,7 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.util.Map;
 import java.util.Properties;
 
 import static com.android.SdkConstants.FD_PLATFORM_TOOLS;
@@ -48,6 +50,9 @@ public class DefaultSdkParser implements SdkParser {
     private final String mSdkLocation;
     private SdkManager mManager;
 
+    private File mPlatformTools;
+    private final Map<String, File> mToolsMap = Maps.newHashMapWithExpectedSize(6);
+
     public DefaultSdkParser(@NonNull String sdkLocation) {
         if (!sdkLocation.endsWith(File.separator)) {
             mSdkLocation = sdkLocation + File.separator;
@@ -77,7 +82,7 @@ public class DefaultSdkParser implements SdkParser {
 
     @Override
     public FullRevision getPlatformToolsRevision() {
-        File platformTools = new File(mSdkLocation, FD_PLATFORM_TOOLS);
+        File platformTools = getPlatformTools();
         if (!platformTools.isDirectory()) {
             return null;
         }
@@ -109,31 +114,54 @@ public class DefaultSdkParser implements SdkParser {
 
     @Override
     public File getAapt() {
-        File platformTools = new File(mSdkLocation, FD_PLATFORM_TOOLS);
-        if (!platformTools.isDirectory()) {
-            return null;
-        }
-
-        return new File(platformTools, SdkConstants.FN_AAPT);
+        return getTool(SdkConstants.FN_AAPT);
     }
 
     @Override
     public File getAidlCompiler() {
-        File platformTools = new File(mSdkLocation, FD_PLATFORM_TOOLS);
-        if (!platformTools.isDirectory()) {
-            return null;
-        }
-
-        return new File(platformTools, SdkConstants.FN_AIDL);
+        return getTool(SdkConstants.FN_AIDL);
     }
 
     @Override
     public File getRenderscriptCompiler() {
-        File platformTools = new File(mSdkLocation, FD_PLATFORM_TOOLS);
-        if (!platformTools.isDirectory()) {
-            return null;
+        return getTool(SdkConstants.FN_RENDERSCRIPT);
+    }
+
+    @Override
+    public File getDx() {
+        return getTool(SdkConstants.FN_DX);
+    }
+
+    @Override
+    public File getZipAlign() {
+        return getTool(SdkConstants.FN_ZIPALIGN);
+    }
+
+    @Override
+    public File getAdb() {
+        return getTool(SdkConstants.FN_ADB);
+    }
+
+    private File getTool(String filename) {
+        File f = mToolsMap.get(filename);
+        if (f == null) {
+            File platformTools = getPlatformTools();
+            if (!platformTools.isDirectory()) {
+                return null;
+            }
+
+            f = new File(platformTools, filename);
+            mToolsMap.put(filename, f);
+        }
+
+        return f;
+    }
+
+    private File getPlatformTools() {
+        if (mPlatformTools == null) {
+            mPlatformTools = new File(mSdkLocation, FD_PLATFORM_TOOLS);
         }
 
-        return new File(platformTools, SdkConstants.FN_RENDERSCRIPT);
+        return mPlatformTools;
     }
 }
diff --git a/builder/src/main/java/com/android/builder/PlatformSdkParser.java b/builder/src/main/java/com/android/builder/PlatformSdkParser.java
new file mode 100644 (file)
index 0000000..9fbb36f
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2013 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.builder;
+
+import com.android.SdkConstants;
+import com.android.annotations.NonNull;
+import com.android.builder.internal.FakeAndroidTarget;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.internal.repository.packages.FullRevision;
+import com.android.utils.ILogger;
+import com.google.common.collect.Maps;
+
+import java.io.File;
+import java.util.Map;
+
+/**
+ * Implementation of {@link SdkParser} for the SDK prebuilds in the Android source tree.
+ */
+class PlatformSdkParser implements SdkParser {
+    private final String mPlatformRootFolder;
+
+    private File mHostTools;
+    private final Map<String, File> mToolsMap = Maps.newHashMapWithExpectedSize(6);
+    private File mDx;
+    private File mAdb;
+
+    PlatformSdkParser(@NonNull String sdkLocation) {
+        mPlatformRootFolder = sdkLocation;
+    }
+
+    @Override
+    public IAndroidTarget resolveTarget(String target, ILogger logger) {
+        return new FakeAndroidTarget(mPlatformRootFolder, target);
+    }
+
+    @Override
+    public String getAnnotationsJar() {
+        String host;
+        if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_DARWIN) {
+            host = "darwin-x86";
+        } else if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_LINUX) {
+            host = "linux";
+        } else {
+            throw new IllegalStateException("Windows is not supported for platform development");
+        }
+
+        return mPlatformRootFolder + "/out/host/" + host + "/framework/annotations.jar";
+    }
+
+    @Override
+    public FullRevision getPlatformToolsRevision() {
+        return new FullRevision(99);
+    }
+
+    @Override
+    public File getAapt() {
+        return getTool(SdkConstants.FN_AAPT);
+    }
+
+    @Override
+    public File getAidlCompiler() {
+        return getTool(SdkConstants.FN_AIDL);
+    }
+
+    @Override
+    public File getRenderscriptCompiler() {
+        return getTool(SdkConstants.FN_RENDERSCRIPT);
+    }
+
+    @Override
+    public File getDx() {
+        if (mDx == null) {
+            mDx =  new File(mPlatformRootFolder, "prebuilts/sdk/tools/dx");
+        }
+
+        return mDx;
+    }
+
+    @Override
+    public File getZipAlign() {
+        return getTool(SdkConstants.FN_ZIPALIGN);
+    }
+
+    @Override
+    public File getAdb() {
+        if (mAdb == null) {
+
+            if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_DARWIN) {
+                mAdb = new File(mPlatformRootFolder, "out/host/darwin-x86/bin/adb");
+            } else if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_LINUX) {
+                mAdb = new File(mPlatformRootFolder, "out/host/linux-x86/bin/adb");
+            } else {
+                throw new IllegalStateException("Windows is not supported for platform development");
+            }
+        }
+
+        return mAdb;
+    }
+
+    private File getTool(String filename) {
+        File f = mToolsMap.get(filename);
+        if (f == null) {
+            File platformTools = getHostToolsFolder();
+            if (!platformTools.isDirectory()) {
+                return null;
+            }
+
+            f = new File(platformTools, filename);
+            mToolsMap.put(filename, f);
+        }
+
+        return f;
+    }
+
+    private File getHostToolsFolder() {
+        if (mHostTools == null) {
+            File tools = new File(mPlatformRootFolder, "prebuilts/sdk/tools");
+            if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_DARWIN) {
+                mHostTools = new File(tools, "darwin");
+            } else if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_LINUX) {
+                mHostTools = new File(tools, "linux");
+            } else {
+                throw new IllegalStateException("Windows is not supported for platform development");
+            }
+        }
+        return mHostTools;
+    }
+}
index fe9441f..0d269ff 100644 (file)
@@ -67,4 +67,19 @@ public interface SdkParser {
      * Returns the location of the renderscript compiler.
      */
     File getRenderscriptCompiler();
+
+    /**
+     * Returns the location of the dx tool.
+     */
+    File getDx();
+
+    /**
+     * Returns the location of the zip align tool.
+     */
+    File getZipAlign();
+
+    /**
+     * Returns the location of the adb tool.
+     */
+    File getAdb();
 }
\ No newline at end of file
diff --git a/builder/src/main/java/com/android/builder/internal/FakeAndroidTarget.java b/builder/src/main/java/com/android/builder/internal/FakeAndroidTarget.java
new file mode 100644 (file)
index 0000000..24e76d8
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2013 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.builder.internal;
+
+import com.android.SdkConstants;
+import com.android.sdklib.AndroidVersion;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.ISystemImage;
+import com.android.sdklib.util.SparseArray;
+
+import java.util.Map;
+
+/**
+ * Fake IAndroidTarget used for SDK prebuilts in the Android source tree.
+ */
+public class FakeAndroidTarget implements IAndroidTarget {
+    private final String mSdkLocation;
+    private final SparseArray<String> mPaths = new SparseArray<String>();
+    private final int mApiLevel;
+
+    public FakeAndroidTarget(String sdkLocation, String target) {
+        mSdkLocation = sdkLocation;
+        mApiLevel = getApiLevel(target);
+
+        String apiPrebuilts = mSdkLocation + "/prebuilts/sdk/" + Integer.toString(mApiLevel) + "/";
+        String rsPrebuilts = mSdkLocation + "/prebuilts/sdk/renderscript/";
+
+        // pre-build the path to the platform components
+        mPaths.put(ANDROID_JAR, apiPrebuilts + SdkConstants.FN_FRAMEWORK_LIBRARY);
+        mPaths.put(ANDROID_AIDL, apiPrebuilts + SdkConstants.FN_FRAMEWORK_AIDL);
+
+        // location of the renderscript imports.
+        mPaths.put(ANDROID_RS, rsPrebuilts + SdkConstants.OS_FRAMEWORK_RS);
+        mPaths.put(ANDROID_RS_CLANG, rsPrebuilts + SdkConstants.OS_FRAMEWORK_RS_CLANG);
+    }
+
+    private int getApiLevel(String target) {
+        if (target.startsWith("android-")) {
+            return Integer.parseInt(target.substring("android-".length()));
+        }
+
+        throw new IllegalArgumentException("Android target '%s' is not recognized.");
+    }
+
+    @Override
+    public String getPath(int pathId) {
+        return mPaths.get(pathId);
+    }
+
+    @Override
+    public String getLocation() {
+        return mSdkLocation;
+    }
+
+    @Override
+    public String getVendor() {
+        return "android";
+    }
+
+    @Override
+    public String getName() {
+        return "android";
+    }
+
+    @Override
+    public String getFullName() {
+        return "android";
+    }
+
+    @Override
+    public String getClasspathName() {
+        return "android";
+    }
+
+    @Override
+    public String getShortClasspathName() {
+        return "android";
+    }
+
+    @Override
+    public String getDescription() {
+        return "android";
+    }
+
+    @Override
+    public AndroidVersion getVersion() {
+        return new AndroidVersion(mApiLevel, null);
+    }
+
+    @Override
+    public String getVersionName() {
+        return "Android API level " + mApiLevel;
+    }
+
+    @Override
+    public int getRevision() {
+        return 1;
+    }
+
+    @Override
+    public boolean isPlatform() {
+        return true;
+    }
+
+    @Override
+    public IAndroidTarget getParent() {
+        return null;
+    }
+
+    @Override
+    public boolean hasRenderingLibrary() {
+        return false;
+    }
+
+    @Override
+    public String[] getSkins() {
+        return new String[0];
+    }
+
+    @Override
+    public String getDefaultSkin() {
+        return null;
+    }
+
+    @Override
+    public IOptionalLibrary[] getOptionalLibraries() {
+        return new IOptionalLibrary[0];
+    }
+
+    @Override
+    public String[] getPlatformLibraries() {
+        return new String[0];
+    }
+
+    @Override
+    public String getProperty(String name) {
+        return null;
+    }
+
+    @Override
+    public Integer getProperty(String name, Integer defaultValue) {
+        return null;
+    }
+
+    @Override
+    public Boolean getProperty(String name, Boolean defaultValue) {
+        return null;
+    }
+
+    @Override
+    public Map<String, String> getProperties() {
+        return null;
+    }
+
+    @Override
+    public int getUsbVendorId() {
+        return 0;
+    }
+
+    @Override
+    public ISystemImage[] getSystemImages() {
+        return new ISystemImage[0];
+    }
+
+    @Override
+    public ISystemImage getSystemImage(String abiType) {
+        return null;
+    }
+
+    @Override
+    public boolean canRunOn(IAndroidTarget target) {
+        return false;
+    }
+
+    @Override
+    public String hashString() {
+        return "android-" + mApiLevel;
+    }
+
+    @Override
+    public int compareTo(IAndroidTarget iAndroidTarget) {
+        FakeAndroidTarget that = (FakeAndroidTarget) iAndroidTarget;
+        return mSdkLocation.compareTo(that.mSdkLocation);
+    }
+}
index 344a987..655af00 100644 (file)
@@ -1,16 +1,28 @@
 0.3
 
-* Requires Gradle 1.3. Runtime check will ensure this.
-* Requires Android Platform Tools 16.0.2+. Runtime check will ensure this.
-* Default Java compile target set to 1.6.
-* API to manipulate Build Variants
-* Support for multi resource folders. See 'multires' sample
-* versionName suffix in build type.
-* Improved DSL to setup signing info.
-* new API to relocate full sourceSet. See 'migrated' sample.
-* Running tests on device now breaks the build if any test fails, and create a nice report, for each flavor/project, but also aggregated.
-* New plugin 'android-reporting' to aggregate android test results accross projects. See 'flavorlib' sample.
-* Tests now runs on all connected devices in parallel.
+* System requirements:
+   - Gradle 1.3+ (tested on 1.3/1.4)
+   - Android Platform Tools 16.0.2+
+* New Features:
+   - Renderscript support.
+   - Support for multi resource folders. See 'multires' sample.
+      * PNG crunch is now done incrementally and in parallel.
+   - Support for multi asset folders.
+   - Support for asset folders in Library Projects.
+   - API to manipulate Build Variants.
+   - Support for versionName suffix provided by the BuildType.
+   - Testing
+      * Tests now runs on all connected devices in parallel.
+      * Running tests on device now breaks the build if any test fails.
+      * Generate an HTML report for each flavor/project, but also aggregated.
+      * New plugin 'android-reporting' to aggregate android test results across projects. See 'flavorlib' sample.
+   - Improved DSL:
+      * replaced android.target with android.compileSdkVersion to make it less confusing vs min/targetSdkVersion
+      * signing information now a SigningConfig object reusable across BuildType and ProductFlavor
+      * ability to relocated a full sourceSet. See 'migrated' sample.
+* Fixes:
+   - Default Java compile target set to 1.6.
+   - Fix generation of R classes in case libraries share same package name as the app project.
 
 0.2
 
index 2bfb775..4e943f7 100644 (file)
@@ -514,6 +514,6 @@ class AppPlugin extends com.android.build.gradle.BasePlugin implements org.gradl
 
     @Override
     protected String getTarget() {
-        return extension.target;
+        return extension.compileSdkVersion;
     }
 }
index 4be37aa..8ae1ba3 100644 (file)
@@ -35,7 +35,7 @@ import org.gradle.internal.reflect.Instantiator
  */
 public abstract class BaseExtension {
 
-    String target
+    private String target
 
     final ProductFlavor defaultConfig
     final AaptOptionsImpl aaptOptions
@@ -95,6 +95,22 @@ public abstract class BaseExtension {
         }
     }
 
+    void compileSdkVersion(int apiLevel) {
+        this.target = "android-" + apiLevel
+    }
+
+    void setCompileSdkVersion(int apiLevel) {
+        compileSdkVersion(apiLevel)
+    }
+
+    void compileSdkVersion(String target) {
+        this.target = target
+    }
+
+    void setCompileSdkVersion(String target) {
+        compileSdkVersion(target)
+    }
+
     void sourceSets(Action<NamedDomainObjectContainer<AndroidSourceSet>> action) {
         action.execute(sourceSetsContainer)
     }
@@ -128,4 +144,8 @@ public abstract class BaseExtension {
         plugin.createAndroidTasks()
         return testBuildVariants
     }
+
+    public String getCompileSdkVersion() {
+        return target
+    }
 }
index eb20548..173f460 100644 (file)
@@ -53,6 +53,7 @@ import com.android.builder.BuilderConstants
 import com.android.builder.DefaultSdkParser
 import com.android.builder.JarDependency
 import com.android.builder.ManifestDependency
+import com.android.builder.PlatformSdkParser
 import com.android.builder.ProductFlavor
 import com.android.builder.SdkParser
 import com.android.builder.SourceProvider
@@ -102,8 +103,7 @@ public abstract class BasePlugin {
     final Map<SigningConfig, ValidateSigningTask> validateSigningTaskMap = [:]
 
     protected Project project
-    protected File sdkDir
-    private DefaultSdkParser androidSdkParser
+    protected SdkParser androidSdkParser
     private LoggerWrapper loggerWrapper
 
     private boolean hasCreatedTasks = false
@@ -134,8 +134,6 @@ public abstract class BasePlugin {
         project.tasks.assemble.description =
             "Assembles all variants of all applications and secondary packages."
 
-        findSdk(project)
-
         uninstallAll = project.tasks.add("uninstallAll")
         uninstallAll.description = "Uninstall all applications."
         uninstallAll.group = INSTALL_GROUP
@@ -164,6 +162,8 @@ public abstract class BasePlugin {
     }
 
     final void createAndroidTasks() {
+        findSdk(project)
+
         if (hasCreatedTasks) {
             return
         }
@@ -187,10 +187,6 @@ public abstract class BasePlugin {
     }
 
     SdkParser getSdkParser() {
-        if (androidSdkParser == null) {
-            androidSdkParser = new DefaultSdkParser(sdkDir.absolutePath)
-        }
-
         return androidSdkParser;
     }
 
@@ -220,10 +216,13 @@ public abstract class BasePlugin {
     private void findSdk(Project project) {
         // if already set through tests.
         if (TEST_SDK_DIR != null) {
-            sdkDir = TEST_SDK_DIR
+            androidSdkParser = new DefaultSdkParser(TEST_SDK_DIR.absolutePath)
             return
         }
 
+        boolean defaultParser = true
+        File sdkDir = null
+
         def rootDir = project.rootDir
         def localProperties = new File(rootDir, SdkConstants.FN_LOCAL_PROPERTIES)
         if (localProperties.exists()) {
@@ -232,10 +231,19 @@ public abstract class BasePlugin {
                 properties.load(instr)
             }
             def sdkDirProp = properties.getProperty('sdk.dir')
-            if (!sdkDirProp) {
-                throw new RuntimeException("No sdk.dir property defined in local.properties file.")
+
+            if (sdkDirProp != null) {
+                sdkDir = new File(sdkDirProp)
+            } else {
+                sdkDirProp = properties.getProperty('android.dir')
+                if (sdkDirProp != null) {
+                    sdkDir = new File(rootDir, sdkDirProp)
+                    defaultParser = false
+                } else {
+                    throw new RuntimeException(
+                            "No sdk.dir property defined in local.properties file.")
+                }
             }
-            sdkDir = new File(sdkDirProp)
         } else {
             def envVar = System.getenv("ANDROID_HOME")
             if (envVar != null) {
@@ -252,6 +260,12 @@ public abstract class BasePlugin {
             throw new RuntimeException(
                     "The SDK directory '$sdkDir' specified in local.properties does not exist.")
         }
+
+        if (defaultParser) {
+            androidSdkParser = new DefaultSdkParser(sdkDir.absolutePath)
+        } else {
+            androidSdkParser = new PlatformSdkParser(sdkDir.absolutePath)
+        }
     }
 
     protected String getRuntimeJars(ApplicationVariant variant) {
@@ -668,9 +682,10 @@ public abstract class BasePlugin {
         testFlavorTask.plugin = this
         testFlavorTask.variant = variant
         testFlavorTask.testedVariant = testedVariant
-        testFlavorTask.sdkDir = sdkDir
         testFlavorTask.flavorName = variant.flavorName
 
+        testFlavorTask.conventionMapping.adbExe = { androidSdkParser.adb }
+
         testFlavorTask.conventionMapping.testApp = { variant.outputFile }
         if (testedVariant.config.type != VariantConfiguration.Type.LIBRARY) {
             testFlavorTask.conventionMapping.testedApp = { testedVariant.outputFile }
@@ -780,7 +795,7 @@ public abstract class BasePlugin {
                     project.file(
                             "$project.buildDir/apk/${project.archivesBaseName}-${variant.baseName}.apk")
                 }
-                zipAlignTask.sdkDir = sdkDir
+                zipAlignTask.conventionMapping.zipAlignExe = { androidSdkParser.zipAlign }
 
                 appTask = zipAlignTask
                 variant.outputFile = project.file(
@@ -793,7 +808,7 @@ public abstract class BasePlugin {
             installTask.group = INSTALL_GROUP
             installTask.dependsOn appTask
             installTask.conventionMapping.packageFile = { appTask.outputFile }
-            installTask.sdkDir = sdkDir
+            installTask.conventionMapping.adbExe = { androidSdkParser.adb }
 
             variant.installTask = installTask
         }
@@ -812,7 +827,7 @@ public abstract class BasePlugin {
         uninstallTask.description = "Uninstalls the " + variant.description
         uninstallTask.group = INSTALL_GROUP
         uninstallTask.variant = variant
-        uninstallTask.sdkDir = sdkDir
+        uninstallTask.conventionMapping.adbExe = { androidSdkParser.adb }
 
         variant.uninstallTask = uninstallTask
         uninstallAll.dependsOn uninstallTask
index e49309e..71f5105 100644 (file)
@@ -300,6 +300,6 @@ public class LibraryPlugin extends BasePlugin implements Plugin<Project> {
 
     @Override
     protected String getTarget() {
-        return extension.target
+        return extension.compileSdkVersion
     }
 }
index 840c037..92fd0d9 100644 (file)
@@ -21,7 +21,8 @@ import org.gradle.api.tasks.TaskAction
  * Task installing an app.
  */
 public class InstallTask extends DefaultTask {
-    File sdkDir
+    @InputFile
+    File adbExe
 
     @InputFile
     File packageFile
@@ -29,7 +30,7 @@ public class InstallTask extends DefaultTask {
     @TaskAction
     void generate() {
         project.exec {
-            executable = new File(getSdkDir(), "platform-tools${File.separator}adb")
+            executable = getAdbExe()
             args 'install'
             args '-r'
             args getPackageFile()
index bcc8930..7c15af6 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 package com.android.build.gradle.internal.tasks
-import com.android.SdkConstants
+
 import com.android.annotations.NonNull
 import com.android.annotations.Nullable
 import com.android.build.gradle.internal.ApplicationVariant
@@ -42,8 +42,8 @@ import java.util.concurrent.Callable
  */
 public class TestFlavorTask extends BaseTask implements AndroidTestTask {
 
-    @Input
-    File sdkDir
+    @InputFile
+    File adbExe
 
     @InputFile
     File testApp
@@ -156,10 +156,8 @@ public class TestFlavorTask extends BaseTask implements AndroidTestTask {
     protected void runTests() {
         AndroidDebugBridge.initIfNeeded(false /*clientSupport*/)
 
-        File platformTools = new File(getSdkDir(), SdkConstants.FD_PLATFORM_TOOLS)
-
-        AndroidDebugBridge bridge = AndroidDebugBridge.createBridge(
-                new File(platformTools, SdkConstants.FN_ADB).absolutePath, false /*forceNewBridge*/)
+        AndroidDebugBridge bridge = AndroidDebugBridge.createBridge(getAdbExe().absolutePath,
+                false /*forceNewBridge*/)
 
         long timeOut = 30000 // 30 sec
         int sleepTime = 1000
index 0111b6c..96892a0 100644 (file)
  */
 package com.android.build.gradle.internal.tasks
 
+import org.gradle.api.tasks.InputFile
 import org.gradle.api.tasks.TaskAction
 
 public class UninstallTask extends BaseTask {
-    File sdkDir
+    @InputFile
+    File adbExe
 
     @TaskAction
     public void uninstall() {
         String packageName = variant.packageName
         logger.info("Uninstalling app: " + packageName)
         project.exec {
-            executable = new File(getSdkDir(), "platform-tools${File.separator}adb")
+            executable = getAdbExe()
             args "uninstall"
             args packageName
         }
index b6d3b74..10cc75f 100644 (file)
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 package com.android.build.gradle.tasks
-
 import org.gradle.api.DefaultTask
-import org.gradle.api.tasks.Input
 import org.gradle.api.tasks.InputFile
 import org.gradle.api.tasks.OutputFile
 import org.gradle.api.tasks.TaskAction
@@ -33,13 +31,13 @@ public class ZipAlign extends DefaultTask {
 
     // ----- PRIVATE TASK API -----
 
-    @Input
-    File sdkDir
+    @InputFile
+    File zipAlignExe
 
     @TaskAction
     void zipAlign() {
         project.exec {
-            executable = new File(getSdkDir(), "tools${File.separator}zipalign")
+            executable = getZipAlignExe()
             args '-f', '4'
             args getInputFile()
             args getOutputFile()
index b532581..ea41919 100644 (file)
@@ -36,7 +36,50 @@ public class AppPluginDslTest extends BaseTest {
         project.apply plugin: 'android'
 
         project.android {
-            target "android-15"
+            compileSdkVersion 15
+        }
+
+        Set<BuildVariant> variants = project.android.buildVariants
+        assertEquals(2, variants.size())
+
+        Set<BuildVariant> testVariants = project.android.testBuildVariants
+        assertEquals(1, testVariants.size())
+
+        checkTestedVariant("Debug", "Test", variants, testVariants)
+        checkNonTestedVariant("Release", variants)
+    }
+
+    /**
+     * Same as Basic but with a slightly different DSL.
+     */
+    public void testBasic2() {
+        Project project = ProjectBuilder.builder().withProjectDir(
+                new File(testDir, "basic")).build()
+
+        project.apply plugin: 'android'
+
+        project.android {
+            compileSdkVersion = 15
+        }
+
+        Set<BuildVariant> variants = project.android.buildVariants
+        assertEquals(2, variants.size())
+
+        Set<BuildVariant> testVariants = project.android.testBuildVariants
+        assertEquals(1, testVariants.size())
+
+        checkTestedVariant("Debug", "Test", variants, testVariants)
+        checkNonTestedVariant("Release", variants)
+    }
+
+    public void testBasicWithStringTarget() {
+        Project project = ProjectBuilder.builder().withProjectDir(
+                new File(testDir, "basic")).build()
+
+        project.apply plugin: 'android'
+
+        project.android {
+            compileSdkVersion "android-15"
         }
 
         Set<BuildVariant> variants = project.android.buildVariants
@@ -56,7 +99,7 @@ public class AppPluginDslTest extends BaseTest {
         project.apply plugin: 'android'
 
         project.android {
-            target "android-15"
+            compileSdkVersion 15
 
             sourceSets {
                 main {
@@ -77,7 +120,7 @@ public class AppPluginDslTest extends BaseTest {
         project.apply plugin: 'android'
 
         project.android {
-            target "android-15"
+            compileSdkVersion 15
             testBuildType "staging"
 
             buildTypes {
@@ -107,7 +150,7 @@ public class AppPluginDslTest extends BaseTest {
         project.apply plugin: 'android'
 
         project.android {
-            target "android-15"
+            compileSdkVersion 15
 
             productFlavors {
                 flavor1 {
@@ -140,7 +183,7 @@ public class AppPluginDslTest extends BaseTest {
         project.apply plugin: 'android'
 
         project.android {
-            target "android-15"
+            compileSdkVersion 15
 
             flavorGroups   "group1", "group2"
 
index 7c6dfb7..c1d2918 100644 (file)
@@ -44,7 +44,7 @@ public class AppPluginInternalTest extends BaseTest {
         project.apply plugin: 'android'
 
         project.android {
-            target "android-15"
+            compileSdkVersion 15
         }
 
         AppPlugin plugin = AppPlugin.pluginHolder.plugin
@@ -76,7 +76,7 @@ public class AppPluginInternalTest extends BaseTest {
         project.apply plugin: 'android'
 
         project.android {
-            target "android-15"
+            compileSdkVersion 15
 
             signingConfigs {
                 fakeConfig {
@@ -119,7 +119,7 @@ public class AppPluginInternalTest extends BaseTest {
         project.apply plugin: 'android'
 
         project.android {
-            target "android-15"
+            compileSdkVersion 15
             testBuildType "staging"
 
             buildTypes {
@@ -158,7 +158,7 @@ public class AppPluginInternalTest extends BaseTest {
         project.apply plugin: 'android'
 
         project.android {
-            target "android-15"
+            compileSdkVersion 15
 
             productFlavors {
                 flavor1 {
@@ -193,7 +193,7 @@ public class AppPluginInternalTest extends BaseTest {
         project.apply plugin: 'android'
 
         project.android {
-            target "android-15"
+            compileSdkVersion 15
 
             flavorGroups   "group1", "group2"
 
@@ -252,7 +252,7 @@ public class AppPluginInternalTest extends BaseTest {
         project.apply plugin: 'android'
 
         project.android {
-            target "android-15"
+            compileSdkVersion 15
 
             signingConfigs {
                 one {
@@ -358,7 +358,7 @@ public class AppPluginInternalTest extends BaseTest {
         project.apply plugin: 'android'
 
         project.android {
-            target "android-15"
+            compileSdkVersion 15
 
             signingConfigs {
                 debug {
@@ -383,7 +383,7 @@ public class AppPluginInternalTest extends BaseTest {
         project.apply plugin: 'android'
 
         project.android {
-            target "android-15"
+            compileSdkVersion 15
 
             signingConfigs {
                 foo.initWith(owner.signingConfigs.debug)
index 5f342ba..1fcb51b 100644 (file)
@@ -35,7 +35,7 @@ public class LibraryPluginDslTest extends BaseTest {
         project.apply plugin: 'android-library'
 
         project.android {
-            target "android-15"
+            compileSdkVersion 15
         }
 
         Set<BuildVariant> variants = project.android.buildVariants
@@ -59,7 +59,7 @@ public class LibraryPluginDslTest extends BaseTest {
         project.apply plugin: 'android-library'
 
         project.android {
-            target "android-15"
+            compileSdkVersion 15
 
             debugSigningConfig {
                 storePassword = "foo"
index b7c5602..40f4391 100644 (file)
@@ -35,7 +35,7 @@ public class BuildTypeDslTest extends BaseTest {
         project.apply plugin: 'android'
 
         project.android {
-            target "android-15"
+            compileSdkVersion 15
         }
 
         AppPlugin plugin = AppPlugin.pluginHolder.plugin
@@ -57,7 +57,7 @@ public class BuildTypeDslTest extends BaseTest {
         project.apply plugin: 'android'
 
         project.android {
-            target "android-15"
+            compileSdkVersion 15
         }
 
         AppPlugin plugin = AppPlugin.pluginHolder.plugin
index dc42ba2..077f203 100644 (file)
@@ -12,6 +12,6 @@ buildscript {
 apply plugin: 'android'
 
 android {
-    target = "android-15"
+    compileSdkVersion 15
 
 }
\ No newline at end of file
index 6eb2be7..85e4c9d 100644 (file)
@@ -1,7 +1,7 @@
 apply plugin: 'android'
 
 android {
-    target "android-15"
+    compileSdkVersion 15
 }
 
 // query for all (non-test) variants and inject a new step in the builds
index 1045da6..50837f7 100644 (file)
@@ -1,8 +1,7 @@
 apply plugin: 'android-library'
 
 android {
-    target = "android-15"
-
+    compileSdkVersion 15
 }
 
 // query for all (non-test) variants and inject a new step in the builds
index abc0dbd..8d1c513 100644 (file)
@@ -1,7 +1,7 @@
 apply plugin: 'android'
 
 android {
-    target = "android-15"
+    compileSdkVersion 15
 }
 
 //
index 5ca87af..99ff711 100644 (file)
@@ -1,7 +1,7 @@
 apply plugin: 'android-library'
 
 android {
-    target = "android-15"
+    compileSdkVersion 15
 
        defaultConfig {
                testPackageName = "com.android.tests.testprojecttest.testlib"
index b8a8bd0..8f2f7cb 100644 (file)
@@ -12,7 +12,7 @@ buildscript {
 apply plugin: 'android'
 
 android {
-    target "android-15"
+    compileSdkVersion 15
     testBuildType "debug"
 
     signingConfigs {
index b7beef4..97076a4 100644 (file)
@@ -22,7 +22,7 @@ dependencies {
 }
 
 android {
-    target "android-15"
+    compileSdkVersion 15
     testBuildType "blah"
 
     defaultConfig {
index 7b6b01f..c5944c3 100644 (file)
@@ -12,7 +12,7 @@ buildscript {
 apply plugin: 'android'
 
 android {
-    target = "android-15"
+    compileSdkVersion 15
     testBuildType = "staging"
 
     defaultConfig {
index 6d3041a..c3111bf 100644 (file)
@@ -1,7 +1,7 @@
 apply plugin: 'android'
 
 android {
-    target = "android-15"
+    compileSdkVersion 15
 
     productFlavors {
         flavor1 {
index f7838fb..182f845 100644 (file)
@@ -1,5 +1,5 @@
 apply plugin: 'android-library'
 
 android {
-    target = "android-15"
+    compileSdkVersion 15
 }
\ No newline at end of file
index f7838fb..182f845 100644 (file)
@@ -1,5 +1,5 @@
 apply plugin: 'android-library'
 
 android {
-    target = "android-15"
+    compileSdkVersion 15
 }
\ No newline at end of file
index dcaac3c..485c953 100644 (file)
@@ -1,7 +1,7 @@
 apply plugin: 'android'
 
 android {
-    target = "android-15"
+    compileSdkVersion 15
 
     productFlavors {
         flavor1 {
index f7838fb..182f845 100644 (file)
@@ -1,5 +1,5 @@
 apply plugin: 'android-library'
 
 android {
-    target = "android-15"
+    compileSdkVersion 15
 }
\ No newline at end of file
index f7838fb..182f845 100644 (file)
@@ -1,5 +1,5 @@
 apply plugin: 'android-library'
 
 android {
-    target = "android-15"
+    compileSdkVersion 15
 }
\ No newline at end of file
index cc59029..d499442 100644 (file)
@@ -9,7 +9,7 @@ buildscript {
 apply plugin: 'android'
 
 android {
-    target         "android-15"
+    compileSdkVersion 15
     flavorGroups   "group1", "group2"
 
     productFlavors {
index eded7c2..2506b09 100644 (file)
@@ -1,7 +1,7 @@
 apply plugin: 'android'
 
 android {
-    target = "android-15"
+    compileSdkVersion 15
 }
 
 //
index 3624c3b..f1e1e87 100644 (file)
@@ -5,5 +5,5 @@ dependencies {
 }
 
 android {
-    target = "android-15"
+    compileSdkVersion 15
 }
\ No newline at end of file
index a810790..182f845 100644 (file)
@@ -1,6 +1,5 @@
 apply plugin: 'android-library'
 
 android {
-    target = "android-15"
-
+    compileSdkVersion 15
 }
\ No newline at end of file
index a810790..182f845 100644 (file)
@@ -1,6 +1,5 @@
 apply plugin: 'android-library'
 
 android {
-    target = "android-15"
-
+    compileSdkVersion 15
 }
\ No newline at end of file
index a810790..182f845 100644 (file)
@@ -1,6 +1,5 @@
 apply plugin: 'android-library'
 
 android {
-    target = "android-15"
-
+    compileSdkVersion 15
 }
\ No newline at end of file
index fd8ca17..fa7cbfd 100644 (file)
@@ -12,7 +12,7 @@ buildscript {
 apply plugin: 'android'
 
 android {
-    target = "android-15"
+    compileSdkVersion 15
 
     sourceSets {
         main {
index a8af53e..11f65ff 100644 (file)
@@ -5,7 +5,7 @@
 apply plugin: 'android'
 
 android {
-    target 'android-15'
+    compileSdkVersion 15
 }
 
 dependencies {
index f05d025..6c5b6a5 100644 (file)
@@ -1,7 +1,7 @@
 apply plugin: 'android-library'
 
 android {
-    target 'android-15'
+    compileSdkVersion 15
 }
 
 dependencies {
index a5f742c..bcce608 100644 (file)
@@ -1,7 +1,7 @@
 apply plugin: 'android-library'
 
 android {
-    target 'android-15'
+    compileSdkVersion 15
 }
 
 dependencies {
index a54bbbf..7353f59 100644 (file)
@@ -9,7 +9,7 @@ buildscript {
 apply plugin: 'android'
 
 android {
-    target "android-15"
+    compileSdkVersion 15
 
     sourceSets {
         main {
index 8601ef1..60b8d4f 100644 (file)
@@ -10,5 +10,5 @@ buildscript {
 apply plugin: 'android'
 
 android {
-    target "android-15"
+    compileSdkVersion 15
 }
\ No newline at end of file
index e08ca60..3ec6b79 100644 (file)
@@ -10,7 +10,7 @@ buildscript {
 apply plugin: 'android'
 
 android {
-    target "android-15"
+    compileSdkVersion 15
 
     productFlavors {
         one {}
index 1a92390..820afb8 100644 (file)
@@ -12,7 +12,7 @@ buildscript {
 apply plugin: 'android'
 
 android {
-    target "android-17"
+    compileSdkVersion 17
 
     defaultConfig {
         renderscriptTargetApi = 17
index f04e302..982c831 100644 (file)
@@ -1,7 +1,7 @@
 apply plugin: 'android'
 
 android {
-    target "android-17"
+    compileSdkVersion 17
 
     defaultConfig {
         renderscriptTargetApi = 11
index b7ce7ab..7b79c44 100644 (file)
@@ -1,5 +1,5 @@
 apply plugin: 'android-library'
 
 android {
-    target 'android-15'
+    compileSdkVersion 15
 }
index 13825b4..d947c94 100644 (file)
@@ -12,7 +12,7 @@ buildscript {
 apply plugin: 'android'
 
 android {
-    target "android-17"
+    compileSdkVersion 17
 
     defaultConfig {
         renderscriptTargetApi = 11
index 2c0db45..bf2e2fb 100644 (file)
@@ -19,6 +19,6 @@ dependencies {
 }
 
 android {
-    target 'android-15'
+    compileSdkVersion 15
 }
 
index 60dd603..6a8b95b 100644 (file)
@@ -18,9 +18,9 @@ public class MainActivity extends Activity {
         setContentView(R.layout.main);
 
         // some random code to test dependencies on util and guava
-       Person p = new Person("foo");
-       List<Person> persons = Lists.newArrayList();
-       persons.add(p);
+        Person p = new Person("foo");
+        List<Person> persons = Lists.newArrayList();
+        persons.add(p);
     }
 
     public void sendMessage(View view) {
index 89445f9..9ae0271 100644 (file)
@@ -20,7 +20,7 @@ dependencies {
 }
 
 android {
-    target 'android-15'
+    compileSdkVersion 15
 }
 
 group = 'com.example.android.multiproject'
index 90ed7b6..84c8d6f 100644 (file)
@@ -19,7 +19,7 @@ dependencies {
 }
 
 android {
-    target 'android-15'
+    compileSdkVersion 15
 }
 
 group = 'com.example.android.multiproject'
index 3d4a6f5..dfb03f0 100644 (file)
@@ -8,5 +8,5 @@ dependencies {
 }
 
 android {
-    target = "android-15"
+    compileSdkVersion 15
 }
index f7838fb..182f845 100644 (file)
@@ -1,5 +1,5 @@
 apply plugin: 'android-library'
 
 android {
-    target = "android-15"
+    compileSdkVersion 15
 }
\ No newline at end of file