Well since we have that YAML parser handy....<div><br></div><div>I definitely think that there should be a '--recipe=foo.yaml' commandline option, which in a straightforward and transparent way calls down into `ExecuteRecipe("foo.yaml")`, or similar. There can be a couple overloads for ExecuteRecipe, one taking an in-memory YAML structure, etc. The different drivers can then basically amount to something like `ExecuteRecipe(GNULdCmdLineParser(argv, argc))`.</div>
<div><br></div><div>It might pay to put an extra layer between YAML and the libraries, which is basically a TableGen'd "schema" for the data in the human-readable YAML, with a 1-1 correspondence so it is easy to go back and forth between them for debugging; the goal of this extra layer would be to make it more natural (and faster) to pass around in the libraries since it is just "regular C++", and not some YAML node.</div>
<div><div><font face="arial, sans-serif"><br></font></div><div><font face="arial, sans-serif">--Sean Silva</font></div><div><font face="arial, sans-serif"><br></font></div><div><div class="gmail_quote">On Mon, May 7, 2012 at 4:39 PM, Jim Grosbach <span dir="ltr"><<a href="mailto:grosbach@apple.com" target="_blank">grosbach@apple.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5"><br>
On May 4, 2012, at 5:36 PM, Nick Kledzik <<a href="mailto:kledzik@apple.com">kledzik@apple.com</a>> wrote:<br>
<br>
> On May 4, 2012, at 3:07 PM, Michael Spencer wrote:<br>
>> On Thu, May 3, 2012 at 6:41 PM, Nick Kledzik <<a href="mailto:kledzik@apple.com">kledzik@apple.com</a>> wrote:<br>
>>> I'd like to do some more work on the darwin executable writer.  But most of the work is mach-o variations that are driven by command line options.  So I wanted to work out with you how command line processing will work.<br>

>>><br>
>>> Looking at the Darwin man page for ld(1), it seems most options are darwin specific.  I image other platform linkers are similar.  So, to me it does not make sense to have one big interface that supports all options on all linkers.  Instead, Core just needs to model common options.  Then all platform specific options are a "private" interface within the platform.<br>

>>><br>
>>> In other words, I see:<br>
>>> 1) llvm/Support providing class to make command line parsing easy.<br>
>>> 2) lld/Core providing utilities for managing search paths (for finding input files).<br>
>>> 3) Each platform has its own main() which:<br>
>>> 3a) uses the generic command line utilities to parse the options<br>
>>> 3b) uses the options to set up the ResolverOptions<br>
>>> 3c) calls Core/Resolver<br>
>>> 3d) calls appropriate Passes (may depend on command line options)<br>
>>> 3e) calls its platform executable writer, using private interface to specify platform specific options<br>
>>><br>
>>><br>
>>> Thoughts?<br>
>>><br>
>>> -Nick<br>
>><br>
>> The problem I see with this is embeddability and code duplication.<br>
>> Programmatically setting up a link with common options for the target<br>
>> platform should be trivial, this complicates that by requiring manual<br>
>> setup of the process.<br>
>><br>
>> I was discussing this problem with Chandler, in addition to how to<br>
>> share option parsing code with Clang. The general idea is to have a<br>
>> tablegen file for canonical options (e.g. cc1 options in Clang). Then<br>
>> each specific (ld64, gnu-ld, link.exe) driver would get a td file that<br>
>> mapped each option to one or more canonical options either by a common<br>
>> mapping operation, or calling a custom function.<br>
> Ok.  We need the non-command-line-parse part of main() to be available for use by clients that are embedding linker functionality into other programs, and tablegen could be a nice way to manage the options.  Then my modified proposal is:<br>

><br>
> 1) llvm provides utilities to make command line parsing easy, possibly tablegen based. For embedded linking, it should be easy to programmatically set these options and the defaults should all be reasonable.<br>
> 2) lld/Core providing utilities for managing search paths (for finding input files).<br>
> 3) Each platform has a link() function which:<br>
> 3a) is called by the static linker's main() after command line options are parsed<br>
> 3b) uses the options to set up the ResolverOptions<br>
> 3c) calls Core/Resolver<br>
> 3d) calls appropriate Passes (may depend on command line options)<br>
> 3e) calls its platform executable writer, which can access the parsed command line options.<br>
><br>
> One design point I think is important is to encapsulate the parsed command line options into some class/struct/namespace.  It should not be a bunch of global variables (like llvm::cl::opt<> leads to).  If you want to embed a compiler and linker into one program, you don't want conflicting global variables.<br>

><br>
<br>
</div></div>+1 to this last point in particular. It's important to be able to serialize that state. For example, we'll want to be able to dump out a human-readable version to help debug problems where such a combined program fails to link, but we want to reproduce the problem manually w/ a standalone linker. Being able to dump the intermediate files and a state description for the linker should allow us to generate a recipe for "run the linker w/ these options on these files and you'll see the same behavior the combined program is getting).<br>

<span class="HOEnZb"><font color="#888888"><br>
-Jim<br>
</font></span><div class="HOEnZb"><div class="h5">_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:LLVMdev@cs.uiuc.edu">LLVMdev@cs.uiuc.edu</a>         <a href="http://llvm.cs.uiuc.edu" target="_blank">http://llvm.cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br>
</div></div></blockquote></div><br></div></div>