[LLVMdev] CommandLine: using cl::Positional with enum

Daniel Liew daniel.liew at imperial.ac.uk
Sun May 12 06:19:04 PDT 2013


On 10 May 2013 09:44, Pedro Delgado Perez
<pedro.delgadoperez at mail.uca.es> wrote:
> Hi Daniel,
>
> I would like to go deeper with CommandLine and I was asking if you could
> help me again.
>
> Look, following the same example you put in the last message:
>
> ./prog <option1> | ( <option2> --arg1 --arg2) | ( <option3> --arg1 )
>
> What I really really want is the same except I don't want the "--" prefix is
> present in any of the arguments.
>
> ./prog <option1> | ( <option2> arg1 arg2) | ( <option3> arg1 )
>
> The problem is clear: in this case, the arguments can't be optional. So I
> thought to delete all the "cl:opt" and process the arguments before calling:
>
> ClangTool Tool(OptionsParser.getCompilations(),
> OptionsParser.getSourcePathList());

Oh you're using Clang stuff. I know nothing about this so I can't
really help you here.


> in order to give an error if the arguments provided were not correct. But,
> if arguments are correct, then the next error is shown:
>
> warning: /home/user/clang-llvm/build/arg1: 'linker' input unused
>
>
> error: unable to handle compilation, expected exactly one compiler job in ''
> Error while processing /home/user/clang-llvm/build/arg1
>
> How can I manage this? I was thinking about not calling the ClangTool
> Tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList());
> but, I don't know if this would be another problem. In addition, I would
> have to create my own option --help, isn't it?
> What do you recommend me to do?

I am considering fixing the bug in the LLVM CommandLine library but is
going to be a long time before I can look at it. So don't wait for me
to do that.

If you are really desperate to have the command line options in the
way you want they you may need to implement it yourself or use another
library (e.g. http://www.boost.org/doc/libs/1_53_0/doc/html/program_options.html
).

Personally I think it's more important your tool does something rather
than spending time worrying about how it's command line interface
looks, so I would personally just implement everything as an optional
argument and then after parsing check yourself that your options have
been set as you want them.

Thanks,
Dan.

> Thanks in advance,
>
> Pedro.
>
> El dia 08 may 2013 13:56, Daniel Liew <daniel.liew at imperial.ac.uk> escribió:
>
> Hi,
>
> Please try and format your e-mails better. Your e-mail is incredibly
> hard to read due to its lack of new lines.
>
> I don't think the designer of the CommandLine library ever intended for
> cl::Positional to be used with cl::opt<T> where T is an enum.
>
> e.g.
>
> enum OptLevel {
> g, O1, O2, O3
> };
>
> cl::opt<OptLevel> OptimizationLevel(cl::desc("Choose optimization level:"),
> cl::values(
> clEnumVal(g , "No optimizations, enable debugging"),
> clEnumVal(O1, "Enable trivial optimizations"),
> clEnumVal(O2, "Enable default optimizations"),
> clEnumVal(O3, "Enable expensive optimizations"),
> clEnumValEnd),
> cl::Positional
> );
>
> int
> main (int argc, char ** argv)
> {
> cl::ParseCommandLineOptions(argc, argv);
>
> // Easy access in gdb (getValue is inlined!)
> OptLevel* test = &(OptimizationLevel.getValue() );
> }
>
> It also doesn't make a huge amount of sense (based on the output of
> -help) either because the OptimizationLevel options have the "-" prefix
> which is almost always taken to mean that it is optional and NOT
> positional. -help shows...
>
> Choose optimization level:
> -g - No optimizations, enable debugging
> -O1 - Enable trivial optimizations
> -O2 - Enable default optimizations
> -O3 - Enable expensive optimizations
>
> Trying
>
> $ ./program -O1
> $ ./program O1
> $ ./program -- -O1
> $ ./program -- O1
>
> does not result in OptimizationLevel being modified by calling
> ParseCommandLineOptions (I tested this in gdb).
>
> This behaviour is arguably a bug. You're welcome to try and fix it.
>
> I would like to suggest an alternative though. If I understand you
> correctly you're looking for your command line syntax to be something
> like...
>
> ./prog <option1> | ( <option2> --arg1 --arg2) | ( <option3> --arg1 )
>
> I don't see why you should really care about the order, i.e. this is
> probably okay.
>
> ./prog --arg1 <option1>
>
> So why not make every argument optional (i.e. no positional arguments)
>
> then after calling ParseCommandLineOptions you can check the user has
> used the right options by doing something like...
>
> // Note cl::opt<T> is a type of Option
> Option* NOTValidForOption1[] = { &arg1, &arg2};
> Option* NOTValidForOption3[] = { &arg2 };
>
> switch(YourOption)
> {
> case Option1:
> for(int I=0; I < sizeof(NOTValidForOption1)/sizeof(Option*);++I)
> {
> if(NotValidForOption1[I]->getNumOccurrences() != 0)
> {
> //Fail
> }
> }
> break;
>
> case Option2:
> break;
>
> case Option3:
> // similar to Option1
> }
>
> ^ Note the above certainly code be coded better, this is just to give
> you an idea.
>
> You could also make it more obvious in the output of -help that only
> certain options should be used with each other by putting them into
> categories (see cl::cat() in documentation). Note this will only work
> for you if arguments are mutually exclusive as an option may only be in
> one category.
>
> Hope that helps.
>
> Dan.
>
> On 07/05/13 08:58, Pedro Delgado Perez wrote:
>
> Hi,I've been trying to code through CommandLine the options I want my tool
> accepts, but I find quite impossible to achieve robustly what I need .Look,
> I want the tool accepts a list of arguments in a particular order. For this
> goal, I know the cl::Positional flag. But, the problem is that *the first
> argument must be one of a set of options *(like a kind of subcommand of the
> tool). In my case, only the three next commands are possible:
>
> myTool option1myTool option2 arg1 arg2 myTool option3 arg1and I don't want a
> different order is possible, for instance, this is not permitted:myTool arg2
> option2 arg1So, I thought about using an enum for this first argument:enum
> OptLevel{option1, option2, option3};cl::opt<OptLevel>
> OptionsLevel(cl::Positional, cl::desc("Choose one of these
> options:"),cl::values(clEnumVal(option1, "..."),clEnumVal(option2,
> "..."),clEnumVal(option3, "..."), clEnumValEnd),);After that, the rest of
> arguments are also particular of the option selected as the first argument,
> i.e, the rest of arguments are related with the first one. So I thought I
> could independently parse these arguments with:cl::list<std::string> Argv
> (cl::ConsumeAfter, cl::desc("<program arguments>..."));But, doing this when
> I run:myTool option1 file.cpp --I got the next error:"error - this
> positional option will never be matched, because it does not Require a value
> and a cl::ConsumeAfter option is active!"So, I modify "OptionsLeve
>
> lOptionsLevel" including the cl::Required flagThe error is now:"option: does
> not allow a value! option1 specified.option: must be specified at least
> once!option: must be specified at least once!option: must be specified at
> least once!"Then, I decided to use cl::PositionalEatsArgs instead of
> cl::ConsumeAfter. Then, this is the result:"option: does not allow a value!
> option1 specified."But, this time, the program continues. However, if I run
> "myTool option3 arg1 file.cpp --" it gives me a different problem:"warning:
> ../build/arg1: 'linker' input unusederror: unable to handle compilation,
> expected exactly one compiler job in ' '"But the program still goes on.Is
> there a way to accomplish what I have explained? I don't want those errors
> and warnings. Thanks,Pedro.
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev




More information about the llvm-dev mailing list