如何避免 LLVM 的 Support CommandLine 泄漏库参数?
How to avoid LLVM's Support CommandLine leaking library arguments?
我一直在为我的一种语言开发编译器,并想利用 LLVM 支持库 CommandLine 来处理参数解析。
我只添加了两个简单的声明:
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);
然后我在 main 中添加通常的调用:
int main(int argc, char *argv[])
{
cl::ParseCommandLineOptions(argc, argv, " My compiler\n");
...
将 -help
传递给我的程序时,问题非常明显:
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 (e.g. 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's 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
我显然想减少噪音以仅显示我公开的相关命令行选项。
我意识到 CommandLine 实用程序正在使用全局变量和 模板元编程,我的问题可能是由于与 LLVM 静态链接造成的。
我发现了几个似乎涉及该问题的链接,但除了可能动态链接到 LLVM 之外,没有其他具体的解决方案。
- LLVM CommandLine: how to reset arguments?
- LLVMdev: Command line options being put in Target backend libraries
- Bugzilla 8860: command-line argument parser provides too many options when building with --enable-shared
我 运行 OS X El Capitan 版本 10.11.1
我安装的llvm如下:
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
我的 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 $@
据我所知,最好的办法是将所有选项放入特定类别,如果只有一个类别,则使用 void llvm::cl::HideUnrelatedOptions(ArrayRef Categories) (or cl::HideUnrelatedOptions(cl::OptionCategory & Category)。文档表明 clang 使用它来控制命令行选项,但我还没有检查 clang 源代码以查看是否真的如此。
Geoff Reedy 的回答对我来说非常有用,所以我接受了他的回答,但是,我想提供有关您如何设置它的更多详细信息,以及我找到的其他一些信息。
和以前一样,我在 main
函数上方有声明形式的选项,但是我添加了一个声明 OptionCategory
并将其包含在该类别中每个选项的声明中:
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));
然后我在 main
内调用 HideUnrelatedOptions
就在 ParseCommandLineOptions
之前:
int main(int argc, char *argv[])
{
cl::HideUnrelatedOptions( CompilerCategory );
cl::ParseCommandLineOptions(argc, argv, " My compiler\n");
...
现在我的 OPTIONS
输出看起来好多了:
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
这基本上将所有选项标记为 cl::ReallyHidden
,因此它们甚至不会显示为 -help-hidden
:)。
我在 CommandLine Library Manual.
上找到的其他有用信息
我知道 LLVM 在不断变化,所以以防将来页面消失,这里是示例:
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");
...
}
这基本上展示了系统的强大功能,并演示了如何根据需要修改特定选项。
我一直在为我的一种语言开发编译器,并想利用 LLVM 支持库 CommandLine 来处理参数解析。
我只添加了两个简单的声明:
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);
然后我在 main 中添加通常的调用:
int main(int argc, char *argv[])
{
cl::ParseCommandLineOptions(argc, argv, " My compiler\n");
...
将 -help
传递给我的程序时,问题非常明显:
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 (e.g. 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's 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
我显然想减少噪音以仅显示我公开的相关命令行选项。
我意识到 CommandLine 实用程序正在使用全局变量和 模板元编程,我的问题可能是由于与 LLVM 静态链接造成的。
我发现了几个似乎涉及该问题的链接,但除了可能动态链接到 LLVM 之外,没有其他具体的解决方案。
- LLVM CommandLine: how to reset arguments?
- LLVMdev: Command line options being put in Target backend libraries
- Bugzilla 8860: command-line argument parser provides too many options when building with --enable-shared
我 运行 OS X El Capitan 版本 10.11.1
我安装的llvm如下:
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
我的 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 $@
据我所知,最好的办法是将所有选项放入特定类别,如果只有一个类别,则使用 void llvm::cl::HideUnrelatedOptions(ArrayRef Categories) (or cl::HideUnrelatedOptions(cl::OptionCategory & Category)。文档表明 clang 使用它来控制命令行选项,但我还没有检查 clang 源代码以查看是否真的如此。
Geoff Reedy 的回答对我来说非常有用,所以我接受了他的回答,但是,我想提供有关您如何设置它的更多详细信息,以及我找到的其他一些信息。
和以前一样,我在 main
函数上方有声明形式的选项,但是我添加了一个声明 OptionCategory
并将其包含在该类别中每个选项的声明中:
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));
然后我在 main
内调用 HideUnrelatedOptions
就在 ParseCommandLineOptions
之前:
int main(int argc, char *argv[])
{
cl::HideUnrelatedOptions( CompilerCategory );
cl::ParseCommandLineOptions(argc, argv, " My compiler\n");
...
现在我的 OPTIONS
输出看起来好多了:
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
这基本上将所有选项标记为 cl::ReallyHidden
,因此它们甚至不会显示为 -help-hidden
:)。
我在 CommandLine Library Manual.
上找到的其他有用信息我知道 LLVM 在不断变化,所以以防将来页面消失,这里是示例:
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"); ... }
这基本上展示了系统的强大功能,并演示了如何根据需要修改特定选项。