Packaging proprietary software for Linux

2020-02-17 10:33发布

I'm doing cross-platform development and I want to build a nice, self-contained (!) package for Linux. I know that that's not the way it's usually done, but the application requires all data in one place, so I'm installing it into /opt, like many other proprietary software packages do. I will eventually provide deb and rpm packages, but it will only be .tar.gz for now. The user should extract it somewhere and it should work. I'd rather not have an installer.

First my questions, then the details:

  1. How do other people package proprietary software for Linux?
  2. Are there tools for packaging software including shared libraries?

Now for some details: This is my project's (I call it foo for this purpose) layout:

  • foo (binary)
  • config.ini
  • data

Now in the package, there will be two additional elements:

  • libs
  • foo.sh

libs will contain all the shared libraries the project requires, and foo.sh is a script that sets LD_LIBRARY_PATH to include libs. Therefore, the user will execute foo.sh and the program should start.

I have a shell script that packages the software in the following steps:

  1. Create empty directory and copy foo.sh to it
  2. Invoke the build process and make install into the new directory
  3. Copy shared libs from the filesystem
  4. Package everything as .tar.gz

What do you think of this? There are some problems with this approach:

  • I have to hard code all dependencies twice (once in CMake, once in the packaging script)
  • I have to define the version number twice (once in the source code, once in the packaging script)

How do you do it?

Edit: Another question that just came up: How do you determine on which libraries your software depends? I did an ldd foo, but there's an awfull lot. I looked at how WorldOfGoo packages look, and they ship only very few libraries. How can I make assumptions about which library will be present on a user's system and which won't? Just install all targeted distributions into a virtual matine and see what's required?

2条回答
冷血范
2楼-- · 2020-02-17 11:13

Generic issues

Your way to package your stuff (with dependent libs) to /opt is how proprietary (and even open-source) software is packaged. It's recommended practice of The Linux Foundation (see my answer to the other question for links).

External libs may be either compiled from scratch and embedded into your build process as a separate step (especially if you modify them), or fetched from packages of some distributions. The second approach is easier, but the first one allows more flexibility.

Note that it's not necessary to include some really low-level libraries (such as glibc, Xorg) into your package. They'd be better left to system vendors to tune, and you may just assume they exist. Moreover, there's an Linux Standard Base, that documents the most important libraries; these libraries exist almost everywhere, and can be trusted.

Note also that if you compile under a newer system, most likely, users of older systems won't be able to use it, while the reverse is not true. So, to reach better compatibility, it might be useful to compile package under a system that's two years older than today.

I just outlined some generic stuff, but I believe that Linux Developers Network website contains more information about packaging and portability.

Packaging

Judging by what I saw in the open-source distribution projects, your script does it the same way distribution vendors package software. Their scripts automatically patch sources, mimic installation of software and package the resultant folders into DEBs and RPMs.

Tar.gz, or course, could also work, but creating, for example, an RPM is not complex enough for you to miss such an opportunity to make life of your users so much easier.

Answering your questions,

  • Yes, you have to hard-code dependencies twice.

    The thing is that when you hardocde them in CMake, you specify them in the other terms than when you specify them in a packaging script. CMake refers to shared libraries and header files, while packaging script refers to packages.

    There's no cross-distribution one-to-one relationship between package names and shared libs and headers. It varies through distributions. Therefore, it should be specified twice.

    But the package can be easily re-packed by distribution vendors, especially if you strive to packing all dependent libs into it (so there'll be less external dependencies to port). Also, a tool that can port packages from one distribution to another will appear soon (I'll update my answer when it's released).

  • Yes, you have to specify your version twice.

    But the thing is that you may organize your packaging process in such a way that package and software versions never get out-of-sync. Just make the packaging script check out from your repository (or download from your website) exactly the same version that the script will write to package specifications.

Analyzing Dependencies

To analyze dependencies of your software, you may use our open-source, free Linux Application Checker tool. It will report the list of libraries it depends on, show distributions your software is compatible with, and help your application be more portable across distributions. It turns out that sometimes more cross-distribution compatibility can be achieved by little effort, and you don't have to lock yourself into support of just a few selected distributions.

查看更多
SAY GOODBYE
3楼-- · 2020-02-17 11:19

Think long and hard (or ask your product development department) which distributions / architectures you need to support.

Make sure that they fully understand the testing implications.

I expect you will come up with a very short list of supported distributions and architectures.

It really depends on which customers are paying for Linux support. Most people use Redhat Enterprise (on servers) or Centos (which is indistinguishable from a technical perspective).

If you only need to support Redhat, you only need to support RPM, job's a good'un.

查看更多
登录 后发表回答