Can I create a package without a preexisting source file? - linux

As I understand it, the purpose of the Source: header in an rpm spec file is to specify a file (often a tar archive) that is used as the package payload. This source file is typically generated beforehand, perhaps by make, and then rpmbuild is executed afterwards.
I'm wondering if it's possible to cut make out of the picture and just use rpmbuild. Can the source file be created as part of the rpmbuild process itself, perhaps in the %build or %install step in the spec file?
If so, what does one use as the Source: header? I can't just leave it blank, because rpmbuild complains. Is there a way to tell rpm that the payload file is generated from within the spec file, and not supplied externally?
I don't want to create the source file separately because that would mean keeping track of the package name and version number in two places: in the rpm spec file, and also in whatever makefile or other script creates the payload file. It seems like I should be able to do everything from within the spec file.

You want to call
%setup -q -c -T
see [1]. Example:
Name: test
Version: 1
Release: 1%{?dist}
Summary: Test
License: ...
%description
Test
%prep
%setup -q -c -T
%build
echo "int main() { return 0; } " > test.cpp
gcc -o test test.cpp
%install
install -Dpm 0755 test %{buildroot}%{_bindir}/test
%files
%{_bindir}/test
%changelog
...
[1] http://www.rpm.org/max-rpm/s1-rpm-specref-macros.html

I had the a similar problem recently. I ended up writing a script that read the spec file and did all the work. We no longer had to manage Makefiles and spec files and whatever other ways some of our developers were managing this.
The script is publicly posted on github at:
https://github.com/alexnelsone/jenkins-rpm-build/blob/master/README.md.
It parses the info out of the spec file and then does all the work for you.

Related

Removing paths from .so files so that RPM check-buildroot succeeds

I am packaging some Python libraries as RPMs. Some of the libraries are only available as source distributions (no wheels).
In my RPM spec I do:
pip install --root=%{buildroot} --prefix=/x/y tornado
When rpmbuild finishes up it runs check-buildroot, and the build fails with errors like:
Binary file /a/b/c/BUILDROOT/my-rpm-1.0.0-1.el7.x86_64/x/y/lib64/python2.7/site-packages/tornado/speedups.so matches
I see the %{buildroot} path listed if I run strings tornado.so | grep BUILDROOT.
How can I sanitize the .so files? Or more generally, how can I make check-buildroot pass?
I figured out how to remove the paths from the SO files.
I determined that the paths were embedded debug information using this command:
readelf --debug-dump=line speedups.so | less
The strip command can remove debug information from SO files, so I added this to my RPM spec:
BuildRequires: binutils
set +e
find "%{buildroot}{%_prefix}/lib64/python2.7/site-packages" -type f -name "*.so" | while read so_file
do
strip --strip-debug "$so_file"
done
set -e
Note: strip segfaults on some SO files, and it's not clear why. I disabled immediate exits with set +e so that the build ignores them.

How to understand this SWI-Prolog makefile - how Linux executable is created?

I am trying to compile grammar parser https://github.com/RichardMoot/Grail into Linux program according to instructions https://github.com/RichardMoot/Grail/blob/master/README and http://www.labri.fr/perso/moot/tutorial/install.html. There is manual how to create Linux executable from SWI-Prolog code http://www.swi-prolog.org/FAQ/UnixExe.html. All that is fine. But I can not find in the Makefile https://github.com/RichardMoot/Grail/blob/master/Makefile any compilation command. SWI-Prolo uses swipl command for compilation but this Makefile swipl calls only once - for displaying the version of the swipl.
I experience some hardship in installation and compilation, that is fine, I can execute/debug Makefile line by line and arrive at the result. But there is problem in my case - I can not see the ultimate goal in my makefile: which lines are responsible for the production of object files (if necessary) and which lines are responsible for the creation of the final Linux executable.
This is windowed program. The source code and documentation contains warnings about incompatibility with the SWI-Prolog 7, but that is fine, I can resolvem them myself, but as I said - I can not see the Makefile lines for creation of exe.
The source code is created by eminent scientist and I certainly don't want to disturb him by so low-level technical question. I would be happy if he continues work on theory and doesn't waste time on low level programming questions. Hope, that there are SWI-Prolog experts.
I am using latest (7.x) SWI-Prolog on Ubuntu 16.x and I have already installed all the mentioned prerequisites.
If you look closely at the provided Makefile, you'll find that the rules all and install are defined as follows (comments added by me):
all:
-cd source ; $(edit) g3 > g3.tmp # Replaces placeholders for your
# ... GRAIL_ROOT install directory.
-cd source ; mv -f g3.tmp g3 # Overwrites `g3` with the filled file.
cd source ; chmod a+x g3 # Makes it executable.
install: # Essentially copies all files to
-mkdir $(datarootdir) # ... your install directory.
-mkdir $(datadir)
cp -f $(images) $(datadir)
-mkdir $(bindir)
cp -f source/insertdot $(bindir)
chmod a+x $(bindir)/insertdot
cp -f $(resources) $(datadir)
cp -f source/*.pl $(bindir)
cp -f source/g3 $(bindir)
If you then do the common make && make install you'll end up with two folders installed in your Grail directory: bin and share. Inside the binary directory you'll have the g3 file that, regardless of being a SWI-Prolog source, has this initial line:
#!/usr/bin/swipl -q -g start -f
% [... prolog code.]
This header should allow your console terminal to determine what interpreter to use for this script (in this case, swipl). In my case, executing Grail with ./g3 returned a SWI-Prolog message indicating that wrong options/command arguments were used.
According to the man, Unix systems have to use option -s at the end of the header (but this didn't work either in my case):
From the manual:
-s file
Load file as a script. This option may be used from the shell to
make Prolog load a file before entering the toplevel.
It is also used to turn a file into an executable Prolog script
on Unix systems using the following first line
#!/usr/bin/swipl option ... -s
If you want to run this program, simply call the same command from your terminal:
swipl -q -g start -s g3

rpm %config(noreplace) override with %config

In my rpm I have a full directory that I want to tag with %config(noreplace). There is a file in that directory that I want to replace on every install with the latest from the rpm, using the semantics from %config.
Using the guide here: http://www-uxsup.csx.cam.ac.uk/~jw35/docs/rpm_config.html, I tried the following:
%files
%config(noreplace) /my/saved/dir/*
%config /my/saved/dir/file1
and
%files
%config /my/saved/dir/file1
%config(noreplace) /my/saved/dir/*
hoping that the specific command would override the glob, but it didn't work. Is there any RPM like command that I can use to force the %config behaviour on a file that's nested under a %config(noreplace) directory?
From:
http://ftp.rpm.org/max-rpm/s1-rpm-inside-files-list-directives.html
There is a restriction to the %config directive, and that restriction
is that no more than one filename may follow the %config. This means
that the following example is the only allowable way to specify config
files:
%config /etc/foonly
Note that the full path to the file, as it is installed at build time, is required.
However you can craft that list dynamically in %install section:
%install
echo '%dir /etc' >> list.txt
echo '%config(noreplace) /etc/foo' >> list.txt
# use for-loop or any other shell scripting technique
%files -f list.txt
The assumption is that every file in the package is listed in the %files section (list) of .spec file exactly once. I bet when you were running rpmbuild there was the following line in the output
warning: File listed twice: /my/saved/dir/file1
The solution is to list configuration file (which you want to be always overwritten) only once and with proper directive i.e. %config(noreplace). This is no matter if it is specified directly or indirectly through wildcard character.
The statement referenced in msuchy's answer
There is a restriction to the %config directive, and that restriction
is that no more than one filename may follow the %config.
must be from distant past for there are examples of spec files using wildcard characters in %config directive as early as in year 2008.
The problem is not in using wildcard characters per se. The problem is that one and the same file is listed twice (once directly, and once indirectly as a result of usage of wildcard character) with different %config directives (once with plain %config and once with %config(noreplace)). Your test – changing order of these two declarations – and the result you observe suggests that rpm merges these two declarations into one %config(noreplace). This would explain why the order of declarations does not matter. However, as I wrote above, the assumption is that every file is listed exactly once and this could be the reason I couldn't find any information on what is supposed to happen when some file is listed more than once.
Please note, that the file specified with %config(noreplace) must have changed – in the package – between the version already installed and the newer version being installed for .rpmnew files to be written – see .rpmnew file not created on package upgrade?
Please be also aware that installation of newer version of some package is not treated like updating the package – see Unexpected RPM conflict on %config(noreplace) files
Below are spec files for those wanting to try themselves.
mypackage-old.spec:
Summary: old version
Name: mypackage
Version: 1
Release: 1
License: BSD
%description
https://stackoverflow.com/questions/32610487/
%prep
%build
%install
rm -rf %{buildroot}
mkdir -p %{buildroot}/foo
echo 'replace' > %{buildroot}/foo/replace
echo 'noreplace' > %{buildroot}/foo/noreplace
%clean
rm -rf %{buildroot}
%files
%defattr(-,root,root,-)
%config /foo/replace
%config(noreplace) /foo/*
mypackage-new.spec:
Summary: new version
Name: mypackage
Version: 2
Release: 1
License: BSD
%description
https://stackoverflow.com/questions/32610487/
%prep
%build
%install
rm -rf %{buildroot}
mkdir -p %{buildroot}/foo
echo 'new replace' > %{buildroot}/foo/replace
echo 'new noreplace' > %{buildroot}/foo/noreplace
%clean
rm -rf %{buildroot}
%files
%defattr(-,root,root,-)
# declaration A
%config /foo/replace
# declaration B
%config(noreplace) /foo/*
The result with RPM version 4.14.0 is the same no matter what order we place declarations A and B above:
% rpmbuild -ba ./mypackge-old.spec
% rpmbuild -ba ./mypackge-new.spec
% sudo rpm -i ~/rpmbuild/RPMS/x86_64/mypackage-1-1.x86_64.rpm
% echo modified >> /foo/replace
% echo modified >> /foo/noreplace
% sudo rpm -U ~/rpmbuild/RPMS/x86_64/mypackage-2-1.x86_64.rpm
warning: /foo/noreplace created as /foo/noreplace.rpmnew
warning: /foo/replace created as /foo/replace.rpmnew

Passing user defined argument to RPM is possible while installing?

Passing User defined argument to RPM is possible while installing?.
for example:
~>rpm -i sample.rpm -license_path=/path/
or
~>rpm -i -license_path=/path/ sample.rpm
or
~>rpm -i -somearg sample.rpm
-Sakthi
RPMs aren't meant to take user defined arguments.
See RPM - Install time parameters
Another similar question is at https://superuser.com/questions/408852/is-it-possible-to-get-users-input-during-installation-of-rpm
One workaround is to have the rpm's postinstall script ask for input from stdin, in which case you can pass in the answers by redirecting stdio from a file or here document.
>rpm -i sample.rpm <<__NOT_RECOMMENDED__
somearg
__NOT_RECOMMENDED__
It looks like you are trying to create a relocatable RPM.
In the preamble of your .spec file, put the prefix of the file path that can be relocated.
For example, if the full path to your file is
/base/path/to/my/file
then /base can be changed during RPM installation but /path/to/my/file will remain the same.
Here's what you put in your .spec file:
#Preamble: Summary, Name, etc.
Prefix: /base
Ensure that you mention this prefix while listing all relocatable files in the %install and %files sections in the .spec file. There are conditions where a relocatable RPM may not work, so check out these things to consider as well.
%files
%{prefix}/path/to/my/file
Now when you install the RPM, you can specify a different prefix.
rpm -i sample.rpm --prefix /tmp
This will install the file in /tmp/path/to/my/file.

how to update a pre-existing config file using rpmbuild?

I've been looking into how to use an rpmbuild spec file to update an already existing config file.
As an example, in my rpm I'd like to add lines to a config file e.g. /etc/stunnel/stunnel
[SomeAppName]
accept = 8006
connect = 127.0.0.1:5006
I've currently got this in my %install section:
cat stunnel/stunnel.conf >> %{buildroot}/etc/stunnel/stunnel.conf
Now clearly this is rubbish because each time I run the rpm it will add these same lines to the config file.
I also don't want the /etc/stunnel/stunnel.conf file to be part of my rpm as I don't want it removed when I erase my rpm package.
My questions are:
How can I exclude the /etc/stunnel/stunnel.conf from being part of my rpm?
What is the correct way to add lines to a config file during an rpm?
Please could someone provide some links where I can see how to get this working or example of a few lines that I can use in my spec file.
I've look at the official guide over at Max Rpm but so far I've not found the answer to my issue.
a) Many more modern tools also support a .d configuration directory parallel to flat files for this exact reason. For example, my Debian wheezy distribution treats /etc/stunnel as a directory in which each .conf file is a separate stunnel configuration.
b) The established alternative seems to be a conditional construct like
grep -q '[SomeAppName]' %{buildroot}/etc/stunnel/stunnel.conf || cat ...
(or, if not sure if stunnel.conf already exists)
grep -s '[SomeAppName]' %{buildroot}/etc/stunnel/stunnel.conf || cat ...

Resources