読者です 読者をやめる 読者になる 読者になる

Android Studioの build.gradle どこまで弄れるか試してみた

android gradle IDEA AS

前回までのエントリはこちら


初期設定では色々と詰まってる人も多いみたいなので実際色々と弄ってみた
つうか
確かに一般人は groovy や gradle やjenkinsなんかしらんわな。。。(苦笑



さて本題。
まあ下記の話あたりは
android gradle plugin v4 の制限だと思うので
version上がればなんとかなるんじゃないかと思われる。。



結局の処 android maven project 縛りがまだきついんかな・・・(汗
でもclasspathに 既にv4入ってるって謎やん。
でもそうだとすると

  • nakamapはカスタムしたv4使ってる臭くて 差し替えると落ちる

なんでオワコン臭が。。(苦笑

注)
 一応後記の対応(@さん感謝!)で 相対パスでおlibrary-projectが正常に動くようになりました*1

その代わり

  • support-v4.jarが参照してるプロジェクト全部俯瞰して 複数あると怒られる現象が発生

eclipseの場合は

  • 各プロジェクトのlibs に同じverの support-v4.jar おくこと前提だけど実際の挙動はどうなん?

 有一AS(IDEA)さわってみました系の記事以外で
初めて実装コードの話が出てきたのは下記のtwだけかも。。。

ぶっちゃけ差分ってどこかな。。。って考えると


明示的にJava6を $HOME/.bash_profileに設定してるぐらい??*2

  • $HOME/.bash_profile


export JAVA_HOME=`/usr/libexec/java_home -v 1.6`
#export JAVA_HOME=`/usr/libexec/java_home -v 1.7`

export JAVA_OPTS='-Dfile.encoding=UTF-8 -Dgroovy.source.encoding=UTF-8'
export _JAVA_OPTIONS='-Dfile.encoding=UTF-8 -Dgroovy.source.encoding=UTF-8'



実際弄った構成)

  • MainProject (android_yutori)
  • libraryProject (yutori_lib)

両方ASで作る

libraryProject は
librariesディレクトリをMainProjectに作って
yutori_lib/yutori_lib の部分を中身コピー

構成的にはこんなん?


android_yutori
build.gradle
settings.gradle
 yutori_hisotry
build.gradle
yutori.keystore
libraries
yutori_lib (yutori_lib/yutori_lib をコピー)
build.gradle

  • build.gradle
repositories {
   mavenCentral()
}
apply plugin: 'eclipse'
  • settings.gradle
include ':yutori_hisotory'
include ':libraries:yutori_lib'
rootProject.name = 'hogeDriven' //☆
  • AS & AS 構成だと怒られなく放ったけど名前が変わらない・・・*3
  • gradle.properties (追加)
# systemProp. を付けないとgradleに反映されないようなので修正(0525)
systemProp.ANDROID_HOME=/Users/XXXX/android-sdk-macosx
systemProp.JAVA_OPTS=-Dgroovy.source.encoding=UTF-8 -Dfile.encoding=UTF-8

key_store=yutori.keystore
key_alias=yutoriworld
key_store_password=yutoriworld
key_alias_password=yutoriworld
  • yutori_hisotory/build.gradle
buildscript {
    repositories {
        maven { url 'http://repo1.maven.org/maven2' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.4'
    }
}
apply plugin: 'android'


dependencies {
    compile fileTree(dir: 'libs', includes: ['*.jar'])
    //compile files('libs/android-support-v4.jar')
    //compile files("${System.getenv('ANDROID_HOME')}/extras/android/support/v4/android-support-v4.jar")
    //compile files("${ANDROID_HOME}/extras/android/support/v4/android-support-v4.jar")
    compile project(':libraries:yutori_lib')
    //compile project('file:../yutori_lib')  //[NG] multi projectは相対パス指定参照が厳しい?
}


android {
    compileSdkVersion 17
    buildToolsVersion "17.0.0"

    defaultConfig {
        minSdkVersion 4
        targetSdkVersion 17
    }

    signingConfigs {
        debug {
            //storeFile file("debug.keystore")
            storeFile file("${System.getenv('HOME')}/.android/debug.keystore")  //☆☆
        }

        //[NOTE] 一応予想な形で書いてみたけど、未定義エラーにはならない =>動くっぽいけど でも変な挙動するみたな話が‥‥。
        //  NewBuildSystem公式記述 だと違う名前をあえて定義してるということはなんか有る??
/*
        release {
            storeFile file("yutori.keystore")
            keyAlias "yutori_history"
            keyPassword "yutori_world"
            storePassword "yutori_black_world"
        }
*/
        //[◎]別名なら問題ないよう。なんか名前ぶつかってるの??
        myConfig {
            storeFile file("yutori.keystore")
            keyAlias "yutori_history"
            keyPassword "yutori_world"
            storePassword "yutori_black_world"
        }
    }

    //[◎]別名にするばあいはこの定義が必要
    buildTypes {
        release {
            signingConfig signingConfigs.myConfig
        }
    }
}

//==== append =====
sourceCompatibility=1.6
targetCompatibility=1.6

//ASだとbuildタスクしか動いてないようなんで毎回cleanしたいなら
build.dependsOn clean 
//か
//defaultTasks 'clean'

version = "x.y.z" //エラー出ないけど適応はされない

/*
//[TODO]これはエラるので gradle java pluginベースとかでは無いよう。フルスクラッチ?ソースどこ?

def enc = 'UTF-8'
[compileJava, compileTestJava].each{ it.options.encoding = enc }
*/
    • ☆☆ が凄くもにょった。。公式サイトの記述は上。。。
  • libraries/yutori_lib/build.gradle
buildscript {
    repositories {
        maven { url 'http://repo1.maven.org/maven2' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.4'
    }
}

//apply plugin: 'android'  //library-projectでも こっちで生成されるのでASのバグっぽい。下記に修正すること(eclipse版は問題無)
apply plugin: 'android-library'

dependencies {
    //compile files('libs/android-support-v4.jar')
    compile fileTree(dir: 'libs', include: '*.jar')
}

android {
    compileSdkVersion 17
    buildToolsVersion "17.0.0"

    defaultConfig {
        minSdkVersion 4
        targetSdkVersion 17
    }
}

//==== append =====
sourceCompatibility=1.6
targetCompatibility=1.6




補足)
 
compile project(':libraries:yutori_lib')
のライブラリプロジェクトをメインプロジェクトの下にフォルダ掘って置かないとダメな件
@ さんに対処法解決して頂きました! すごい感謝!
G系クラスタとしては 大喜利 状態かも *4

たぶん一般的に相対パスのままでやろうとすると


ln -s libraries/yutori_lib ../yutori_lib/yutori_lib
とか狡い手で対応するんでしょうね。。できなくはないけどすごく微妙
 Android界隈で凄く有名な方もその手法で試されている方が多いようだしね。。*5

  • settings.gradle
include ':yutori_hisotory'
//include ':libraries:yutori_lib' 	        //プロジェクト	パスが存在する必要があり
includeFlat ':yutori_lib'			//プロジェクト	仮想パスでOK
rootProject.name = 'hogeDriven'

//======(ここから追加)================
def yutori_prg = project(':yutori_lib');  //仮想パス版
//println yutori_prg.dump()
//yutori_prg.projectDir=new File('../yutori_lib/')            //[NG]LibraryProject直下参照だとsettings.gradleがバッティング?
//yutori_prg.projectDir=new File('../yutori_lib/yutori_lib') //[OK]直接サブプロジェクトを見る

//[NOTE] ./gradewで対象フォルダ内で 動かす場合は上記で問題ないけど AS上で動かす場合は下記のほうが良(5/20 add)
yutori_prg.projectDir=new File(settingsDir,'../yutori_lib/yutori_lib')


println yutori_prg.projectDir
  • build.gradle
dependencies {
    compile fileTree(dir: 'libs', includes: ['*.jar'])
    //compile files('libs/android-support-v4.jar')
    //compile files("${System.getenv('ANDROID_HOME')}/extras/android/support/v4/android-support-v4.jar")
    //compile project('file:../yutori_lib')
   compile project(':yutori_lib')	//仮想パス版
}

これで


android_yutori
build.gradle //空
settings.gradle //☆ここ修正
yutori_history
build.gradle //メインプロジェクト本体
yutori_lib
build.gradle //空
settings.gradle //[☓]今回ここが悪影響!!
yutori_lib
build.gradle //サブプロジェクト本体


上記の考察に関してコメントをいただきました。
間違った認識ならG師匠に教えて欲しいけど、G系の人Android興味ない<嫌いな人が多い>からなー(苦笑

http://twitter.com/kimukou2628/status/336401379444785152:twitter:detail:right

自分の理想形はこうなら動くはずだけど、settingsDirを使って絶対パス化すればマルチ出来るかもしれな・・
(今だとsettings.gradleがカレントから見にこうとして解釈できないよ!と確かに言っているようにみえる)
ので検証してみる

  • yutori_hisotory/settings.gradle
//yutori_prg.projectDir=new File(settingsDir,'../yutori_lib/yutori_lib')
yutori_prg.projectDir=new File(settingsDir,'../yutori_lib')
  • yutori_lib/settings.gradle
include ':yutori_lib'

def yutori_prg = project(':yutori_lib');
//yutori_prg.projectDir=new File(settingsDir,"yutori_lib/")  //[NG]settingsDirが多分親の見てるから。。
yutori_prg.projectDir=new File(settingsDir,"../yutori_lib/yutori_lib") //[NG]親からみたと同じ想定にしてみる。でもだめ
println yutori_prg.projectDir

とこう変更してみる
やはり予想通り動かない。残念。


A problem occurred configuring project ':yutori_hisotory'.
> Failed to notify project evaluation listener.
   > Configuration with name 'default' not found.

多分gradle自体にその想定がなかったんだと思うです*6


MainP
settings.gradle
MainP
LibP
settings.gradle(:LibP記述)//<= ここの設定を現在再帰で読まない
LibP //現在はここを直指定しないと駄目
build.gradle



 原型っぽいプロジェクトの情報もいただきました。 *7

GitHub - jvoegele/gradle-android-plugin: Android plugin for the Gradle build system.
とだいぶ構成違うな。。。(汗


だと、どこまでサポートされてるかよくわかんないんで task一覧を表示してみる*8


./gradlew tasks

                                                                                                                      • -

All tasks runnable from root project

                                                                                                                      • -

Android tasks

                        • -

androidDependencies - Displays the Android dependencies of the project
signingReport - Displays the signing info for each variant

Build tasks

                    • -

assemble - Assembles all variants of all applications and secondary packages.
assembleDebug - Assembles all Debug builds
assembleRelease - Assembles all Release builds
assembleTest - Assembles the Test build for the Debug build
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
clean - Deletes the build directory.

Build Setup tasks

                                • -

setupBuild - Initializes a new Gradle build. [incubating]

Help tasks

                  • -

dependencies - Displays all dependencies declared in root project 'android_yutori_as'.
dependencyInsight - Displays the insight into a specific dependency in root project 'android_yutori_as'.
help - Displays a help message
projects - Displays the sub-projects of root project 'android_yutori_as'.
properties - Displays the properties of root project 'android_yutori_as'.
tasks - Displays the tasks runnable from root project 'android_yutori_as' (some of the displayed tasks may belong to subprojects).

IDE tasks

                • -

cleanEclipse - Cleans all Eclipse files.
eclipse - Generates all Eclipse files.

Install tasks

                        • -

installDebug - Installs the Debug build
installTest - Installs the Test build for the Debug build
uninstallAll - Uninstall all applications.
uninstallDebug - Uninstalls the Debug build
uninstallRelease - Uninstalls the Release build
uninstallTest - Uninstalls the Test build for the Debug build

Verification tasks

                                  • -

check - Runs all checks.
connectedCheck - Runs all device checks on currently connected devices.
connectedInstrumentTest - Installs and runs the tests for Build 'Debug' on connected devices.
deviceCheck - Runs all device checks using Device Providers and Test Servers.

To see all tasks and more detail, run with --all.

BUILD SUCCESSFUL

な感じ。

これみてると


./gradlew clean build installDebug
のデバック転送はあるけど、release転送はない感じ・・・

apk自体は
android_yutori/yutori_hisotry/build/apk に

  • yutori_hisotory-debug-unaligned.apk
  • yutori_hisotory-release-unsigned.apk


./gradlew clean assemble
っぽいなー と思ってためしてみるけど変化なし。

  • まだrelease build (署名付き)が 出来ないみたいですね。。。
  • installRelease がそれに当たるのかも(まだタスクがない)
    • これはeclipseGUIにもないからかな? 自分はその手のインストまで遣ってくれるスクリプト作っちゃってるけど
  • proguardの設定も見つからないな。。


備考

 signingConfigs {
        myConfig {
            storeFile file("yutori.keystore")
            keyAlias "yutori_history"
            keyPassword "yutori_world"
            storePassword "yutori_black_world"
        }
    }

    buildTypes {
        release {
            signingConfig signingConfigs.myConfig
        }
    }


./gradlew assembleRelease
で作れ的な話があるようですけど


./gradlew build
でも出来た感じ。

でも


./gradlew installRelease
はまだ何故無いんだろう??

備考

そうか。。

println android.buildTypes.release.dump()

あたりすればよかったのか。。。マニュアルだけ見て頑張ろうとしてた。。(汗

    buildTypes {
        release {
            debuggable false //☆
            runProguard true  //☆
            signingConfig signingConfigs.myConfig
        }
    }

☆を追記すればよかったのね。。
コードにドキュメントが全く追いついてないですね。皆さん混乱するわけだわ。。。

でも記述の状態のままだとまだ問題はあって除外設定を読み込まない

  • proguard-project.txt
-dontwarn twitter4j.**
-dontnote twitter4j.**
-keep class twitter4j.** {*;}
  • project.properties
target=android-17
#android.library=true
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

と設定してももちろん効かない

でfkmさんがやったみたいにDSLをdumpして追っていきましょう。

println "[buildTypes]${buildTypes.release.dump()}"
[buildTypes]<com.android.build.gradle.internal.dsl.BuildTypeDsl_Decorated@3c31db1d
dynamicObjectHelper=org.gradle.api.internal.AsmBackedClassGenerator$MixInExtensibleDynamicObject@3dab3ff9
mapping=org.gradle.api.internal.ConventionAwareHelper@35f51410
signingConfigSet=true
renderscriptDebugBuildSet=false
proguardFilesSet=false
versionNameSuffixSet=false
runProguardSet=true
debuggableSet=true
jniDebugBuildSet=false
nameSet=false
zipAlignSet=false
packageNameSuffixSet=false
renderscriptOptimLevelSet=false
buildConfigSet=false
proguardFiles=[]
mName=release
mDebuggable=false
mJniDebugBuild=false
mRenderscriptDebugBuild=false
mRenderscriptOptimLevel=3
mPackageNameSuffix=null
mVersionNameSuffix=null
mRunProguard=true
mSigningConfig=SigningConfigDsl_Decorated{name=myConfig,
storeFile=/Users/kimura/Documents/workspace/ShojiPosPos_v5/key,
storePassword=android,
keyAlias=posposshoji,
keyPassword=android,
storeType=/Users/kimura/Documents/workspace/ShojiPosPos_v5/key}
mZipAlign=true
mBuildConfigLines=[]>

とでてきますので
proguardFilesに値を設定すればよさそうです

でbuildTypes DSLの下に下記イメージで追加していきます

/*	
	buildTypes.release.proguardFiles.add "${ANDROID_HOME}/tools/proguard/proguard-android.txt"
	//buildTypes.release.proguardFiles.add "${System.getenv('ANDROID_HOME')}/tools/proguard/proguard-android.txt"
	buildTypes.release.proguardFiles.add "proguard-project.txt"
*/
	buildTypes.release.proguardFiles = [
		"${ANDROID_HOME}/tools/proguard/proguard-android.txt",
                //"${System.getenv('ANDROID_HOME')}/tools/proguard/proguard-android.txt",
		"proguard-project.txt"
	] //as ArrayList
	
	//println "[buildTypes]${buildTypes.release.dump()}"
	println "[buildTypes.proguardFiles]${buildTypes.release.proguardFiles.dump()}"

無事に通るようになりました。

一応こういう設定方法もあるようです

buildTypes.release.proguardFile getDefaultProguardFile('proguard-android.txt')
buildTypes.release.proguardFile file('proguard-project.txt')

getDefaultProguardFile の場合は
${sdk.dir}/tools/proguard/proguard-android.txt
を見てくれるらしいので、こちらの指定のほうが少し楽そうですねーでも

buildTypes.release.proguardFile の指定だと後勝ちしていないかどうか不安
と思って確認してみたら

[buildTypes.proguardFiles]<java.util.ArrayList@c58ac617
elementData=[
$ANDROID_HOME/tools/proguard/proguard-android.txt,
XXX/GradleAndroidNdkExample-master/proguard-project.txt,
null,
null,
null,
null,
null,
null,
null,
null]
size=2
modCount=2>

で確かにAddされてる動きなので問題無さそうですね

*1:これGradleやABSのMLでも解決策出てなかったりしてたので、実は超すごいことなんですよね。。

*2:gradleは毎回 _JAVA_OPTIONS の方実行時の参照してるよう・・・

*3:./gradlew だとreadonlyだと警告

*4:MultiProjectの相対パス指定はビルド職人の方々の夢だったので

*5:既存のLibraryProjectの構成が頭にあると確かにそうなる

*6:仮想パスを使った遣り方はgradle公式Docにも記載がない。。。

*7:これは実はドンピシャで、今現在Androidのレポで管理されているらしい。あの言及のあとalterakeyさんandroidのレポのコード直接読んで解析進めてたw

*8:将来的なことまで書いてる気がするので