summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jiakai Zhang <jiakaiz@google.com> 2023-07-26 11:24:10 +0100
committer Jiakai Zhang <jiakaiz@google.com> 2023-07-26 16:46:11 +0000
commit9dcdda055c4e17476b00a6929d8f114c6a686c22 (patch)
treed605b464e42779a2041e327096924487574ad5aa
parent35cca3e296346277422aaee030edced697e09319 (diff)
Update generate-boot-image to support host.
We'll use it to generate the boot image for target Golem. Bug: 290583827 Test: out/host/linux-x86/bin/generate-boot-image64 --output-dir=out/x86_64/target/product/armv8/apex/art_boot_images/javalib --compiler-filter=speed --use-profile=false --dex2oat-bin=out/host/linux-x86/bin/dex2oat64 --android-root=out/x86_64/target/product/armv8/system --instruction-set=arm64 Change-Id: I80f9cacb60dcc0bfa3a5d463d4ff391c1d974c42
-rw-r--r--libartbase/base/common_art_test.cc21
-rw-r--r--libartbase/base/common_art_test.h4
-rw-r--r--libartbase/base/testing.cc21
-rw-r--r--libartbase/base/testing.h14
-rw-r--r--test/generate-boot-image/Android.bp2
-rw-r--r--test/generate-boot-image/generate-boot-image.cc178
6 files changed, 188 insertions, 52 deletions
diff --git a/libartbase/base/common_art_test.cc b/libartbase/base/common_art_test.cc
index e83cc0d967..0692bf8c20 100644
--- a/libartbase/base/common_art_test.cc
+++ b/libartbase/base/common_art_test.cc
@@ -448,28 +448,25 @@ std::vector<std::string> CommonArtTestImpl::GetLibCoreModuleNames() const {
std::vector<std::string> CommonArtTestImpl::GetLibCoreDexFileNames(
const std::vector<std::string>& modules) const {
- return art::testing::GetLibCoreDexFileNames(modules);
+ return art::testing::GetLibCoreDexFileNames(kIsTargetBuild ? "" : GetAndroidRoot(), modules);
}
std::vector<std::string> CommonArtTestImpl::GetLibCoreDexFileNames() const {
std::vector<std::string> modules = GetLibCoreModuleNames();
- return art::testing::GetLibCoreDexFileNames(modules);
+ return art::testing::GetLibCoreDexFileNames(kIsTargetBuild ? "" : GetAndroidRoot(), modules);
}
std::vector<std::string> CommonArtTestImpl::GetLibCoreDexLocations(
const std::vector<std::string>& modules) const {
- std::vector<std::string> result = GetLibCoreDexFileNames(modules);
+ std::string prefix = "";
if (IsHost()) {
- // Strip the ANDROID_BUILD_TOP directory including the directory separator '/'.
- std::string prefix = GetAndroidBuildTop();
- for (std::string& location : result) {
- CHECK_GT(location.size(), prefix.size());
- CHECK_EQ(location.compare(0u, prefix.size(), prefix), 0)
- << " prefix=" << prefix << " location=" << location;
- location.erase(0u, prefix.size());
- }
+ std::string android_root = GetAndroidRoot();
+ std::string build_top = GetAndroidBuildTop();
+ CHECK(android::base::StartsWith(android_root, build_top))
+ << " android_root=" << android_root << " build_top=" << build_top;
+ prefix = android_root.substr(build_top.size());
}
- return result;
+ return art::testing::GetLibCoreDexFileNames(prefix, modules);
}
std::vector<std::string> CommonArtTestImpl::GetLibCoreDexLocations() const {
diff --git a/libartbase/base/common_art_test.h b/libartbase/base/common_art_test.h
index 9a1e84eabf..1e39716417 100644
--- a/libartbase/base/common_art_test.h
+++ b/libartbase/base/common_art_test.h
@@ -157,10 +157,10 @@ class CommonArtTestImpl {
// Gets the paths of the libcore dex files.
std::vector<std::string> GetLibCoreDexFileNames() const;
- // Gets the locations of the libcore dex files for given modules.
+ // Gets the on-host or on-device locations of the libcore dex files for given modules.
std::vector<std::string> GetLibCoreDexLocations(const std::vector<std::string>& modules) const;
- // Gets the locations of the libcore dex files.
+ // Gets the on-host or on-device locations of the libcore dex files.
std::vector<std::string> GetLibCoreDexLocations() const;
static std::string GetClassPathOption(const char* option,
diff --git a/libartbase/base/testing.cc b/libartbase/base/testing.cc
index c260be7bfb..3cd2836876 100644
--- a/libartbase/base/testing.cc
+++ b/libartbase/base/testing.cc
@@ -26,8 +26,7 @@ namespace testing {
namespace {
-std::string GetDexFileName(const std::string& jar_prefix, bool host) {
- std::string prefix(host ? GetAndroidRoot() : "");
+std::string GetDexFileName(const std::string& jar_prefix, const std::string& prefix) {
const char* apexPath =
(jar_prefix == "conscrypt") ?
kAndroidConscryptApexDefaultPath :
@@ -60,18 +59,28 @@ std::vector<std::string> GetLibCoreModuleNames(bool core_only) {
return modules;
}
-std::vector<std::string> GetLibCoreDexFileNames(const std::vector<std::string>& modules) {
+std::vector<std::string> GetLibCoreDexFileNames(const std::string& prefix,
+ const std::vector<std::string>& modules) {
std::vector<std::string> result;
result.reserve(modules.size());
for (const std::string& module : modules) {
- result.push_back(GetDexFileName(module, !kIsTargetBuild));
+ result.push_back(GetDexFileName(module, prefix));
}
return result;
}
-std::vector<std::string> GetLibCoreDexFileNames(bool core_only) {
+std::vector<std::string> GetLibCoreDexFileNames(const std::string& prefix, bool core_only) {
std::vector<std::string> modules = GetLibCoreModuleNames(core_only);
- return GetLibCoreDexFileNames(modules);
+ return GetLibCoreDexFileNames(prefix, modules);
+}
+
+std::vector<std::string> GetLibCoreDexLocations(const std::vector<std::string>& modules) {
+ return GetLibCoreDexFileNames(/*prefix=*/"", modules);
+}
+
+std::vector<std::string> GetLibCoreDexLocations(bool core_only) {
+ std::vector<std::string> modules = GetLibCoreModuleNames(core_only);
+ return GetLibCoreDexLocations(modules);
}
} // namespace testing
diff --git a/libartbase/base/testing.h b/libartbase/base/testing.h
index 65bd3f6058..88d0aee6e0 100644
--- a/libartbase/base/testing.h
+++ b/libartbase/base/testing.h
@@ -25,16 +25,26 @@
namespace art {
namespace testing {
+// Note: "libcore" here means art + conscrypt + icu.
+
// Gets the names of the libcore modules.
// If `core_only` is true, only returns the names of CORE_IMG_JARS in Android.common_path.mk.
std::vector<std::string> GetLibCoreModuleNames(bool core_only = false);
// Gets the paths of the libcore dex files for given modules.
-std::vector<std::string> GetLibCoreDexFileNames(const std::vector<std::string>& modules);
+std::vector<std::string> GetLibCoreDexFileNames(const std::string& prefix,
+ const std::vector<std::string>& modules);
// Gets the paths of the libcore dex files.
// If `core_only` is true, only returns the filenames of CORE_IMG_JARS in Android.common_path.mk.
-std::vector<std::string> GetLibCoreDexFileNames(bool core_only = false);
+std::vector<std::string> GetLibCoreDexFileNames(const std::string& prefix, bool core_only = false);
+
+// Gets the on-device locations of the libcore dex files for given modules.
+std::vector<std::string> GetLibCoreDexLocations(const std::vector<std::string>& modules);
+
+// Gets the on-device locations of the libcore dex files.
+// If `core_only` is true, only returns the filenames of CORE_IMG_JARS in Android.common_path.mk.
+std::vector<std::string> GetLibCoreDexLocations(bool core_only = false);
} // namespace testing
} // namespace art
diff --git a/test/generate-boot-image/Android.bp b/test/generate-boot-image/Android.bp
index e03aade347..00ce3d328a 100644
--- a/test/generate-boot-image/Android.bp
+++ b/test/generate-boot-image/Android.bp
@@ -28,7 +28,7 @@ art_cc_binary {
defaults: [
"art_defaults",
],
- host_supported: false,
+ host_supported: true,
compile_multilib: "both",
multilib: {
lib32: {
diff --git a/test/generate-boot-image/generate-boot-image.cc b/test/generate-boot-image/generate-boot-image.cc
index 1b3eccf0e5..64390c3163 100644
--- a/test/generate-boot-image/generate-boot-image.cc
+++ b/test/generate-boot-image/generate-boot-image.cc
@@ -14,31 +14,91 @@
* limitations under the License.
*/
-/** A commandline tool to generate a primary boot image for testing. */
-
#include <sys/stat.h>
#include <sysexits.h>
#include <algorithm>
#include <cstdlib>
+#include <iostream>
#include <string>
#include <vector>
+#include "android-base/parsebool.h"
#include "android-base/stringprintf.h"
#include "android-base/strings.h"
#include "arch/instruction_set.h"
#include "base/file_utils.h"
#include "base/globals.h"
+#include "base/macros.h"
#include "base/os.h"
#include "base/testing.h"
namespace art {
+namespace gbi {
namespace {
+using ::android::base::ConsumePrefix;
+using ::android::base::ConsumeSuffix;
using ::android::base::Join;
+using ::android::base::ParseBool;
+using ::android::base::ParseBoolResult;
using ::android::base::StringPrintf;
using ::art::testing::GetLibCoreDexFileNames;
+using ::art::testing::GetLibCoreDexLocations;
+
+constexpr const char* kUsage = R"(
+A commandline tool to generate a primary boot image for testing.
+
+Usage: generate-boot-image --output-dir=OUTPUT_DIR [OPTIONS]...
+
+Supported options:
+ --help: Print this text.
+ --output-dir=OUTPUT_DIR: The directory to output the boot image. Required.
+ --compiler-filter=COMPILER_FILTER: The compiler filter option to pass to dex2oat. Default: verify
+ --use-profile=true|false: If true, use a profile. Default: true
+ --dex2oat-bin=DEX2OAT_BIN: The path to the dex2oat binary. Required when running on host. Default
+ on target: /apex/com.android.art/bin/dex2oat{32,64,32d,64d}
+ --android-root=ANDROID_ROOT: The root directory to search for bootclasspath jars. The file
+ structure under the root must be in the form of:
+ /apex
+ /com.android.art
+ /javalib
+ /core-oj.jar
+ ...
+ /com.android.i18n
+ /javalib
+ ...
+ /com.android.conscrypt
+ /javalib
+ ...
+ Required when running on host. Default on target: /
+ --profile-file=PROFILE_FILE: The path to the profile file. Required when running on host and
+ --use-profile is true. Default on target: /apex/com.android.art/etc/boot-image.prof
+ --instruction-set=ISA: The instruction set option to pass to dex2oat. Required when running on
+ host. The default on target is based on the ISA of this binary.
+ --core-only=true|false: If true, only compile ART jars. Otherwise, also compile core-icu4j and
+ conscrypt. Default: true
+)";
+
+struct Options {
+ std::string output_dir = "";
+ // Set the compiler filter to `verify` by default to make test preparation
+ // faster.
+ std::string compiler_filter = "verify";
+ bool use_profile = true;
+ std::string dex2oat_bin = "";
+ std::string android_root = "";
+ std::string profile_file = "";
+ std::string instruction_set = "";
+ bool core_only = true;
+};
+
+[[noreturn]] void Usage(const std::string& message) {
+ LOG(ERROR) << message << '\n';
+ std::cerr << message << "\n" << kUsage << "\n";
+ exit(EX_USAGE);
+}
std::string GetCompilerExecutable() {
std::string compiler_executable = GetArtBinDir() + "/dex2oat";
@@ -64,23 +124,30 @@ std::string BuildCommand(const std::vector<std::string>& args) {
return command;
}
-int GenerateBootImage(const std::string& dir, const std::string& compiler_filter) {
- std::string isa = GetInstructionSetString(kRuntimeISA);
-
+int GenerateBootImage(const Options& options) {
std::vector<std::string> args;
- args.push_back(GetCompilerExecutable());
+ args.push_back(options.dex2oat_bin);
- std::vector<std::string> dex_files = GetLibCoreDexFileNames(/*core_only=*/true);
+ std::vector<std::string> dex_files =
+ GetLibCoreDexFileNames(options.android_root, options.core_only);
+ std::vector<std::string> dex_locations = GetLibCoreDexLocations(options.core_only);
args.push_back("--runtime-arg");
args.push_back("-Xbootclasspath:" + Join(dex_files, ":"));
+ args.push_back("--runtime-arg");
+ args.push_back("-Xbootclasspath-locations:" + Join(dex_locations, ":"));
for (const std::string& file : dex_files) {
args.push_back("--dex-file=" + file);
}
+ for (const std::string& location : dex_locations) {
+ args.push_back("--dex-location=" + location);
+ }
- args.push_back("--instruction-set=" + isa);
+ args.push_back("--instruction-set=" + options.instruction_set);
args.push_back(StringPrintf("--base=0x%08x", ART_BASE_ADDRESS));
- args.push_back("--compiler-filter=" + compiler_filter);
- args.push_back(StringPrintf("--profile-file=%s/etc/boot-image.prof", GetArtRoot().c_str()));
+ args.push_back("--compiler-filter=" + options.compiler_filter);
+ if (options.use_profile) {
+ args.push_back("--profile-file=" + options.profile_file);
+ }
args.push_back("--avoid-storing-invocation");
args.push_back("--generate-debug-info");
args.push_back("--generate-build-id");
@@ -88,7 +155,7 @@ int GenerateBootImage(const std::string& dir, const std::string& compiler_filter
args.push_back("--strip");
args.push_back("--android-root=out/empty");
- std::string path = StringPrintf("%s/%s", dir.c_str(), isa.c_str());
+ std::string path = ART_FORMAT("{}/{}", options.output_dir, options.instruction_set);
if (!OS::DirectoryExists(path.c_str())) {
CHECK_EQ(mkdir(path.c_str(), S_IRWXU), 0);
}
@@ -102,32 +169,85 @@ int GenerateBootImage(const std::string& dir, const std::string& compiler_filter
return exit_code;
}
-} // namespace
-} // namespace art
-
-int main(int argc, char** argv) {
+int Main(int argc, char** argv) {
android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
- std::string dir = "";
- // Set the compiler filter to `verify` by default to make test preparation
- // faster.
- std::string compiler_filter = "verify";
+ Options options;
for (int i = 1; i < argc; i++) {
std::string_view arg{argv[i]};
- if (android::base::ConsumePrefix(&arg, "--output-dir=")) {
- dir = arg;
- } else if (android::base::ConsumePrefix(&arg, "--compiler-filter=")) {
- compiler_filter = arg;
+ if (arg == "--help") {
+ std::cerr << kUsage << "\n";
+ exit(0);
+ } else if (ConsumePrefix(&arg, "--output-dir=")) {
+ options.output_dir = arg;
+ } else if (ConsumePrefix(&arg, "--compiler-filter=")) {
+ options.compiler_filter = arg;
+ } else if (ConsumePrefix(&arg, "--use-profile=")) {
+ ParseBoolResult result = ParseBool(arg);
+ if (result == ParseBoolResult::kError) {
+ Usage(ART_FORMAT("Unrecognized --use-profile value: '{}'", arg));
+ }
+ options.use_profile = result == ParseBoolResult::kTrue;
+ } else if (ConsumePrefix(&arg, "--dex2oat-bin=")) {
+ options.dex2oat_bin = arg;
+ } else if (ConsumePrefix(&arg, "--android-root=")) {
+ ConsumeSuffix(&arg, "/");
+ options.android_root = arg;
+ } else if (ConsumePrefix(&arg, "--profile-file=")) {
+ options.profile_file = arg;
+ } else if (ConsumePrefix(&arg, "--instruction-set=")) {
+ options.instruction_set = arg;
+ } else if (ConsumePrefix(&arg, "--core-only=")) {
+ ParseBoolResult result = ParseBool(arg);
+ if (result == ParseBoolResult::kError) {
+ Usage(ART_FORMAT("Unrecognized --core-only value: '{}'", arg));
+ }
+ options.core_only = result == ParseBoolResult::kTrue;
} else {
- LOG(ERROR) << android::base::StringPrintf("Unrecognized argument: '%s'", argv[i]);
- exit(EX_USAGE);
+ Usage(ART_FORMAT("Unrecognized argument: '{}'", argv[i]));
}
}
- if (dir.empty()) {
- LOG(ERROR) << "--output-dir must be specified";
- exit(EX_USAGE);
+ if (options.output_dir.empty()) {
+ Usage("--output-dir must be specified");
}
- return art::GenerateBootImage(dir, compiler_filter);
+ if (options.dex2oat_bin.empty()) {
+ if (kIsTargetBuild) {
+ options.dex2oat_bin = GetCompilerExecutable();
+ } else {
+ Usage("--dex2oat-bin must be specified when running on host");
+ }
+ }
+
+ if (options.android_root.empty()) {
+ if (!kIsTargetBuild) {
+ Usage("--android-root must be specified when running on host");
+ }
+ }
+
+ if (options.use_profile && options.profile_file.empty()) {
+ if (kIsTargetBuild) {
+ options.profile_file = ART_FORMAT("{}/etc/boot-image.prof", GetArtRoot());
+ } else {
+ Usage("--profile-file must be specified when running on host and --use-profile is true");
+ }
+ }
+
+ if (options.instruction_set.empty()) {
+ if (kIsTargetBuild) {
+ options.instruction_set = GetInstructionSetString(kRuntimeISA);
+ } else {
+ Usage("--instruction-set must be specified when running on host");
+ }
+ }
+
+ return GenerateBootImage(options);
}
+
+} // namespace
+
+} // namespace gbi
+} // namespace art
+
+int main(int argc, char** argv) { return art::gbi::Main(argc, argv); }