¿Cómo incrustar una gema de rubí en un proyecto de C#y solicitarla de un script de IronRuby incrustado?
.net msbuild (3)
Tengo un proyecto de C # en el que he incorporado un programa de IronRuby. El proyecto (incluido mi script ruby) se compila en un archivo .exe en Visual Studio 2010 para su distribución. Estoy usando un patrón similar a este para arrancar el script de IronRuby: http://pastebin.com/NKes1cyc (y Jimmy Schementi entra en más detalles aquí: http://blog.jimmy.schementi.com/2009/12/ironruby-rubyconf-2009-part-35.html ).
Mi problema: me gustaría incrustar una gema (json_pure) en mi ensamblaje de C # y llamarlo desde el script ruby.
Algunos recursos que he encontrado:
En JRuby, puede empaquetar fácilmente una gema en un archivo jar y luego simplemente solicitar el archivo jar en tiempo de ejecución: http://blog.nicksieger.com/articles/2009/01/10/jruby-1-1-6-gems-in-a-jar
La herramienta irpack (en http://github.com/kumaryu/irpack ) es capaz de compilar a Ruby en un archivo .exe (creo que crea y compila dinámicamente un proyecto de C #) mientras incrusta la biblioteca estándar de ruby. Pero parece que solo está incrustando los archivos .Rll de IronRuby pre-construidos, no los archivos ruby .rb. El enfoque que utiliza esta herramienta funcionaría si pudiera averiguar cómo compilar los archivos fuente de Ruby en un archivo .dll.
¿Cómo puedo incrustar una gema de IronRuby en un ensamblaje de C # (o compilar una gema de IronRuby en un archivo .dll)?
EDITAR:
La página 472 de IronRuby In Action ("Uso de bibliotecas externas") explica cómo solicitar bibliotecas estándar de ruby desde un archivo ruby incrustado. Implica agregar la (s) carpeta (s) a la colección de rutas de búsqueda de tiempo de ejecución, de la siguiente manera (editada por brevedad y claridad):
ScriptEngine engine = IronRuby.Ruby.CreateEngine();
var searchPaths = engine.GetSearchPaths().Concat(new[]
{
"C://Program Files (x86)//IronRuby 1.1//Lib//ruby//1.9.1",
"C://Program Files (x86)//IronRuby 1.1//Lib//ironruby"
});
engine.SetSearchPaths(searchPaths)
Este enfoque asume que la máquina host tiene IronRuby instalado, pero quiero incrustar archivos ruby (de una gema) en el ensamblaje para que pueda ejecutarse sin IronRuby preinstalado.
EDIT 2 (investigación adicional):
Al leer el código fuente de la herramienta irpack mencionada anteriormente, observo que Kumaryu está incrustando recursos en el ensamblaje final a través de la clase System.IO.Packaging.Package, y luego pasa el paquete a la llamada a msbuild (consulte https://github.com/kumaryu/irpack/blob/master/lib/irpack/packager.rb ). Quizás alguna investigación adicional sobre el empaquetado de archivos en un ejecutable lleve a una solución. El problema que veo es que los archivos ruby en una gema require
otros archivos ruby ... ¿puede un archivo ruby en un paquete de ensamblaje require
otros archivos ruby en el mismo paquete?
EDITAR 3:
Todavía no he llegado más lejos a una respuesta, pero me interesaría escuchar los comentarios de cualquiera, incluso si es solo un enlace o una sugerencia sobre dónde buscar. Soy nuevo en msbuild, y la documentación es bastante fuerte. Una búsqueda inicial en la web de "msbuild embed zip package" no reveló nada relevante.
Estoy trabajando con https://.com/users/2086/mcintyre321 para convertir su biblioteca en C # / IronRuby usando mi código de empaque ( https://github.com/rifraf/IronRubyAppPackager#readme ).
Hay algunos arreglos necesarios en el paso de la venta que están relacionados con las versiones posteriores de Ruby con RubyGems incrustado en lugar de cargarse, pero se está avanzando.
Su código requiere ''json'', y tengo un truco para forzarlo a usar la implementación de Ruby en lugar de los archivos .so de C-linkage. Esto debería significar que funcionará con IronRuby ok. Informaré, o no dude en contactarme con la fuente que desea ejecutar.
intente esto https://github.com/rifraf/IronRubyAppPackager#readme (o espere a que le informe si funciona con la biblioteca que estoy intentando incrustar)
Informando de nuevo:
El proceso al que he ido es ...
bifurque y submodule todos los proyectos (IronRubyEmbeddedApps, IronRubyAppPackager, Serfs and Vendorize) desde https://github.com/rifraf , y los agregó a todos en una solución VS. Actualicé todos los proyectos a .NET4 y los hice referenciarse en lugar de los ensamblados .net2 incluidos.
Ejecute Vendorize para extraer todas las dependencias / gemas
D:/projects/SomeLibrary/lib_vendor_
ejecutando:D:/projects/SomeLibrary/lib>ruby -I../../Vendorize/lib -rvendorize some_lib.rb
Generado ac # project en
D:/projects/SomeLibrary/lib/_IRPackager_/some_lib.csproj
ejecutando:D:/projects/SomeLibrary/lib>ruby -I../../IronRubyAppPackager/lib/IRPackager.rb some_lib.rb
Agregué el some_lib.csproj a mi solución, lo actualicé a .net4 y reparé las referencias
- En este punto, puede ejecutar el proyecto en .NET, independiente, ejecutando
var Ruby = new EmbeddedRuby(); Ruby.Decoder = new Program.GZipDecoder(); Ruby.Mount("App"); Ruby.Run("gocardless.rb");
¡Y lo consiguió! Brillante, pensé!
En realidad, en este punto, descubrí que había fallado en el paso 2 para vender todas las bibliotecas requeridas. La venta a través del proveedor intercepta llamadas require
y luego guarda los archivos rb llamados en _Vendor_
- si no se ejecuta require
(así que ejecute todas las pruebas y espero que la cobertura de la prueba sea del 100%) no se detectará.
Por alguna razón, no estaba recogiendo uno de los archivos requeridos, aunque hubo un requerimiento. Al final, creé manualmente el contenido para el directorio del proveedor copiando mi biblioteca y usando el comando bundle install --deployment
. Repita los pasos 3 y 4 y termino ... ¿verdad?
No, recibo un error acerca de la falta de no such file to load -- json/pure
cuando ejecuto el proyecto generado, creo que esto es algo para hacer una combinación de ironruby que no tiene una implementación json nativa, yo hago la venta manual y yo Para bodge cosas en varios puntos hoy.
Para concluir, este método funciona muy casi, funcionará si su biblioteca y sus dependencias funcionan correctamente con ironruby, y puede conseguir que el proveedor funcione correctamente.
Me estoy rindiendo y portando la biblioteca a la forma antigua.
edición: como se menciona a continuación, rifraf me está ayudando y está buscando actualizar las herramientas que estaba usando. ¡mira este espacio!
Require es un método que se puede anular como cualquier otro método de ruby. Creo que así es como funcionaba el paquete original de gemas rubí, las gemas simplemente anularían el require
.
Si puede empaquetar la gema en su .exe de alguna manera, puede anular la require
de cargar desde el ensamblaje.