1use super::aapt2_tool;
2use crate::error::{CommandExt, Error, Result};
3use std::path::{Path, PathBuf};
4
5#[derive(Debug, Default)]
40pub struct Aapt2Link {
41 inputs: Vec<PathBuf>,
42 compiled_res: Option<PathBuf>,
43 output_apk: PathBuf,
44 manifest: PathBuf,
45 android_jar: Option<PathBuf>,
46 assets: Option<PathBuf>,
47 individual_flat: Option<PathBuf>,
48 package_id: Option<String>,
49 allow_reserved_package_id: bool,
50 java: Option<PathBuf>,
51 proguard_options: Option<PathBuf>,
52 proguard_main_dex: Option<PathBuf>,
53 proguard_conditional_keep_rules: bool,
54 proguard_minimal_keep_rules: bool,
55 no_auto_version: bool,
56 no_version_vectors: bool,
57 no_version_transitions: bool,
58 no_resource_deduping: bool,
59 no_resource_removal: bool,
60 enable_sparse_encoding: bool,
61 package_identifier: bool,
62 suggested_strings: bool,
63 config: Vec<String>,
64 preferred_density: Option<i32>,
65 product: Option<PathBuf>,
66 output_to_dir: Option<PathBuf>,
67 no_xml_namespaces: bool,
68 min_sdk_version: Option<u32>,
69 target_sdk_version: Option<u32>,
70 version_code: Option<u32>,
71 version_code_major: Option<u32>,
72 version_name: Option<String>,
73 replace_version: bool,
74 compile_sdk_version_code: Option<u32>,
75 compile_sdk_version_name: Option<String>,
76 shared_lib: bool,
77 static_lib: bool,
78 proto_format: bool,
79 no_static_lib_packages: bool,
80 non_final_ids: bool,
81 no_proguard_location_reference: bool,
82 emit_ids: Option<PathBuf>,
83 stable_ids: Option<PathBuf>,
84 private_symbols: Option<String>,
85 custom_package: Option<PathBuf>,
86 extra_packages: Option<PathBuf>,
87 add_javadoc_annotation: Option<String>,
88 output_text_symbols: Option<PathBuf>,
89 auto_add_overlay: bool,
90 override_styles_instead_of_overlaying: bool,
91 rename_manifest_package: Option<String>,
92 rename_resources_package: Option<String>,
93 rename_instrumentation_target_package: Option<String>,
94 extensions: Vec<String>,
95 no_compress: bool,
96 keep_raw_values: bool,
97 no_compress_regex: Option<String>,
98 warn_manifest_validation: bool,
99 split: Option<PathBuf>,
100 strict_visibility: bool,
101 exclude_sources: bool,
102 trace_folder: Option<String>,
103 merge_only: bool,
104 verbose: bool,
105 help: bool,
106}
107
108impl Aapt2Link {
109 pub fn new(inputs: &[PathBuf], output_apk: &Path, manifest: &Path) -> Self {
119 Self {
120 inputs: inputs.to_vec(),
121 compiled_res: None,
122 output_apk: output_apk.to_owned(),
123 manifest: manifest.to_owned(),
124 ..Default::default()
125 }
126 }
127
128 pub fn new_from_compiled_res(
138 compiled_res: Option<PathBuf>,
139 output_apk: &Path,
140 manifest: &Path,
141 ) -> Self {
142 Self {
143 inputs: Vec::new(),
144 compiled_res,
145 output_apk: output_apk.to_owned(),
146 manifest: manifest.to_owned(),
147 ..Default::default()
148 }
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
157 pub fn proguard_minimal_keep_rules(&mut self, proguard_minimal_keep_rules: bool) -> &mut Self {
159 self.proguard_minimal_keep_rules = proguard_minimal_keep_rules;
160 self
161 }
162
163 pub fn no_resource_removal(&mut self, no_resource_removal: bool) -> &mut Self {
165 self.no_resource_removal = no_resource_removal;
166 self
167 }
168 pub fn package_identifier(&mut self, package_identifier: bool) -> &mut Self {
170 self.package_identifier = package_identifier;
171 self
172 }
173
174 pub fn product(&mut self, product: PathBuf) -> &mut Self {
176 self.product = Some(product);
177 self
178 }
179
180 pub fn no_xml_namespaces(&mut self, no_xml_namespaces: bool) -> &mut Self {
182 self.no_xml_namespaces = no_xml_namespaces;
183 self
184 }
185
186 pub fn version_code_major(&mut self, version_code_major: u32) -> &mut Self {
189 self.version_code_major = Some(version_code_major);
190 self
191 }
192
193 pub fn version_name(&mut self, version_name: String) -> &mut Self {
195 self.version_name = Some(version_name);
196 self
197 }
198
199 pub fn replace_version(&mut self, replace_version: bool) -> &mut Self {
203 self.replace_version = replace_version;
204 self
205 }
206
207 pub fn compile_sdk_version_code(&mut self, compile_sdk_version_code: u32) -> &mut Self {
209 self.compile_sdk_version_code = Some(compile_sdk_version_code);
210 self
211 }
212
213 pub fn shared_lib(&mut self, shared_lib: bool) -> &mut Self {
215 self.shared_lib = shared_lib;
216 self
217 }
218
219 pub fn static_lib(&mut self, static_lib: bool) -> &mut Self {
221 self.static_lib = static_lib;
222 self
223 }
224
225 pub fn no_static_lib_packages(&mut self, no_static_lib_packages: bool) -> &mut Self {
227 self.no_static_lib_packages = no_static_lib_packages;
228 self
229 }
230
231 pub fn no_proguard_location_reference(
233 &mut self,
234 no_proguard_location_reference: bool,
235 ) -> &mut Self {
236 self.no_proguard_location_reference = no_proguard_location_reference;
237 self
238 }
239
240 pub fn private_symbols(&mut self, private_symbols: String) -> &mut Self {
243 self.private_symbols = Some(private_symbols);
244 self
245 }
246
247 pub fn override_styles_instead_of_overlaying(
250 &mut self,
251 override_styles_instead_of_overlaying: bool,
252 ) -> &mut Self {
253 self.override_styles_instead_of_overlaying = override_styles_instead_of_overlaying;
254 self
255 }
256
257 pub fn rename_resources_package(&mut self, rename_resources_package: String) -> &mut Self {
259 self.rename_resources_package = Some(rename_resources_package);
260 self
261 }
262
263 pub fn android_jar(&mut self, android_jar: PathBuf) -> &mut Self {
268 self.android_jar = Some(android_jar);
269 self
270 }
271
272 pub fn assets(&mut self, assets: PathBuf) -> &mut Self {
279 self.assets = Some(assets);
280 self
281 }
282
283 pub fn individual_flat(&mut self, individual_flat: PathBuf) -> &mut Self {
289 self.individual_flat = Some(individual_flat);
290 self
291 }
292
293 pub fn package_id(&mut self, package_id: String) -> &mut Self {
298 self.package_id = Some(package_id);
299 self
300 }
301
302 pub fn allow_reserved_package_id(&mut self, allow_reserved_package_id: bool) -> &mut Self {
311 self.allow_reserved_package_id = allow_reserved_package_id;
312 self
313 }
314
315 pub fn java(&mut self, java: PathBuf) -> &mut Self {
317 self.java = Some(java);
318 self
319 }
320
321 pub fn proguard_options(&mut self, proguard_options: PathBuf) -> &mut Self {
323 self.proguard_options = Some(proguard_options);
324 self
325 }
326
327 pub fn proguard_conditional_keep_rules(
329 &mut self,
330 proguard_conditional_keep_rules: bool,
331 ) -> &mut Self {
332 self.proguard_conditional_keep_rules = proguard_conditional_keep_rules;
333 self
334 }
335
336 pub fn no_auto_version(&mut self, no_auto_version: bool) -> &mut Self {
338 self.no_auto_version = no_auto_version;
339 self
340 }
341
342 pub fn no_version_vectors(&mut self, no_version_vectors: bool) -> &mut Self {
345 self.no_version_vectors = no_version_vectors;
346 self
347 }
348
349 pub fn no_version_transitions(&mut self, no_version_transitions: bool) -> &mut Self {
352 self.no_version_transitions = no_version_transitions;
353 self
354 }
355
356 pub fn no_resource_deduping(&mut self, no_resource_deduping: bool) -> &mut Self {
359 self.no_resource_deduping = no_resource_deduping;
360 self
361 }
362
363 pub fn enable_sparse_encoding(&mut self, enable_sparse_encoding: bool) -> &mut Self {
366 self.enable_sparse_encoding = enable_sparse_encoding;
367 self
368 }
369
370 pub fn suggested_strings(&mut self, suggested_strings: bool) -> &mut Self {
372 self.suggested_strings = suggested_strings;
373 self
374 }
375
376 pub fn config(&mut self, config: String) -> &mut Self {
386 self.config.push(config);
387 self
388 }
389
390 pub fn preferred_density(&mut self, preferred_density: i32) -> &mut Self {
396 self.preferred_density = Some(preferred_density);
397 self
398 }
399
400 pub fn output_to_dir(&mut self, output_to_dir: &Path) -> &mut Self {
407 self.output_to_dir = Some(output_to_dir.to_path_buf());
408 self
409 }
410
411 pub fn min_sdk_version(&mut self, min_sdk_version: u32) -> &mut Self {
413 self.min_sdk_version = Some(min_sdk_version);
414 self
415 }
416
417 pub fn target_sdk_version(&mut self, target_sdk_version: u32) -> &mut Self {
419 self.target_sdk_version = Some(target_sdk_version);
420 self
421 }
422
423 pub fn version_code(&mut self, version_code: u32) -> &mut Self {
426 self.version_code = Some(version_code);
427 self
428 }
429
430 pub fn compile_sdk_version_name(&mut self, compile_sdk_version_name: String) -> &mut Self {
433 self.compile_sdk_version_name = Some(compile_sdk_version_name);
434 self
435 }
436
437 pub fn proto_format(&mut self, proto_format: bool) -> &mut Self {
442 self.proto_format = proto_format;
443 self
444 }
445
446 pub fn non_final_ids(&mut self, non_final_ids: bool) -> &mut Self {
449 self.non_final_ids = non_final_ids;
450 self
451 }
452
453 pub fn emit_ids(&mut self, emit_ids: PathBuf) -> &mut Self {
456 self.emit_ids = Some(emit_ids);
457 self
458 }
459
460 pub fn stable_ids(&mut self, stable_ids: PathBuf) -> &mut Self {
466 self.stable_ids = Some(stable_ids);
467 self
468 }
469
470 pub fn custom_package(&mut self, custom_package: PathBuf) -> &mut Self {
472 self.custom_package = Some(custom_package);
473 self
474 }
475
476 pub fn extra_packages(&mut self, extra_packages: PathBuf) -> &mut Self {
478 self.extra_packages = Some(extra_packages);
479 self
480 }
481
482 pub fn add_javadoc_annotation(&mut self, add_javadoc_annotation: String) -> &mut Self {
484 self.add_javadoc_annotation = Some(add_javadoc_annotation);
485 self
486 }
487
488 pub fn output_text_symbols(&mut self, output_text_symbols: PathBuf) -> &mut Self {
493 self.output_text_symbols = Some(output_text_symbols);
494 self
495 }
496
497 pub fn auto_add_overlay(&mut self, auto_add_overlay: bool) -> &mut Self {
500 self.auto_add_overlay = auto_add_overlay;
501 self
502 }
503
504 pub fn rename_manifest_package(&mut self, rename_manifest_package: String) -> &mut Self {
506 self.rename_manifest_package = Some(rename_manifest_package);
507 self
508 }
509
510 pub fn rename_instrumentation_target_package(
516 &mut self,
517 rename_instrumentation_target_package: String,
518 ) -> &mut Self {
519 self.rename_instrumentation_target_package = Some(rename_instrumentation_target_package);
520 self
521 }
522
523 pub fn no_compress(&mut self, no_compress: bool) -> &mut Self {
525 self.no_compress = no_compress;
526 self
527 }
528
529 pub fn keep_raw_values(&mut self, keep_raw_values: bool) -> &mut Self {
531 self.keep_raw_values = keep_raw_values;
532 self
533 }
534
535 pub fn extension(&mut self, extension: String) -> &mut Self {
537 self.extensions.push(extension);
538 self
539 }
540
541 pub fn no_compress_regex(&mut self, no_compress_regex: String) -> &mut Self {
545 self.no_compress_regex = Some(no_compress_regex);
546 self
547 }
548
549 pub fn warn_manifest_validation(&mut self, warn_manifest_validation: bool) -> &mut Self {
551 self.warn_manifest_validation = warn_manifest_validation;
552 self
553 }
554
555 pub fn split(&mut self, split: PathBuf) -> &mut Self {
560 self.split = Some(split);
561 self
562 }
563
564 pub fn strict_visibility(&mut self, strict_visibility: bool) -> &mut Self {
566 self.strict_visibility = strict_visibility;
567 self
568 }
569
570 pub fn trace_folder(&mut self, trace_folder: String) -> &mut Self {
572 self.trace_folder = Some(trace_folder);
573 self
574 }
575
576 pub fn exclude_sources(&mut self, exclude_sources: bool) -> &mut Self {
579 self.exclude_sources = exclude_sources;
580 self
581 }
582
583 pub fn merge_only(&mut self, merge_only: bool) -> &mut Self {
586 self.merge_only = merge_only;
587 self
588 }
589
590 pub fn verbose(&mut self, verbose: bool) -> &mut Self {
592 self.verbose = verbose;
593 self
594 }
595
596 pub fn help(&mut self, help: bool) -> &mut Self {
598 self.help = help;
599 self
600 }
601
602 pub fn run(&self) -> Result<PathBuf> {
604 let mut aapt2 = aapt2_tool()?;
605 aapt2.arg("link");
606 if !self.inputs.is_empty() {
607 self.inputs.iter().for_each(|input| {
608 aapt2.arg(input);
609 });
610 } else if let Some(compiled_res) = &self.compiled_res {
611 let paths = std::fs::read_dir(compiled_res)
612 .map_err(|_| Error::CompiledResourcesNotFound)?
613 .flat_map(|e| e.map(|x| x.path()))
614 .collect::<Vec<_>>();
615 paths.iter().for_each(|input| {
616 if !input.ends_with("AndroidManifest.xml") {
617 aapt2.arg(input);
618 }
619 });
620 }
621 aapt2.arg("-o").arg(&self.output_apk);
622 aapt2.arg("--manifest").arg(&self.manifest);
623 if let Some(android_jar) = &self.android_jar {
624 aapt2.arg("-I").arg(android_jar);
625 }
626 if let Some(assets) = &self.assets {
627 aapt2.arg("-A").arg(assets);
628 }
629 if let Some(individual_flat) = &self.individual_flat {
630 aapt2.arg("-R").arg(individual_flat);
631 }
632 if let Some(package_id) = &self.package_id {
633 aapt2.arg("--package-id").arg(package_id);
634 }
635 if self.allow_reserved_package_id {
636 aapt2.arg("--allow-reserved-package-id");
637 }
638 if let Some(java) = &self.java {
639 aapt2.arg("--java").arg(java);
640 }
641 if let Some(proguard_options) = &self.proguard_options {
642 aapt2.arg("--proguard").arg(proguard_options);
643 }
644 if self.proguard_conditional_keep_rules {
645 aapt2.arg("--proguard-conditional-keep-rules");
646 }
647 if self.no_auto_version {
648 aapt2.arg("--no-auto-version");
649 }
650 if self.no_version_vectors {
651 aapt2.arg("--no-version-vectors");
652 }
653 if self.no_version_transitions {
654 aapt2.arg("--no-version-transitions");
655 }
656 if self.no_resource_deduping {
657 aapt2.arg("--no-resource-deduping");
658 }
659 if self.enable_sparse_encoding {
660 aapt2.arg("--enable-sparse-encoding");
661 }
662 if self.suggested_strings {
663 aapt2.arg("-z");
664 }
665 if !self.config.is_empty() {
666 aapt2.arg("-c").arg(self.config.join(","));
667 }
668 if let Some(preferred_density) = self.preferred_density {
669 aapt2
670 .arg("--preferred-density")
671 .arg(preferred_density.to_string());
672 }
673 if let Some(output_to_dir) = &self.output_to_dir {
674 aapt2.arg("--output-to-dir").arg("-o").arg(output_to_dir);
675 }
676 if let Some(min_sdk_version) = self.min_sdk_version {
677 aapt2
678 .arg("--min-sdk-version")
679 .arg(min_sdk_version.to_string());
680 }
681 if let Some(target_sdk_version) = self.target_sdk_version {
682 aapt2
683 .arg("--target-sdk-version")
684 .arg(target_sdk_version.to_string());
685 }
686 if let Some(version_code) = &self.version_code {
687 aapt2.arg("--version-code").arg(version_code.to_string());
688 }
689 if let Some(compile_sdk_version_name) = &self.compile_sdk_version_name {
690 aapt2
691 .arg("--compile-sdk-version-name")
692 .arg(compile_sdk_version_name);
693 }
694 if self.proto_format {
695 aapt2.arg("--proto-format");
696 }
697 if self.non_final_ids {
698 aapt2.arg("--non-final-ids");
699 }
700 if let Some(emit_ids) = &self.emit_ids {
701 aapt2.arg("--emit-ids").arg(emit_ids);
702 }
703 if let Some(stable_ids) = &self.stable_ids {
704 aapt2.arg("--stable-ids").arg(stable_ids);
705 }
706 if let Some(custom_package) = &self.custom_package {
707 aapt2.arg("--custom-package").arg(custom_package);
708 }
709 if let Some(extra_packages) = &self.extra_packages {
710 aapt2.arg("--extra-packages").arg(extra_packages);
711 }
712 if let Some(add_javadoc_annotation) = &self.add_javadoc_annotation {
713 aapt2
714 .arg("--add-javadoc-annotation")
715 .arg(add_javadoc_annotation);
716 }
717 if let Some(output_text_symbols) = &self.output_text_symbols {
718 aapt2.arg("--output-text-symbols").arg(output_text_symbols);
719 }
720 if self.auto_add_overlay {
721 aapt2.arg("--auto-add-overlay");
722 }
723 if let Some(rename_manifest_package) = &self.rename_manifest_package {
724 aapt2
725 .arg("--rename-manifest-package")
726 .arg(rename_manifest_package);
727 }
728 if let Some(rename_instrumentation_target_package) =
729 &self.rename_instrumentation_target_package
730 {
731 aapt2
732 .arg("--rename-instrumentation-target-package")
733 .arg(rename_instrumentation_target_package);
734 }
735 self.extensions.iter().for_each(|extension| {
736 aapt2.arg("-0").arg(extension);
737 });
738 if let Some(split) = &self.split {
739 aapt2.arg("--split").arg(split);
740 }
741 if self.verbose {
742 aapt2.arg("-v");
743 }
744 if self.help {
745 aapt2.arg("-h");
746 }
747 if let Some(proguard_main_dex) = &self.proguard_main_dex {
748 aapt2.arg("--proguard-main-dex").arg(proguard_main_dex);
749 }
750 if self.proguard_minimal_keep_rules {
751 aapt2.arg("--proguard-minimal-keep-rules");
752 }
753 if self.no_resource_removal {
754 aapt2.arg("--no-resource-removal");
755 }
756 if self.package_identifier {
757 aapt2.arg("-x");
758 }
759 if let Some(product) = &self.product {
760 aapt2.arg("--product").arg(product);
761 }
762 if self.no_xml_namespaces {
763 aapt2.arg("--no-xml-namespaces");
764 }
765 if let Some(version_code_major) = &self.version_code_major {
766 aapt2
767 .arg("--version-code-major")
768 .arg(version_code_major.to_string());
769 }
770 if let Some(version_name) = &self.version_name {
771 aapt2.arg("--version-name").arg(version_name);
772 }
773 if self.replace_version {
774 aapt2.arg("--replace-version");
775 }
776 if let Some(compile_sdk_version_code) = &self.compile_sdk_version_code {
777 aapt2
778 .arg("--compile-sdk-version-code")
779 .arg(compile_sdk_version_code.to_string());
780 }
781 if self.shared_lib {
782 aapt2.arg("--shared-lib");
783 }
784 if self.static_lib {
785 aapt2.arg("--static-lib");
786 }
787 if self.no_static_lib_packages {
788 aapt2.arg("--no-static-lib-packages");
789 }
790 if self.no_proguard_location_reference {
791 aapt2.arg("--no-proguard-location-reference");
792 }
793 if let Some(private_symbols) = &self.private_symbols {
794 aapt2.arg("--private-symbols").arg(private_symbols);
795 }
796 if self.override_styles_instead_of_overlaying {
797 aapt2.arg("--override-styles-instead-of-overlaying");
798 }
799 if let Some(rename_resources_package) = &self.rename_resources_package {
800 aapt2
801 .arg("--rename-resources-package")
802 .arg(rename_resources_package);
803 }
804 if self.no_compress {
805 aapt2.arg("--no-compress");
806 }
807 if self.keep_raw_values {
808 aapt2.arg("--keep-raw-values");
809 }
810 if let Some(no_compress_regex) = &self.no_compress_regex {
811 aapt2.arg("--no-compress-regex").arg(no_compress_regex);
812 }
813 if self.warn_manifest_validation {
814 aapt2.arg("--warn-manifest-validation");
815 }
816 if self.strict_visibility {
817 aapt2.arg("--strict-visibility");
818 }
819 if self.exclude_sources {
820 aapt2.arg("--exclude-sources");
821 }
822 if let Some(trace_folder) = &self.trace_folder {
823 aapt2.arg("--trace-folder").arg(trace_folder);
824 }
825 if self.merge_only {
826 aapt2.arg("--merge-only");
827 }
828 aapt2.output_err(true)?;
829 Ok(self.output_apk.clone())
830 }
831}