fuchsia

Fuchsia OS fxl::CommandLineFromArgcArgv() usage?


Fuchsia OS > Guides > Syslog has this example:

#include "src/lib/fsl/syslogger/init.h"
#include "src/lib/fxl/command_line.h"
int main(int argc, char** argv) {
    auto command_line = fxl::CommandLineFromArgcArgv(argc, argv);
    fsl::InitLoggerFromCommandLine(command_line, {"my_program"});
}

Fuchsia OS > Reference does not have FXL listed:

enter image description here

A search of the Fuchsia Project site has one additional example that has fxl::CommandLineFromArgcArgv().

Where do I find arguments, return value and other details on fxl::CommandLineFromArgcArgv()?


Solution

  • The fxl API is not documented as part of the official Fuchsia reference (yet).

    From the readme in the fxl directory (link):

    In an ideal world, FXL wouldn‘t exist and we could use the C++ standard library’s building blocks. [...] We‘d like to keep FXL small and focused on the problem of “fixing” the C++ standard library, which means you probably shouldn’t put your thing in FXL unless it is related to a particular deficiency of the C++ standard library.

    Based on this statement, it seems fxl is not set up as a long-term project, but rather is meant to become empty/obsolete, when the C++ standard library has been sufficiently adapted. It is possible that documentation effort has been limited for this reason.

    We have to rely on the documentation provided directly in the header (link):

    // Builds a |CommandLine| from the usual argc/argv.
    inline CommandLine CommandLineFromArgcArgv(int argc, const char* const* argv)
    

    The CommandLine class is defined in the same header. According to the comments, it distinguishes between optional and positional args. Optional arguments are of the form --key=value or --key (with no value), but not --key value. The positional arguments begin with the first argument not of this form (or the special -- separator).

    The CommandLine member functions are:

    We can write the following example program (uses structured-binding syntax):

    #include <iostream>
    #include "src/lib/fxl/command_line.h"
    
    int main(int argc, char** argv) {
      const auto cl = fxl::CommandLineFromArgcArgv(argc, argv);
    
      std::cout << "Program name = " << cl.argv0() << std::endl;
    
      std::cout << "Optional: " << cl.options().size() << std::endl;
    
      for (const auto& [name,value] : cl.options()) {
        std::cout << name << " -> " << value << std::endl;
      }
    
      std::cout << "Positional: " << cl.positional_args().size() << std::endl;
    
      for (const auto& arg : cl.positional_args()) {
        std::cout << arg << std::endl;
      }
    
      return 0;
    }
    

    After compiling the program (based on this answer), we can get the following output (demonstrating how first positional argument filename turns all following arguments into positional arguments):

    $ hello_world_cpp --k1=v1 --k2 --k3=v3 filename --k4=v4
    Program name = hello_world_cpp
    Optional: 3
    k1 -> v1
    k2 ->
    k3 -> v3
    Positional: 2
    filename
    --k4=v4
    

    Demonstrating -- as a separator:

    $ hello_world_cpp --k1=v1 -- --k2=v2
    Program name = hello_world_cpp
    Optional: 1
    k1=v1
    Positional: 1
    --k2=v2
    

    We could do simple argument parsing using HasOption:

        size_t index;
    
        if (cl.HasOption("key", &index)) {
          handle_key(cl.options.at(index).value);
        }
    

    Adding this to our program and calling it with --key=abc would then pass abc to handle_key.