From patchwork Thu Nov 11 02:37:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: tangmeng X-Patchwork-Id: 47435 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id CEF08385803A for ; Thu, 11 Nov 2021 02:38:06 +0000 (GMT) X-Original-To: libabigail@sourceware.org Delivered-To: libabigail@sourceware.org Received: from smtpbg506.qq.com (smtpbg506.qq.com [203.205.250.33]) by sourceware.org (Postfix) with ESMTPS id C494E3858010 for ; Thu, 11 Nov 2021 02:37:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org C494E3858010 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=uniontech.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=uniontech.com X-QQ-mid: bizesmtp38t1636598267t7mohf7j Received: from localhost.localdomain (unknown [58.240.82.166]) by esmtp6.qq.com (ESMTP) with id ; Thu, 11 Nov 2021 10:37:42 +0800 (CST) X-QQ-SSF: 0140000000000050C000B00A0000000 X-QQ-FEAT: ssdqv2V8ieJq+dE9/3JSKk7Ccm5lWoXz5MZRL/mipDYnOExP+QUR3bvZCQXS6 p72+IRORlhYIWNWxt0PPx1lzj7rNiV9P0YTfW+/u/QbS5QXDz8xP9VNrO8nOVtWEAjKTbdp 7JWw7DSoF2LpZ7ffITI2zm59+1QO1lj3OAEjYoOnWxzFe8tvt8XKZVtWuajeDj/q2gYzw29 Ml7pszcmd5uSakNdR8lDPMc4MaxwqBXy+l+DLykL1DxUiBgHaE5KtRn76CKX/eaGBu7co2a RNWgUanYhlKQc/kB1LmEhlOUvR2U+SHdEqKRKncb2tEnKOZBYJlp82SoGvSMrS03ogG0txF WhCKpcpR3lsGvQrQty6t96QLoD1vw== X-QQ-GoodBg: 2 From: tangmeng To: libabigail@sourceware.org Subject: [PATCH] abicompat: Make the commands more pleasant Date: Thu, 11 Nov 2021 10:37:40 +0800 Message-Id: <20211111023740.25611-1-tangmeng@uniontech.com> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:uniontech.com:qybgforeign:qybgforeign2 X-QQ-Bgrelay: 1 X-Spam-Status: No, score=-13.2 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_PASS, TXREP, T_SPF_HELO_TEMPERROR autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libabigail@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list of the Libabigail project List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , Cc: tangmeng Errors-To: libabigail-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libabigail" This submission uses getopt_long to replace strcmp to obtain the options and parameters, which will bring the user a better experience. For example, the command will undergo the following changes: case1: # abicompat application lib1-path --lib-debug-info-dir1 before prompt information: abicompat: wrong invocation try the --help option for more information now prompt information: abicompat: option '--lib-debug-info-dir1' requires an argument Now it will be clearly pointed out which option is problematic. case2: # abicompat application lib1-path --lib-debug-info-dir1 \ dir1 --unsupport-option before prompt information: abicompat: unrecognized option: --unsupport-option try the --help option for more information now prompt information: abicompat: unrecognized option '--unsupport-option' Now it will be clear which option is not supported. In addition, options have been added for application, lib1, and lib2, and some prompt messages have been added. * tests/test-abicompat.cc (main): Adapt to the change of command. * tools/abicompat.cc: Add a new enum and an option long_options. (parse_command_line): Use getopt_long to replace strcmp. (main): Cooperate with the changes of parsw_command_line. Signed-off-by: tangmeng --- tests/test-abicompat.cc | 4 +- tools/abicompat.cc | 260 ++++++++++++++++++++-------------------- 2 files changed, 135 insertions(+), 129 deletions(-) diff --git a/tests/test-abicompat.cc b/tests/test-abicompat.cc index a1339eef..33341ae1 100644 --- a/tests/test-abicompat.cc +++ b/tests/test-abicompat.cc @@ -242,9 +242,9 @@ main() abicompat += " --suppressions " + suppression_path; abicompat += " " + abicompat_options; - cmd = abicompat + " " + in_app_path + " " + in_lib1_path; + cmd = abicompat + " --application-path " + in_app_path + " --lib-v1-path " + in_lib1_path; if (!in_lib2_path.empty()) - cmd += string(" ") + in_lib2_path; + cmd += string(" --lib-v2-path ") + in_lib2_path; cmd += " > " + out_report_path; diff --git a/tools/abicompat.cc b/tools/abicompat.cc index addd03a9..5f62ae56 100644 --- a/tools/abicompat.cc +++ b/tools/abicompat.cc @@ -26,6 +26,7 @@ /// library provides. #include +#include #include #include #include @@ -89,16 +90,61 @@ public: {} }; // end struct options +enum +{ + APPLICATION_PATH_OPTION, + LIB_V1_PATH_OPTION, + LIB_V2_PATH_OPTION, + LIST_UNDEFINED_SYSMBOLS_OPTION, + SHOW_BASE_NAMES_OPTION, + APP_DEBUG_INFO_DIR_OPTION, + LIB_DEBUG_INFO_DIR1_OPTION, + LIB_DEBUG_INFO_DIR2_OPTION, + SUPPRESSIONS_OPTION, + NO_REDUNDANT_OPTION, + NO_SHOW_LOCS_OPTION, + REDUNDANT_OPTION, + WEAK_MODE_OPTION, + HELP_OPTION, + VERSION_OPTION +}; + +const option long_options[] = +{ + {"application-path", required_argument, NULL, APPLICATION_PATH_OPTION}, + {"lib-v1-path", required_argument, NULL, LIB_V1_PATH_OPTION}, + {"lib-v2-path", required_argument, NULL, LIB_V2_PATH_OPTION}, + {"list-undefined-symbols", no_argument, NULL, LIST_UNDEFINED_SYSMBOLS_OPTION}, + {"show-base-names", no_argument, NULL, SHOW_BASE_NAMES_OPTION}, + {"app-debug-info-dir", required_argument, NULL, APP_DEBUG_INFO_DIR_OPTION}, + {"appd", required_argument, NULL, APP_DEBUG_INFO_DIR_OPTION}, + {"lib-debug-info-dir1", required_argument, NULL, LIB_DEBUG_INFO_DIR1_OPTION}, + {"libd1", required_argument, NULL, LIB_DEBUG_INFO_DIR1_OPTION}, + {"lib-debug-info-dir2", required_argument, NULL, LIB_DEBUG_INFO_DIR2_OPTION}, + {"libd2", required_argument, NULL, LIB_DEBUG_INFO_DIR2_OPTION}, + {"suppressions", required_argument, NULL, SUPPRESSIONS_OPTION}, + {"suppr", required_argument, NULL, SUPPRESSIONS_OPTION}, + {"no-redundant", no_argument, NULL, NO_REDUNDANT_OPTION}, + {"no-show-locs", no_argument, NULL, NO_SHOW_LOCS_OPTION}, + {"redundant", no_argument, NULL, REDUNDANT_OPTION}, + {"weak-mode", no_argument, NULL, WEAK_MODE_OPTION}, + {"help", no_argument, NULL, HELP_OPTION}, + {"version", no_argument, NULL, VERSION_OPTION}, + {NULL, 0, NULL, 0} +}; + static void display_usage(const string& prog_name, ostream& out) { emit_prefix(prog_name, out) << "usage: " << prog_name - << " [options] [application-path] [lib-v1-path] [lib-v2-path]" + << " [options] --application-path [application-path] " + << "--lib-v1-path [lib-v1-path] --lib-v2-path [lib-v2-path]" << "\n" << " where options can be: \n" - << " --help|-h display this help message\n" - << " --version|-v show program version information and exit\n" + << " --application-path set the path to the application\n" + << " --lib-v1-path set the path to the lib-v1\n" + << " --lib-v2-path set the path to the lib-v2\n" << " --list-undefined-symbols|-u display the list of " "undefined symbols of the application\n" << " --show-base-names|b in the report, only show the base names " @@ -115,122 +161,84 @@ display_usage(const string& prog_name, ostream& out) << " --redundant display redundant changes (this is the default)\n" << " --weak-mode check compatibility between the application and " "just one version of the library.\n" + << " --help|-h display this help message\n" + << " --version|-v show program version information and exit\n" ; } static bool parse_command_line(int argc, char* argv[], options& opts) { - if (argc < 2) - return false; + int c; - for (int i = 1; i < argc; ++i) + while ((c = getopt_long(argc, argv, "vhub", long_options, NULL)) != -1) { - if (argv[i][0] != '-') - { - if (opts.app_path.empty()) - opts.app_path = argv[i]; - else if (opts.lib1_path.empty()) - opts.lib1_path = argv[i]; - else if (opts.lib2_path.empty()) - opts.lib2_path = argv[i]; - else - return false; - } - else if (!strcmp(argv[i], "--version") - || !strcmp(argv[i], "-v")) - { - opts.display_version = true; - return true; - } - else if (!strcmp(argv[i], "--list-undefined-symbols") - || !strcmp(argv[i], "-u")) - opts.list_undefined_symbols_only = true; - else if (!strcmp(argv[i], "--show-base-names") - || !strcmp(argv[i], "-b")) - opts.show_base_names = true; - else if (!strcmp(argv[i], "--app-debug-info-dir") - || !strcmp(argv[i], "--appd")) - { - if (argc <= i + 1 - || argv[i + 1][0] == '-') - return false; - // elfutils wants the root path to the debug info to be - // absolute. - opts.app_di_root_path = - abigail::tools_utils::make_path_absolute(argv[i + 1]); - ++i; - } - else if (!strcmp(argv[i], "--lib-debug-info-dir1") - || !strcmp(argv[i], "--libd1")) - { - if (argc <= i + 1 - || argv[i + 1][0] == '-') - return false; - // elfutils wants the root path to the debug info to be - // absolute. - opts.lib1_di_root_path = - abigail::tools_utils::make_path_absolute(argv[i + 1]); - ++i; - } - else if (!strcmp(argv[i], "--lib-debug-info-dir2") - || !strcmp(argv[i], "--libd2")) - { - if (argc <= i + 1 - || argv[i + 1][0] == '-') - return false; - // elfutils wants the root path to the debug info to be - // absolute. - opts.lib2_di_root_path = - abigail::tools_utils::make_path_absolute(argv[i + 1]); - ++i; - } - else if (!strcmp(argv[i], "--suppressions") - || !strcmp(argv[i], "--suppr")) - { - int j = i + 1; - if (j >= argc) - return false; - opts.suppression_paths.push_back(argv[j]); - ++i; - } - else if (!strcmp(argv[i], "--redundant")) + switch(c) { - opts.show_redundant = true; - opts.redundant_opt_set = true; - } - else if (!strcmp(argv[i], "--no-redundant")) - { - opts.show_redundant = false; - opts.no_redundant_opt_set = true; - } - else if (!strcmp(argv[i], "--no-show-locs")) - opts.show_locs = false; - else if (!strcmp(argv[i], "--help") - || !strcmp(argv[i], "-h")) - { - opts.display_help = true; - return true; - } - else if (!strcmp(argv[i], "--weak-mode")) - opts.weak_mode = true; - else - { - opts.unknow_option = argv[i]; - return false; - } - } - - if (!opts.list_undefined_symbols_only) - { - if (opts.app_path.empty() - || opts.lib1_path.empty()) - return false; - if (!opts.weak_mode && opts.lib2_path.empty()) - opts.weak_mode = true; - } - - return true; + case 'v': + case VERSION_OPTION: + opts.display_version = true; + break; + case 'h': + case HELP_OPTION: + opts.display_help = true; + break; + case APPLICATION_PATH_OPTION: + opts.app_path = optarg; + break; + case LIB_V1_PATH_OPTION: + opts.lib1_path = optarg; + break; + case LIB_V2_PATH_OPTION: + opts.lib2_path = optarg; + break; + case 'u': + case LIST_UNDEFINED_SYSMBOLS_OPTION: + opts.list_undefined_symbols_only = true; + break; + case 'b': + case SHOW_BASE_NAMES_OPTION: + opts.show_base_names = true; + break; + case APP_DEBUG_INFO_DIR_OPTION: + opts.app_di_root_path = + abigail::tools_utils::make_path_absolute(optarg); + break; + case LIB_DEBUG_INFO_DIR1_OPTION: + // elfutils wants the root path to the debug info to be + // absolute. + opts.lib1_di_root_path = + abigail::tools_utils::make_path_absolute(optarg); + break; + case LIB_DEBUG_INFO_DIR2_OPTION: + // elfutils wants the root path to the debug info to be + // absolute. + opts.lib2_di_root_path = + abigail::tools_utils::make_path_absolute(optarg); + break; + case SUPPRESSIONS_OPTION: + opts.suppression_paths.push_back(optarg); + break; + case NO_REDUNDANT_OPTION: + opts.show_redundant = false; + opts.no_redundant_opt_set = true; + break; + case NO_SHOW_LOCS_OPTION: + opts.show_locs = false; + break; + case REDUNDANT_OPTION: + opts.show_redundant = true; + opts.redundant_opt_set = true; + break; + case WEAK_MODE_OPTION: + opts.weak_mode = true; + break; + default: + display_usage(argv[0], cout); + return 1; + } + } + return 0; } using abigail::tools_utils::check_file; @@ -615,23 +623,8 @@ main(int argc, char* argv[]) { options opts(argv[0]); - if (!parse_command_line(argc, argv, opts)) - { - if (!opts.unknow_option.empty()) - { - emit_prefix(argv[0], cerr) - << "unrecognized option: " << opts.unknow_option << "\n" - << "try the --help option for more information\n"; - return (abigail::tools_utils::ABIDIFF_USAGE_ERROR - | abigail::tools_utils::ABIDIFF_ERROR); - } - - emit_prefix(argv[0], cerr) - << "wrong invocation\n" - << "try the --help option for more information\n"; - return (abigail::tools_utils::ABIDIFF_USAGE_ERROR - | abigail::tools_utils::ABIDIFF_ERROR); - } + if (parse_command_line(argc, argv, opts) != 0) + return 1; if (opts.display_help) { @@ -648,6 +641,19 @@ main(int argc, char* argv[]) return 0; } + if (!opts.list_undefined_symbols_only) + { + if (opts.app_path.empty() + || opts.lib1_path.empty()) + { + emit_prefix(argv[0], cerr) + << "The application path and lib-v1 path options must be set!\n"; + return false; + } + if (!opts.weak_mode && opts.lib2_path.empty()) + opts.weak_mode = true; + } + if (opts.weak_mode && !opts.lib2_path.empty()) { emit_prefix(argv[0], cout)