Packaging tricks

From FedoraProject

(Difference between revisions)
Jump to: navigation, search
(make sed more secure - try to remove shebang only on the first line)
m (Recommended values for the Group: tag)
Line 272: Line 272:
 
== Recommended values for the Group: tag ==
 
== Recommended values for the Group: tag ==
  
The Group: tag is not used for anything in fedora, [[PackageMaintainers/CompsXml| comps]] are used for
+
The Group: tag is not used for anything in Fedora, [[PackageMaintainers/CompsXml| comps]] are used for
 
grouping of packages. Still, it is  probably best to use one of
 
grouping of packages. Still, it is  probably best to use one of
 
the existing groups listed in /usr/share/doc/rpm-%{version}/GROUPS
 
the existing groups listed in /usr/share/doc/rpm-%{version}/GROUPS

Revision as of 10:46, 26 February 2013

This page is used to hold packaging related information that should not be in guidelines (because they are controversial, or because we don't want to inflate the guidelines even more). The guidelines are listed on PackageMaintainers/MainPagePackaging. A page for common rpmlint issues carries similar recommendations PackageMaintainers/Common Rpmlint Issues. A similar page targeted at multilib issues, with also some hints about keeping timestamps is at PackagingDrafts/MultilibTricks. Understanding when to apply these tips may help you make better packages.

Contents

Recommendations for review requests

  • Use pkgs.fedoraproject.org to view the .spec file of an existing package that are in Fedora. Having a look at other packages can give very interesting insights. However, it should always be remembered that some packages may not be in sync with the current guidelines (and some packages are under review).
  • Run rpmlint on both the SRPM and the binary RPMs before uploading them for review. Look at the output closely and fix those things that need fixing. (Run "rpmlint -i" for additional explanatory information about each issue.) If there are errors where you are unsure if they need fixing mention them in the bug report and ask for advice. If there are known false-positives mention them, too. Some additional information about common rpmlint errors and how to deal with them is at PackageMaintainers/Common Rpmlint Issues.
  • Increase the "Release" tag every time you upload a new package to avoid confusion. The reviewer and other interested parties probably still have older versions of your SRPM lying around to check what has changed between the old and new packages; those get confused when the revision didn't change.
  • One Review-Bug for one package. Reviewing and tracking multiple packages in one bug is painful. If the packages depend on each other let the bugs block each other (See the fields "Bug ??? depends on:" and "Bug ??? blocks" in bugzilla).
  • List your binary rpms in verbose mode (rpm -qplv filename.rpm) and verify that the included files and directories and their file access permissions are correct. During review there are still too many packages, which install files into a new directory, but don't include the directory itself, or which install files with wrong access permissions (like executable documentation or non-executable shared libraries).

Recommendations for a sane review process

  • Let everybody comment on the review.
  • Comments on items that are not blockers in the guidelines are relevant. The goal of the review is to have good packages, the guidelines are not bureaucratic formal rules, but best packaging practices (and conventions), still they cannot and should not cover everything.
  • Exceptions from guidelines may happen. In that case it may be a good idea to have somebody ask on the relevant lists for help/advice, especially if there is disagreement.
  • Answer questions from all the comments, even those that are not blockers.
  • Even if the review has been accepted, let some time for others to comment if the review was fast.
  • Comments that are to be fixed upstream may be relevant in a review request. Don't hesitate to communicate with upstream during the review if an issue that is relevant for upstream has been found out. It may happen that a packages not in shape for inclusion in fedora and requires some work upstream before being imported.

Avoiding application binary interface changes in releases (controversial)

Application binary interface (ABI) changes in libraries (with a change in soname) should be avoided in fedora releases and done only in rawhide, except when solving a security issue or a very grave bug.

When breaking Application binary interface

When breaking ABI, it is nice to warn on the fedora-devel-announce list:

http://www.redhat.com/archives/fedora-devel-announce/

and especially the package maintainers who depend on your package ABI. Dependent packages may be found using:

 repoquery --repoid=rawhide-source --arch=src --whatrequires mypackage-devel 

Some interesting utilities exist for finding differences in ABI, and finding which package provide sonames, rpmsoname and rpmsodiff.

Acceptable use of rpath

Using rpath for libraries in system library directories is forbidden in fedora. It may be acceptable, and even desirable to use rpath for internal libraries that are nevertheless installed (for example to factor out code for different executables). That way it could be avoided to have these libraries installed on system paths. For example the libraries could be installed in:

 %{_libdir}/myapp/libmyapp.so.0.3.4 

And have the rpath set to %{_libdir}/myapp/.

Install dlopened objects out of %{_libdir} (controversial)

Objects that are dlopened and not linked against should not be in %{_libdir}, but in a directory below libdir where the application dlopening the object should search for. This is already the setup used by most packages, for example, there is typically a specific directory for plugins containing the dlopened objects.

Use of common namespace

Package files and directory are installed in places where name conflicts are possible. Therefore the file names should be specific of the package. This means avoiding short names (less that 4 or 5 letters), or names that are too generic (like compiler, viewer, show, convert...). The package names also share a common namespace, so should not be generic. It is better to avoid generic names than force the user to change their scripts or modify afterwards the package or utility names, leading to confusion. This is even more problematic when packages or file share the same name but have different functionalities.

There are some packages that already have generic names or have files with generic names. For some packages it is not an issue since they are covered by a standard (like POSIX utilities cat, ls), or have a long history.

The naming guidelines imposes the package naming, so those renaming issues should be tackled with upstream, explaining that in fedora we have to consider a broader perspective of a mix of packages of unknown size. If upstream cannot be convinced, it may be wise to search over the Internet for packages that already use that name and think about which one should keep the main name, and a prefix or postfix can be used in fedora if disambiguation is needed.

For an example, see https://www.redhat.com/archives/fedora-devel-list/2008-August/msg00127.html.

In addition to the conflict issue, it should be remembered that generic names and names with less than 5 letters are scarce and so a first come first serve use of these words may lead to misuses. Upstream may not have a view of these issues, and choose a word selfishly (though with good intentions) without thinking about the big picture, so trying to work with upstream and convince upstream not to use generic names during reviews may be worth it.

Avoiding using fedora or redhat (controversial)

It is better to avoid using the words fedora or redhat in a visible manner in spec files, to help others wanting to reuse the spec files (in EPEL, in 3rd party repository, in derived distributions, in local repository or in private but internet facing repository). package, rpm, dist or distribution can be used instead. For example README.fedora could be called README.package instead. Of course this doesn't cover internal details like spec file conditionals like %fedora or %rhel. See Packaging/DistTag#Conditionals.

Some information is really fedora specific, so using the fedora name together with this information is ok. However, the fact that the package is done for fedora doesn't mean that all information is fedora specific. If it is only package specific, like, for example, post-installation hints, licensing related informations, explanation of how the package may be different from how upstream document things, precision about file locations, avoiding fedora is better.

It also happens that fedora packagers put Fedora bugzilla location, component name and packager name in the package documentation. In general it is not a good idea, these are informations that should not be documented at each package level, but available globally.

Executable stack

In typical use, gcc generates code that disables execution on the stack. Other compilers do not disable stack execution (e.g., some versions of the OCaml compiler), even though they do not need that capability. Rpmlint will complain if you generate code that permits stack execution, and rightly so, since this is rarely needed and it's often used by attacker to exploit vulnerabilities.

If the compiler you're using generates code that permits stack execution, but doesn't actually need it, you can use "execstack -c" during the building process. This marks the executable as one that does not really need stack execution. If you do this, remember to:

BuildRequires: prelink

so that execstack is available.

Examples

If you're including some examples (configurations, source files, whatever), consider installing them in a document subdirectory named "%{_defaultdocdir}/%{name}-%{version}/examples/". As with all documentation, these files should not be directly referenced by any program: they're there for the benefit of the system administrator and users as documentation only. If the entire purpose of a package is to provide examples, then there's no need to bother; consider placing the whole set in %doc instead. This would be consistent with Debian policy guidelines; Fedora doesn't need to follow that, but it's a nice gesture for consistency.

If there are only few examples, it may be better to put them directly in %doc or "%{_defaultdocdir}/%{name}-%{version}".

Installing documentation: 2 paths

Documentation directory is "%{_defaultdocdir}/%{name}-%{version}/". However, there are two ways to install in this directory, either using %doc or directly into the staged directory "$RPM_BUILD_ROOT%{_defaultdocdir}/%{name}-%{version}/". Both ways cannot be mixed since %doc erases everything installed in the staged doc directory after the %install stage.

With %doc

With %doc, in case the documentation is already in a directory named docs you can simply do:

%doc docs

In more complex cases you may want to clean up the directory before putting it in %doc, for example when the documentation consist in examples and when tests are run in the examples directory. In that case code similar with the following could help. It is a complex case where make clean has to be run in a directory located in the top directory:

rm -rf __dist_examples
cp -pr examples __dist_examples
make -C __dist_examples clean
find __dist_examples -name '*akefile*' -exec rm {} \;
rm __dist_examples/extest
rm __dist_examples/testall
rm -rf __dist_code_examples
mkdir __dist_code_examples
mv __dist_examples __dist_code_examples/code_examples
...
%files
...
%doc __dist_code_examples/code_examples

If documentation files are installed as part of the staged install, but you still want to use %doc, you can move the installed files back to the source directory:

%install
...
make DESTDIR=$RPM_BUILD_ROOT install
...
mkdir __doc
mv  $RPM_BUILD_ROOT%{_datadir}/doc/elektra/* __doc
rm -rf $RPM_BUILD_ROOT%{_datadir}/doc/elektra
...
%files
%doc __doc/*

As part of the staged install

If documentation files are handled like any other file in %install and %files sections, they will still be identified as documentation files (e.g., rpm -qild PACKAGENAME will still work correctly). E.G.:

%install
...
install -d %{buildroot}/%{_defaultdocdir}/%{name}-%{version}/examples/
cp -p ...normal documents...%{buildroot}/%{_defaultdocdir}/%{name}-%{version}/
cp -p ...examples... %{buildroot}/%{_defaultdocdir}/%{name}-%{version}/examples/
...
%files
...
%{_defaultdocdir}/%{name}-%{version}/
...

Installing TeX files (unvetted)

Here are some things to consider if installing TeX-related files such as LaTeX styles, metafont information, etc. For formal information on fonts, see Packaging/FontsPolicy.

Depend on the virtual packages tex(tex) and tex(latex), not on specific packages like texlive. Fedora has changed its upstream source already, so it seems reasonable to prepare for that again:

Requires:       tex(tex), tex(latex)
BuildRequires:  tex(tex), tex(latex)

For filenames, follow the TeX file installation conventions documented in "info tds" of texlive-texmf. In general, TeX files belong under  %{_datadir}/texmf/TYPE/PACKAGENAME (i.e., it's under /usr/share/texmf). For LaTeX styles the type is "tex/latex".

After installing a metafont file (.mf), you may want to pre-generate the .tfm and *pk font files using mktextfm. (Watch out: You'll need to use mktexfm's --destdir option, and provide `pwd` and not "." as its option, or the pre-generation won't work if those files are already installed.) For example:

%define latexdir  %{_texmf_main}/tex/latex/%{name}
%define mfdir   %{_texmf_main}/metafont/%{name}
%define tfmdirr %{_texmf_main}/fonts/tfm/%{name}
%define tfmdir  %{tfmdirr}/oxsz
%define pkdirr  %{_texmf_main}/fonts/pk/%{name}
%define pkdir   %{pkdirr}/oxsz
... during %build:
for file in *.mf ; do
 mktextfm --destdir `pwd` `basename $file .mf`
done
... during %install:
install -d %{buildroot}%{latexdir}
install -d %{buildroot}%{mfdir}
install -d %{buildroot}%{tfmdir}
install -d %{buildroot}%{pkdir}
cp -p *.sty %{buildroot}%{latexdir}
cp -p tex/*.tfm %{buildroot}%{tfmdir}
cp -p tex/*pk %{buildroot}%{pkdir}
... in %files:
%{latexdir}/
%{mfdir}/
%{tfmdirr}/
%{pkdirr}/

After installing and uninstalling into /usr/share/texmf, run mktexlsr (which replaces texhash). This fixes up the "ls-R" files /usr/share/texmf so that TeX can find files rapidly. You should add "|| :" so that things can continue to work even if the update fails, and you should ensure that the tex(tex) package is installed during %post and %postun, like this:

Requires(post): tex(tex)
Requires(postun): tex(tex)
...
%post
mktexlsr >/dev/null 2>&1 || :
%postun
mktexlsr >/dev/null 2>&1 || :

Convert encoding to UTF-8

iconv --from=ISO-8859-1 --to=UTF-8 file.txt > file.txt.new

If you want to keep timestamps, you can do:

iconv --from=ISO-8859-1 --to=UTF-8 file.txt > file.txt.new && \
touch -r file.txt file.txt.new && \
mv file.txt.new file.txt

If you have more files to convert, you can do:

# Convert to utf-8
for file in AUTHORS ChangeLog THANKS TODO; do
    iconv -f ISO-8859-1 -t UTF-8 -o $file.new $file && \
    touch -r $file $file.new && \
    mv $file.new $file
done

Remove DOS line endings

Remove DOS line endings to Unix from a file in-place

 sed -i "s|\r||g" file.txt

If you need to keep the time stamp (or you have multiple files to convert), run

for file in README.TXT LICENSE; do
 sed "s|\r||g" $file > $file.new && \
 touch -r $file $file.new && \
 mv $file.new $file
done

Remove shebang from Python libraries

If you get non-executable-script warnings from Python libraries, run e.g.

for lib in %{buildroot}%{python_sitearch}/(python library)/*.py; do
 sed '1{\@^#!/usr/bin/env python@d}' $lib > $lib.new &&
 touch -r $lib $lib.new &&
 mv $lib.new $lib
done

No debug info packages?

Make sure redhat-rpm-config is installed on your system.

Transparent background for desktop icon and convert to png


BuildRequires: ImageMagick
...
convert -transparent black thinkabooicon.ico %{name}.png

Preserve the timestamp on a patched autotools

Preserving the timestamp on a patched autotools source file to prevent unnecessary triggering of autoconf/automake/etc.


touch -r configure.ac configure.ac.stamp
%patch0 -p0
touch -r configure.ac.stamp configure.ac

Recommended values for the Group: tag

The Group: tag is not used for anything in Fedora, comps are used for grouping of packages. Still, it is probably best to use one of the existing groups listed in /usr/share/doc/rpm-%{version}/GROUPS as long as rpm mandates its presence.

Amusements/Games
Amusements/Graphics
Applications/Archiving
Applications/Communications
Applications/Databases
Applications/Editors
Applications/Emulators
Applications/Engineering
Applications/File
Applications/Internet
Applications/Multimedia
Applications/Productivity
Applications/Publishing
Applications/System
Applications/Text
Development/Debuggers
Development/Languages
Development/Libraries
Development/System
Development/Tools
Documentation
System Environment/Base
System Environment/Daemons
System Environment/Kernel
System Environment/Libraries
System Environment/Shells
User Interface/Desktops
User Interface/X
User Interface/X Hardware Support

Remove shebang from files

There are several ways to remove a shebang from a file

sed -i -e '/^#!\//, 1d' *.py

If you have several files, you can do:

for Files in demo.py utils.py __init__.py test.py; do
  %{__sed} -i.orig -e 1d ${Files}
  touch -r ${Files}.orig ${Files}
  %{__rm} ${Files}.orig
done

Add shebang

Add a Perl shebang

sed -i -e '1i#!/usr/bin/perl' xxx.pl


Add a Python shebang

sed -i -e '1i#!/usr/bin/python' xxx.py

Exec permission

If rpmlint rightly complains about permission, you may have to set those.

chmod a+x %{buildroot}%{sugaractivitydir}Analyze.activity/analyze.py

If you have more than one file

for file in %{buildroot}%{python_sitelib}/Onboard/{settings,settings-dialog,Keyboard,utils}.py; do
   chmod a+x $file
done

or

chmod a+x %{buildroot}%{python_sitelib}/Onboard/{settings,settings-dialog,Keyboard,utils}.py

Zero length files

Sometime zero length files are not useful. You can remove all of them with:

find %{buildroot} -size 0 -delete

.desktop files

The standard way to change/modify desktop files is the usage of desktop-file-install. Unfortunately are there some tags which can be handled this way.

sed -i 's|Comment=Picture downloader|Comment=Downloader for images from the internet|g' %{name}.desktop

Within the Icon tag in desktop files the short name of the icon without file extension is preferred. .png is the default. As a further example the removing of the extension in a desktop file.

sed -i 's|Icon=%{name}.png|Icon=%{name}|g' %{name}.desktop

With sed you can fix spelling error without making a patch for the desktop file.