From patchwork Thu Nov 11 02:42:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: tangmeng X-Patchwork-Id: 47436 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 F33F1385840A for ; Thu, 11 Nov 2021 02:43:06 +0000 (GMT) X-Original-To: libabigail@sourceware.org Delivered-To: libabigail@sourceware.org Received: from smtpbg516.qq.com (smtpbg516.qq.com [203.205.250.54]) by sourceware.org (Postfix) with ESMTPS id 0398A3858407 for ; Thu, 11 Nov 2021 02:42:58 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 0398A3858407 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: bizesmtp49t1636598574t9o0mm37 Received: from localhost.localdomain (unknown [58.240.82.166]) by esmtp6.qq.com (ESMTP) with id ; Thu, 11 Nov 2021 10:42:47 +0800 (CST) X-QQ-SSF: 0140000000200050C000000A0000000 X-QQ-FEAT: 3VHFGWe+x7FXKi5es1ukP7mmMuRALiAf3cvTW6x/WeRl3Qo0zrA+s2gM2du4o gIp3CsNoWbrpxOqyFeHs/3ilP1ZSzVeWFRbCQ2I08B2/x4z6a+Onfq10g1682SPz5dry77D 8q827Zw3Eg21zv2AP/Hks5uwx0Cw/0OiUaga8Tj/ISFHWx2tHZXMB7UdEPZR1novxLOLuT0 wRZMT2bvfiimfa6BTZTwZyOdkFzduKvE4u8ewO4dseIKSoekYH01J+uieZp/phyGhzLCjDB Wo4upUTfzrFgY5j/g3gcHdPNy9vtJJo9FUs7Yalxzr4CoOGQM4SRQROoBRhL34aJeWk1g2/ mU3YYWEVc69GW5xJ7nZS6dy/eM4d2Sz+Imsmf0H/mmqJHjef+A= X-QQ-GoodBg: 2 From: tangmeng To: libabigail@sourceware.org Subject: [PATCH v2] abicompat: Make the commands more pleasant Date: Thu, 11 Nov 2021 10:42:45 +0800 Message-Id: <20211111024245.25955-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_H3, RCVD_IN_MSPIKE_WL, 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: # 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. 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)