title: Compiling an IronPython WPF project to exe
body: <p>What is the best way to pack up an IronPython application for deployment? After scouring the web the best thing I've come up with (and what I'm currently doing) is using <code>clr.CompileModules()</code> to glue together my entire project's .py files into one .dll, and then having a single <code>run.py</code> do this to run the dll: </p>
  
  <pre><code>import clr
  clr.AddReference('compiledapp.dll')
  
  import app
  </code></pre>
  
  <p>This is still suboptimal, though, because it means I have to</p>
  
  <ol>
  <li>distribute 3 files (the <code>.dll</code>, the <code>.xaml</code>, and the <code>run.py</code> launcher) </li>
  <li>install IronPython on the host machine</li>
  </ol>
  
  <p>Plus, this feels so... hacky, after the wonderful integration IronPython already has with Visual Studio 2010. I'm completely mystified as to why there is no integrated build system for IPy apps, seeing as it all boils down to IL anyway.</p>
  
  <p>Ideally, I want to be able to have a single <code>.exe</code> with the <code>.xaml</code> merged inside somehow (I read that C# apps compile XAML to BAML and merge them in the executable), and without requiring IronPython to be installed to run. Is this at least halfway possible? (I suppose it's ok if the exe needs some extra .DLLs with it or something. The important part is that it's in .exe form.)</p>
  
  <hr>
  
  <p><strong>Some edits to clarify:</strong> I have tried <em>pyc.py</em>, but it seems to not acknowledge the fact that my project is not just <code>app.py</code>. The size of the exe it produces suggests  that it is just 'compiling' <code>app.py</code> without including any of the other files into the exe. So, how do I tell it to compile every file in my project? </p>
  
  <p><a href="https://imgur.com/dd44u.png" rel="noreferrer">To help visualize this, here is a screenshot of my project's solution explorer window.</a></p>
  
  <hr>
  
  <p><strong>Edit II:</strong> It seems that unfortunately the only way is to use <code>pyc.py</code> and pass <em>every single file</em> to it as a parameter. There are two questions I have for this approach:</p>
  
  <ol>
  <li>How do I possibly process a command line that big? There's a maximum of 256 characters in a command.</li>
  <li>How does pyc.py know to preserve the package/folder structure? As shown in my project screenshot above, how will my compiled program know to access modules that are in subfolders, such as accessing DT\Device? Is the hierarchy somehow 'preserved' in the dll?</li>
  </ol>
  
  <hr>
  
  <p><strong>Edit III</strong>: Since passing 70 filenames to <code>pyc.py</code> through the command line will be unwieldy, and in the interest of solving the problem of building IPy projects more elegantly, I've decided to augment <code>pyc.py</code>. </p>
  
  <p>I've added code that reads in a <code>.pyproj</code> file through the <code>/pyproj:</code> parameter, parses the XML, and grabs the list of py files used in the project from there. This has been working pretty well; however, the executable produced seems to be unable to access the python subpackages (subfolders) that are part of my project. My version of <code>pyc.py</code> with my <code>.pyproj</code> reading support patch can be found here: <a href="http://pastebin.com/FgXbZY29" rel="noreferrer">http://pastebin.com/FgXbZY29</a></p>
  
  <p>When this new <code>pyc.py</code> is run on my project, this is the output:</p>
  
  <pre><code>c:\Projects\GenScheme\GenScheme&gt;"c:\Program Files (x86)\IronPython 2.7\ipy.exe"
  pyc.py /pyproj:GenScheme.pyproj /out:App /main:app.py /target:exe
  Input Files:
          c:\Projects\GenScheme\GenScheme\__init__.py
          c:\Projects\GenScheme\GenScheme\Agent.py
          c:\Projects\GenScheme\GenScheme\AIDisplay.py
          c:\Projects\GenScheme\GenScheme\app.py
          c:\Projects\GenScheme\GenScheme\BaseDevice.py
          c:\Projects\GenScheme\GenScheme\BaseManager.py
          c:\Projects\GenScheme\GenScheme\BaseSubSystem.py
          c:\Projects\GenScheme\GenScheme\ControlSchemes.py
          c:\Projects\GenScheme\GenScheme\Cu64\__init__.py
          c:\Projects\GenScheme\GenScheme\Cu64\agent.py
          c:\Projects\GenScheme\GenScheme\Cu64\aidisplays.py
          c:\Projects\GenScheme\GenScheme\Cu64\devmapper.py
          c:\Projects\GenScheme\GenScheme\Cu64\timedprocess.py
          c:\Projects\GenScheme\GenScheme\Cu64\ui.py
          c:\Projects\GenScheme\GenScheme\decorators.py
          c:\Projects\GenScheme\GenScheme\DeviceMapper.py
          c:\Projects\GenScheme\GenScheme\DT\__init__.py
          c:\Projects\GenScheme\GenScheme\DT\Device.py
          c:\Projects\GenScheme\GenScheme\DT\Manager.py
          c:\Projects\GenScheme\GenScheme\DT\SubSystem.py
          c:\Projects\GenScheme\GenScheme\excepts.py
          c:\Projects\GenScheme\GenScheme\FindName.py
          c:\Projects\GenScheme\GenScheme\GenScheme.py
          c:\Projects\GenScheme\GenScheme\PMX\__init__.py
          c:\Projects\GenScheme\GenScheme\PMX\Device.py
          c:\Projects\GenScheme\GenScheme\PMX\Manager.py
          c:\Projects\GenScheme\GenScheme\PMX\SubSystem.py
          c:\Projects\GenScheme\GenScheme\pyevent.py
          c:\Projects\GenScheme\GenScheme\Scheme.py
          c:\Projects\GenScheme\GenScheme\Simulated\__init__.py
          c:\Projects\GenScheme\GenScheme\Simulated\Device.py
          c:\Projects\GenScheme\GenScheme\Simulated\SubSystem.py
          c:\Projects\GenScheme\GenScheme\speech.py
          c:\Projects\GenScheme\GenScheme\stdoutWriter.py
          c:\Projects\GenScheme\GenScheme\Step.py
          c:\Projects\GenScheme\GenScheme\TimedProcess.py
          c:\Projects\GenScheme\GenScheme\UI.py
          c:\Projects\GenScheme\GenScheme\VirtualSubSystem.py
          c:\Projects\GenScheme\GenScheme\Waddle.py
  Output:
          App
  Target:
          ConsoleApplication
  Platform:
          ILOnly
  Machine:
          I386
  Compiling...
  Saved to App
  </code></pre>
  
  <p>So it correctly read in the list of files in the <code>.pyproj</code>... Great! But running the exe gives me this:</p>
  
  <pre><code>Unhandled Exception: IronPython.Runtime.Exceptions.ImportException: 
  No module named Cu64.ui
  </code></pre>
  
  <p>So even though <code>Cu64\ui.py</code> is obviously included in compilation, the exe, when run, can't find it. This is what I was afraid of in point #2 in the previous edit. How do I preserve the package hierarchy of my project? Perhaps compiling each package seperately may be needed?</p>
  
  <p><em>I'll extend the bounty for this question. Ultimately my hope is that we can get a working pyc.py that reads in pyproj files and produces working exes in one step. Then maybe it could even be submitted to IronPython's codeplex to be included in the next release... ;]</em></p>