Posts in category rpm

Spoofing an RPM's host name

I came up with this method years ago, and thought I posted it, but couldn't find it. So here's the latest incarnation:

# This spoofs the build host for both 32- and 64-bit applications

# To use:
# 1. Add libmyhostname as a target that calls rpmbuild
# 2. Add "myhostnameclean" as a target to your "clean"
# 3. Call rpmbuild or any other program with $(SPOOF_HOSTNAME) prefix

MYHOSTNAME_MNAME:=$(shell uname -m)
libmyhostname:=libmyhostname_$(MYHOSTNAME_MNAME).so
MYHOSTNAME_PWD:=$(shell pwd)
SPOOF_HOSTNAME:=LD_PRELOAD=$(MYHOSTNAME_PWD)/myhostname/\$$LIB/$(libmyhostname)

.PHONY: myhostnameclean
.SILENT: myhostnameclean
.IGNORE: myhostnameclean
myhostnameclean:
        rm -rf myhostname

# Linux doesn't support explicit 32- vs. 64-bit LD paths like Solaris, but ld.so
# does accept a literal "$LIB" in the path to expand to lib vs lib64. So we need
# to make our own private library tree myhostname/lib{,64} to feed to rpmbuild.
.PHONY: libmyhostname
.SILENT: libmyhostname
libmyhostname: /usr/include/gnu/stubs-32.h /lib/libgcc_s.so.1
        mkdir -p myhostname/lib{,64}
        $(MAKE) -I $(MYHOSTNAME_PWD) -s --no-print-directory -C myhostname/lib   -f $(MYHOSTNAME_PWD)/Makefile $(libmyhostname) MYHOSTARCH=32
        $(MAKE) -I $(MYHOSTNAME_PWD) -s --no-print-directory -C myhostname/lib64 -f $(MYHOSTNAME_PWD)/Makefile $(libmyhostname) MYHOSTARCH=64

.SILENT: /usr/include/gnu/stubs-32.h /lib/libgcc_s.so.1
/usr/include/gnu/stubs-32.h:
        echo "You need to install the 'glibc-devel.i686' package."
        echo "'sudo yum install glibc-devel.i686' should do it for you."
        false

/lib/libgcc_s.so.1:
        echo "You need to install the 'libgcc.i686' package."
        echo "'sudo yum install libgcc.i686' should do it for you."
        false

.SILENT: libmyhostname $(libmyhostname) libmyhostname_$(MYHOSTNAME_MNAME).o libmyhostname_$(MYHOSTNAME_MNAME).c
$(libmyhostname): libmyhostname_$(MYHOSTNAME_MNAME).o
        echo "Building $(MYHOSTARCH)-bit version of hostname spoofing library."
        gcc -m$(MYHOSTARCH) -shared -o [email protected] $<

libmyhostname_$(MYHOSTNAME_MNAME).o: libmyhostname_$(MYHOSTNAME_MNAME).c
        gcc -m$(MYHOSTARCH) -fPIC -rdynamic -g -c -Wall $<

libmyhostname_$(MYHOSTNAME_MNAME).c:
        echo "$$libmyhostname_body" > [email protected]

define libmyhostname_body
#include <string.h>
#include <asm/errno.h>

int gethostname(char *name, size_t len) {
        const char *myhostname = "buildhost_$(MYHOSTNAME_MNAME).myprojectname.proj";
        if (len < strlen(myhostname))
                return(EINVAL);
        strcpy(name, myhostname);
        return(0);
}
endef
export libmyhostname_body

Delay Before RPM Installs

I wanted the user to have a chance to abort an install, for the ones that insist on using rpm vs yum.

%if <something>
%else
%global fake %%(for i in {1..100}; do echo " "; done)
%{echo:%{fake}WARNING: RPM will not properly require vendor drivers! }
%global fake %%(for i in {1..5}; do echo " "; done)
%{echo:%{fake}}
%global fake %(sleep 10)
%endif

Have RPM Require an Environmental Variable

$(warning RHEL4 is no longer supported!)
$(warning The driver RPMs no longer support RHEL4 and the RPM that is generated will not properly require them.)
ifeq ($(TARGET_RHEL_OVERRIDE),)
$(warning If you are OK with that, then you can re-run with TARGET_RHEL_OVERRIDE=1)
$(error RHEL4 is no longer supported!)
endif

RPM Compression

The other day at work I noticed that at the end of an RPM build, it seemed to hang. It turns out, it was compressing the files to create the installer. I'd rather not have it do that if I am building development versions since they only get scp'd to a lab environment.

Even if it does compress, I'd like to have feedback as to what it is doing. So I added these lines to my .spec file. They should be easy enough to tweak and add to a system-level macros file.

Background: We had "dev" appended to the version number already, so this was the easiest way to do it:

%if 0%(echo %{rpm_version} | grep -c dev)
%define _source_payload w0.gzdio %%{echo:Skipping source RPM compression...}
%define _binary_payload w0.gzdio %%{echo:Skipping binary RPM compression...}
%else
%define _source_payload w9.gzdio %%{echo:Maximum source RPM compression...}
%define _binary_payload w9.gzdio %%{echo:Maximum binary RPM compression...}
%global _enable_debug_packages 0
%global _debug_package %{nil}
%endif

So now my RPMs are about four times as large as they were, but are built a lot faster.

Optional requirements for RPM

(Wow, it's been over a year since my last blog post...)

At work, I have a program that optionally could use the Qt libraries, but I didn't want my RPM to actually require libqt-mt.so like it wanted to. And RPM doesn't seem to support an "OptRequires" or something similar... so here's my hack of a solution.

I put this script named find-requires into my project's "build" subdirectory so it is included in the "Source" tarball that rpmbuild will be using. I wrote it to be expandable.

#!/usr/bin/perl -w
use strict;
use IPC::Open2;

# This quick script will run the native find-requires (first parameter)
# and then strip out packages we don't want listed.

open2(\*IN, \*OUT, @ARGV);
print OUT while (<STDIN>);
close(OUT);
my $list = join('', <IN>);

# Apply my filter(s):
$list =~ s/^libqt-mt.so.*?$//mg;

print $list;

Then put in your .spec file this, which will call our script with the original script as the first parameter:

# Note: 'global' evaluates NOW, 'define' allows recursion later...
%global _use_internal_dependency_generator 0
%global __find_requires_orig %{__find_requires}
%define __find_requires %{_builddir}/%{?buildsubdir}/build/find-requires %{__find_requires_orig}