How to avoid LLVM CommandLine support for leaking library arguments?

I worked on a compiler for my language and wanted to use the LLVM CommandLine support library to handle argument parsing.

I added only two simple declarations:

static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename")); static cl::list<std::string> InputFilenames("i", cl::desc("Input files"), cl::value_desc("filenames"), cl::OneOrMore); 

Then I add the usual call basically:

 int main(int argc, char *argv[]) { cl::ParseCommandLineOptions(argc, argv, " My compiler\n"); ... 

The problem is very obvious when passing -help to my program:

 General options: -aarch64-neon-syntax - Choose style of NEON code to emit from AArch64 backend: =generic - Emit generic NEON assembly =apple - Emit Apple-style NEON assembly -cppfname=<function name> - Specify the name of the generated function -cppfor=<string> - Specify the name of the thing to generate -cppgen - Choose what kind of output to generate =program - Generate a complete program =module - Generate a module definition =contents - Generate contents of a module =function - Generate a function definition =functions - Generate all function definitions =inline - Generate an inline function =variable - Generate a variable definition =type - Generate a type definition -debugger-tune - Tune debug info for a particular debugger =gdb - gdb =lldb - lldb =sce - SCE targets (eg PS4) -disable-spill-fusing - Disable fusing of spill code into instructions -enable-implicit-null-checks - Fold null checks into faulting memory operations -enable-load-pre - -enable-objc-arc-opts - enable/disable all ARC Optimizations -enable-scoped-noalias - -enable-tbaa - -exhaustive-register-search - Exhaustive Search for registers bypassing the depth and interference cutoffs of last chance recoloring -gpsize=<uint> - Global Pointer Addressing Size. The default size is 8. -i=<filenames> - Input files -imp-null-check-page-size=<uint> - The page size of the target in bytes -join-liveintervals - Coalesce copies (default=true) -limit-float-precision=<uint> - Generate low-precision inline sequences for some float libcalls -merror-missing-parenthesis - Error for missing parenthesis around predicate registers -merror-noncontigious-register - Error for register names that aren't contigious -mfuture-regs - Enable future registers -mips16-constant-islands - Enable mips16 constant islands. -mips16-hard-float - Enable mips16 hard float. -mno-compound - Disable looking for compound instructions for Hexagon -mno-ldc1-sdc1 - Expand double precision loads and stores to their single precision counterparts -mno-pairing - Disable looking for duplex instructions for Hexagon -mwarn-missing-parenthesis - Warn for missing parenthesis around predicate registers -mwarn-noncontigious-register - Warn for register names that arent contigious -mwarn-sign-mismatch - Warn for mismatching a signed and unsigned value -nvptx-sched4reg - NVPTX Specific: schedule for register pressue -o=<filename> - Output filename -print-after-all - Print IR after each pass -print-before-all - Print IR before each pass -print-machineinstrs=<pass-name> - Print machine instrs -regalloc - Register allocator to use =default - pick register allocator based on -O option =fast - fast register allocator =greedy - greedy register allocator =pbqp - PBQP register allocator -rewrite-map-file=<filename> - Symbol Rewrite Map -rng-seed=<seed> - Seed for the random number generator -stackmap-version=<int> - Specify the stackmap encoding version (default = 1) -stats - Enable statistics output from program (available with Asserts) -time-passes - Time each pass, printing elapsed time for each on exit -verify-debug-info - -verify-dom-info - Verify dominator info (time consuming) -verify-loop-info - Verify loop info (time consuming) -verify-regalloc - Verify during register allocation -verify-region-info - Verify region info (time consuming) -verify-scev - Verify ScalarEvolution backedge taken counts (slow) -x86-asm-syntax - Choose style of code to emit from X86 backend: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly Generic Options: -help - Display available options (-help-hidden for more) -help-list - Display list of available options (-help-list-hidden for more) -version - Display the version of this program 

I clearly would like to reduce the noise in order to show only the corresponding command line parameters that I set.

I understand that CommandLine utility uses global variables and template metaprogramming , and my problem is probably related to binding to LLVM statically.

I found a few links that seem to address this issue, but nothing concrete as a solution other than this, possibly dynamically linked to LLVM.



I work on OS X El Capitan version 10.11.1

I installed llvm as follows:

 git clone http://llvm.org/git/llvm.git git clone http://llvm.org/git/clang.git llvm/tools/clang git clone http://llvm.org/git/clang-tools-extra.git llvm/tools/clang/tools/extra git clone http://llvm.org/git/compiler-rt.git llvm/projects/compiler-rt git clone http://llvm.org/git/libcxx.git llvm/projects/libcxx git clone http://llvm.org/git/libcxxabi.git llvm/projects/libcxxabi mkdir build_llvm cd build_llvm && cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=prefix=/usr/local/llvm ../llvm make 

Relevant parts of my makefile:

 LLVMCONFIG = llvm-config CPPFLAGS = `$(LLVMCONFIG) --cxxflags` -std=c++11 LDFLAGS = `$(LLVMCONFIG) --ldflags` -lpthread -ldl -lz -lncurses -rdynamic LIBS = `$(LLVMCONFIG) --libs` %.o: %.cpp clang++ -I /usr/local/llvm/include -c $(CPPFLAGS) $< -o $@ mycompiler: $(OBJECTS) clang++ -I /usr/local/llvm/include -g $^ $(LIBS) $(LDFLAGS) -o $@ 
+5
source share
2 answers

As far as I can tell, the best thing you can do is put all your options in certain categories and use void llvm :: cl :: HideUnrelatedOptions (ArrayRef Categories) (or cl :: HideUnrelatedOptions (cl :: OptionCategory and Category) , if you have only one category). The documentation indicates that clang uses it to gain control of command line options, although I have not checked the clang source to make sure this is true.

+3
source

Jeff Reedy's answer worked great for me, so I accepted his answer, however, I would like to give more detailed information about how you configured it, as well as other information that I found.

As before, I have my options in a declarative form above my main function, however I added a declarative OptionCategory and included this in the declarations of each option in this category:

 cl::OptionCategory CompilerCategory("Compiler Options", "Options for controlling the compilation process."); static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"), cl::cat(CompilerCategory)); static cl::list<std::string> InputFilenames("i", cl::desc("Input files"), cl::value_desc("filenames"), cl::OneOrMore, cl::cat(CompilerCategory)); 

Then I have a call to HideUnrelatedOptions inside main just before ParseCommandLineOptions :

 int main(int argc, char *argv[]) { cl::HideUnrelatedOptions( CompilerCategory ); cl::ParseCommandLineOptions(argc, argv, " My compiler\n"); ... 

Now my OPTIONS output looks much better:

 OPTIONS: Compiler Options: Options for controlling the compilation process. -i=<filenames> - Input files -o=<filename> - Output filename Generic Options: -help - Display available options (-help-hidden for more) -help-list - Display list of available options (-help-list-hidden for more) -version - Display the version of this program 

This basically marks all options as cl::ReallyHidden , so they don't even show up with -help-hidden :).

Other useful information I found was in the CommandLine Reference Guide .

I know that LLVM is in a constant stream, so just in case the page has gone into the future, here is an example:

 using namespace llvm; int main(int argc, char **argv) { cl::OptionCategory AnotherCategory("Some options"); StringMap<cl::Option*> Map; cl::getRegisteredOptions(Map); //Unhide useful option and put it in a different category assert(Map.count("print-all-options") > 0); Map["print-all-options"]->setHiddenFlag(cl::NotHidden); Map["print-all-options"]->setCategory(AnotherCategory); //Hide an option we don't want to see assert(Map.count("enable-no-infs-fp-math") > 0); Map["enable-no-infs-fp-math"]->setHiddenFlag(cl::Hidden); //Change --version to --show-version assert(Map.count("version") > 0); Map["version"]->setArgStr("show-version"); //Change --help description assert(Map.count("help") > 0); Map["help"]->setDescription("Shows help"); cl::ParseCommandLineOptions(argc, argv, "This is a small program to demo the LLVM CommandLine API"); ... } 

This basically shows the power of the system and demonstrates how to change specific parameters as you wish.

+4
source

Source: https://habr.com/ru/post/1237621/


All Articles