This page should morph into a guidelines document upstream developpers can consult before releasing material for us to package. It should list clear requirements, and provide a terse explanation on the reasons behind each of the rules we lay out.
The original JPackage version can be found at http://www.jpackage.org/request.php
What we are talking about
All the rules outlined in the following document apply to the release dumps of archive files a project publishes. Unlike an external developer, an external packager will usually not devote his energies to a single project. Web tools like FAQs, cvswebs, bugzillas, and mail archives are of little interest to a packager. He will use them, but only as a last resort. The developer realm is the application. The packager realm is the whole system. This broader focus means a packager cannot afford as deep a knowledge of individual projects as a developer can.
A well run project will provide releases that stand on their own, include all build/licensing/usage documentation, and do not require any external patches to run. This only applies for the materials the project "owns" and maintains - external tools and libraries are subject to their own separate packaging processes.
What we are absolutely not talking about
All the restrictions listed in this document do not apply to internal project tools. We absolutely do not care about the project CVS organization, the shortcuts developers take to simplify their lives, etc as long as they do not bleed into the release archives.
Bear in mind though, if the internal project layout drifts too far from the requirements of the release archives, releasing your project will become increasingly painful and expensive.
What we are not talking about yet
Since the actual packaging rules each distribution uses have not been standardized yet, we do not ask upstream projects to provide Linux packages or automated tasks to create them. Even if there is a common packaging policy and tools, please do not include the package build scripts debian/, RPM spec file in the distribution, as packagers will need to modify them and they will get out of sync with the upstream version.
However, even when generic packages will be possible, and upstream authors will provide the scritps/description files/<whatever we agree upon>, there will probably still be a need for fine-tuning these files. The actual changes though should become more and more minor and will be done in the usual patching procedure during package builds.
And now, the actual rules.
1. Provide source-only releases
When building software from sources, binaries are only a waste of bandwidth and disk space. The same is true for javadocs, generated docs, and so on. But nothing prevents for you from providing a binary release either.
2. Do not include external binaries
Including external binaries is evil because:
- They are useless for people trusting only self-built software.
- They are useless for people who already have those binaries.
- It makes tracking dependencies a nightmare.
- It makes archives bigger.
- It makes it too easy to avoid following the source project. As a result, your software risks depending on customized versions no one else uses, and it will prove impossible to include in an integrated system like a Linux distribution.
But nothing prevents you from providing those binaries in a separate archive.
3. Document your application dependencies
A clean doc listing:
- all the external dependencies you use,
- where they come from,
- what versions have been tested,
- what you are using them for are they optional, only used for tests, only used as an implementation of a public spec
... can help an external packager immensely. Bundling the dependency binaries with your archive is no substitute - people won't trust a binary blob of unknown origins, investigating these origins will often make packaging your software much too expensive.
4. Provide all the sources and scripts needed for building
It is always a pain to not have doclet sources, or an ant build script, as it prevents to recreate original building process.
This does not mean you have to bundle external stuff see previous point. You shall however provide all the facilities needed to build your project that you are maintaining yourself.
Moreover, if several of your projects use the same infrastructure, making it a standalone public project is often a worthwhile move.
5. Do not download any files during the build process
- Building can occur in a non-networked environment
- The integrity of the downloaded files can not be checked, even if you checksum them. In the case of binary files, the packager has no way to check how they were built, and therefore will not trust them and therefore will never sign the resulting package
6. Help people specify the build <tt>CLASSPATH</tt>
When people add your software to an integrated system, they will use the external dependencies already provided by this system, not the jar files you use internally. This means they will need to specify a classpath part for each dependency of your software. Do not assume:
- the dependency will be provided by a jar somewhere in your built tree. The jars we use will be somewhere else in the system.
- The jar file will have the name you're used to.
- It will be a single jar. Competing implementations of the same specification to not lay out their classes in the same way - they frequently a different number of files.
Make specifying the build classpath easy using either command line switches or property files and document it.
7. Do not use non-API classes
We try to get a package working with as many JVM and environments alternative sources/versions for one API as possible. Every use of a non API sun. classes, java.home layout, basicly everything, which isn't explictly declared API can break a package on different systems. Non-API can change without notice, even in minor releases. Don't depend on it!
This is especially true if non sun derived JVM like kaffe, gij/gcj and sablevm are used to run your application and the application usees internal sun. classes or assumes a java.home layout.
8. Do not use or rely on Class-Path references in jar MANIFESTs
The Class-Path system of MANIFESTs is evil because:
- It doesn't work with JDK 1.x.
- It only works at runtime, not at build time.
- It only works for a specific installation hierarchy.
- It can not be configured.
Classpath handling is a generic problem and will be handled at the system level see also ApplicationClasspath.
9. Do not assume a single-root file layout
Unlike a Windows system, a Linux system will install your files in different parts of the filesystem depending on their use and the filesystem properties they need. This is an hard requirement for all applications regardless of the langage they're written in.
The filesystem layout used by every single Linux distribution is documented in the Filesystem Hierarchy Standard. Read the spec and see how all the file/directories you use fit in.
10. Do not assume the user will be the system administrator
Unix system have a clear administrator/user separation. If your software is intended for a end-user, do not assume he will be allowed to manipulate common configuration files or plugin directories.
11. Provide Unix archives
The zip format doesn't preserve Unix file permissions, and is inefficient. Gzipped, or even better, bzipped tarballs are more convenient. But nothing prevents you from providing also zip format archives.
12. Use clear versionning
And include it in your archive filenames.
Having a single URI pointing to different contents at different points of times makes packaging difficult.
An untagged CVS dump is not a proper version.
The usual naming is a name-x.y.z.tar.gz archive containing the same name-x.y.z top directory. No top directory or a top directory named a different way than the archive can be handled but it's generally a pain. Please do not try and mix all namexyz name.xyz NAME_x_y_z... permutations - choose one, preferably name-x.y.z, and stick to it.
13. Provide a cryptographically GPG signed hash of your archives
So people can check they are really using the sources you released, and your software has not been modified by a malicious entity on your download servers.
14. Provide a clear licensing document
So it can be added to the package documentation.
Avoid custom licenses - packagers and end-users are no lawyers. If they are not sure of what you allow them to, they'll pass. Use widely-distributed licenses everyone understands and that have been reviewed by organisations like the OSI http://www.opensource.org/licenses/
15. Provide a sensical default configuration
... if your software can be configured.
Ideally it should be sufficient to test your software, and not dangerous security-wise.
If people need to read a lenghty documentation to use your sofware, they will pass on it the packager first of them
16. Do include tests
... in your release archives. Bear in mind though if one needs deep knowledge of your application to run the tests, they won't be used. In this case including them in your release is a waste of bandwidth. The same attention should be put into the test scripts as in the build scripts - people won't waste time fixing hardcoded jar references in a test file.
Also, a packager may not have the knowledge necessary to evaluate test output. A simple summary at the end of the run listing the tests that passed and the tests that failed, the tests that are critical and the tests that aren't helps a lot
17. Do include examples and documentation
But bear in mind if some part of the documentation does not follow the same release cycle as the rest of your product, it will be easier for everyone if it has its own release process and release archives.
Also, if some part of the documentation can be generated from the source files like javadoc or docbook documents a linux packager will always prefer regenerating it than using precooked files see 1.. So either do not include them at all, or put them in a separate archive and do include clean versions of the scripts used to generate this documentation.
18. debian only yet Do not rely on environment variables to run your app
Debian has a policy that a application must run without any set environment variables. A user shouldn't need to do some configuration beforehand to get a app working.
So don't use JAVA_HOME to figure out the JVM see FindingWorkingRuntime for proposed solutions to the problem.