Pautas de empaquetamiento de Ruby
JRuby Gems: Although Fedora has fully functioning JRuby integrated with system RubyGems, we have decided to not include the JRuby specific packaging guidelines here, as they need some more work. They will appear here as soon as we feel that we’ve got everything covered properly. You can contact us on Ruby-SIG mailing list in case of any questions about the prepared JRuby packaging guidelines. |
Hay tres categorías básicas de paquetes Ruby: RubyGems, paquetes Ruby que no son gemas y aplicaciones escritas en Ruby. Estas directrices contienen secciones comunes a todas ellas, así como secciones que se aplican a cada una de forma individual. Asegúrate de leer todas las directrices relevantes para el tipo de paquete Ruby que estás creando.
Compatibilidad con Ruby
Cada paquete de Ruby DEBE indicar sus dependencias en un interpretador de Ruby (esto no se aplica a RubyGems. Utilice requerimiento virtual ruby(release)
para lograr eso:
Requires: ruby(release)
Si el paquete requiere Ruby de cierta(s) versión(es), haga con la versión del requerimiento como este:
Requires: ruby(release) >= 1.9.1
Intérpretes alternos:
Alterna los intérpretes de Ruby (actualmente JRuby)
además Provide: ruby(release) .
Esto implica, que paquetes de RubyGems puro (estos están compartidos entre intérpretes) NO TENDRÍAN Requires: ruby o Requires: jruby para tener sus dependencias satisfechas por cualquiera de estos intérpretes.
|
Over specified ruby(release) versioning:
Please note that if the ruby(release) version requirement is too specific,
it might cause an unexpected interpreter to be drawn in.
E.g. ruby(release) = 1.8 will require JRuby package,
since it is the only package that provides it.
|
Compatibilidad de Diferentes Intérpretes
Most of the pure Ruby packages will work on all Ruby interpreters. There are however cases when the packages use interpreter-specific functions (like fork()
) and won’t run on other interpreters (JRuby). In this case, the package SHOULD require that interpreter. For example, a package that uses fork
SHOULD explicitly specify Requires: ruby
. In case of such package, packager SHOULD file a bug to ask upstream to provide support for other interpreter(s). This SHOULD be documented in specfile.
Líneas shebang
En Fedora, /usr/bin/ruby
está implementado por medio de Rubypick. Rubypick es una herramienta similar a RVM o rbenv. Permite elegir intérprete para ejecutar guion de Ruby. Rubypick enruta cualquiera ejecutado por medio de /usr/bin/ruby
a /usr/bin/ruby-mri
o /usr/bin/jruby
. Por defecto, ejecuta MRI (Implementación Ruby de Matz), pero el usuario puede especificar explícitamente el intérprete utilizando _mri_
o _jruby_
como un primer parámetro. Por ejemplo:
ruby _jruby_ jruby_script.rb gem _mri_ install foo rails _jruby_ s
Al utilizar la variable de entorno RUBYPICK
puede logar el mismo resultado. La variable del entorno puede ser utilizada para establecer un intérprete como el predeterminado global:
export RUBYPICK=_jruby_ ruby jruby_script.rb # Empleará jruby gem install foo # Además empleará jruby
Ejecutables Ruby que son conocidos para ejecutar solo en una implementación Ruby UTILIZARÍAN que implementación específica en su shebang (#!/usr/bin/ruby-mri
o #!/usr/bin/jruby
) para asegurar que ejecutan utilizando que implementación. Todos otros códigos UTILIZARÁN #!/usr/bin/ruby
.
Pautas de Nomenclatura
-
Paquetes que contengan Ruby Gems DEBEN ser invocados
rubygem-%{gem_name}
. -
El nombre de un paquete de extensión/biblioteca de Ruby DEBE comenzar con el intérprete con el que está compilado (ruby, jruby, etc.) y entonces el nombre
UPSTREAM
. Por ejemplo:ruby-UPSTREAM
. Si el nombre últimoUPSTREAM
contieneruby
, ese SERÍA descartado desde el nombre. Por ejemplo, el controlador de base de datos SQLite para ruby es invocadosqlite2-ruby
. El paquete correspondiente de Fedora SERÍA invocadoruby-sqlite3-ruby
. -
Paquetes de aplicación que mayormente proporcionen herramientas de nivel usuario que sucedan para ser escritos en Ruby DEBEN seguir en su lugar la Guia de Nombrado general.
Macros
Non-gem ruby packages and ruby gem packages install to certain standard locations. The ruby-devel
and rubygems-devel
packages contain macros useful for the respective package types. Alternate ruby interpreters will have equivalent locations (to be added to this table later).
Macro | Ruta expandida | Modo de empleo |
---|---|---|
Desde ruby-devel; intentado para paquetes distintos de gem |
||
|
|
Lugar para arquitectura específica p.e. archivos *.so). |
|
|
Lugar para arquitectura independiente archivos p.ej. *.rb). |
|
|
Lugar para arquitectura local específica archivos (p.ej. *.so). |
|
|
Lugar para arquitectura local independiente en archivos (p.ej. *.rb). |
Desde rubygems-devel; intentado para gem paquetes. |
||
|
|
Cima de directorio para la estructura Gem. |
|
|
Directorio con el contenido actual de la Gem. |
|
|
La carpeta |
|
|
La Gem cacheada. |
|
|
El archivo de la especificación Gem. |
|
|
La documentación rdoc de la Gem. |
|
|
El directorio para extensiones MRI Ruby Gem. |
Independencia de intérprete y directorio de macros
Es posible que hayas notado que la tabla anterior tiene diferentes directorios para bibliotecas que no son gem en diferentes intérpretes de Ruby, pero solo un único conjunto de directorios para bibliotecas rubygem. Esto se debe a que el código escrito para un intérprete de Ruby a menudo se ejecutará en todos los intérpretes de Ruby que incluye Fedora (Ruby, JRuby, etc.). Sin embargo, algunos códigos utilizan métodos que no están disponibles en todos los intérpretes (consulte [Compatibilidad entre diferentes intérpretes]). Rubygems tiene la capacidad de incluir diferentes versiones del código en la misma gema, de modo que esta pueda ejecutarse en todas las versiones del intérprete, por lo que solo necesitamos tener un directorio común para rubygems que puedan utilizar todos los intérpretes.
The standard ruby %{vendorlib}
directories lack this facility. For this reason, non-gem libraries need to be placed in per-interpreter directories and MUST have a separate subpackage (or package depending on upstream) for each interpreter that they support.
Bibliotecas
These guidelines only apply to Ruby packages whose main purpose is providing a Ruby library; packages that mainly provide user-level tools that happen to be written in Ruby MUST follow the Ruby applications Guidelines instead.
RubyGems
RubyGems son el formato de empaquetado propio de Ruby. Las gemas contienen muchos de los mismos metadatos que necesitan los RPM, lo que permite una interoperabilidad bastante fluida entre RPM y Gems. Esta directriz garantiza que las gemas se empaqueten como RPM de manera que dichos RPM encajen perfectamente con el resto de la distribución y permite al usuario final satisfacer las dependencias de una gema instalando la Gem empaquetada en RPM adecuada.
Both RPM’s and Gems use similar terminology; there are specfiles, package names, dependencies, etc. for both. To keep confusion to a minimum, terms relating to Gem concepts will be explicitly referred to with the word "Gem" prefixed, e.g., "Gem specification" (.gemspec). An unqualified "package" in the following always means an RPM.
-
Los archivos Spec DEBEN contener una definición de
%{gem_name}
, que es el nombre de la especificación de Gem. -
La
Source
del paquete DEBE ser la URL completa del archivo Gem publicado; la versión del paquete DEBE ser la versión de Gem. -
El paquete DEBE tener
BuildRequires: rubygems-devel
para arrancar en las macros necesarias para compilación. -
NO DEBE aparecer ninguna gem de Ruby con
Requires
niProvides
, ya que estas se generan automáticamente. -
NO DEBE haber
Requires: ruby(release)
, a menos que desee especificar explícitamente la compatibilidad de la versión de Ruby. La dependencia generada automáticamente en RubyGems (Requires: ruby(rubygems)
) es suficiente.
Filtrado de Requisitos y Provisiones
Los requisitos y provisiones de tiempo de ejecución se generan automáticamente mediante el generador de dependencias de RPM. Sin embargo, en ocasiones puede generar dependencias adicionales contrarias a la realidad. Para solucionar esto, es necesario anular el generador de dependencias para que se puedan filtrar las dependencias adicionales. Consulte AutoProvidesAndRequiresFiltering para obtener más detalles.
Compilar gems
Since gems aren’t just an archive format but instead encapsulate both an archive and information used for building the Ruby library, building an RPM from a gem looks a little different from other RPMs.
Una muestra específica para compilar gems sería como esto:
%prep %autosetup -p1 -n %{gem_name}-%{version} # Modifique la especificación de gemspec si es necesario %build # Crea la gema como gem install solamente funciona en un archivo gem gem build ../%{gem_name}-%{version}.gemspec # %%gem_install compila cualquier extensión de C e instala el gem dentro ./%%gem_dir # por defecto, tal que podamos moverlo al buildroot en %%install %gem_install %install mkdir -p %{buildroot}%{gem_dir} cp -a ./%{gem_dir}/* %{buildroot}%{gem_dir}/ # Si hubo programas instalados: mkdir -p %{buildroot}%{_bindir} cp -a ./%{_bindir}/* %{buildroot}%{_bindir} # Si hubo extensiones de C, copiadas al extdir. mkdir -p %{buildroot}%{gem_extdir_mri} cp -a .%{gem_extdir_mri}/{gem.build_complete,*.so} %{buildroot}%{gem_extdir_mri}/
%prep
RPM (a partir de la versión 4.14) puede descomprimir directamente archivos gem, por lo que podemos llamar a gem unpack
para extraer el código fuente del gem. A continuación, llamamos a %setup -n %{gem_name}-%{version}
para indicar a rpm en qué directorio se ha descomprimido el gem. En el mismo nivel de directorio, también se crea automáticamente el archivo %{gem_name}-%{version}.gemspec. Este archivo .gemspec
se utilizará para recompilar la gema más adelante. Si necesitamos modificar el .gemspec
(por instancia, si la versión de las dependencias es incorrecta para Fedora o si el .gemspec
utiliza campos antiguos que ya no son compatibles), lo haríamos aquí. Los parches al código también se pueden realizar aquí.
%build
Después compilamos la gema: Debido a que %gem_install
solamente opera en archivadores gema, después recreamos la gema con gem buils
. El archivo gem que es creado es entonces utilizado por %gem_install
para compilar e instalar el código en el directorio temporal, el cual es por defecto ./%{gem_dir}
. Hacemos esto porque la instrucción %gem_install
compila e instala ambos el código dentro de un paso tal que necesitamos tener un directorio temporal para colocar las fuentes de compilación antes de instalarlas en la sección %install
.
la macro %gem_install
acepta dos opciones adicionales:
- -n <gem_file>
-
Permite sobrescribir gema utilizada para instalación. Esto tal vez obtenga útilies para convertir especificaciones heredadas, tales que quizá especifiquen %{SOURCE0} como una gema para instalación.
- -d <install_dir>
-
Tal vez sustituya el destino de la instalación de gema. Sin embargo no sugerimos utilizar esta opción.
La macro %gem_install NO DEBE ser utilizado para instalar en el %{buildroot}
|
%install
Here we actually install into the %{buildroot}
. We create the directories that we need and then copy what was installed into the temporary directories into the %{buildroot}
hierarchy. Finally, if this ruby gem creates shared objects the shared objects are moved into the arch specific %{gem_extdir_mri}
path.
Parchear requiere versiones de gema
Una necesidad habitual de parcheo es cambiar los requisitos de versión demasiado estrictos en el archivo .gemspec
superior. Esto podría deberse a que el archivo .gemspec
superior solo menciona las versiones con las que se han realizado pruebas explícitas, pero sabemos que otra versión también funcionaría, o porque sabemos que los paquetes que enviamos han aplicado correcciones para comportamientos problemáticos sin aumentar el número de versión (por ejemplo, correcciones retroportadas). Para ajustar estas dependencias, puede utilizar las macros %gemspec_add_dep
y %gemspec_remove_dep
.
Por ejemplo, si quisiera utilizar cualquier versión de Aruba en lugar de la versión excesivamente específica solicitada por versión siguiente, pudo utilizar dentro de la sección %prep
siguiendo dos líneas:
%gemspec_remove_dep -g aruba "~> 0.14.2" %gemspec_add_dep -g aruba
Use macros only on top of generated .gemspec: The %gemspec_add_dep and %gemspec_remove_dep macros work reliably only on .gemspec generated using the ruby spec command. Please don’t use the macros on upstream .gemspec files.
|
Be sure to test: Do not simply change versions without testing that the new version works. There are times the upstream is overly strict but there are also times when the version requirement was specified because a specific bug was encountered or the API changed in a minor release. |
Packaging for Gem and non-Gem use
Ya no es necesario empaquetar para uso no Gem: Originalmente, los módulos rubygem no se colocaban en la ruta de la biblioteca de Ruby, por lo que empaquetábamos rubygems para su uso tanto con gems como sin gems. Esto permitía que el código que utilizaba require('ARubyModulePackagedAsAGem'); funcionara. El módulo rubygem actual añade todas las gemas a la ruta de la biblioteca de Ruby cuando se requiere. Por lo tanto, los empaquetadores NO DEBEN crear subpaquetes que no sean Gem de rubygems para los nuevos paquetes. Dado que la mayoría de los paquetes Ruby en Fedora ahora se empaquetan como gemas instaladas, es posible que tengas que parchear el código para utilizar require('rubygem') lo antes posible en el programa, a fin de garantizar que estos componentes Ruby se encuentren correctamente. Los paquetes para gemas Ruby que actualmente crean un subpaquete que no es una gema DEBEN adaptarse para dejar de enviar el subpaquete que no es una gema (con un Obsoletes y Provides adecuados en el paquete rubygem principal).
|
Paquetes Sin Gem
Los paquetes Ruby Sin Gem DEBEN requerir el paquete ruby-devel en tiempo de compilación con un BuildRequires: ruby-devel
, y PUEDE indicar la versión de ruby mínima necesaria para compilar.
Arquitectura de Compilación y Lugar de Archivo
The following only affects the files that the package installs into %{ruby_vendorarchdir}
and %{ruby_vendorlibdir}
(the actual Ruby library files). All other files in a Ruby package MUST adhere to the general Fedora packaging conventions.
Site versus Vendor: Previously, %{ruby_sitelibdir} and %{ruby_sitearchdir} were used. However, as they are meant only for local installations, please use %{ruby_vendorlibdir} and %{ruby_vendorarchdir} instead.
|
Paquetes Pure Ruby
Los paquetes Pure Ruby DEBEN ser compilados como paquetes noarch.
Los archivos de biblioteca de Ruby dentro de un paquete Ruby puro DEBE ser puesto0 en %{ruby_vendorlibdir}
(o su propio subdirectorio). EL archivo specfile DEBE utilizar esta macro.
Los paquetes Ruby con contenido binario/bibliotecas compartidas
Para paquetes con contenido binario, p.ej. controladores de BdD o cualquier otro vínculo Ruby a bibliotecas C, el paquete DEBE ser de arquitectura específica.
Los archivos binarios dentro de un paquete Ruby con contenido binario DEBE ser puesto en %{ruby_vendorarchdir}
(o su subdirectorio apropiado). Los archivos Ruby es tal que un paquete SERÍA puesto en %{ruby_vendorlibdir}. El archivo específico DEBE utilizar estas macros.
Para paquetes los cuales crean bibliotecas compartidas de C utilizando extconf.rb
export CONFIGURE_ARGS="--with-cflags='%{optflags}'"
SERÍA utilizado para aprobar CFLAGS
a Makefile
correctamente. Además, para colocar los archivos en las carpetas correctas durante compilación, aprueba --vendor
para extconf.rd
como esto:
extconf.rb --vendor
Aplicaciones
Las aplicaciones son
-
programas que proporcionan herramientas de nivel-usuario o
-
aplicaciones de web, típicamente compiladas utilizando Rails, Sinatra o marcos de trabajos similares.
Los paquetes RPM DEBEN obedecer reglas FHS. SERÍAN instalados en %{_datadir}
. La macro siguiente puede ayudarle:
%global app_root %{_datadir}/%{name}
Estos paquetes típicamente no están en la sección Provides
, ya que ningunas otras bibliotecas o aplicaciones dependen de estas.
Aquí hay un ejemplo abreviado:
%global app_root %{_datadir}/%{name} Sumario: Deltacloud REST API Nombre deltacloud-core Versión: 0.3.0 Liberación: 3%{?dist} Grupo: Development/Languages Licencia: Apache-2.0 AND MIT URL: https://incubator.apache.org/deltacloud Origen: https://rubygems.org/gems/%{name}-%{version}.gem Requisitos: rubygem-haml #... Requires(post): chkconfig #... BuildRequires: rubygem-haml #... BuildArch: noarch %description La API Deltacloud es compilada como un API REST basado en servicio. No enlace directamente una biblioteca Deltacloud en su programa a utilizarla. En su lugar, un cliente habla con el API de Deltacloud sobre HTTP a un servidor el cual implementa el interfaz de REST. %package doc Summary: Documentación para %{name} Group: Documentación Requires:%{name} = %{version}-%{release} %description doc Documentación para %{name} %prep %setup -q -n %{name}-%{version} %build %install mkdir -p %{buildroot}%{app_root} mkdir -p %{buildroot}%{_initddir} mkdir -p %{buildroot}%{_bindir} cp -r * %{buildroot}%{app_root} mv %{buildroot}%{app_root}/support/fedora/%{name} %{buildroot}%{_initddir} find %{buildroot}%{app_root}/lib -type f | xargs chmod -x chmod 0755 %{buildroot}%{_initddir}/%{name} chmod 0755 %{buildroot}%{app_root}/bin/deltacloudd rm -rf %{buildroot}%{app_root}/support rdoc --op %{buildroot}%{_defaultdocdir}/%{name} %post # Esto agrega los enlaces /etc/rc*.d propios para el script /sbin/chkconfig --add %{name} %files %{_initddir}/%{name} %{_bindir}/deltacloudd %dir %{app_root}/ %{app_root}/bin #... %files doc %{_defaultdocdir}/%{name} %{app_root}/tests %{app_root}/%{name}.gemspec %{app_root}/Rakefile %changelog #...
Tenga en cuenta que, aunque la fuente es una RubyGem, tenemos que instalar los archivos manualmente bajo %{_datadir}/%{name}, %{_bindir}, etc. para seguir FHS y guias de empaquetado general. si archivos específicos de Fedora adicional (archivos .service
de systemd, configuraciones) se requieren, SERÍAN
-
añadidos por medio de otra etiqueta
%SOURCE
Source1: deltacloudd-fedora
-
colocado en lugares apropiados durante la etapa
%install
install -m 0755 %{SOURCE1} %{buildroot}%{_bindir}/deltacloudd
Ejecutar conjunto de pruebas
Si está disponible un conjunto de pruebas para el paquete (incluso separadamente, por ejemplo no incluido en el gem pero disponible en el repositorio upstream), SERÍA ejecutado en %check
. El conjunto de pruebas es la herramienta únicamente automatizada la cual puede asegurar la funcionalidad básica del paquete. Ejecutándolo es especialmente ayudante cuando son requeridas recompilaciones masivas. PUEDE omitir la ejecución del conjunto de pruebas cuando no son necesarias todas las dependencias de compilación pero esto DEBE ser documentada dentro del archivo de especificación specfile. Las dependencias ausentes de compilación para habilitar la suite de prueba SERÍA empaquetada para Fedora tan pronto como sea posible y la suite de prueba re-habilitada.
Las pruebas NO SERÍAN ejecutadas utilizando Rake, como al menos Rake siempre dibuja en algunas dependencias innecesarias como hoe o gemcutter. Para razones similares, una dependencia en Bundler SERÍA evitada. Además, la cobertura del código del marco de trabajo tal como SimpleCov y Coveralls SERÍA evitada.
Probar Con Diferentes Implementaciones de Ruby
Para ejecutar con implementaciones diferentes de Ruby tales como JRuby, añada BuildRequires: jruby
Después utilice intercambiador de intérprete de Rubypick:
ruby _jruby_ -Ilib -e 'Dir.glob "./test/test_*.rb", &method(:require)'
Si tu paquete ejecuta pruebas unitarias para ruby-mri y está destinado a ejecutarse en intérpretes alternativos, entonces también debe ejecutar las pruebas unitarias en todos los intérpretes alternativos. Este es el único método que tenemos para comprobar la compatibilidad del código en cada intérprete. Se aplican las mismas reglas: puedes omitir esto si las bibliotecas que necesitas no están disponibles para un intérprete alternativo específico, pero DEBES incluir un comentario para explicarlo.
Probando el empleo de los marcos de trabajo
La comunidad de Ruby admite muchas pruebas de marcos de trabajo. Las secciones siguientes demuestran como varias de las pruebas de ejecución utilizando las más comunes de ellas.
MiniTest / Test::UNIT
MiniTest y Test::UNIT se incluyen con Ruby. Para utilizarlos, debe usar BuildRequires: rubygem-minitest
o BuildRequires: rubygem-testunit
respectivamente. Para ejecutar el conjunto de pruebas, puede usar algo como:
%check ruby -Ilib -e 'Dir.glob "./test/**/*_test.rb", &method(:require)'
You might need to adjust -Ilib
to be -Ilib:test
, or you could need to use a slightly different matching pattern for test_*.rb
, etc. Packagers are expected to use the right pattern for each gem.
Conjunto de pruebas no incluidas dentro del paquete
A veces tiene que obtener las pruebas separadamente desde el paquete de gem de versión superior. Como un ejemplo deja proporcionar que está empaquetando rubygem-delorean
, versión 1.2.0, lo cual es hospedado en Github. Las pruebas no incluyen en el mismo Gem, tal que necesite obtenerlas y ajustar el archivo specfile correspondientemente:
# git clone https://github.com/bebanjo/delorean.git && cd delorean # git checkout v1.2.0 # tar -czf rubygem-delorean-1.2.0-specs.tgz spec/ Source1: %{name}-%{version}-specs.tgz # ... %prep %setup -q -n %{gem_name}-%{version} -b 1 # ... %check pushd ./%{gem_instdir} # Enlace la suite de pruebas en el lugar correcto en el árbol de fuente. ln -s %{_builddir}/spec . # Ejecutar pruebas rspec spec popd # ...
-
Asegúrese incluir la versión de las pruebas dentro del nombre de fuente, tal que cuando actualice a la versión nueva, rpmbuild fallará porque no encontraría el propio
%{SOURCE1}
(y esto le recordará actualizar las pruebas, también). -
Añada las instrucciones utilizadas para obtener las pruebas en el specfile como instrucciones. Esto lo hará un montón más fácil la siguiente vez que necesitará obtenerlos.
-
Ejecutar las pruebas como normalmente haría.
Want to help? Learn how to contribute to Fedora Docs ›