You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
275 lines
8.0 KiB
275 lines
8.0 KiB
/* |
|
* Copyright (C) 2015, The Android Open Source Project |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
#include "options.h" |
|
|
|
#include <cstring> |
|
#include <iostream> |
|
#include <stdio.h> |
|
|
|
#include "logging.h" |
|
#include "os.h" |
|
|
|
using std::cerr; |
|
using std::endl; |
|
using std::string; |
|
using std::unique_ptr; |
|
using std::vector; |
|
|
|
namespace android { |
|
namespace aidl { |
|
namespace { |
|
|
|
unique_ptr<JavaOptions> java_usage() { |
|
fprintf(stderr, |
|
"usage: aidl OPTIONS INPUT [OUTPUT]\n" |
|
" aidl --preprocess OUTPUT INPUT...\n" |
|
"\n" |
|
"OPTIONS:\n" |
|
" -I<DIR> search path for import statements.\n" |
|
" -d<FILE> generate dependency file.\n" |
|
" -a generate dependency file next to the output file with " |
|
"the name based on the input file.\n" |
|
" -ninja generate dependency file in a format ninja " |
|
"understands.\n" |
|
" -p<FILE> file created by --preprocess to import.\n" |
|
" -o<FOLDER> base output folder for generated files.\n" |
|
" -b fail when trying to compile a parcelable.\n" |
|
"\n" |
|
"INPUT:\n" |
|
" An aidl interface file.\n" |
|
"\n" |
|
"OUTPUT:\n" |
|
" The generated interface files.\n" |
|
" If omitted and the -o option is not used, the input filename is " |
|
"used, with the .aidl extension changed to a .java extension.\n" |
|
" If the -o option is used, the generated files will be placed in " |
|
"the base output folder, under their package folder\n"); |
|
return unique_ptr<JavaOptions>(nullptr); |
|
} |
|
|
|
} // namespace |
|
|
|
unique_ptr<JavaOptions> JavaOptions::Parse(int argc, const char* const* argv) { |
|
unique_ptr<JavaOptions> options(new JavaOptions()); |
|
int i = 1; |
|
|
|
if (argc >= 2 && 0 == strcmp(argv[1], "--preprocess")) { |
|
if (argc < 4) { |
|
return java_usage(); |
|
} |
|
options->output_file_name_ = argv[2]; |
|
for (int i = 3; i < argc; i++) { |
|
options->files_to_preprocess_.push_back(argv[i]); |
|
} |
|
options->task = PREPROCESS_AIDL; |
|
return options; |
|
} |
|
|
|
options->task = COMPILE_AIDL_TO_JAVA; |
|
// OPTIONS |
|
while (i < argc) { |
|
const char* s = argv[i]; |
|
const size_t len = strlen(s); |
|
if (s[0] != '-') { |
|
break; |
|
} |
|
if (len <= 1) { |
|
fprintf(stderr, "unknown option (%d): %s\n", i, s); |
|
return java_usage(); |
|
} |
|
// -I<system-import-path> |
|
if (s[1] == 'I') { |
|
if (len > 2) { |
|
options->import_paths_.push_back(s + 2); |
|
} else { |
|
fprintf(stderr, "-I option (%d) requires a path.\n", i); |
|
return java_usage(); |
|
} |
|
} else if (s[1] == 'd') { |
|
if (len > 2) { |
|
options->dep_file_name_ = s + 2; |
|
} else { |
|
fprintf(stderr, "-d option (%d) requires a file.\n", i); |
|
return java_usage(); |
|
} |
|
} else if (strcmp(s, "-a") == 0) { |
|
options->auto_dep_file_ = true; |
|
} else if (s[1] == 'p') { |
|
if (len > 2) { |
|
options->preprocessed_files_.push_back(s + 2); |
|
} else { |
|
fprintf(stderr, "-p option (%d) requires a file.\n", i); |
|
return java_usage(); |
|
} |
|
} else if (s[1] == 'o') { |
|
if (len > 2) { |
|
options->output_base_folder_= s + 2; |
|
} else { |
|
fprintf(stderr, "-o option (%d) requires a path.\n", i); |
|
return java_usage(); |
|
} |
|
} else if (strcmp(s, "-b") == 0) { |
|
options->fail_on_parcelable_ = true; |
|
} else if (strcmp(s, "-ninja") == 0) { |
|
options->dep_file_ninja_ = true; |
|
} else { |
|
// s[1] is not known |
|
fprintf(stderr, "unknown option (%d): %s\n", i, s); |
|
return java_usage(); |
|
} |
|
i++; |
|
} |
|
// INPUT |
|
if (i < argc) { |
|
options->input_file_name_ = argv[i]; |
|
i++; |
|
} else { |
|
fprintf(stderr, "INPUT required\n"); |
|
return java_usage(); |
|
} |
|
if (!EndsWith(options->input_file_name_, ".aidl")) { |
|
cerr << "Expected .aidl file for input but got " |
|
<< options->input_file_name_ << endl; |
|
return java_usage(); |
|
} |
|
|
|
// OUTPUT |
|
if (i < argc) { |
|
options->output_file_name_ = argv[i]; |
|
i++; |
|
} else if (options->output_base_folder_.empty()) { |
|
// copy input into output and change the extension from .aidl to .java |
|
options->output_file_name_= options->input_file_name_; |
|
if (!ReplaceSuffix(".aidl", ".java", &options->output_file_name_)) { |
|
// we should never get here since we validated the suffix. |
|
LOG(FATAL) << "Internal aidl error."; |
|
return java_usage(); |
|
} |
|
} |
|
|
|
// anything remaining? |
|
if (i != argc) { |
|
fprintf(stderr, "unknown option%s:", |
|
(i == argc - 1 ? (const char*)"" : (const char*)"s")); |
|
for (; i < argc - 1; i++) { |
|
fprintf(stderr, " %s", argv[i]); |
|
} |
|
fprintf(stderr, "\n"); |
|
return java_usage(); |
|
} |
|
|
|
return options; |
|
} |
|
|
|
string JavaOptions::DependencyFilePath() const { |
|
if (auto_dep_file_) { |
|
return output_file_name_ + ".d"; |
|
} |
|
return dep_file_name_; |
|
} |
|
|
|
namespace { |
|
|
|
unique_ptr<CppOptions> cpp_usage() { |
|
cerr << "usage: aidl-cpp INPUT_FILE HEADER_DIR OUTPUT_FILE" << endl |
|
<< endl |
|
<< "OPTIONS:" << endl |
|
<< " -I<DIR> search path for import statements" << endl |
|
<< " -d<FILE> generate dependency file" << endl |
|
<< " -ninja generate dependency file in a format ninja " |
|
"understands" << endl |
|
<< endl |
|
<< "INPUT_FILE:" << endl |
|
<< " an aidl interface file" << endl |
|
<< "HEADER_DIR:" << endl |
|
<< " empty directory to put generated headers" << endl |
|
<< "OUTPUT_FILE:" << endl |
|
<< " path to write generated .cpp code" << endl; |
|
return unique_ptr<CppOptions>(nullptr); |
|
} |
|
|
|
} // namespace |
|
|
|
unique_ptr<CppOptions> CppOptions::Parse(int argc, const char* const* argv) { |
|
unique_ptr<CppOptions> options(new CppOptions()); |
|
int i = 1; |
|
|
|
// Parse flags, all of which start with '-' |
|
for ( ; i < argc; ++i) { |
|
const size_t len = strlen(argv[i]); |
|
const char *s = argv[i]; |
|
if (s[0] != '-') { |
|
break; // On to the positional arguments. |
|
} |
|
if (len < 2) { |
|
cerr << "Invalid argument '" << s << "'." << endl; |
|
return cpp_usage(); |
|
} |
|
const string the_rest = s + 2; |
|
if (s[1] == 'I') { |
|
options->import_paths_.push_back(the_rest); |
|
} else if (s[1] == 'd') { |
|
options->dep_file_name_ = the_rest; |
|
} else if (strcmp(s, "-ninja") == 0) { |
|
options->dep_file_ninja_ = true; |
|
} else { |
|
cerr << "Invalid argument '" << s << "'." << endl; |
|
return cpp_usage(); |
|
} |
|
} |
|
|
|
// There are exactly three positional arguments. |
|
const int remaining_args = argc - i; |
|
if (remaining_args != 3) { |
|
cerr << "Expected 3 positional arguments but got " << remaining_args << "." << endl; |
|
return cpp_usage(); |
|
} |
|
|
|
options->input_file_name_ = argv[i]; |
|
options->output_header_dir_ = argv[i + 1]; |
|
options->output_file_name_ = argv[i + 2]; |
|
|
|
if (!EndsWith(options->input_file_name_, ".aidl")) { |
|
cerr << "Expected .aidl file for input but got " << options->input_file_name_ << endl; |
|
return cpp_usage(); |
|
} |
|
|
|
return options; |
|
} |
|
|
|
bool EndsWith(const string& str, const string& suffix) { |
|
if (str.length() < suffix.length()) { |
|
return false; |
|
} |
|
return std::equal(str.crbegin(), str.crbegin() + suffix.length(), |
|
suffix.crbegin()); |
|
} |
|
|
|
bool ReplaceSuffix(const string& old_suffix, |
|
const string& new_suffix, |
|
string* str) { |
|
if (!EndsWith(*str, old_suffix)) return false; |
|
str->replace(str->length() - old_suffix.length(), |
|
old_suffix.length(), |
|
new_suffix); |
|
return true; |
|
} |
|
|
|
|
|
|
|
} // namespace android |
|
} // namespace aidl
|
|
|