13

I'm creating an RPM for an application that doesn't already have one. I've got it building and installing fine in the /opt directory using $RPM_BUILD_ROOT, but I would also like to create a couple symlinks in /usr/bin so that the application is available on the path. All of my attempts to do this have yielded "permission denied" errors because I'm running rpmbuild as a non-root user and it's not allowed to create files in /usr/bin/.

Here's my current .spec file:

Summary: Berkeley UPC
Name: berkeley_upc
Version: 2.8.0
Release: 1
Source0: %{name}-%{version}.tar.gz
License: GPL
Group: Development/Tools
BuildRoot: %{_builddir}/%{name}-root
Prefix: /opt/bupc2.8
Prefix: /usr

%description
Berkeley UPC on the BASS for the comp633 class.

%prep
%setup -q

%build
./configure CC=gcc44 CXX=g++44 --disable-aligned-segments --prefix=/opt/bupc2.8
make %{_smp_mflags}

%install
rm -rf $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install

mkdir -p ${RPM_BUILD_ROOT}%{_bindir}
mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man1

ln -sf /opt/bupc2.8/bin/upcc          ${RPM_BUILD_ROOT}%{_bindir}
ln -sf /opt/bupc2.8/bin/upcc_multi    ${RPM_BUILD_ROOT}%{_bindir}
ln -sf /opt/bupc2.8/bin/upcc_multi.pl ${RPM_BUILD_ROOT}%{_bindir}
ln -sf /opt/bupc2.8/bin/upcdecl       ${RPM_BUILD_ROOT}%{_bindir}
ln -sf /opt/bupc2.8/bin/upcrun        ${RPM_BUILD_ROOT}%{_bindir}
ln -sf /opt/bupc2.8/bin/upc_trace     ${RPM_BUILD_ROOT}%{_bindir}

ln -sf /opt/bupc2.8/man/man1/upcc.1      ${RPM_BUILD_ROOT}%{_mandir}/man1
ln -sf /opt/bupc2.8/man/man1/upcdecl.1   ${RPM_BUILD_ROOT}%{_mandir}/man1
ln -sf /opt/bupc2.8/man/man1/upcrun.1    ${RPM_BUILD_ROOT}%{_mandir}/man1
ln -sf /opt/bupc2.8/man/man1/upc_trace.1 ${RPM_BUILD_ROOT}%{_mandir}/man1

%clean
rm -rf $RPM_BUILD_ROOT

%files
%defattr(-,root,root)
/opt/bupc2.8
%config /opt/bupc2.8/etc
%config /opt/bupc2.8/opt/etc

%{_bindir}/upcc
%{_bindir}/upcc_multi
%{_bindir}/upcc_multi.pl
%{_bindir}/upcdecl
%{_bindir}/upcrun
%{_bindir}/upc_trace

%{_mandir}/man1/upcc.1.gz
%{_mandir}/man1/upcdecl.1.gz
%{_mandir}/man1/upcrun.1.gz
%{_mandir}/man1/upc_trace.1.gz
Edward Dale
  • 247
  • 1
  • 3
  • 8

2 Answers2

6

ln -sf /opt/bupc2.8/bin/upcc ${RPM_BUILD_ROOT}/%{_bindir}

The link needs to be created in the %build section and it also needs to point to where you're installing the RPM.

Before creating the link make sure that the destination directory exists, i.e. ${RPM_BUILD_ROOT}/%{_bindir}. You can use mkdir or install -d for this.

Cristian Ciupitu
  • 6,396
  • 2
  • 42
  • 56
  • I edited my .spec file according to what I think you suggested and I'm getting the following error: + ln -sf /opt/bupc2.8/bin/upcc /home/eddale/src/rpm/tmp/berkeley_upc-root/usr/bin ln: creating symbolic link `/home/eddale/src/rpm/tmp/berkeley_upc-root/usr/bin' to `/opt/bupc2.8/bin/upcc': No such file or directory – Edward Dale Nov 06 '09 at 20:03
  • I think that you need to create the destination directory, i.e. `/home/.../usr/bin`. Here's how I do it: http://github.com/ciupicri/rpmbuild/blob/master/SPECS/python-trml2pdf.spec#L36 (line 36). – Cristian Ciupitu Nov 06 '09 at 21:13
  • That was the problem. I've updated the question to contain the final working version. Thanks! – Edward Dale Nov 08 '09 at 18:34
4

macro %{__ln_s} is good also

example add symbolic link post install:

%post
%{__ln_s} -f %{_bindir}/exec %{_bindir}/exec2

example remove symbolic link uninstall:

%postun
case "$1" in
  0) # last one out put out the lights
    rm -f %{_bindir}/exec2
  ;;
esac

The case statement ensures that the file is only removed on uninstall, and not upgrade, downgrade, or reinstall. RPM %postun for the old package runs after %post for the new package (even if that's the same version).

Rich
  • 135
  • 8
tuxnux
  • 41
  • 1
  • 3
    During an rpm -U upgrade, the old rpm will execute the %postun and destroy that file. The new rpm will not have a link, your code is bad. – ljdelight Jan 22 '16 at 03:36
  • @ljdelight - This was trivial to fix - 5 years down the road. – Rich Mar 19 '21 at 22:29