assemble_vintf: allow multiple input files.
Bug: 38217107
Test: test with DEVICE_MANIFEST_FILE variable split
into multiple files
Change-Id: I18cc374296344400dc3d05f8cda30e9a0f9933cb
diff --git a/assemble_vintf.cpp b/assemble_vintf.cpp
index fb96359..62d65b0 100644
--- a/assemble_vintf.cpp
+++ b/assemble_vintf.cpp
@@ -138,27 +138,54 @@
return true;
}
+ enum AssembleStatus { SUCCESS, FAIL_AND_EXIT, TRY_NEXT };
+ template <typename Schema, typename AssembleFunc>
+ AssembleStatus tryAssemble(const XmlConverter<Schema>& converter, const std::string& schemaName,
+ AssembleFunc assemble) {
+ Schema schema;
+ if (!converter(&schema, read(mInFiles.front()))) {
+ return TRY_NEXT;
+ }
+ auto firstType = schema.type();
+ for (auto it = mInFiles.begin() + 1; it != mInFiles.end(); ++it) {
+ Schema additionalSchema;
+ if (!converter(&additionalSchema, read(*it))) {
+ std::cerr << "File \"" << mInFilePaths[std::distance(mInFiles.begin(), it)]
+ << "\" is not a valid " << firstType << " " << schemaName
+ << " (but the first file is a valid " << firstType << " " << schemaName
+ << "). Error: " << converter.lastError() << std::endl;
+ return FAIL_AND_EXIT;
+ }
+ if (additionalSchema.type() != firstType) {
+ std::cerr << "File \"" << mInFilePaths[std::distance(mInFiles.begin(), it)]
+ << "\" is a " << additionalSchema.type() << " " << schemaName
+ << " (but a " << firstType << " " << schemaName << " is expected)."
+ << std::endl;
+ return FAIL_AND_EXIT;
+ }
+ schema.addAll(std::move(additionalSchema));
+ }
+ return assemble(&schema) ? SUCCESS : FAIL_AND_EXIT;
+ }
+
bool assemble() {
- if (!mInFile.is_open()) {
+ using std::placeholders::_1;
+ if (mInFiles.empty()) {
std::cerr << "Missing input file." << std::endl;
return false;
}
- std::string fileContent = read(mInFile);
+ auto status = tryAssemble(gHalManifestConverter, "manifest",
+ std::bind(&AssembleVintf::assembleHalManifest, this, _1));
+ if (status == SUCCESS) return true;
+ if (status == FAIL_AND_EXIT) return false;
- HalManifest halManifest;
- if (gHalManifestConverter(&halManifest, fileContent)) {
- if (assembleHalManifest(&halManifest)) {
- return true;
- }
- }
+ resetInFiles();
- CompatibilityMatrix matrix;
- if (gCompatibilityMatrixConverter(&matrix, fileContent)) {
- if (assembleCompatibilityMatrix(&matrix)) {
- return true;
- }
- }
+ status = tryAssemble(gCompatibilityMatrixConverter, "compatibility matrix",
+ std::bind(&AssembleVintf::assembleCompatibilityMatrix, this, _1));
+ if (status == SUCCESS) return true;
+ if (status == FAIL_AND_EXIT) return false;
std::cerr << "Input file has unknown format." << std::endl
<< "Error when attempting to convert to manifest: "
@@ -175,8 +202,10 @@
}
bool openInFile(const char* path) {
- mInFile.open(path);
- return mInFile.is_open();
+ mInFilePaths.push_back(path);
+ mInFiles.push_back({});
+ mInFiles.back().open(path);
+ return mInFiles.back().is_open();
}
bool openCheckFile(const char* path) {
@@ -184,10 +213,18 @@
return mCheckFile.is_open();
}
+ void resetInFiles() {
+ for (auto& inFile : mInFiles) {
+ inFile.clear();
+ inFile.seekg(0);
+ }
+ }
+
void setOutputMatrix() { mOutputMatrix = true; }
private:
- std::ifstream mInFile;
+ std::vector<std::string> mInFilePaths;
+ std::vector<std::ifstream> mInFiles;
std::unique_ptr<std::ofstream> mOutFileRef;
std::ifstream mCheckFile;
bool mOutputMatrix = false;
@@ -201,11 +238,14 @@
" fill in build-time flags into the given file.\n"
"assemble_vintf -h\n"
" Display this help text.\n"
- "assemble_vintf -i <input file> [-o <output file>] [-m] [-c [<check file>]]\n"
- " [--kernel=<version>:<android-base.cfg>]\n"
+ "assemble_vintf -i <input file>[:<input file>[...]] [-o <output file>] [-m]\n"
+ " [-c [<check file>]]\n"
" Fill in build-time flags into the given file.\n"
- " -i <input file>\n"
- " Input file. Format is automatically detected.\n"
+ " -i <input file>[:<input file>[...]]\n"
+ " A list of input files. Format is automatically detected for the\n"
+ " first file, and the remaining files must have the same format.\n"
+ " Files other than the first file should only have <hal> defined;\n"
+ " other entries are ignored.\n"
" -o <output file>\n"
" Optional output file. If not specified, write to stdout.\n"
" -m\n"
@@ -225,21 +265,25 @@
int main(int argc, char **argv) {
const struct option longopts[] = {{0, 0, 0, 0}};
- std::string inFilePath;
+ std::string outFilePath;
::android::vintf::AssembleVintf assembleVintf;
int res;
int optind;
while ((res = getopt_long(argc, argv, "hi:o:mc:", longopts, &optind)) >= 0) {
switch (res) {
case 'i': {
- inFilePath = optarg;
- if (!assembleVintf.openInFile(optarg)) {
- std::cerr << "Failed to open " << optarg << std::endl;
- return 1;
+ char* inFilePath = strtok(optarg, ":");
+ while (inFilePath != NULL) {
+ if (!assembleVintf.openInFile(inFilePath)) {
+ std::cerr << "Failed to open " << optarg << std::endl;
+ return 1;
+ }
+ inFilePath = strtok(NULL, ":");
}
} break;
case 'o': {
+ outFilePath = optarg;
if (!assembleVintf.openOutFile(optarg)) {
std::cerr << "Failed to open " << optarg << std::endl;
return 1;
@@ -258,7 +302,7 @@
}
} else {
std::cerr << "WARNING: no compatibility check is done on "
- << inFilePath << std::endl;
+ << (outFilePath.empty() ? "output" : outFilePath) << std::endl;
}
} break;