creator_tools/tools/aapt2/compile.rs
1use std::path::{Path, PathBuf};
2use std::process::Command;
3
4/// # Compile
5/// AAPT2 supports compilation of all Android resource types, such as drawables and XML
6/// files. When you invoke AAPT2 for compilation, you should pass a single resource file
7/// as an input per invocation. AAPT2 then parses the file and generates an intermediate
8/// binary file with a .flat extension.
9///
10/// Although you can pass resource directories containing more than one resource files to
11/// AAPT2 using the --dir flag, you do not gain the benefits of incremental resource
12/// compilation when doing so. That is, when passing whole directories, AAPT2 recompiles
13/// all files in the directory even when only one resource has changed.
14///
15/// The output file types can differ based on the input you provide for compilation.
16/// The files AAPT2 outputs are not executables and you must later include these binary
17/// files as input in the link phase to generate an APK. However, the generated APK file
18/// is not an executable that you can deploy on an Android device right away, as it does
19/// not contain DEX files (compiled bytecode) and is not signed.
20///
21/// ## Compile syntax
22/// The general syntax for using compile is as follows:
23///
24/// ```sh
25/// aapt2 compile path-to-input-files [options] -o output-directory/
26/// ```
27/// ### Note
28/// For resource files, the path to input files must match the following structure:
29/// ```sh
30/// path/resource-type[-config]/file
31/// ```
32///
33/// In the following example, AAPT2 compiles resource files named values.xml and
34/// myImage.png individually:
35///
36/// ```sh
37/// aapt2 compile project_root/module_root/src/main/res/values-en/strings.xml -o compiled/
38/// aapt2 compile project_root/module_root/src/main/res/drawable/myImage.png -o compiled/
39/// ```
40///
41/// As shown in the table above, the name of the output file depends on the input file
42/// name and the name of its parent directory (the resource type and configuration).
43/// For the example above with strings.xml as input, aapt2 automatically names the output
44/// file as values-en_strings.arsc.flat. On the other hand, the file name for the compiled
45/// drawable file stored in the drawable directory will be drawable_img.png.flat.
46pub struct Aapt2Compile {
47 input: PathBuf,
48 /// Specifies the output path for the compiled resource(s).
49 ///
50 /// This is a required flag because you must specify a path to a directory where AAPT2
51 /// can output and store the compiled resources.
52 o: PathBuf,
53 /// Specifies the directory to scan for resources.
54 ///
55 /// Although you can use this flag to compile multiple resource files with one
56 /// command, it disables the benefits of incremental compilation and thus, should not
57 /// be used for large projects.
58 dir: Option<PathBuf>,
59 /// Generates pseudo-localized versions of default strings, such as en-XA and en-XB.
60 pseudo_localize: bool,
61 /// Disables PNG processing.
62 ///
63 /// Use this option if you have already processed the PNG files, or if you are
64 /// creating debug builds that do not require file size reduction. Enabling this
65 /// option results in a faster execution, but increases the output file size.
66 no_crunch: bool,
67 /// Treats errors that are permissible when using earlier versions of AAPT as
68 /// warnings.
69 ///
70 /// This flag should be used for unexpected compile time errors.
71 /// To resolve known behavior changes that you might get while using AAPT2, read
72 /// [Behavior changes in AAPT2.](https://developer.android.com/studio/command-line/aapt2#aapt2_changes)
73 legacy: bool,
74 /// Enable verbose logging.
75 v: bool,
76}
77
78impl Aapt2Compile {
79 pub fn new(input: &Path, o: &Path) -> Self {
80 Self {
81 input: input.to_owned(),
82 o: o.to_owned(),
83 dir: None,
84 pseudo_localize: false,
85 no_crunch: false,
86 legacy: false,
87 v: false,
88 }
89 }
90
91 pub fn dir(&mut self, dir: &Path) -> &mut Self {
92 self.dir = Some(dir.to_owned());
93 self
94 }
95
96 pub fn pseudo_localize(&mut self) -> &mut Self {
97 self.pseudo_localize = true;
98 self
99 }
100
101 pub fn no_crunch(&mut self) -> &mut Self {
102 self.no_crunch = true;
103 self
104 }
105
106 pub fn legacy(&mut self) -> &mut Self {
107 self.legacy = true;
108 self
109 }
110
111 pub fn v(&mut self) -> &mut Self {
112 self.v = true;
113 self
114 }
115
116 pub fn run(&self) {
117 let mut aapt2 = Command::new("aapt2");
118 aapt2.arg("compile");
119 aapt2.arg(&self.input);
120 aapt2.arg("-o").arg(&self.o);
121 if let Some(dir) = &self.dir {
122 aapt2.arg("--dir").arg(dir);
123 }
124 if self.pseudo_localize {
125 aapt2.arg("--pseudo-localize");
126 }
127 if self.no_crunch {
128 aapt2.arg("--no-crunch");
129 }
130 if self.legacy {
131 aapt2.arg("--legacy");
132 }
133 if self.v {
134 aapt2.arg("-v");
135 }
136 aapt2.output().expect("failed to execute process"); // TODO: Remove expect
137 }
138}