Reputation: 110
I'm trying to use rpmbuild to do the following.
I have a prebuilt project, about 100 files in a single directory, as a tar file. I want to create an RPM which will bundle those files, and when installed on a new machine using rpm -i, will unpack the files, create a directory under /usr/bin, and copy them into there. Finally, it should run a bash script file.
Running rpmbuild -bs creates an SRPM, but when I try to install that with rpm -i, nothing happens.
Running rpmbuild -bb runs all the steps - configure, build, install, etc, most of which I don't need. However, it does not create an RPM, and the install step is what I expected to happen on the target machine when I use rpm -i, not on the machine I'm trying to create the RPM on.
I think I'm missing something basic. Any hints?
Upvotes: 2
Views: 2748
Reputation: 181824
Running rpmbuild -bs creates an SRPM, but when I try to install that with rpm -i, nothing happens.
Not nothing. Successfully installing an SRPM installs the spec file and sources (including patches) into your RPM build tree, ready for you to build an RPM with. Depending on where you built it and as whom you installed it, however, that might have just overwritten your original sources and spec with identical copies. An SRPM is not what you're looking for, though you should still create one for your own future use.
Running rpmbuild -bb runs all the steps - configure, build, install, etc, most of which I don't need.
Well sure, but the steps you don't need don't have to do anything. It sounds like you can get away with an empty %build
scriptlet, and with an empty %prep
scriptlet, too, if you know how. Most of the work can be done in %install
, and that's fine.
However, it does not create an RPM,
That would be surprising. Are you sure you're looking in the right place? It would go into the appropriate arch-specific subdirectory of RPMS/
in your RPM build area. For example, RPMS/x86_64/mypackage-1.2.3-1.x86_64.rpm
.
But only if rpmbuild
succeeds, of course. It can fail after the %install
stage for various reasons, but it emits a diagnostic if it does.
and the install step is what I expected to happen on the target machine when I use rpm -i, not on the machine I'm trying to create the RPM on.
Well, that depends in part on how you write the install scriptlet in your spec. If you write it correctly then it will install the files to be packaged into a staging area designated to you by rpmbuild
.
I think I'm missing something basic. Any hints?
I think you're missing several basic things:
Rule #1 of building RPMs: do not build RPMs as root! That you say the install step does what you expect rpm -i
to do tells me that you are violating this rule. Only if you build as root should it even be possible for rpmbuild
to write files to system directories.
The %install
scriptlet (that you provide in the spec file) should write files to a filesystem image rooted at the build root provided by rpmbuild, not to the main tree rooted at the real filesystem root. The %install
scriptlet can identify the build root via either the %{buildroot}
macro or the $BUILDROOT
shell variable. The scriptlet should create that directory and any subdirectories it needs within, and write the files to install there.
It is possible to provide scripts to run at package installation and / or removal time, and these are pretty common, but be sure yours is doing things that can only be done on the target system, after the package's files are installed. Creating local users and configuring system services are examples. Do not use such scriptlets to do anything that you could have baked right into the package, such as setting file ownership or permissions or modifying files.
Overall, it sounds like you want something along these lines:
Name: mypackage
Version: 1.2.3
Release: 1%{?dist}
Summary: My package
License: proprietary
Source0: mypackage-1.2.3.tar.gz
# Only rather old rpmbuild requires you to choose a build root yourself
# BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
# You probably can let rpmbuild discover the dependencies for you
# Requires:
%description
My cool package.
%prep
# empty
%build
# empty
%install
# make sure to start clean
rm -rf %{buildroot}
# Create the buildroot and appropriate directory structure within
mkdir -p %{buildroot}%{_bindir}
cd %{buildroot}%{_bindir}
# Unpack the tarball directly into the build root.
# This is a bit unusual, but it works when your tarball contains pre-built
# binaries. The macro %{S:0} refers to source 0.
tar -xzf %{S:0}
# Optionally move / rename the unpacked directory or its contents
mv mypackage-1.2.3 mypackage
%files
# Installed files will be owned by root:root, but they will have whatever
# modes they do in the build root:
%defattr(-,root,root,-)
# Or whatever the install directory was, less the build root portion:
%{_bindir}/mypackage
%post
# post-installation script inline here ...
# Can use the installed files, including running scripts among them.
# Make sure that this script cannot exit with a nonzero exit status.
%changelog
* Fri Jun 08 2018 user3587642 <[email protected]> 1.2.3-1
- Initial spec
Upvotes: 3