• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef AAPT2_LINK_H
18 #define AAPT2_LINK_H
19 
20 #include <optional>
21 #include <regex>
22 #include <string>
23 #include <unordered_map>
24 #include <unordered_set>
25 #include <vector>
26 
27 #include "Command.h"
28 #include "Resource.h"
29 #include "androidfw/IDiagnostics.h"
30 #include "cmd/Util.h"
31 #include "format/binary/TableFlattener.h"
32 #include "format/proto/ProtoSerialize.h"
33 #include "link/ManifestFixer.h"
34 #include "split/TableSplitter.h"
35 #include "trace/TraceBuffer.h"
36 
37 namespace aapt {
38 
39 enum class OutputFormat {
40   kApk,
41   kProto,
42 };
43 
44 struct LinkOptions {
45   std::string output_path;
46   std::string manifest_path;
47   std::vector<std::string> include_paths;
48   std::vector<std::string> overlay_files;
49   std::vector<std::string> assets_dirs;
50   bool output_to_directory = false;
51   bool auto_add_overlay = false;
52   bool override_styles_instead_of_overlaying = false;
53   OutputFormat output_format = OutputFormat::kApk;
54   std::optional<std::string> rename_resources_package;
55 
56   // Java/Proguard options.
57   std::optional<std::string> generate_java_class_path;
58   std::optional<std::string> custom_java_package;
59   std::set<std::string> extra_java_packages;
60   std::optional<std::string> generate_text_symbols_path;
61   std::optional<std::string> generate_proguard_rules_path;
62   std::optional<std::string> generate_main_dex_proguard_rules_path;
63   bool generate_conditional_proguard_rules = false;
64   bool generate_minimal_proguard_rules = false;
65   bool generate_non_final_ids = false;
66   bool no_proguard_location_reference = false;
67   std::vector<std::string> javadoc_annotations;
68   std::optional<std::string> private_symbols;
69 
70   // Optimizations/features.
71   bool no_auto_version = false;
72   bool no_version_vectors = false;
73   bool no_version_transitions = false;
74   bool no_resource_deduping = false;
75   bool no_resource_removal = false;
76   bool no_xml_namespaces = false;
77   bool do_not_compress_anything = false;
78   bool use_sparse_encoding = false;
79   std::unordered_set<std::string> extensions_to_not_compress;
80   std::optional<std::regex> regex_to_not_compress;
81   bool no_compress_fonts = false;
82   FeatureFlagValues feature_flag_values;
83 
84   // Static lib options.
85   bool no_static_lib_packages = false;
86   bool merge_only = false;
87 
88   // AndroidManifest.xml massaging options.
89   ManifestFixerOptions manifest_fixer_options;
90 
91   // Products to use/filter on.
92   std::unordered_set<std::string> products;
93 
94   // Flattening options.
95   TableFlattenerOptions table_flattener_options;
96   SerializeTableOptions proto_table_flattener_options;
97   bool keep_raw_values = false;
98 
99   // Split APK options.
100   TableSplitterOptions table_splitter_options;
101   std::vector<SplitConstraints> split_constraints;
102   std::vector<std::string> split_paths;
103 
104   // Configurations to exclude
105   std::vector<std::string> exclude_configs_;
106 
107   // Stable ID options.
108   std::unordered_map<ResourceName, ResourceId> stable_id_map;
109   std::optional<std::string> resource_id_map_path;
110 
111   // When 'true', allow reserved package IDs to be used for applications. Pre-O, the platform
112   // treats negative resource IDs [those with a package ID of 0x80 or higher] as invalid.
113   // In order to work around this limitation, we allow the use of traditionally reserved
114   // resource IDs [those between 0x02 and 0x7E].
115   bool allow_reserved_package_id = false;
116 
117   // Whether we should fail on definitions of a resource with conflicting visibility.
118   bool strict_visibility = false;
119 };
120 
121 class LinkCommand : public Command {
122  public:
LinkCommand(android::IDiagnostics * diag)123   explicit LinkCommand(android::IDiagnostics* diag) : Command("link", "l"), diag_(diag) {
124     SetDescription("Links resources into an apk.");
125     AddRequiredFlag("-o", "Output path.", &options_.output_path, Command::kPath);
126     AddRequiredFlag("--manifest", "Path to the Android manifest to build.",
127         &options_.manifest_path, Command::kPath);
128     AddOptionalFlagList("-I", "Adds an Android APK to link against.", &options_.include_paths,
129          Command::kPath);
130     AddOptionalFlagList("-A", "An assets directory to include in the APK. These are unprocessed.",
131         &options_.assets_dirs, Command::kPath);
132     AddOptionalFlagList("-R", "Compilation unit to link, using `overlay` semantics.\n"
133         "The last conflicting resource given takes precedence.", &overlay_arg_list_,
134         Command::kPath);
135     AddOptionalFlag("--package-id",
136         "Specify the package ID to use for this app. Must be greater or equal to\n"
137             "0x7f and can't be used with --static-lib or --shared-lib.", &package_id_);
138     AddOptionalFlag("--java", "Directory in which to generate R.java.",
139         &options_.generate_java_class_path, Command::kPath);
140     AddOptionalFlag("--proguard", "Output file for generated Proguard rules.",
141         &options_.generate_proguard_rules_path, Command::kPath);
142     AddOptionalFlag("--proguard-main-dex",
143         "Output file for generated Proguard rules for the main dex.",
144         &options_.generate_main_dex_proguard_rules_path, Command::kPath);
145     AddOptionalSwitch("--proguard-conditional-keep-rules",
146         "Generate conditional Proguard keep rules.",
147         &options_.generate_conditional_proguard_rules);
148     AddOptionalSwitch("--proguard-minimal-keep-rules",
149         "Generate a minimal set of Proguard keep rules.",
150         &options_.generate_minimal_proguard_rules);
151     AddOptionalSwitch("--no-auto-version", "Disables automatic style and layout SDK versioning.",
152         &options_.no_auto_version);
153     AddOptionalSwitch("--no-version-vectors",
154         "Disables automatic versioning of vector drawables. Use this only\n"
155             "when building with vector drawable support library.",
156         &options_.no_version_vectors);
157     AddOptionalSwitch("--no-version-transitions",
158         "Disables automatic versioning of transition resources. Use this only\n"
159             "when building with transition support library.",
160         &options_.no_version_transitions);
161     AddOptionalSwitch("--no-resource-deduping", "Disables automatic deduping of resources with\n"
162             "identical values across compatible configurations.",
163         &options_.no_resource_deduping);
164     AddOptionalSwitch("--no-resource-removal", "Disables automatic removal of resources without\n"
165             "defaults. Use this only when building runtime resource overlay packages.",
166         &options_.no_resource_removal);
167     AddOptionalSwitch(
168         "--enable-sparse-encoding",
169         "Enables encoding sparse entries using a binary search tree.\n"
170         "This decreases APK size at the cost of resource retrieval performance.\n"
171         "Only applies sparse encoding if minSdk of the APK is >= 32",
172         &options_.use_sparse_encoding);
173     AddOptionalSwitch("--enable-compact-entries",
174         "This decreases APK size by using compact resource entries for simple data types.",
175         &options_.table_flattener_options.use_compact_entries);
176     AddOptionalSwitch("-x", "Legacy flag that specifies to use the package identifier 0x01.",
177         &legacy_x_flag_);
178     AddOptionalSwitch("-z", "Require localization of strings marked 'suggested'.",
179         &require_localization_);
180     AddOptionalFlagList("-c",
181         "Comma separated list of configurations to include. The default\n"
182             "is all configurations.", &configs_);
183     AddOptionalFlag("--preferred-density",
184         "Selects the closest matching density and strips out all others.",
185         &preferred_density_);
186     AddOptionalFlag("--product", "Comma separated list of product names to keep", &product_list_);
187     AddOptionalSwitch("--output-to-dir", "Outputs the APK contents to a directory specified by -o.",
188         &options_.output_to_directory);
189     AddOptionalSwitch("--no-xml-namespaces", "Removes XML namespace prefix and URI information\n"
190             "from AndroidManifest.xml and XML binaries in res/*.",
191         &options_.no_xml_namespaces);
192     AddOptionalFlag("--min-sdk-version",
193         "Default minimum SDK version to use for AndroidManifest.xml.",
194         &options_.manifest_fixer_options.min_sdk_version_default);
195     AddOptionalFlag("--target-sdk-version",
196         "Default target SDK version to use for AndroidManifest.xml.",
197         &options_.manifest_fixer_options.target_sdk_version_default);
198     AddOptionalFlag("--version-code",
199         "Version code (integer) to inject into the AndroidManifest.xml if none is\n"
200             "present.", &options_.manifest_fixer_options.version_code_default);
201     AddOptionalFlag("--version-code-major",
202         "Version code major (integer) to inject into the AndroidManifest.xml if none is\n"
203             "present.", &options_.manifest_fixer_options.version_code_major_default);
204     AddOptionalFlag("--version-name",
205         "Version name to inject into the AndroidManifest.xml if none is present.",
206         &options_.manifest_fixer_options.version_name_default);
207     AddOptionalFlag("--revision-code",
208         "Revision code (integer) to inject into the AndroidManifest.xml if none is\n"
209             "present.", &options_.manifest_fixer_options.revision_code_default);
210     AddOptionalSwitch("--replace-version",
211         "If --version-code, --version-name, and/or --revision-code are specified, these\n"
212             "values will replace any value already in the manifest. By\n"
213             "default, nothing is changed if the manifest already defines\n"
214             "these attributes.",
215         &options_.manifest_fixer_options.replace_version);
216     AddOptionalFlag("--compile-sdk-version-code",
217         "Version code (integer) to inject into the AndroidManifest.xml if none is\n"
218             "present.",
219         &options_.manifest_fixer_options.compile_sdk_version);
220     AddOptionalFlag("--compile-sdk-version-name",
221         "Version name to inject into the AndroidManifest.xml if none is present.",
222         &options_.manifest_fixer_options.compile_sdk_version_codename);
223     AddOptionalSwitch(
224         "--no-compile-sdk-metadata",
225         "Suppresses output of compile SDK-related attributes in AndroidManifest.xml,\n"
226         "including android:compileSdkVersion and platformBuildVersion.",
227         &options_.manifest_fixer_options.no_compile_sdk_metadata);
228     AddOptionalFlagList("--fingerprint-prefix", "Fingerprint prefix to add to install constraints.",
229                         &options_.manifest_fixer_options.fingerprint_prefixes);
230     AddOptionalSwitch("--shared-lib", "Generates a shared Android runtime library.",
231         &shared_lib_);
232     AddOptionalSwitch("--static-lib", "Generate a static Android library.", &static_lib_);
233     AddOptionalSwitch("--proto-format",
234         "Generates compiled resources in Protobuf format.\n"
235             "Suitable as input to the bundle tool for generating an App Bundle.",
236         &proto_format_);
237     AddOptionalSwitch("--no-static-lib-packages",
238         "Merge all library resources under the app's package.",
239         &options_.no_static_lib_packages);
240     AddOptionalSwitch("--non-final-ids",
241         "Generates R.java without the final modifier. This is implied when\n"
242             "--static-lib is specified.",
243         &options_.generate_non_final_ids);
244     AddOptionalSwitch("--no-proguard-location-reference",
245         "Keep proguard rules files from having a reference to the source file",
246         &options_.no_proguard_location_reference);
247     AddOptionalFlag("--stable-ids", "File containing a list of name to ID mapping.",
248         &stable_id_file_path_);
249     AddOptionalFlag("--emit-ids",
250         "Emit a file at the given path with a list of name to ID mappings,\n"
251             "suitable for use with --stable-ids.",
252         &options_.resource_id_map_path);
253     AddOptionalFlag("--private-symbols",
254         "Package name to use when generating R.java for private symbols.\n"
255             "If not specified, public and private symbols will use the application's\n"
256             "package name.",
257         &options_.private_symbols);
258     AddOptionalFlag("--custom-package", "Custom Java package under which to generate R.java.",
259         &options_.custom_java_package);
260     AddOptionalFlagList("--extra-packages",
261         "Generate the same R.java but with different package names.",
262         &extra_java_packages_);
263     AddOptionalFlagList("--add-javadoc-annotation",
264         "Adds a JavaDoc annotation to all generated Java classes.",
265         &options_.javadoc_annotations);
266     AddOptionalFlag("--output-text-symbols",
267         "Generates a text file containing the resource symbols of the R class in\n"
268             "the specified folder.",
269         &options_.generate_text_symbols_path);
270     AddOptionalSwitch("--allow-reserved-package-id",
271         "Allows the use of a reserved package ID. This should on be used for\n"
272             "packages with a pre-O min-sdk\n",
273         &options_.allow_reserved_package_id);
274     AddOptionalSwitch("--auto-add-overlay",
275         "Allows the addition of new resources in overlays without\n"
276             "<add-resource> tags.",
277         &options_.auto_add_overlay);
278     AddOptionalSwitch("--override-styles-instead-of-overlaying",
279         "Causes styles defined in -R resources to replace previous definitions\n"
280             "instead of merging into them\n",
281         &options_.override_styles_instead_of_overlaying);
282     AddOptionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml.",
283         &options_.manifest_fixer_options.rename_manifest_package);
284     AddOptionalFlag("--rename-resources-package", "Renames the package in resources table",
285         &options_.rename_resources_package);
286     AddOptionalFlag("--rename-instrumentation-target-package",
287         "Changes the name of the target package for instrumentation. Most useful\n"
288             "when used in conjunction with --rename-manifest-package.",
289         &options_.manifest_fixer_options.rename_instrumentation_target_package);
290     AddOptionalFlag("--rename-overlay-target-package",
291         "Changes the name of the target package for overlay. Most useful\n"
292             "when used in conjunction with --rename-manifest-package.",
293         &options_.manifest_fixer_options.rename_overlay_target_package);
294     AddOptionalFlag("--rename-overlay-category", "Changes the category for the overlay.",
295                     &options_.manifest_fixer_options.rename_overlay_category);
296     AddOptionalFlagList("-0", "File suffix not to compress.",
297         &options_.extensions_to_not_compress);
298     AddOptionalSwitch("--no-compress", "Do not compress any resources.",
299         &options_.do_not_compress_anything);
300     AddOptionalSwitch("--keep-raw-values", "Preserve raw attribute values in xml files.",
301         &options_.keep_raw_values);
302     AddOptionalFlag("--no-compress-regex",
303         "Do not compress extensions matching the regular expression. Remember to\n"
304             "use the '$' symbol for end of line. Uses a case-sensitive ECMAScript"
305             "regular expression grammar.",
306         &no_compress_regex);
307     AddOptionalSwitch("--no-compress-fonts",
308         "Do not compress files with common extensions for fonts.\n"
309             "This allows loading fonts directly from the APK, without needing to\n"
310             "decompress them first. Loading fonts will be faster and use less memory.\n"
311             "The downside is that the APK will be larger.\n"
312             "Passing this flag is functionally equivalent to passing the following flags:\n"
313             "-0 .ttf -0 .otf -0 .ttc",
314         &options_.no_compress_fonts);
315     AddOptionalSwitch("--warn-manifest-validation",
316         "Treat manifest validation errors as warnings.",
317         &options_.manifest_fixer_options.warn_validation);
318     AddOptionalFlagList("--split",
319         "Split resources matching a set of configs out to a Split APK.\n"
320             "Syntax: path/to/output.apk:<config>[,<config>[...]].\n"
321             "On Windows, use a semicolon ';' separator instead.",
322         &split_args_);
323     AddOptionalFlagList("--exclude-configs",
324         "Excludes values of resources whose configs contain the specified qualifiers.",
325         &options_.exclude_configs_);
326     AddOptionalSwitch("--debug-mode",
327         "Inserts android:debuggable=\"true\" in to the application node of the\n"
328             "manifest, making the application debuggable even on production devices.",
329         &options_.manifest_fixer_options.debug_mode);
330     AddOptionalSwitch("--strict-visibility",
331         "Do not allow overlays with different visibility levels.",
332         &options_.strict_visibility);
333     AddOptionalSwitch("--exclude-sources",
334         "Do not serialize source file information when generating resources in\n"
335             "Protobuf format.",
336         &options_.proto_table_flattener_options.exclude_sources);
337     AddOptionalFlag("--trace-folder",
338         "Generate systrace json trace fragment to specified folder.",
339         &trace_folder_);
340     AddOptionalSwitch("--merge-only",
341         "Only merge the resources, without verifying resource references. This flag\n"
342             "should only be used together with the --static-lib flag.",
343         &options_.merge_only);
344     AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
345     AddOptionalFlagList("--feature-flags",
346                         "Specify the values of feature flags. The pairs in the argument\n"
347                         "are separated by ',' the name is separated from the value by '='.\n"
348                         "The name can have a suffix of ':ro' to indicate it is read only."
349                         "Example: \"flag1=true,flag2:ro=false,flag3=\" (flag3 has no given value).",
350                         &feature_flags_args_);
351     AddOptionalSwitch("--non-updatable-system",
352                       "Mark the app as a non-updatable system app. This inserts\n"
353                       "updatableSystem=\"false\" to the root manifest node, overwriting any\n"
354                       "existing attribute. This is ignored if the manifest has a versionCode.",
355                       &options_.manifest_fixer_options.non_updatable_system);
356   }
357 
358   int Action(const std::vector<std::string>& args) override;
359 
360  private:
361   android::IDiagnostics* diag_;
362   LinkOptions options_;
363 
364   std::vector<std::string> overlay_arg_list_;
365   std::vector<std::string> extra_java_packages_;
366   std::optional<std::string> package_id_;
367   std::vector<std::string> configs_;
368   std::optional<std::string> preferred_density_;
369   std::optional<std::string> product_list_;
370   std::optional<std::string> no_compress_regex;
371   bool legacy_x_flag_ = false;
372   bool require_localization_ = false;
373   bool verbose_ = false;
374   bool shared_lib_ = false;
375   bool static_lib_ = false;
376   bool proto_format_ = false;
377   std::optional<std::string> stable_id_file_path_;
378   std::vector<std::string> split_args_;
379   std::optional<std::string> trace_folder_;
380   std::vector<std::string> feature_flags_args_;
381 };
382 
383 }// namespace aapt
384 
385 #endif //AAPT2_LINK_H
386