Loading tools/aapt2/cmd/Compile.cpp +16 −4 Original line number Diff line number Diff line Loading @@ -75,8 +75,10 @@ struct ResourcePathData { }; // Resource file paths are expected to look like: [--/res/]type[-config]/name static Maybe<ResourcePathData> ExtractResourcePathData(const std::string& path, const char dir_sep, std::string* out_error) { static Maybe<ResourcePathData> ExtractResourcePathData(const std::string& path, const char dir_sep, std::string* out_error, const CompileOptions& options) { std::vector<std::string> parts = util::Split(path, dir_sep); if (parts.size() < 2) { if (out_error) *out_error = "bad resource path"; Loading Loading @@ -121,7 +123,11 @@ static Maybe<ResourcePathData> ExtractResourcePathData(const std::string& path, } } return ResourcePathData{Source(path), dir_str.to_string(), name.to_string(), const Source res_path = options.source_path ? StringPiece(options.source_path.value()) : StringPiece(path); return ResourcePathData{res_path, dir_str.to_string(), name.to_string(), extension.to_string(), config_str.to_string(), config}; } Loading Loading @@ -667,7 +673,8 @@ int Compile(IAaptContext* context, io::IFileCollection* inputs, IArchiveWriter* // Extract resource type information from the full path std::string err_str; ResourcePathData path_data; if (auto maybe_path_data = ExtractResourcePathData(path, inputs->GetDirSeparator(), &err_str)) { if (auto maybe_path_data = ExtractResourcePathData( path, inputs->GetDirSeparator(), &err_str, options)) { path_data = maybe_path_data.value(); } else { context->GetDiagnostics()->Error(DiagMessage(file->GetSource()) << err_str); Loading Loading @@ -747,6 +754,11 @@ int CompileCommand::Action(const std::vector<std::string>& args) { context.GetDiagnostics()->Error(DiagMessage() << "only one of --dir and --zip can be specified"); return 1; } else if ((options_.res_dir || options_.res_zip) && options_.source_path && args.size() > 1) { context.GetDiagnostics()->Error(DiagMessage(kPath) << "Cannot use an overriding source path with multiple files."); return 1; } else if (options_.res_dir) { if (!args.empty()) { context.GetDiagnostics()->Error(DiagMessage() << "files given but --dir specified"); Loading tools/aapt2/cmd/Compile.h +4 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ namespace aapt { struct CompileOptions { std::string output_path; Maybe<std::string> source_path; Maybe<std::string> res_dir; Maybe<std::string> res_zip; Maybe<std::string> generate_text_symbols_path; Loading Loading @@ -69,6 +70,9 @@ class CompileCommand : public Command { AddOptionalSwitch("-v", "Enables verbose logging", &options_.verbose); AddOptionalFlag("--trace-folder", "Generate systrace json trace fragment to specified folder.", &trace_folder_); AddOptionalFlag("--source-path", "Sets the compiled resource file source file path to the given string.", &options_.source_path); } int Action(const std::vector<std::string>& args) override; Loading tools/aapt2/cmd/Compile_test.cpp +87 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include "io/ZipArchive.h" #include "java/AnnotationProcessor.h" #include "test/Test.h" #include "format/proto/ProtoDeserialize.h" namespace aapt { Loading Loading @@ -253,4 +254,90 @@ TEST_F(CompilerTest, DoNotTranslateTest) { AssertTranslations(this, "donottranslate_foo", expected_not_translatable); } TEST_F(CompilerTest, RelativePathTest) { StdErrDiagnostics diag; const std::string res_path = BuildPath( {android::base::Dirname(android::base::GetExecutablePath()), "integration-tests", "CompileTest", "res"}); const std::string path_values_colors = GetTestPath("values/colors.xml"); WriteFile(path_values_colors, "<resources>" "<color name=\"color_one\">#008577</color>" "</resources>"); const std::string path_layout_layout_one = GetTestPath("layout/layout_one.xml"); WriteFile(path_layout_layout_one, "<LinearLayout " "xmlns:android=\"http://schemas.android.com/apk/res/android\">" "<TextBox android:id=\"@+id/text_one\" android:background=\"@color/color_one\"/>" "</LinearLayout>"); const std::string compiled_files_dir = BuildPath( {android::base::Dirname(android::base::GetExecutablePath()), "integration-tests", "CompileTest", "compiled"}); CHECK(file::mkdirs(compiled_files_dir.data())); const std::string path_values_colors_out = BuildPath({compiled_files_dir,"values_colors.arsc.flat"}); const std::string path_layout_layout_one_out = BuildPath({compiled_files_dir, "layout_layout_one.flat"}); ::android::base::utf8::unlink(path_values_colors_out.c_str()); ::android::base::utf8::unlink(path_layout_layout_one_out.c_str()); const std::string apk_path = BuildPath( {android::base::Dirname(android::base::GetExecutablePath()), "integration-tests", "CompileTest", "out.apk"}); const std::string source_set_res = BuildPath({"main", "res"}); const std::string relative_path_values_colors = BuildPath({source_set_res, "values", "colors.xml"}); const std::string relative_path_layout_layout_one = BuildPath({source_set_res, "layout", "layout_one.xml"}); CompileCommand(&diag).Execute({ path_values_colors, "-o", compiled_files_dir, "--source-path", relative_path_values_colors}, &std::cerr); CompileCommand(&diag).Execute({ path_layout_layout_one, "-o", compiled_files_dir, "--source-path", relative_path_layout_layout_one}, &std::cerr); std::ifstream ifs_values(path_values_colors_out); std::string content_values((std::istreambuf_iterator<char>(ifs_values)), (std::istreambuf_iterator<char>())); ASSERT_NE(content_values.find(relative_path_values_colors), -1); ASSERT_EQ(content_values.find(path_values_colors), -1); Link({"-o", apk_path, "--manifest", GetDefaultManifest(), "--proto-format"}, compiled_files_dir, &diag); std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(apk_path, &diag); ResourceTable* resource_table = apk.get()->GetResourceTable(); const std::vector<std::unique_ptr<StringPool::Entry>>& pool_strings = resource_table->string_pool.strings(); ASSERT_EQ(pool_strings.size(), 2); ASSERT_EQ(pool_strings[0]->value, "res/layout/layout_one.xml"); ASSERT_EQ(pool_strings[1]->value, "res/layout-v1/layout_one.xml"); // Check resources.pb contains relative sources. io::IFile* proto_file = apk.get()->GetFileCollection()->FindFile("resources.pb"); std::unique_ptr<io::InputStream> proto_stream = proto_file->OpenInputStream(); io::ProtoInputStreamReader proto_reader(proto_stream.get()); pb::ResourceTable pb_table; proto_reader.ReadMessage(&pb_table); const std::string pool_strings_proto = pb_table.source_pool().data(); ASSERT_NE(pool_strings_proto.find(relative_path_values_colors), -1); ASSERT_NE(pool_strings_proto.find(relative_path_layout_layout_one), -1); } } // namespace aapt Loading
tools/aapt2/cmd/Compile.cpp +16 −4 Original line number Diff line number Diff line Loading @@ -75,8 +75,10 @@ struct ResourcePathData { }; // Resource file paths are expected to look like: [--/res/]type[-config]/name static Maybe<ResourcePathData> ExtractResourcePathData(const std::string& path, const char dir_sep, std::string* out_error) { static Maybe<ResourcePathData> ExtractResourcePathData(const std::string& path, const char dir_sep, std::string* out_error, const CompileOptions& options) { std::vector<std::string> parts = util::Split(path, dir_sep); if (parts.size() < 2) { if (out_error) *out_error = "bad resource path"; Loading Loading @@ -121,7 +123,11 @@ static Maybe<ResourcePathData> ExtractResourcePathData(const std::string& path, } } return ResourcePathData{Source(path), dir_str.to_string(), name.to_string(), const Source res_path = options.source_path ? StringPiece(options.source_path.value()) : StringPiece(path); return ResourcePathData{res_path, dir_str.to_string(), name.to_string(), extension.to_string(), config_str.to_string(), config}; } Loading Loading @@ -667,7 +673,8 @@ int Compile(IAaptContext* context, io::IFileCollection* inputs, IArchiveWriter* // Extract resource type information from the full path std::string err_str; ResourcePathData path_data; if (auto maybe_path_data = ExtractResourcePathData(path, inputs->GetDirSeparator(), &err_str)) { if (auto maybe_path_data = ExtractResourcePathData( path, inputs->GetDirSeparator(), &err_str, options)) { path_data = maybe_path_data.value(); } else { context->GetDiagnostics()->Error(DiagMessage(file->GetSource()) << err_str); Loading Loading @@ -747,6 +754,11 @@ int CompileCommand::Action(const std::vector<std::string>& args) { context.GetDiagnostics()->Error(DiagMessage() << "only one of --dir and --zip can be specified"); return 1; } else if ((options_.res_dir || options_.res_zip) && options_.source_path && args.size() > 1) { context.GetDiagnostics()->Error(DiagMessage(kPath) << "Cannot use an overriding source path with multiple files."); return 1; } else if (options_.res_dir) { if (!args.empty()) { context.GetDiagnostics()->Error(DiagMessage() << "files given but --dir specified"); Loading
tools/aapt2/cmd/Compile.h +4 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ namespace aapt { struct CompileOptions { std::string output_path; Maybe<std::string> source_path; Maybe<std::string> res_dir; Maybe<std::string> res_zip; Maybe<std::string> generate_text_symbols_path; Loading Loading @@ -69,6 +70,9 @@ class CompileCommand : public Command { AddOptionalSwitch("-v", "Enables verbose logging", &options_.verbose); AddOptionalFlag("--trace-folder", "Generate systrace json trace fragment to specified folder.", &trace_folder_); AddOptionalFlag("--source-path", "Sets the compiled resource file source file path to the given string.", &options_.source_path); } int Action(const std::vector<std::string>& args) override; Loading
tools/aapt2/cmd/Compile_test.cpp +87 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include "io/ZipArchive.h" #include "java/AnnotationProcessor.h" #include "test/Test.h" #include "format/proto/ProtoDeserialize.h" namespace aapt { Loading Loading @@ -253,4 +254,90 @@ TEST_F(CompilerTest, DoNotTranslateTest) { AssertTranslations(this, "donottranslate_foo", expected_not_translatable); } TEST_F(CompilerTest, RelativePathTest) { StdErrDiagnostics diag; const std::string res_path = BuildPath( {android::base::Dirname(android::base::GetExecutablePath()), "integration-tests", "CompileTest", "res"}); const std::string path_values_colors = GetTestPath("values/colors.xml"); WriteFile(path_values_colors, "<resources>" "<color name=\"color_one\">#008577</color>" "</resources>"); const std::string path_layout_layout_one = GetTestPath("layout/layout_one.xml"); WriteFile(path_layout_layout_one, "<LinearLayout " "xmlns:android=\"http://schemas.android.com/apk/res/android\">" "<TextBox android:id=\"@+id/text_one\" android:background=\"@color/color_one\"/>" "</LinearLayout>"); const std::string compiled_files_dir = BuildPath( {android::base::Dirname(android::base::GetExecutablePath()), "integration-tests", "CompileTest", "compiled"}); CHECK(file::mkdirs(compiled_files_dir.data())); const std::string path_values_colors_out = BuildPath({compiled_files_dir,"values_colors.arsc.flat"}); const std::string path_layout_layout_one_out = BuildPath({compiled_files_dir, "layout_layout_one.flat"}); ::android::base::utf8::unlink(path_values_colors_out.c_str()); ::android::base::utf8::unlink(path_layout_layout_one_out.c_str()); const std::string apk_path = BuildPath( {android::base::Dirname(android::base::GetExecutablePath()), "integration-tests", "CompileTest", "out.apk"}); const std::string source_set_res = BuildPath({"main", "res"}); const std::string relative_path_values_colors = BuildPath({source_set_res, "values", "colors.xml"}); const std::string relative_path_layout_layout_one = BuildPath({source_set_res, "layout", "layout_one.xml"}); CompileCommand(&diag).Execute({ path_values_colors, "-o", compiled_files_dir, "--source-path", relative_path_values_colors}, &std::cerr); CompileCommand(&diag).Execute({ path_layout_layout_one, "-o", compiled_files_dir, "--source-path", relative_path_layout_layout_one}, &std::cerr); std::ifstream ifs_values(path_values_colors_out); std::string content_values((std::istreambuf_iterator<char>(ifs_values)), (std::istreambuf_iterator<char>())); ASSERT_NE(content_values.find(relative_path_values_colors), -1); ASSERT_EQ(content_values.find(path_values_colors), -1); Link({"-o", apk_path, "--manifest", GetDefaultManifest(), "--proto-format"}, compiled_files_dir, &diag); std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(apk_path, &diag); ResourceTable* resource_table = apk.get()->GetResourceTable(); const std::vector<std::unique_ptr<StringPool::Entry>>& pool_strings = resource_table->string_pool.strings(); ASSERT_EQ(pool_strings.size(), 2); ASSERT_EQ(pool_strings[0]->value, "res/layout/layout_one.xml"); ASSERT_EQ(pool_strings[1]->value, "res/layout-v1/layout_one.xml"); // Check resources.pb contains relative sources. io::IFile* proto_file = apk.get()->GetFileCollection()->FindFile("resources.pb"); std::unique_ptr<io::InputStream> proto_stream = proto_file->OpenInputStream(); io::ProtoInputStreamReader proto_reader(proto_stream.get()); pb::ResourceTable pb_table; proto_reader.ReadMessage(&pb_table); const std::string pool_strings_proto = pb_table.source_pool().data(); ASSERT_NE(pool_strings_proto.find(relative_path_values_colors), -1); ASSERT_NE(pool_strings_proto.find(relative_path_layout_layout_one), -1); } } // namespace aapt