Meego Wiki
Views

Packaging/Deb conversion example

From MeeGo wiki
(Difference between revisions)
Jump to: navigation, search
(How to build RPMs using Python Distutils)
(Writing Spec File: fixed URL)
Line 89: Line 89:
| Homepage          || URL                                                ||                                   
| Homepage          || URL                                                ||                                   
|-
|-
-
| Build-Depends      || BuildRequires                                      || This needs manual thinking and tinkering and will often require a bit of trial and error. Try to match the Debian packages to http://repo.meego.com/MeeGo/test/trunk-test/repo/ia32/os/i586/ package names.  
+
| Build-Depends      || BuildRequires                                      || This needs manual thinking and tinkering and will often require a bit of trial and error. Try to match the Debian packages to http://repo.meego.com/MeeGo/builds/trunk/daily/core/repos/ia32/packages/i586/ package names.  
|-
|-
| Depends            || Requires                                          || Only if some specifics not covered by the non-devel version of BuildRequires package. In this example, the only non-macro dependency in control file's Depends: fields is lsb-base (>= 3.0), which corresponds to meego-lsb in MeeGo.  
| Depends            || Requires                                          || Only if some specifics not covered by the non-devel version of BuildRequires package. In this example, the only non-macro dependency in control file's Depends: fields is lsb-base (>= 3.0), which corresponds to meego-lsb in MeeGo.  

Revision as of 13:18, 30 November 2010

Contents

.deb to .rpm Conversion Example

This page aims to act as a helpful source for people having .deb packages and wishing to offer them as .rpm packages instead in MeeGo. It will mean manual work for every package, but this page should help in getting a first working draft done quicker.

Package Meta Files – .deb vs .rpm

In a DEB package, most of the package meta information is located under the directory debian, mainly in files control and rules but also a few others. Meanwhile, the .spec file of an RPM contains all the RPM meta data in a single file. Notation of these files is completely different, similarities exist in separation of build phases into logical sections and vivid use of conditional variables. Source RPM (.srpm) package has the upstream .tar.gz together with patches while "source DEB" (a bundle which is fetched by the dget tool by pointing the tool to a .dsc file) is three files: .dsc, orig.tar.gz and .debian.tar.gz. The DEB files unpacked with dpkg-source -x, or during fetching with dget -x, becomes the combination where packaging is under debian/ and possible patches usually under debian/patches.

A table below describes the highest level differences:

Data deb source format rpm source format
upstream source as is as is
full packaged source 3 files, of which the .dsc file is a pointer that can be used to fetch and unpack 1) original source and 2) debian packaging and patches in .debian.tar.gz .srpm that includes 1) original source, 2) spec file and optionally 3) patches
packaging metadata after unpacking the debian/ directory as a whole after unpacking the .spec file and patches separately

Getting The Source

In this example we select a random package to convert from deb format to rpm format. The lucky winner was Transmission BitTorrent Client. Note that it is already packaged for various other rpm distributions, so it's just for the sake of an example and in practice it would be probably beneficial to glance at existing .spec files. We are taking the debian/ directory and the upstream Transmission source to look at from Debian project by looking at and running (on our Debian/Ubuntu machine):

# Download only
dget -d http://ftp.debian.org/debian/pool/main/t/transmission/transmission_1.92-1.dsc
# Unpack upstream source
tar jxvf transmission_1.92.orig.tar.bz2
# Unpack debian/ directory separately
tar zxvf transmission_1.92-1.debian.tar.gz

Writing Spec File

Start editing transmission.spec by copy-pasting the following template into your favorite text editor:

Name:
Version:
Release:1%{?dist}
Summary:
Group:
License:
URL:
Source0:
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)

BuildRequires:
Requires:

%description

%prep
%setup -q

%build
%configure
make %{?_smp_mflags}

%install
rm -rf %{buildroot}
make install DESTDIR=%{buildroot}

%clean
rm -rf %{buildroot}

%files
%defattr(-,root,root,-)
%doc

%changelog

It is more common than not in the rpm world to provide single binary package instead of multiple binary packages. Even so, it is possible to create multiple binaries from one source package even with rpm:s. For the sake of this example, we will do only one binary package similar to Transmission packaging in Fedora, even though Debian has multiple binaries generated.

In another window, go to the unpackaged debian/ directory and first take a look at the control file.

debian/control file entry .spec file entry notes
Source Name
1st line of Description of the main binary package Summary Should begin always with capital letter in the RPM world as per rpmlint policies
Description  %description
Section Group See less /usr/share/doc/rpm*/GROUPS and find a match
Homepage URL
Build-Depends BuildRequires This needs manual thinking and tinkering and will often require a bit of trial and error. Try to match the Debian packages to http://repo.meego.com/MeeGo/builds/trunk/daily/core/repos/ia32/packages/i586/ package names.
Depends Requires Only if some specifics not covered by the non-devel version of BuildRequires package. In this example, the only non-macro dependency in control file's Depends: fields is lsb-base (>= 3.0), which corresponds to meego-lsb in MeeGo.

More precisely the mapping of build depends from debian/control to .spec file goes like this:

Debian dependency MeeGo dependency Notes
debhelper not needed deb packaging related
autotools-dev not needed contains only config.sub and config.guess system-wide files
libgtk2.0-dev gtk2-devel
libevent-dev (>= 1.4) libevent-devel >= 1.4
libglib2.0-dev glib2-devel
libnotify-dev libnotify-devel
libssl-dev openssl-devel
libcurl4-dev / libcurl-dev libcurl-devel
chrpath chrpath
intltool (>= 0.40) intltool >= 0.40
qt4-qmake qt-devel qt-devel includes both dev files and qmake
libqt4-dev qt-devel qt-devel includes both dev files and qmake
libcanberra-gtk-dev libcanberra-devel Note: commented out in control, but we can use them in our package
libgconf2-dev GConf-dbus-devel Note: commented out in control, but we can use them in our package

Other stuff to fill in the .spec file from debian/ files:

.spec file entry Where to find
License debian/copyright
Source0 upstream or debian/copyright
Version obvious, or debian/changelog

Now we have all the basics covered. Let's see what's remaining and potentially needing importing in some form or another:

debian/ file What to do
*.install, *.dirs, *.links Consider to be listed in .spec file's %files section
*.postinst  %post section
*.postrm  %postun section
changelog  %changelog, but should be new for the .rpm package

In the case of post-installation scripts of Transmission, they deal with setting the permissions of the transmission-daemon binary so that it will be run as a special user. We can mimick that behavior in the %post section (and %postun section) of the spec file. A rough take on it is included in the example final spec file, but take into account that there may be or maybe will be policies defining a better way of doing eg. permission handling.

Files Section

This section is used to include all the wanted files to the resulting rpm binary package. When filling in the %files section of the .spec file, it is rather easy to miss files that are installed during the building. One tip is to check the build log for "error: Installed (but unpackaged) file(s) found" or "RPM build errors: Installed (but unpackaged) file(s) found" and utilize that information to select more files to the package.

%{_bindir}, %{_datadir}, %{_mandir} etc. variables should be used in the section to use standard directory names.

Localization files are handled specially. An rpm macro called %find_lang will find all the locale files that belong to the package, and put the list in a file, usually %{name}.lang. That file can be then used to include all of the locales. The "name" parameter given to %find_lang equals to package name, but if the translation domain differs from the package name, it should be specified instead. The generated list can be used with the -f parameter to %files when starting the %files section.

Final .spec File

This is the result of following the example through.

Name: transmission
Version: 1.92
Release: 1%{?dist}
Summary: Lightweight BitTorrent client
Group: Applications/Internet
License: MIT
URL: http://www.transmissionbt.com/
Source0: http://download.m0k.org/transmission/files/transmission-1.92.tar.bz2
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)

BuildRequires: gtk2-devel,libevent-devel >= 1.4,glib2-devel,libnotify-devel,openssl-devel,libcurl-devel,chrpath,intltool >= 0.40,qt-devel,libcanberra-devel,GConf-dbus-devel
Requires: meego-lsb >= 3.0

%description
Transmission is a simple BitTorrent client. It features a very simple,
intuitive interface (gui and command-line) on top on an efficient,
cross-platform back-end.

%prep
%setup -q

%build
%configure
make %{?_smp_mflags}

%install
rm -rf %{buildroot}
make install DESTDIR=%{buildroot}
%find_lang %{name}

%post
addgroup --system --quiet meego-transmission
adduser --system --group --no-create-home --quiet meego-transmission
chown meego-transmission:meego-transmission /var/lib/transmission-daemon/info
chown meego-transmission:meego-transmission /var/lib/transmission-daemon/downloads
chown meego-transmission:meego-transmission /etc/transmission-daemon/settings.json

%postun
if [ -d /var/lib/transmission-daemon/info ]; then
  rm -rf /var/lib/transmission-daemon/info/*
fi

%clean
rm -rf %{buildroot}

%files -f %{name}.lang
%defattr(-,root,root,-)
%doc AUTHORS COPYING NEWS README
%{_bindir}/transmission*
%{_datadir}/applications/transmission.desktop
%{_datadir}/icons/hicolor/*/apps/transmission.png
%{_datadir}/icons/hicolor/scalable/apps/transmission.svg
%{_datadir}/pixmaps/*
%{_datadir}/transmission
%doc %{_mandir}/man1/transmission*

%changelog
* Mon Apr 26 2010 Timo Jyrinki <timo.jyrinki@nomovok.com> - 1.92
- http://trac.transmissionbt.com/wiki/Changes#version-1.92

After build, rpmlint will give a couple of warnings, but no errors. The warnings currently relate to localizations for languages not yet supported in MeeGo, and two duplicate png image files that could be fixed by symlinking.

.deb to .rpm Conversion Example (Python Distutils)

If you already have a Python package that makes use of Distutils then producing RPM based packages is reasonably simple. Once you know how. Some of this information was taken from http://darkness.codefu.org/wordpress/2006/03/17/230.

Creating a RPM can be a simple as issuing the following command:

python setup.py bdist_rpm

Distutils will automatically create a .spec file and in turn generate a RPM with little or no extra work. There are a variety of parameters you can pass setup.py and these are described in detail here: http://docs.python.org/distutils/builtdist.html.


Handling files with spaces in their name

One thing you may notice is that if any of the files in the package have a space in the name generating an RPM will fail. This is because the list of installable files generated by Distutils aren't quoted. The RPM build program assumes these are two seperate files, and fails.

In order to fix this one needs to correct the INSTALLED_FILES file generated by Distutils, and to do this a script needs to be written.

First add the following to setup.cfg, it instructs Distutils to run bdist_rpm_install for the %install part of the .spec file:

vi ./setup.cfg
[bdist_rpm]
install_script = bdist_rpm_install

Next we need to create the bdist_rpm_install script and add the following to it:

vi ./bdist_rpm_install
python2.5 setup.py install --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES
sed -i -e '/ /s/\(.*\)/"\1"/' INSTALLED_FILES

Notice that the Python version is explicitly set in the script, this appears to be necessary if you want to use a non-default version of Python.

If you now try and build the RPM, but produce the .spec file only, you'll see the following in the %install section:

python setup.py bdist_rpm --spec-only
cat dist/[packagename].spec
<snip>
%install
python2.5 setup.py install --single-version-externally-managed --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES
sed -i -e '/ /s/\(.*\)/"\1"/' INSTALLED_FILES
</snip>

Now, should you have any spaces in your filenames, the RPM build won't fail.

python setup.py bdist_rpm
Personal tools