Spec rpm: how to enter in build directory without using tar files? - rpmbuild

I want to build a project from git, and create the rpm,this is the spec,is incomplete, but the most interesting part is first one.
I need to enter in build dir created by git,but fail
This is the part of spec. file
%define build_timestamp %(date +"%Y%m%d")
#
Summary: My git project
Name: gitproject
Release: 1
Version: %{build_timestamp}
License: GPLv2+
Group: Unspecified
URL: https://mygitserver.com/myname/myproject
#-----------------------------------------------------
Requires: openssl
BuildRequires: compat-openssl10-devel
BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot
#-----------------------------------------------------
AutoReqProv: no
%description
Git personal project, is in testing
%prep
git clone https://mygitserver.com/myname %{name}
cd %{name}
The problem is..instead of enter in %{name} enter in BUILD..which of course contain a lot of dirs..but not the makefile.
+ umask 022
+ cd /home/user/rpmbuild/BUILD
+ make -j2
make: *** No targets specified and no makefile found. Stop.
How can I enter %{name}?

I wouldn't skip the tgz part, but let git do the work for you. The way I solve this: use Source and %setup -q in your spec file:
Source: %{name}-%{version}.tgz
%prep
%setup -q
now you can use git to create this tgz file for you:
git archive --format=tgz --prefix=gitproject-1.2.3-1 <hash or tag> > /home/user/rpmbuild/SOURCES/gitproject-1.2.3.tgz
note that the prefix ang filename need to match the %name-%version.tgz from the Source tag in your spec file. You can change those naming conventions of course.
PS: I have write a whole convenience script around this; but with these commands you should get most of the way.

Related

Why use %files directive in RPM spec file and how to automate file listing in that section?

Why does %files needed and why it cannot be created automatically by listing $RPM_BUILD_ROOT directory contents?
For example, in that spec file i have to use some modifications in it in script, that build an RPM package for me. I have to cd into ~/RPM/SOURCES, then find . in it and echo each line into .spec file to setup %files section. It can be done automatically by the tool using the same techniuque i do in the background but from $RPM_BUILD_ROOT directory instead?
%install
mkdir -p $RPM_BUILD_ROOT/opt/MyCompany/MyProduct/
cp -rf -- ~/RPM/SOURCES/* $RPM_BUILD_ROOT/opt/MyCompany/MyProduct/
%files
/opt/MyCompany/MyProduct/file_1
/opt/MyCompany/MyProduct/file_2
/opt/MyCompany/MyProduct/file_3
... - a lot of lines here
/opt/MyCompany/MyProduct/file_100000
UPD:
Yes it is possible to use all copied files automatically (Doc http://ftp.rpm.org/max-rpm/s1-rpm-inside-files-list-directives.html)
In my case %files can be rewritten as that
%files
/opt/MyCompany/MyProduct/*
It will take files from $RPM_BUILD_ROOT/opt/MyCompany/MyProduct, so to use star we need to omit build root which is $RPM_BUILD_ROOT or %{buildroot} (Which is default path where rpm searches for files IIUC)
Why does %files needed and why it cannot be created automatically by listing
$RPM_BUILD_ROOT directory contents?
It is common that one spec file build creates multiple (sub)packages - then also
multiple %files sections are needed.
Even though there exist some automatic %files
section
generators,
nb there's the
%files -f option,
in general it isn't possible to split the files automatically.
Worth saying that most of the package maintainers don't maintain the software
source code, but just package the "upstream" releases. If the %files sections
are rather manually maintained (in contrast with the wildcard patterns), the
package maintainer has everything a bit more under control because he is
notified about the changes in the software installation layout (e.g. when a new
file appears in /usr/bin with a new release, rpmbuild starts complaining that
there's a new "unpackaged" file, see below).
It can be done automatically by the tool using the same techniuque i do in the
background but from $RPM_BUILD_ROOT directory instead?
You don't even have to run find manually. As long as %install creates the
files in $RPM_BUILD_ROOT, if you don't mention them in %files - you get reports
like those:
$ rpmbuild -bb *.spec
...
Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/user/rpmbuild/BUILDROOT/test-1-1.x86_64
error: Installed (but unpackaged) file(s) found:
/usr/bin/not-packaged
RPM build errors:
Installed (but unpackaged) file(s) found:
/usr/bin/not-packaged

rpm subpackages %install section

Is it possible to have a separate %install section for a subpackage in a spec file?
For example, files can be specified for the main package as
%files
and for the subpackage like this:
%files mysubpackage
however, I have only seen one
%install
section, and I get an error if I do
%install mysubpackage
no, you cannot have, and you don't need a separate %install section.
Let's suppose a typical example: you compile a program and want to create two packages; library.rpm and library-devel.rpm (with the headers). Then you'll have a spec file something like this:
Name: library
# probably some other fields...
%description
describre library
%package devel
Summary: headers for library
%description devel
describe library-devel package
%prep
# some common prep code for both packages; eg
%setup -q
%build
make (or whatever to build your program)
%install
# install files for both rpm packages; library AND headers
mkdir -p ${RPM_BUILD_ROOT}/%_libdir/
mkdir -p ${RPM_BUILD_ROOT}/usr/include/
cp library.so* ${RPM_BUILD_ROOT}/%_libdir/
cp include/*.h* ${RPM_BUILD_ROOT}/usr/include/
%files
%defattr(-,root,root)
%_libdir/*.so.*
%files devel
%defattr(-,root,root)
%_libdir/*.so # yes; if you use version numbers; the versioned .so go in the normal package; the one without version number in the devel package
/usr/include/*
further reading: RPM packaging guide

rpmbuild - issues with ${RPM_BUILD_ROOT}

The powers that be have decided that I have to use this tool which I've grown to hate in a short time.
I have packed a few things (binary, script, library) on a tarball that I want to put in a secluded place... specifically under $HOME but it could be anywhere. I can get all that to work but everything under %files automatically prepends my rpm's buildroot, which happens to be ~/rpmbuild/BUILDROOT/blah/blah.
I'm actually using a template from a colleague, but getting nowhere. Tried changing ${RPM_BUILD_ROOT} but that has the same results: installing everything to the root directory. Here's what I assume are the interesting parts. Again, it's just a program I made, something to kick it off, and a library it requires.
Source0: %{name}-%{version}.tar.gz
%install
rm -rf ${RPM_BUILD_ROOT}
mkdir -p ${RPM_BUILD_ROOT}/MyApp
/bin/tar -C ${RPM_BUILD_ROOT} -xf ${RPM_SOURCE_DIR}/${RPM_PACKAGE_NAME}-${RPM_PACKAGE_VERSION}.tar.gz
%files
%defattr(7550,root,root,-)
/MyApp.1.0-r10
/MyApp.py
/lib/libMyLibrary.so.1.0.0
If I change the tar line in %install to chdir to ${HOME} it copies the files there, but then %files fails, due to the prepending issue.

If condition inside the %Files section on a SPEC file

I'm kinda a new to writing spec files and building RPM's. Currently I have one RPM that is supposed to deploy some files in 1 of 2 possible directories that will vary with the OS.
How can I, within the %files section, verify them? I can't use variable...I can't verify both paths because one will for sure fail...I tried to define a macro earlier in the %install section but it will be defined just once and won't be redefined on every RPM installation...
what can I do here?
Thanks
I had a similar situation where additional files were included in the RPM in case of a DEBUG build over and above all files in the RELEASE build.
The trick is to pass a list of files to %files alongwith a regular list of files below it:
%install
# Create a temporary file containing the list of files
EXTRA_FILES=$RPM_BUILD_ROOT/ExtraFiles.list
touch %{EXTRA_FILES}
# If building in DEBUG mode, then include additional test binaries in the package
%if %{build_mode} == "DEBUG"
# %{build_mode} is a variable that is passed to the spec file when invoked by the build script
# Like: rpmbuild --define "build_mode DEBUG"
echo path/to/file1 > %{EXTRA_FILES}
echo path/to/file2 >> %{EXTRA_FILES}
%endif
%files -f %{EXTRA_FILES}
path/to/release/file1
path/to/release/file2
In your case, you can leverage the %if conditional in the %install section, use the OS as a spec variable passed to rpmbuild (or detect it in the RPM spec itself) and then pass the file containing the list to %files
The %files section can have variables in it, but usually this would be something like your path that is defined so you don't have to repeat it a bunch. so %{long_path}/file_name, where long_path was defined earlier in the spec file. the %files section is all the information that goes into the RPM database, and is created when you build the RPM so you won't be able to change those values based on machine information when installed.
If you really want to do this, you could include a tar file inside of the main tarball that gets extracted depending on certain conditions (since the spec file is just bash). Now keep in mind this is an awful idea. The files won't be tracked by the RPM database, so when you remove the RPM these files will still exist.
In reality you should build two RPMs, this will allow for better support going forward into the future in the event you have to hand this off to someone, as well as preserving your own sanity a year from now when you need to update the RPM.
This is how I solved my problem
step 1 :
In Build section .. somewhere I wrote :
%build
.....
#check my condition here & if true define some macro
%define is_valid %( if [ -f /usr/bin/myfile ]; then echo "1" ; else echo "0"; fi )
#after his normal continuation
.....
...
Step 2: in install section
%install
......
#do something in that condition
if %is_valid
install -m 0644 <file>
%endif
#rest all your stuff
................
Step 3:in files section
%files
%if %is_valid
%{_dir}/<file>
%endif
That's it
It works.
PS : I cannot give you full code hence giving all useful snippet
Forrest suggests the best solution, but if that is not possible practical you can detect the OS version at runtime in the post-install section, move the script to the appropriate location, and then delete it post-uninstall, eg:
# rpm spec snippets
%define OS_version %(hacky os detection)
...
Source2: script.sh
...
%install
install %{_sourcedir}/script.sh %{buildroot}/some/known/location
...
%post
%if %{OS_version} == "..."
mv /some/known/location/script.sh /distro/specific/script.sh
%elif %{OS_version} == "..."
...
%preun
rm -rf /all/script/locations
Much more error prone than building different RPMs on different OSes, but will scale a little better if you need to support many different OSes.

Create a custom symbolic link to a library at install time with CMake

Under Linux with CMake, I'm building a shared library libIex-2_0.so.10.0.1
ADD_LIBRARY (Iex SHARED
[*.cpp]
)
SET_TARGET_PROPERTIES(Iex PROPERTIES OUTPUT_NAME "Iex-2_0")
The 10.0.1 version is set with a call to
SET_TARGET_PROPERTIES ( Iex
PROPERTIES
VERSION 10.0.1
SOVERSION 10
)
In the installation folder, these links are created
libIex-2_0.so -> libIex-2_0.so.10
libIex-2_0.so.10 -> libIex-2_0.so.10.0.1
libIex-2_0.so.10.0.1
However, to match previous builds made with another build system, I need to add a legacy symbolic link, stripping the 2_0 suffix :
libIex.so -> libIex-2_0.so.10.0.1
What would be the proper CMake way to create such a link ?
One way to do it could be using CMake add_custom_command and add_custom_target. In your case it would be something like the following:
SET( legacy_link ${CMAKE_INSTALL_PREFIX}/libIex.so)
SET( legacy_target ${CMAKE_INSTALL_PREFIX}/libIex-2_0.so.10.0.1)
ADD_CUSTOM_COMMAND( OUTPUT ${legacy_link}
COMMAND ln -s ${legacy_target} ${legacy_link}
DEPENDS install ${legacy_target}
COMMENT "Generating legacy symbolic link")
ADD_CUSTOM_TARGET( install_legacy DEPENDS ${legacy_link} )
At this point you should have a target install_legacy in your generated Makefile with the correct dependency to generate libIex.so.
Another way is to run some install(CODE shell-script). It does correctly attach to the general "make install" target by the way. With better control on the working_directory it is also possible to create relative symlinks easily.
I did also require that make install DESTDIR=/buildroot works and for that it is required to leave $DESTDIR unexpanded until the shell-script is invoked. Along with some magic for portability it looks like this:
get_target_property(libname MyLib OUTPUT_NAME)
get_target_property(libversion MyLib VERSION)
set(lib ${CMAKE_SHARED_LIBRARY_PREFIX})
set(dll ${CMAKE_SHARED_LIBRARY_SUFFIX})
install(CODE "execute_process(
COMMAND bash -c \"set -e
cd $DESTDIR/${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}
echo -n .. Installing: `pwd`
ln -sv ${lib}${libname}${dll}.${libversion} ${lib}${libname}${dll}.11
echo -n .. Installing: `pwd`
ln -sv ${lib}${libname}${dll}.${libversion} ${lib}${libname}${dll}.12
\")")
P.S. assuming include ( GNUInstallDirs ) here.

Resources