Используйте linux getopt в macOS - PullRequest
0 голосов
/ 16 марта 2020

Я пытаюсь проанализировать аргументы командной строки, используя getopt() в c++:

#include <unistd.h>
#include <iostream>

int main(int argc, char** argv) {
  int opt;

  opterr = 0; // Don't allow getopt to print err messages

  // Parse command line args using getopt
  // "s:" means s is a required argument
  while (optind < argc) {
    if ((opt = getopt(argc, argv, "as:")) != -1) {
      // std::cout << char(opt) << "\n";
      switch (opt) {
        case 'a':
          std::cout << "flag 'a' set" << "\n";
          break;
        case 's':
          std::cout << "got argument for option 's': " << optarg << "\n";
          break;
        case '?':  // Unknown option
          if (optopt == 's')
            std::cerr << "'s' option requires an argument -- " 
                      << char(optopt) << "\n";
          std::cerr << "Invalid option -- " 
                    << char(optopt) << "\n";
          break;
        default:
          break;
      }
    }
    else {
      std::cout << "Non option argument: " << argv[optind] << "\n"; 
      optind++;
    }
  }
}

Это работает, как и ожидалось, на моем Ma c. Я скомпилировал, используя g++ -g -std=c++11. Это вывод для g++ -v:

Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 11.0.0 (clang-1100.0.33.17)
Target: x86_64-apple-darwin19.3.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

Это вывод во время выполнения:

$ ./a.out -a -s 12 file_path1 file_path2 -s 123
flag 'a' set
got argument for option 's': 12
Non option argument: file_path1
Non option argument: file_path2
got argument for option 's': 123

Но, когда я запускаю это на машине linux (после компиляции с те же флаги), я получаю другой вывод:

$ ./a.out -a -s 12 file_path1 file_path2 -s 123
flag 'a' set
got argument for option 's': 12
got argument for option 's': 123

Вот вывод для g++ -v на linux:

Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)

Я также тестировал с g++ v9.2 на Linux, но вывод остается прежним. Я даже установил g++ v9.3 на macOS, используя brew, и я все еще получаю те же результаты.

Копая эту проблему немного дальше, я обнаружил, что linux использует расширенную версию (это может быть документацией для linux версии ) getopt. Эта версия в основном анализирует все аргументы от 1 до argc независимо от того, встречает ли он неопциональный аргумент или нет. Он обновляет optind до следующего параметра параметра idx (переходит, если между ними есть неопциональные аргументы). Принимая во внимание, что в macOS он останавливается на первом аргументе без опций (см. this manpage ). Он не будет автоматически увеличивать optind до следующего параметра idx аргумента.

Одним из возможных решений является обнаружение аргументов, не являющихся параметрами, отдельно от while() l oop , Но я пытаюсь выяснить, отсутствует ли какой-либо флаг, или есть какой-то другой обходной путь, который позволил бы компилятору использовать расширенную версию getopt в macOS.

Спасибо!

...