I'd like to improve the distribution and versioning of a program I've inherited, which is currently distributed as a .tar.gz file, by building a .rpm for RHEL7 that just extracts the contents to /usr/bin/. The tarball is not small, consisting in around 120 MB worth of files.
I'm new around package building so I've been following the bello example from https://rpm-packaging-guide.github.io, but the example is too simple for my needs.
So far I have this .spec file:
Name: my-app
Version: 2.0
Release: 1%{?dist}
Summary: My application
License: Internal license
URL: <my-website>
Source0: <my-website>/%{name}-%{version}.rhel7.x86_64.tar.gz
Requires: bash
BuildArch: x86_64
%description
My application
%prep
%setup -q
%build
%install
mkdir -p %{buildroot}/%{_bindir}
install -m 0755 %{name} %{buildroot}/%{_bindir}/%{name}
%files
%{_bindir}/%{name}
Which generates a very small .rpm with just /usr/bin/my-app. On installation if complains about many missing dependencies that are inside the tarball's lib directory, but of course not in my package.
As far as I understand, the %files directive must contain a list of all the files that are supposed to be inside the .rpm, but those are hundreds. So I'm assuming there's a better way to build the package, after all is just decompressing the tarball.
Do you have any pointers?
install -m 0755 %{name} %{buildroot}/%{_bindir}/%{name}
you are only installing the binary. You should also install the dependencies if they are in your tgz, Then make sure to package them as well under %files.
Related
TL;DR: I made a .spec file that successfully builds a .rpm, but rpm -i <file>.rpm doesn't do all the actions I think it should. Why?
Excerpt from <file>.spec:
%install
sudo python2.7 -m pip install 'tornado<5'
...#other pip commands...
cp -r $RPM_BUILD_DIR/%{name}-%{version}/* %{buildroot}
(I know this isn't the ideal way to do it, but I'm forced to use CentOS 6 and can't upgrade the system version of python because corporate/shared environment so this was the best way I could figure out.)
All the commands under %install are correctly run when building the .rpm, so all of the pip packages get installed on the machine creating the .rpm from the .spec. rpmbuild -ba <file>.spec completes with exit 0. However, when I try to install the .noarch.rpm file that is created (on another system with identical OS/architecture), all that happens is the rpm-specified dependencies get installed and the files get shoved to the correct directories, but the other commands from %install are not run. What ends up happening is that I try to call the executable that gets made and it errors out because of the missing python packages.
RPM.org says:
Performing any tasks required before the install:
There are cases where one or more commands must be given prior to the actual installation of a package. RPM performs these commands exactly as directed by the package builder, thus eliminating a common source of problems during installations.
...Where am I supposed to specify the commands run prior to package installation if not in the %install field of the .spec file?
If you want to run commands after the rpm is installed the, you need to place those commands in the %post target.
If you want the commands to be run right before the rpm itself is installed, place the commands in the %pre target.
The commands in %install is executed when you build the .rpm, it is not run when you install the .rpm.
%install is intended to install your software onto a sandboxed directory hierarchy which should then be packaged and included into the .rpm file.
Don't run commands in %install that alters any system state or that affects anything outside the $RPM_BUILD_DIR or %{buildroot}
The %install scriptlet is run during build, not while installing.
If you wish commands to be run while installing a package, then you need to use the %post section in the spec file.
As others noted, %install is the script section within a specfile to copy the files that have already been compiled during the %build phase (which can be a no-op for python). However, others have not yet noted that sudo python2.7 -m pip install 'tornado<5' is definitely not a command that you should be using in a specfile. You need to get the python files some other way and install them into the proper locations under %{buildroot}.
RPMs should never be built as the root user nor call sudo anywhere. EVER.
I am trying to install some software that's required glib 2.14
so I installed it with this tutorial: How to upgrade glibc from version 2.12 to 2.14 on CentOS?
the problem is glib 2.14 path is /opt/glibc-2.14/lib/libc.so.6
so when I try to install software using rpm i still getting this error:
error: Failed dependencies:
libc.so.6(GLIBC_2.14)(64bit) is needed by xyz-4.6.6-1.x86_64
libc.so.6(GLIBC_2.15)(64bit) is needed by xyz-4.6.6-1.x86_64
libc.so.6(GLIBC_2.17)(64bit) is needed by xyz-4.6.6-1.x86_64
how can I add the custom path for rpm dependencies?
It would help a bit if you gave us the name of the package you are trying to install. You can't just provide a path, RPM checks if it's got any packages on record that provide these libraries, and there aren't any. Here are a couple methods you could use:
Use --nodeps
If you already know that you have everything that is required, using --nodeps is completely fine IMO.
Create virtual packages for the missing libraries (advanced)
You are missing the following libraries: libc.so.6(GLIBC_2.14)(64bit) libc.so.6(GLIBC_2.15)(64bit) libc.so.6(GLIBC_2.17)(64bit).
Here's an example .spec file to create a virtual package that claims to provide these libraries:
Name: libc-virtual-provides
Provides: libc.so.6(GLIBC_2.14)(64bit)
Provides: libc.so.6(GLIBC_2.15)(64bit)
Provides: libc.so.6(GLIBC_2.17)(64bit)
Version: 1.0
Release: 1
Summary: Virtual package providing libc 2.14, 2.15, 2.17
License: Public domain
%description
Virtual package providing libc 2.14, 2.15, 2.17
%prep
%files
%changelog
To create a virtual package from this SPEC file, first create some directories:
mkdir -p ~/rpmbuild/BUILD ~/rpmbuild/BUILDROOT ~/rpmbuild/RPMS ~/rpmbuild/SOURCES ~/rpmbuild/SPECS ~/rpmbuild/SRPMS
Then copy the SPEC file into ~/rpmbuild/SPECS, and build an RPM:
cp virtual-glibc-provides.spec ~/rpmbuild/SPECS
cd ~/rpmbuild/SPECS
rpmbuild -ba virtual-glibc-provides.spec
You'll get output like this:
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.6Jni5u
+ umask 022
+ cd /home/.../rpmbuild/BUILD
+ exit 0
Processing files: glib2.14-virtual-provides-2.14-1.x86_64
Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/.../rpmbuild/BUILDROOT/glib2.14-virtual-provides-2.14-1.x86_64
Wrote: /home/.../rpmbuild/SRPMS/glib2.14-virtual-provides-2.14-1.src.rpm
Wrote: /home/.../rpmbuild/RPMS/x86_64/glib2.14-virtual-provides-2.14-1.x86_64.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.YNj8gP
+ umask 022
+ cd /home/.../rpmbuild/BUILD
+ /bin/rm -rf /home/.../rpmbuild/BUILDROOT/glib2.14-virtual-provides-2.14-1.x86_64
+ exit 0
And you'll have your RPM under /home/.../rpmbuild/RPMS/, which you can then install using rpm -ivh ....rpm. You should then be able to install the other package without any problems.
I've downloaded Node.js directly from https://nodejs.org/en/ onto my Ubuntu Desktop operating system. I can easily unpackage the node-vX.X.0-linux-x64.tar.xz file, and I can see node directories: bin, include, lib, share. I'm guessing my download folder, ~/Downloads/node-vX.X.0-linux-x64, is not going to be the final installation location.
My guess would be to copy all of the directory over to /usr/bin/node/node-vX.X.-linux-x64 but I'm not really sure.
Where do these files go? (I've tried the readme.md file in the download and the docs on that site. I would have thought something, somewhere on nodejs.org would have offered a bit of help...)
Is there a special installation step required here?
I wrote a tutorial to do exactly what you're asking: How to get Node 6.7.0 on Linux -
it's about Node 6.7.0 but you can just change the version number.
In short:
First get the files:
# If you have a 64-bit system then download binary package:
wget https://nodejs.org/dist/v6.7.0/node-v6.7.0-linux-x64.tar.gz
# If you have a 32-bit system then download a different version:
wget https://nodejs.org/dist/v6.7.0/node-v6.7.0-linux-x86.tar.gz
Extract:
# Extract what you downloaded:
tar xzvf node-v6.7.0-linux-x64.tar.gz
# Change the file ownership:
sudo chown -Rv root.root node-v6.7.0-linux-x64
Then install in ONE of the locations:
# Install files in /usr/local
sudo cp -Rvi node-v6.7.0-linux-x64/{bin,include,lib,share} /usr/local
# (change -Rvi to -Rvf if you want to overwrite existing files)
# Install files in /opt/node
sudo cp -Rvi node-v6.7.0-linux-x64 /opt/node
# Install files in /opt/node-6.7.0
sudo cp -Rvi node-v6.7.0-linux-x64 /opt/node-6.7.0
The difference between those 3 locations in the example is explained better in the article. The consequences are mostly related to PATH and installing multiple versions.
Finish the setup:
You need to make sure that directory where you have the node and npm binaries is in your PATH. See my tutorial for details on how to do that.
Beware of shebang lines:
The shebang line of npm in Node installed from binaries is different than when installed from sources. This is one of the reasons I recommand building from sources if you have time for that. The other reason is that installing from sources you can do make test to test the version of Node on your specific system, which you cannot do when installing from binaries or with nvm.
The Problem:
I have a program I am installing from source. When I run ./configure, it stops saying "no protobuf development libraries found", however, protobuf is installed on my system.
How do I specify the path to those libraries when I run ./configure?
The program I am trying to install is osm2pgsql on CentOS 6.6.
Update:
I fixed the problem fortunately.
What Happened?:
osm2pgsql uses pkg-config to point to dependent libraries. On CentOS 7 pkg-config uses this directory /usr/share/pkgconfig/. Within this directory there are .pc files for different programs. These files are used by pkg-config to show where libraries of certain programs are located. When you install protobuf from package manager or source the installation doesn't automatically let pkg-config know where the libraries are at via a .pc file.
The Fix:
Install protobuf from source from their git page. After you've ran make install there will be several .pc files within the cloned directory. You need to place these in /usr/share/pkgconfig. To do this run the following in the cloned directory:
sudo cp protobuf.pc* /usr/share/pkgconfig/
sudo cp protobuf-lite.pc* /usr/share/pkgconfig/
Conclusion:
Ta Da! Now go back to your osm2pgsql install folder and rerun ./configure.
I am trying to build a rpm but unfortunately in my build machine I only have limted permission, which means the operation in %install can't be done inside the build machine. How to build the package(.rpm file) without running %install section? It looks like that no options are available for this purpose:
http://www.rpm.org/max-rpm-snapshot/ch-rpm-b-command.html
My bu.spec file:
Summary: xxxx
Name: xx
Version: 1.0
Release: 1
Group: Applications/Sound
License: Share
%description
%prep
echo "prep"
%build
%install
echo "install"
mkdir -p /opt/xcp_src/
cp scripts.tgz /opt/xcp_src/
%files
/tmp/xcp_src/scripts.tgz
%post
cd /opt/xcp_src/
tar zxvf scripts.tgz
First off, set a buildroot and use that in install, eg:
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
...
%install
mkdir -p %{buildroot}/opt/xcp_src
Second, make sure you can build without being root by moving the RPM build area.
I'd also suggest specifying an actual list of files (rather than having RPM extract a tgz file) as that would make the package cleanly removable.