简体   繁体   English

巴克 - 构建具有多种Gradle风格/构建类型和清单的Android应用程序

[英]Buck - building android app with multiple Gradle flavors/build types and manifests

I'm working on a project where we have several modules, each one of these with a number of dependencies to other modules, and so on and so forth. 我正在开发一个项目,我们有几个模块,每个模块都有许多依赖于其他模块,依此类推。 We migrated our project to Gradle (and also changed the structure to accommodate it to Gradle's defaults) some time ago because we needed versatility when building different versions of the app: free vs paid, debug (no proguard) vs release (proguard), etc. We were really thrilled when we completed the migration, but this happiness quickly became diluted in a puddle of mud when the build time started to become a pain. 我们之前将项目迁移到Gradle(并且还改变了结构以适应Gradle的默认值),因为我们在构建应用程序的不同版本时需要多功能性:免费与付费,调试(无程序)与发布(proguard)等当我们完成迁移时,我们感到非常激动,但是当构建时间开始成为一种痛苦时,这种快乐很快就会在泥浆中被稀释。 Making a rather simple change in the code and deploy the app on the phone takes anywhere 90-120 seconds, and that is simply unacceptable. 对代码进行相当简单的更改并在手机上部署应用程序需要90-120秒,这简直是不可接受的。

So we decided to give Buck a try, as we have heard nothing but good words from other developers. 所以我们决定尝试一下巴克,因为我们只听到其他开发者的好话。 After very little time (way less than with Gradle) we managed to build our app successfully (which, unfortunately, doesn't mean "generating an APK correctly", but at least it built). 经过很短的时间(比使用Gradle的方式少)我们成功地构建了我们的应用程序(不幸的是,这并不意味着“正确生成APK”,但至少它已构建)。 The thing is that, as a general rule, we have one manifest file per flavor, and unless I have overlooked something fundamental, Buck only lets you specify manifest files when using the rule android_binary . 问题是,作为一般规则,我们每种口味都有一个清单文件,除非我忽略了一些基本的东西,否则Buck只允许您在使用规则android_binary时指定清单文件。 The result of this is that the generated APK's manifest file contains only the boilerplate code of the first level module from which Gradle's build chain starts: 结果是生成的APK的清单文件仅包含Gradle的构建链从其开始的第一级模块的样板代码:

main -> debug -> free/paid -> common

That is, the manifest file only contains main's manifest. 也就是说,清单文件只包含main的清单。 This rule is located in the top level BUCK file, which is the file that contains the alias specified in .buckconfig. 此规则位于顶级BUCK文件中,该文件包含.buckconfig中指定的别名。

I'm pretty sure I'm doing something wrong. 我很确定我做错了什么。 It wouldn't make sense Buck doesn't allow you to not have multiple manifests. 没有任何意义,巴克不允许你没有多个清单。

Any ideas? 有任何想法吗?

Francis Toth ( https://stackoverflow.com/users/1873643/francis-toth ) came up with a very comprehensive explanation in the Buck discussion group: Francis Toth( https://stackoverflow.com/users/1873643/francis-toth )在Buck讨论组中提出了一个非常全面的解释:

Just to give you the context, I have an application composed of different library modules, each having an Android-Manifest, some resources, assets etc... and a BUCK file which pretty much look like this : 为了给你上下文,我有一个由不同的库模块组成的应用程序,每个模块都有一个Android-Manifest,一些资源,资产等......以及一个看起来像这样的BUCK文件:

android_library(
  name = 'src',
  srcs = glob(['src/main/java/**/*.java']),
  deps = DEPENDENCIES + [':res'],
  visibility = [ 'PUBLIC' ],
  exported_deps = DEPENDENCIES
)

android_resource(
  name = 'manifest',
  manifest = 'src/main/AndroidManifest.xml',
  deps = ['//othermodule:manifest'],
  visibility = [ 'PUBLIC' ],
)

android_resource(
  name = 'assets',
  assets = 'src/main/assets',
  visibility = [ 'PUBLIC' ],
)

android_resource(
  name = 'res',
  res = 'src/main/res',
  package = 'com.sherpa.android',
  visibility = [ 'PUBLIC' ],
)

project_config(
  src_target = ':src',
  src_roots = ['src/main/java']
)

My app BUCK file looks like this : 我的app BUCK文件看起来像这样:

android_binary (
  name = 'bin',
  manifest = ':manifest', # Here I make a reference on the android_manifest build rule described below
  target = 'Google Inc.:Google APIs:19',
  keystore = ':debug_keystore',
  deps = BINARY_DEPENDENCIES
)

MANIFEST_DEPENDENCIES = ['//module1:manifest', '//module2:manifest']
android_manifest (
  name = 'manifest',
  skeleton = 'AndroidManifest.xml', # The app's base manifest
  deps = MANIFEST_DEPENDENCIES # App's manifest will be merged with all its dependencies (module1 and module2's manifest)
)

Your problem, as far as I understand seems to be pretty similar. 你的问题,据我所知,似乎非常相似。 In order to merge the manifest, you have to create a android_resource build rule which tells where is your module library along with the manifests it has to be merged with. 为了合并清单,你必须创建一个android_resource构建规则,它告诉你的模块库在哪里以及必须与它合并的清单。

And that solved my problem :-) 这解决了我的问题:-)

In buck the manifest merger will never override anything in the manifest tag. 在buck中,清单合并将永远不会覆盖清单标记中的任何内容。 That includes the package attribute, the debuggable attribute, etc. 这包括package属性,debuggable属性等。

There is a feature of manifest_entries in android_binary that isn't documented but it's how OKBuck does build flavors. android_binary中有一个manifest_entries的功能,没有记录,但它是OKBuck构建风格的方式。 Before packaging the manifest, any placeholders in manifest_entries get substituted for any expressions in AndroidManifest.xml 在打包清单之前,manifest_entries中的任何占位符都将替换AndroidManifest.xml中的任何表达式

So if your manifest tag looks something like this: 因此,如果您的清单标记看起来像这样:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package = "com.whatever${flavor}"
   android:debuggable = "${debuggable}"
>

And your manifest_entries in your android_binary looks like this: 而android_binary中的manifest_entries如下所示:

  manifest_entries = {
    'placeholders': {
      'flavor': '.test',
      'debuggable': 'true',
    },
  },

The resulting manifest will look like this: 生成的清单将如下所示:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package = "com.whatever.test"
   android:debuggable = "true"
>

Then you can build up your manifest_entries placeholders with dictionary manipulation and flatten_dicts() 然后,您可以使用字典操作和flatten_dicts()构建manifest_entries占位符

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM