Retrieving current architecture for RPM - linux

I'm automating RPM package building with rpmbuild. The files end up in the architecture subdirectory under RPMS.
Question - how do I retrieve, from a shell script, the architecture name of the host that RPM is using? It's not the same as arch command.

It looks like
rpm --eval '%{_arch}'
does the trick:
$ rpm --eval '%{_arch}'
x86_64
$ rpm --target 'SPARC64' --eval '%{_arch}'
sparc64

There's /usr/lib/rpm/rpmrc that translates known OS-level architecture names into canonical RPM architecture names. The following shell script does the job for me:
ARCH=`arch`
# OS-level architecture name, like 'i686'
ARCH=`cat /usr/lib/rpm/rpmrc | grep "buildarchtranslate: $ARCH" | cut -c21-`
# returns the translate line as "arch-from: arch-to"
ARCH=${ARCH/#*: /}
# strips the prefix up to colon and following space, returns arch-to.
# Assumes just one space after colon. If not, more regex magic is needed.

You're doing it wrong. Redefine %_build_name_fmt in ~/.rpmmacros.

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

How to check os version in rpmbuild spec file

I am building an rpm where I need to check the OS version. If it is rhel5 or rhel6, then it'll work, else it'll stop.
Please advice how can I make it.
Thanks & Regards.
You can use https://unix.stackexchange.com/questions/9296/how-can-i-specify-os-conditional-build-requirements-in-an-rpm-spec-file
however this only decide what go inside of package in buildtime. And you can still install el6 package on el5 and vice versa.
So if you want to do decide that during actual installation, the you need to parse /etc/os-release (IIRC exist only in el7+) or /etc/redhat-release.
Another alternate Use to use the uname command and parse Information
Save time execute the following:
uname -r | cut -d '.' -f6
This is valid in RHEL 6 and 7.
There's %{rhel} you can check
$ rpmbuild --eval %{rhel}
7
You can run cat /etc/issue and parse as necessary

Where would I find the kernel .config file in Lubuntu?

I'm running through the "first kernel patch" tutorial on kernel newbies http://kernelnewbies.org/FirstKernelPatch
While running through the tutorial, i've had absolutely no issues what so ever until now, I am at a point where I am setting up my kernel configuration. I've followed the tutorial exactly as shown but the following command:
cp /boot/config-'uname -r'* .config
leaves me with the following error message in the terminal:
cp: cannot stat '/boot/config-uname -r*': No such file or directory
Is there a way I can generate this file without going through the effort of looking for it in the finder? I'd rather not go through the thousands of files there are in a kernel, it could take me forever.
It seems like your tutorial has a quotation error. instead of ' you should be using ` (backtick)
cp /boot/config-`uname -r`* .config
What it does is execute the command uname -r and place the stdout of the command in place of the command. I'd suggest using $(command) instead of `command` since it's more obvious what is going on.
cp /boot/config-$(uname -r)* .config
First things first .. You're using simple quotes which is wrong, the command is meant to use backticks (`) -- they will include the output of the command inside them:
> uname -r
3.16.1-ck1
> echo /boot/config-`uname -r`
/boot/config-3.16.1-ck1
So this could already solve your problem.
If this file isn't present on your system, you have some alternatives:
If you have the source the running kernel is built from, the kernel config is the file .config there.
Although most packaging/installation systems copy the kernel config to /boot/config-`uname -r`, some just copy it to /boot/config (without version suffix)
The kernel can be built to serve it's config in /proc/config.gz (gzip compressed)
If really neither of these succeed, you're out of luck and your only option is get hold of the source package your kernel is built from.

Programming way to list shared library dependency on linux

Is there any programming way (system call?) to list shared library dependency on Linux? Instead of using ldd ...
readelf -Wa lib.so|grep NEEDED
Gentoo Linux has an lddtree.sh
http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-projects/pax-utils/lddtree.sh?revision=1.22&content-type=text%2Fplain
You may find it helpful.
Set LD_TRACE_LOADED_OBJECTS environment variable to non-empty string and run your binary. Look at this man page.
LD_TRACE_LOADED_OBJECTS
(ELF only) If set to non-empty string, causes the program to list its dynamic library dependencies, as if run by ldd(1), instead of running normally.
This is the simple bash script I use myself on Fedora, it relies on find-requires of rpm package, you can look inside find-requires to find what tools it internally uses.
#!/bin/bash
#
# Use rpm to recursively list dependencies of all files in a directory
#
# Syntax:
# lsdep path/to/directory
# Example:
# lsdep /usr/src/kernels/`uname -r`/
find $1 -type f -exec sh -c 'res=`echo '{}' | /usr/lib/rpm/find-requires`; [ -n "$res" ] && (echo;echo file '{}'; echo $res)' \;

Resources