1use crate::error::{CommandExt, Result};
2use std::{
3 path::{Path, PathBuf},
4 process::Command,
5};
6
7#[derive(Debug, PartialEq, Default)]
42pub struct Aapt2Link {
43 inputs: Vec<PathBuf>,
44 compiled_res: Option<PathBuf>,
45 output_apk: PathBuf,
46 manifest: PathBuf,
47 android_jar: Option<PathBuf>,
48 assets: Option<PathBuf>,
49 individual_flat: Option<PathBuf>,
50 package_id: Option<String>,
51 allow_reserved_package_id: bool,
52 java: Option<PathBuf>,
53 proguard_options: Option<PathBuf>,
54 proguard_main_dex: Option<PathBuf>,
55 proguard_conditional_keep_rules: bool,
56 proguard_minimal_keep_rules: bool,
57 no_auto_version: bool,
58 no_version_vectors: bool,
59 no_version_transitions: bool,
60 no_resource_deduping: bool,
61 no_resource_removal: bool,
62 enable_sparse_encoding: bool,
63 package_identifier: bool,
64 suggested_strings: bool,
65 config: Vec<String>,
66 preferred_density: Option<i32>,
67 product: Option<PathBuf>,
68 output_to_dir: bool,
69 no_xml_namespaces: bool,
70 min_sdk_version: Option<u32>,
71 target_sdk_version: Option<u32>,
72 version_code: Option<u32>,
73 version_code_major: Option<u32>,
74 version_name: Option<String>,
75 replace_version: bool,
76 compile_sdk_version_code: Option<u32>,
77 compile_sdk_version_name: Option<String>,
78 shared_lib: bool,
79 static_lib: bool,
80 proto_format: bool,
81 no_static_lib_packages: bool,
82 non_final_ids: bool,
83 no_proguard_location_reference: bool,
84 emit_ids: Option<PathBuf>,
85 stable_ids: Option<PathBuf>,
86 private_symbols: Option<String>,
87 custom_package: Option<PathBuf>,
88 extra_packages: Option<PathBuf>,
89 add_javadoc_annotation: Option<String>,
90 output_text_symbols: Option<PathBuf>,
91 auto_add_overlay: bool,
92 override_styles_instead_of_overlaying: bool,
93 rename_manifest_package: Option<String>,
94 rename_resources_package: Option<String>,
95 rename_instrumentation_target_package: Option<String>,
96 extensions: Vec<String>,
97 no_compress: bool,
98 keep_raw_values: bool,
99 no_compress_regex: Option<String>,
100 warn_manifest_validation: bool,
101 split: Option<PathBuf>,
102 strict_visibility: bool,
103 exclude_sources: bool,
104 trace_folder: Option<String>,
105 merge_only: bool,
106 verbose: bool,
107 help: bool,
108}
109
110impl Aapt2Link {
111 pub fn new(inputs: &[PathBuf], output_apk: &Path, manifest: &Path) -> Self {
121 Self {
122 inputs: inputs.to_vec(),
123 compiled_res: None,
124 output_apk: output_apk.to_owned(),
125 manifest: manifest.to_owned(),
126 ..Default::default()
127 }
128 }
129 pub fn new_from_compiled_res(
139 compiled_res: Option<PathBuf>,
140 output_apk: &Path,
141 manifest: &Path,
142 ) -> Self {
143 Self {
144 inputs: Vec::new(),
145 compiled_res,
146 output_apk: output_apk.to_owned(),
147 manifest: manifest.to_owned(),
148 ..Default::default()
149 }
150 }
151 pub fn proguard_main_dex(&mut self, proguard_main_dex: PathBuf) -> &mut Self {
153 self.proguard_main_dex = Some(proguard_main_dex);
154 self
155 }
156 pub fn proguard_minimal_keep_rules(&mut self, proguard_minimal_keep_rules: bool) -> &mut Self {
158 self.proguard_minimal_keep_rules = proguard_minimal_keep_rules;
159 self
160 }
161 pub fn no_resource_removal(&mut self, no_resource_removal: bool) -> &mut Self {
163 self.no_resource_removal = no_resource_removal;
164 self
165 }
166 pub fn package_identifier(&mut self, package_identifier: bool) -> &mut Self {
168 self.package_identifier = package_identifier;
169 self
170 }
171 pub fn product(&mut self, product: PathBuf) -> &mut Self {
173 self.product = Some(product);
174 self
175 }
176 pub fn no_xml_namespaces(&mut self, no_xml_namespaces: bool) -> &mut Self {
178 self.no_xml_namespaces = no_xml_namespaces;
179 self
180 }
181 pub fn version_code_major(&mut self, version_code_major: u32) -> &mut Self {
184 self.version_code_major = Some(version_code_major);
185 self
186 }
187 pub fn version_name(&mut self, version_name: String) -> &mut Self {
189 self.version_name = Some(version_name);
190 self
191 }
192 pub fn replace_version(&mut self, replace_version: bool) -> &mut Self {
196 self.replace_version = replace_version;
197 self
198 }
199 pub fn compile_sdk_version_code(&mut self, compile_sdk_version_code: u32) -> &mut Self {
201 self.compile_sdk_version_code = Some(compile_sdk_version_code);
202 self
203 }
204 pub fn shared_lib(&mut self, shared_lib: bool) -> &mut Self {
206 self.shared_lib = shared_lib;
207 self
208 }
209 pub fn static_lib(&mut self, static_lib: bool) -> &mut Self {
211 self.static_lib = static_lib;
212 self
213 }
214 pub fn no_static_lib_packages(&mut self, no_static_lib_packages: bool) -> &mut Self {
216 self.no_static_lib_packages = no_static_lib_packages;
217 self
218 }
219 pub fn no_proguard_location_reference(
221 &mut self,
222 no_proguard_location_reference: bool,
223 ) -> &mut Self {
224 self.no_proguard_location_reference = no_proguard_location_reference;
225 self
226 }
227 pub fn private_symbols(&mut self, private_symbols: String) -> &mut Self {
230 self.private_symbols = Some(private_symbols);
231 self
232 }
233 pub fn override_styles_instead_of_overlaying(
236 &mut self,
237 override_styles_instead_of_overlaying: bool,
238 ) -> &mut Self {
239 self.override_styles_instead_of_overlaying = override_styles_instead_of_overlaying;
240 self
241 }
242 pub fn rename_resources_package(&mut self, rename_resources_package: String) -> &mut Self {
244 self.rename_resources_package = Some(rename_resources_package);
245 self
246 }
247 pub fn android_jar(&mut self, android_jar: PathBuf) -> &mut Self {
252 self.android_jar = Some(android_jar);
253 self
254 }
255 pub fn assets(&mut self, assets: PathBuf) -> &mut Self {
262 self.assets = Some(assets);
263 self
264 }
265 pub fn individual_flat(&mut self, individual_flat: PathBuf) -> &mut Self {
271 self.individual_flat = Some(individual_flat);
272 self
273 }
274 pub fn package_id(&mut self, package_id: String) -> &mut Self {
279 self.package_id = Some(package_id);
280 self
281 }
282 pub fn allow_reserved_package_id(&mut self, allow_reserved_package_id: bool) -> &mut Self {
291 self.allow_reserved_package_id = allow_reserved_package_id;
292 self
293 }
294 pub fn java(&mut self, java: PathBuf) -> &mut Self {
296 self.java = Some(java);
297 self
298 }
299 pub fn proguard_options(&mut self, proguard_options: PathBuf) -> &mut Self {
301 self.proguard_options = Some(proguard_options);
302 self
303 }
304 pub fn proguard_conditional_keep_rules(
306 &mut self,
307 proguard_conditional_keep_rules: bool,
308 ) -> &mut Self {
309 self.proguard_conditional_keep_rules = proguard_conditional_keep_rules;
310 self
311 }
312 pub fn no_auto_version(&mut self, no_auto_version: bool) -> &mut Self {
314 self.no_auto_version = no_auto_version;
315 self
316 }
317 pub fn no_version_vectors(&mut self, no_version_vectors: bool) -> &mut Self {
320 self.no_version_vectors = no_version_vectors;
321 self
322 }
323 pub fn no_version_transitions(&mut self, no_version_transitions: bool) -> &mut Self {
326 self.no_version_transitions = no_version_transitions;
327 self
328 }
329 pub fn no_resource_deduping(&mut self, no_resource_deduping: bool) -> &mut Self {
332 self.no_resource_deduping = no_resource_deduping;
333 self
334 }
335 pub fn enable_sparse_encoding(&mut self, enable_sparse_encoding: bool) -> &mut Self {
338 self.enable_sparse_encoding = enable_sparse_encoding;
339 self
340 }
341 pub fn suggested_strings(&mut self, suggested_strings: bool) -> &mut Self {
343 self.suggested_strings = suggested_strings;
344 self
345 }
346 pub fn config(&mut self, config: String) -> &mut Self {
356 self.config.push(config);
357 self
358 }
359 pub fn preferred_density(&mut self, preferred_density: i32) -> &mut Self {
365 self.preferred_density = Some(preferred_density);
366 self
367 }
368 pub fn output_to_dir(&mut self, output_to_dir: bool) -> &mut Self {
375 self.output_to_dir = output_to_dir;
376 self
377 }
378 pub fn min_sdk_version(&mut self, min_sdk_version: u32) -> &mut Self {
380 self.min_sdk_version = Some(min_sdk_version);
381 self
382 }
383 pub fn target_sdk_version(&mut self, target_sdk_version: u32) -> &mut Self {
385 self.target_sdk_version = Some(target_sdk_version);
386 self
387 }
388 pub fn version_code(&mut self, version_code: u32) -> &mut Self {
391 self.version_code = Some(version_code);
392 self
393 }
394 pub fn compile_sdk_version_name(&mut self, compile_sdk_version_name: String) -> &mut Self {
397 self.compile_sdk_version_name = Some(compile_sdk_version_name);
398 self
399 }
400 pub fn proto_format(&mut self, proto_format: bool) -> &mut Self {
405 self.proto_format = proto_format;
406 self
407 }
408 pub fn non_final_ids(&mut self, non_final_ids: bool) -> &mut Self {
411 self.non_final_ids = non_final_ids;
412 self
413 }
414 pub fn emit_ids(&mut self, emit_ids: PathBuf) -> &mut Self {
417 self.emit_ids = Some(emit_ids);
418 self
419 }
420 pub fn stable_ids(&mut self, stable_ids: PathBuf) -> &mut Self {
426 self.stable_ids = Some(stable_ids);
427 self
428 }
429 pub fn custom_package(&mut self, custom_package: PathBuf) -> &mut Self {
431 self.custom_package = Some(custom_package);
432 self
433 }
434 pub fn extra_packages(&mut self, extra_packages: PathBuf) -> &mut Self {
436 self.extra_packages = Some(extra_packages);
437 self
438 }
439 pub fn add_javadoc_annotation(&mut self, add_javadoc_annotation: String) -> &mut Self {
441 self.add_javadoc_annotation = Some(add_javadoc_annotation);
442 self
443 }
444 pub fn output_text_symbols(&mut self, output_text_symbols: PathBuf) -> &mut Self {
449 self.output_text_symbols = Some(output_text_symbols);
450 self
451 }
452 pub fn auto_add_overlay(&mut self, auto_add_overlay: bool) -> &mut Self {
455 self.auto_add_overlay = auto_add_overlay;
456 self
457 }
458 pub fn rename_manifest_package(&mut self, rename_manifest_package: String) -> &mut Self {
460 self.rename_manifest_package = Some(rename_manifest_package);
461 self
462 }
463 pub fn rename_instrumentation_target_package(
469 &mut self,
470 rename_instrumentation_target_package: String,
471 ) -> &mut Self {
472 self.rename_instrumentation_target_package = Some(rename_instrumentation_target_package);
473 self
474 }
475 pub fn no_compress(&mut self, no_compress: bool) -> &mut Self {
477 self.no_compress = no_compress;
478 self
479 }
480 pub fn keep_raw_values(&mut self, keep_raw_values: bool) -> &mut Self {
482 self.keep_raw_values = keep_raw_values;
483 self
484 }
485 pub fn extension(&mut self, extension: String) -> &mut Self {
487 self.extensions.push(extension);
488 self
489 }
490 pub fn no_compress_regex(&mut self, no_compress_regex: String) -> &mut Self {
494 self.no_compress_regex = Some(no_compress_regex);
495 self
496 }
497 pub fn warn_manifest_validation(&mut self, warn_manifest_validation: bool) -> &mut Self {
499 self.warn_manifest_validation = warn_manifest_validation;
500 self
501 }
502 pub fn split(&mut self, split: PathBuf) -> &mut Self {
507 self.split = Some(split);
508 self
509 }
510 pub fn strict_visibility(&mut self, strict_visibility: bool) -> &mut Self {
512 self.strict_visibility = strict_visibility;
513 self
514 }
515 pub fn trace_folder(&mut self, trace_folder: String) -> &mut Self {
517 self.trace_folder = Some(trace_folder);
518 self
519 }
520 pub fn exclude_sources(&mut self, exclude_sources: bool) -> &mut Self {
523 self.exclude_sources = exclude_sources;
524 self
525 }
526 pub fn merge_only(&mut self, merge_only: bool) -> &mut Self {
529 self.merge_only = merge_only;
530 self
531 }
532 pub fn verbose(&mut self, verbose: bool) -> &mut Self {
534 self.verbose = verbose;
535 self
536 }
537 pub fn help(&mut self, help: bool) -> &mut Self {
539 self.help = help;
540 self
541 }
542
543 pub fn run(&self) -> Result<()> {
544 let mut aapt2 = Command::new("aapt2");
545 aapt2.arg("link");
546 if !self.inputs.is_empty() {
547 self.inputs.iter().for_each(|input| {
548 aapt2.arg(input);
549 });
550 } else if let Some(compiled_res) = &self.compiled_res {
551 let paths = std::fs::read_dir(compiled_res)?
553 .map(|e| e.map(|x| x.path()))
554 .flatten()
555 .collect::<Vec<_>>();
556 paths.iter().for_each(|input| {
557 aapt2.arg(input);
558 });
559 }
560 aapt2.arg("-o").arg(&self.output_apk);
561 aapt2.arg("--manifest").arg(&self.manifest);
562 if let Some(android_jar) = &self.android_jar {
563 aapt2.arg("-I").arg(android_jar);
564 }
565 if let Some(assets) = &self.assets {
566 aapt2.arg("-A").arg(assets);
567 }
568 if let Some(individual_flat) = &self.individual_flat {
569 aapt2.arg("-R").arg(individual_flat);
570 }
571 if let Some(package_id) = &self.package_id {
572 aapt2.arg("--package-id").arg(package_id);
573 }
574 if self.allow_reserved_package_id {
575 aapt2.arg("--allow-reserved-package-id");
576 }
577 if let Some(java) = &self.java {
578 aapt2.arg("--java").arg(java);
579 }
580 if let Some(proguard_options) = &self.proguard_options {
581 aapt2.arg("--proguard").arg(proguard_options);
582 }
583 if self.proguard_conditional_keep_rules {
584 aapt2.arg("--proguard-conditional-keep-rules");
585 }
586 if self.no_auto_version {
587 aapt2.arg("--no-auto-version");
588 }
589 if self.no_version_vectors {
590 aapt2.arg("--no-version-vectors");
591 }
592 if self.no_version_transitions {
593 aapt2.arg("--no-version-transitions");
594 }
595 if self.no_resource_deduping {
596 aapt2.arg("--no-resource-deduping");
597 }
598 if self.enable_sparse_encoding {
599 aapt2.arg("--enable-sparse-encoding");
600 }
601 if self.suggested_strings {
602 aapt2.arg("-z");
603 }
604 if !self.config.is_empty() {
605 aapt2.arg("-c").arg(self.config.join(","));
606 }
607 if let Some(preferred_density) = self.preferred_density {
608 aapt2
609 .arg("--preferred-density")
610 .arg(preferred_density.to_string());
611 }
612 if self.output_to_dir {
613 aapt2.arg("--output-to-dir");
614 }
615 if let Some(min_sdk_version) = self.min_sdk_version {
616 aapt2
617 .arg("--min-sdk-version")
618 .arg(min_sdk_version.to_string());
619 }
620 if let Some(target_sdk_version) = self.target_sdk_version {
621 aapt2
622 .arg("--target-sdk-version")
623 .arg(target_sdk_version.to_string());
624 }
625 if let Some(version_code) = &self.version_code {
626 aapt2.arg("--version-code").arg(version_code.to_string());
627 }
628 if let Some(compile_sdk_version_name) = &self.compile_sdk_version_name {
629 aapt2
630 .arg("--compile-sdk-version-name")
631 .arg(compile_sdk_version_name);
632 }
633 if self.proto_format {
634 aapt2.arg("--proto-format");
635 }
636 if self.non_final_ids {
637 aapt2.arg("--non-final-ids");
638 }
639 if let Some(emit_ids) = &self.emit_ids {
640 aapt2.arg("--emit-ids").arg(emit_ids);
641 }
642 if let Some(stable_ids) = &self.stable_ids {
643 aapt2.arg("--stable-ids").arg(stable_ids);
644 }
645 if let Some(custom_package) = &self.custom_package {
646 aapt2.arg("--custom-package").arg(custom_package);
647 }
648 if let Some(extra_packages) = &self.extra_packages {
649 aapt2.arg("--extra-packages").arg(extra_packages);
650 }
651 if let Some(add_javadoc_annotation) = &self.add_javadoc_annotation {
652 aapt2
653 .arg("--add-javadoc-annotation")
654 .arg(add_javadoc_annotation);
655 }
656 if let Some(output_text_symbols) = &self.output_text_symbols {
657 aapt2.arg("--output-text-symbols").arg(output_text_symbols);
658 }
659 if self.auto_add_overlay {
660 aapt2.arg("--auto-add-overlay");
661 }
662 if let Some(rename_manifest_package) = &self.rename_manifest_package {
663 aapt2
664 .arg("--rename-manifest-package")
665 .arg(rename_manifest_package);
666 }
667 if let Some(rename_instrumentation_target_package) =
668 &self.rename_instrumentation_target_package
669 {
670 aapt2
671 .arg("--rename-instrumentation-target-package")
672 .arg(rename_instrumentation_target_package);
673 }
674 self.extensions.iter().for_each(|extension| {
675 aapt2.arg("-0").arg(extension);
676 });
677 if let Some(split) = &self.split {
678 aapt2.arg("--split").arg(split);
679 }
680 if self.verbose {
681 aapt2.arg("-v");
682 }
683 if self.help {
684 aapt2.arg("-h");
685 }
686 if let Some(proguard_main_dex) = &self.proguard_main_dex {
687 aapt2.arg("--proguard-main-dex").arg(proguard_main_dex);
688 }
689 if self.proguard_minimal_keep_rules {
690 aapt2.arg("--proguard-minimal-keep-rules");
691 }
692 if self.no_resource_removal {
693 aapt2.arg("--no-resource-removal");
694 }
695 if self.package_identifier {
696 aapt2.arg("-x");
697 }
698 if let Some(product) = &self.product {
699 aapt2.arg("--product").arg(product);
700 }
701 if self.no_xml_namespaces {
702 aapt2.arg("--no-xml-namespaces");
703 }
704 if let Some(version_code_major) = &self.version_code_major {
705 aapt2
706 .arg("--version-code-major")
707 .arg(version_code_major.to_string());
708 }
709 if let Some(version_name) = &self.version_name {
710 aapt2.arg("--version-name").arg(version_name);
711 }
712 if self.replace_version {
713 aapt2.arg("--replace-version");
714 }
715 if let Some(compile_sdk_version_code) = &self.compile_sdk_version_code {
716 aapt2
717 .arg("--compile-sdk-version-code")
718 .arg(compile_sdk_version_code.to_string());
719 }
720 if self.shared_lib {
721 aapt2.arg("--shared-lib");
722 }
723 if self.static_lib {
724 aapt2.arg("--static-lib");
725 }
726 if self.no_static_lib_packages {
727 aapt2.arg("--no-static-lib-packages");
728 }
729 if self.no_proguard_location_reference {
730 aapt2.arg("--no-proguard-location-reference");
731 }
732 if let Some(private_symbols) = &self.private_symbols {
733 aapt2.arg("--private-symbols").arg(private_symbols);
734 }
735 if self.override_styles_instead_of_overlaying {
736 aapt2.arg("--override-styles-instead-of-overlaying");
737 }
738 if let Some(rename_resources_package) = &self.rename_resources_package {
739 aapt2
740 .arg("--rename-resources-package")
741 .arg(rename_resources_package);
742 }
743 if self.no_compress {
744 aapt2.arg("--no-compress");
745 }
746 if self.keep_raw_values {
747 aapt2.arg("--keep-raw-values");
748 }
749 if let Some(no_compress_regex) = &self.no_compress_regex {
750 aapt2.arg("--no-compress-regex").arg(no_compress_regex);
751 }
752 if self.warn_manifest_validation {
753 aapt2.arg("--warn-manifest-validation");
754 }
755 if self.strict_visibility {
756 aapt2.arg("--strict-visibility");
757 }
758 if self.exclude_sources {
759 aapt2.arg("--exclude-sources");
760 }
761 if let Some(trace_folder) = &self.trace_folder {
762 aapt2.arg("--trace-folder").arg(trace_folder);
763 }
764 if self.merge_only {
765 aapt2.arg("--merge-only");
766 }
767 aapt2.output_err(true)?;
768 Ok(())
769 }
770}
771
772