Install Binaries into /Bin, /Sbin, /Usr/Bin and /Usr/Sbin, Interactions with --Prefix and Destdir

Install binaries into /bin, /sbin, /usr/bin and /usr/sbin, interactions with --prefix and DESTDIR

Essentially, the distinction between the / and the /usr hierarchies is not and should not lie in the hands of the packages' upstream maintainer (read: Is not your responsibility). Since / should only contain files necessary for booting and making /usr available, it is an administrative decision what goes to /. For installations from source, this decision is made by the installer, and for distributions, by the package maintainer.

For a rationale, suppose someone is trying to build a chroot environment. The distinction between /usr and / is meaningless in the environment, and will not be made. All prefixes are set to /foo/bar/chroot, and any configure script messing with $prefix is likely to induce strange behaviour. The same arguments goes for scripts like the Debian packaging helpers, which rely on the usual $prefix semantics to work.

The cleanest solution is therefore the bash-4.1 solution. You have basically two clean options: Split your package into boot-critical and non-boot-critical parts, or let your configure script offer an alternative prefix for the boot-critical parts, which is set by default to /, leaving $prefix as /usr.

Building a PAM module and install into /lib/security

To address your two things in order:

  • The libtool script intercepts that install instruction and also installs the .so file in the appropriate place.

  • It's putting it in /usr/local/lib probably because you listed it in lib_LTLIBRARIES (although I can't be sure if you don't show your code) and your --prefix is set to its default of /usr/local.

This last one is difficult since Autotools' official stance is that all user-installed programs belong in /usr, whereas many other tools expect things to be in /lib/something. Here's one way to do it, that I personally consider wrong:

# Don't do this
libsecuritydir = /lib/security
libsecurity_LTLIBRARIES = pam_mymodule.la

This bypasses --prefix, which will go horribly, horribly wrong if you try to do a local install of your package without writing directly into your live system, which, trust me, you will want to do at some point. It will also prevent you from packaging your program in most Linux distributions' packaging systems.

The correct way is to push the responsibility onto whoever installs the package: add a --with-libsecuritydir argument to configure.ac using AC_ARG_WITH and let that default to $(libdir)/security:

AC_ARG_WITH([libsecuritydir],
[AS_HELP_STRING([--with-libsecuritydir],
[Directory for PAM modules, pass /lib/security for live install])],
[], [with_libsecuritydir='$(libdir)/security'])
AC_SUBST([libsecuritydir], [$with_libsecuritydir])

and then just do

libsecurity_LTLIBRARIES = pam_mymodule.la

in Makefile.am.

When you want to install a live version directly into your system (or are building a binary package) pass --with-libsecuritydir=/lib/security to configure.

Install systemd service using autotools

Will using AC_CONFIG_HEADERS be appropriate to patch *.service.in into *.service? Is there another macro used for "non-headers" perhaps?

No. AC_CONFIG_HEADERS is for setting up configuration headers to support your build. It is rarely used for anything other than building a config.h recording the results of certain tests that Autoconf performs, and it is not as flexible as other options in this area.

If you have additional files that you want Autoconf to build from templates then you should tell Autoconf about them via AC_CONFIG_FILES. Example:

AC_CONFIG_FILES([Makefile AutoBrightnessCam.service])

But if some of the data with which you are filling that template are installation directories then Autoconf is probably not the right place to do this at all, because it makes provision for the installation prefix to be changed by arguments to make. You would at least need to work around that, but the best thing to do is to roll with it instead, and build the .service file under make's control. It's not that hard, and there are several technical advantages, some applying even if there aren't any installation directory substitutions to worry about.

You can do it the same way that configure does, by running the very same template you're already using through sed, with an appropriate script. Something like this would appear in your Makefile.am:

SERVICE_SUBS = \
s,[@]VARIABLE_NAME[@],$(VARIABLE_NAME),g; \
s,[@]OTHER_VARIABLE[@],$(OTHER_VARIABLE),g

AutoBrightnessCam.service: AutoBrightnessCam.service.in
$(SED) -e '$(SERVICE_SUBS)' < $< > $@

Also, how do I specify that the service file should land (i.e.
installed) in /etc/systemd/system?

You use Automake's standard mechanism for specifying custom installation locations. Maybe something like this:

sytemdsysdir = $(sysconfdir)/systemd/system

systemdsys_DATA = AutoBrightnessCam.service

Is there perhaps a better way of
starting this app at boot time without systemd?

On a systemd-based machine, systemd is in control of what starts at boot. If you want the machine to start your application automatically at boot, then I think your options are limited to

  • Configuring systemd to start it
  • Configuring something in a chain of programs ultimately started by systemd to start it
  • Hacking the bootloader or kernel to start it

There is room for diverging opinions here, but I think the first of those is cleanest and most future-proof, and I cannot recommend the last.

How to install packages in Linux (CentOS) without root user with automatic dependency handling?

It is possible to use yum and rpm to install any package in the repository of the distribution. Here is the recipe:

Find the package name

Use yum search.

Download

Download the package and all of its dependencies using yumdownloader (which is available on CentOS by default). You'll need to pass it --resolve to get dependency resolution. yumdownloader downloads to the current directory unless you specify a --destdir.

mkdir -p ~/rpm
yumdownloader --destdir ~/rpm --resolve vim-common

Choose a prefix location

It might be ~, ~/centos, or ~/y. If your home is slow because it is on a network file system, you can put it in /var/tmp/....

mkdir ~/centos

Extract all .rpm packages

Extract all .rpm packages to your chosen prefix location.

cd ~/centos && rpm2cpio ~/rpm/x.rpm | cpio -id
  • rpm2cpio outputs the .rpm file as a .cpio archive on stdout.
  • cpio reads it from from stdin
  • -i means extract (to the current directory)
  • -d means create missing directory

You can optionally use -v: verbose

Configure the environment

You will need to configure the environment variable PATH and LD_LIBRARY_PATH for the installed packages to work correctly. Here is the corresponding sample from my ~/.bashrc:

export PATH="$HOME/centos/usr/sbin:$HOME/centos/usr/bin:$HOME/centos/bin:$PATH"

export MANPATH="$HOME/centos/usr/share/man:$MANPATH"

L='/lib:/lib64:/usr/lib:/usr/lib64'
export LD_LIBRARY_PATH="$HOME/centos/usr/lib:$HOME/centos/usr/lib64:$L"

Edited note (thanks to @AmitNaidu for pointing out my mistake):

According to bash documentation about startup files, when connecting to a server via ssh, only .bashrc is sourced:

Invoked by remote shell daemon

Bash attempts to determine when it is being run with its standard input connected to a network connection, as when executed by the remote shell daemon, usually rshd, or the secure shell daemon sshd. If Bash determines it is being run in this fashion, it reads and executes commands from ~/.bashrc, if that file exists and is readable.


Now if you want to install a lot of packages that way, you might want to automate the process. If so, have a look at this repository.


Extra note: if you are trying to install any of gcc, zlib, make, cmake, git, fish, zsh or tmux , you should really consider using conda, see my other answer.



Related Topics



Leave a reply



Submit