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

Pedro Delgado Perez pedro.delgado at uca.es
Tue May 14 07:50:19 PDT 2013


 
Hi Daniel,

Thanks for your answer. 

> 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. 
> 
Ok, ok, but, if you end up fixing this, please keep me post.

> 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 [ 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.
> 
Yes, I will try using that library, but if it's too complicated I will simply implement the arguments as optional.

Thanks again,

Pedro.

El dia 12 may 2013 15:19, Daniel Liew <daniel.liew at imperial.ac.uk> escribió:
> 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 [ 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://llvm.cs.uiuc.edu ]
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev [ http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev ]
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130514/90ea7eba/attachment.html>


More information about the llvm-dev mailing list