Custom task for rpmbuild

Hi guys,

We’re currently in the process of moving away from scons to gradle to build the java portions of our software. One thing we need is to build rpm from the spec file. So we tried to write custom task to execute rpmbuild to build rpm from spec file. The code boils down to this:

def rpmPath = 'sample-master-5.0-128000-final.x86_64.rpm'
def rpmArgs = ['--quiet', '-bb', 'SPECS/sample-rpm-spec.spec',  ' --define "rpmdir artifacts"',  ' --define "sourcedir ."', ' --define "version 5.0"', ' --define "targetdir build"', ' --define "name sample"', ' --define "pathname sample"', ' --define "arch x86_64"', ' --define "revision 128000"', ' --define "branchName master"']
project.exec {
    workingDir '.'
    commandLine 'rpmbuild'
    args rpmArgs
}

and here is the spec file:

# --define 'rpmdir dir' to specify the rpm destination directory
# --define 'version x.y.z' to define a build version
# --define 'sourcedir dir' to specify the location of the source directory

%define _builddir .
%define _rpmdir %{?rpmdir}%{!?rpmdir:RPMS}
%define _rpmfilename %{pathname}-%%{VERSION}-%%{RELEASE}%{?final}%{!?final:%{nil}}.%%{ARCH}.rpm

%define xyzapp /opt/xyzapp

Summary: Sample Spec File
Name: %{name}
Version: %{version}

Release: %{revision}
License: Commercial
Group: Applications/Imaging
Vendor: Sample Company Inc.
BuildRoot: %{_tmppath}/%{pathname}-buildroot
BuildArchitectures: %{arch}

Requires: first-rpm%{?branchName:-%{branchName}}%{!?branchName:} >= 2.10.0
Requires: second-rpm%{?branchName:-%{branchName}}%{!?branchName:} >= 2.10.0

%description
Sample Spec description

%build

echo building with rpmdir=%{_rpmdir} version=%{version} sourcedir=%{sourcedir}

# ensure the build root is clean
if [ %{buildroot} != "/" ]; then
   rm -rf %{buildroot}
fi

mkdir -p %{_rpmdir}
mkdir -p %{buildroot}/tmp/classes
mkdir -p %{buildroot}%{xyzapp}
mkdir -p %{buildroot}%{xyzapp}/webapp/WEB-INF/lib/

if [ -f %{targetdir}/distributions/SampleZipArtifact.zip ]; then
   unzip %{targetdir}/distributions/SampleZipArtifact.zip -d %{buildroot}%{xyzapp}/
fi

# remove the server classes that should not be included with this plugin
rm -rf %{buildroot}/tmp

find %{buildroot} -name .svn -o -name .classpath -o -name .project | xargs rm -rf

%clean

if [ %{buildroot} != "/" ]; then
   rm -rf %{buildroot}
fi

%pre

%post

%preun

%postun

%files

%defattr(-,xyzapp,users,-)
%doc

%{xyzapp}/webapp

Essentially, by executing gradle buildSampleRpm
We got the error:

[ERROR] [system.err] error: No compatible architectures found for build

Here’s is the full debug logs to give you more details:

14:23:16.462 [DEBUG] [org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter] Executing actions for task ':buildSampleRpm'.
14:23:16.490 [INFO] [org.gradle.process.internal.DefaultExecHandle] Starting process 'command 'rpmbuild''. Working directory: /mnt/hgfs/CSI/GradleRpmSample Command: rpmbuild --quiet -bb SPECS/sample-rpm-spec.spec  --define "rpmdir artifacts"  --define "sourcedir ."  --define "version 5.0"  --define "targetdir ."  --define "name sample"  --define "pathname sample"  --define "arch x86_64"  --define "revision 128000"  --define "branchName master"
14:23:16.490 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Environment for process 'command 'rpmbuild'': {TERM=xterm, JAVA_HOME=/usr/lib/jvm/java, FLEX_SDK=4.11, SESSION_MANAGER=local/unix:@/tmp/.ICE-unix/2695,unix/unix:/tmp/.ICE-unix/2695, GNOME_DESKTOP_SESSION_ID=this-is-deprecated, MAIL=/var/spool/mail/trungvo, GDMSESSION=gnome, XDG_SESSION_COOKIE=51806fc4a6f192828593c2df00000009-1428348402.461525-264542834, PWD=/mnt/hgfs/CSI/GradleRpmSample, HOSTNAME=tonycsicentos6, CVS_RSH=ssh, GIO_LAUNCHED_DESKTOP_FILE_PID=16285, G_BROKEN_FILENAMES=1, NLSPATH=/usr/dt/lib/nls/msg/%L/%N.cat, GNOME_KEYRING_SOCKET=/tmp/keyring-LiVncy/socket, CSI_DATA=/mnt/hgfs/CSI/Data/trunk, GDM_KEYBOARD_LAYOUT=us, HISTSIZE=1000, EDITOR=vi, PATH=/mnt/hgfs/CSI/Library/rhel5-64/ant/bin:/mnt/hgfs/CSI/Library/rhel5-64/Tools/flex_sdk_4.11/bin:/home/trungvo/gradle-2.3/bin:/mnt/hgfs/CSI/Library/rhel5-64/ant/bin:/mnt/hgfs/CSI/Library/rhel5-64/Tools/flex_sdk_4.11/bin:/home/trungvo/gradle-2.3/bin:/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/apache-ant-1.8.1/bin:/home/trungvo/bin:/opt/apache-ant-1.8.1/bin, GRADLE_HOME=/home/trungvo/gradle-2.3, QTLIB=/usr/lib64/qt-3.3/lib, GDCM_DATA_ROOT=/mnt/hgfs/CSI/Data/trunk/CSI/Rendering/gdcmData, GDM_LANG=en_US.utf8, XAUTHORITY=/var/run/gdm/auth-for-trungvo-dyz7I2/database, WINDOWPATH=1, FLEX_HOME=/mnt/hgfs/CSI/Library/rhel5-64/Tools/flex_sdk_4.11, USERNAME=trungvo, SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass, SHLVL=2, XFILESEARCHPATH=/usr/dt/app-defaults/%L/Dt, COLORTERM=gnome-terminal, CSI_LIB64=/mnt/hgfs/CSI/Library/rhel5-64, GIO_LAUNCHED_DESKTOP_FILE=/usr/share/applications/gnome-terminal.desktop, WINDOWID=44040195, LOGNAME=trungvo, QTDIR=/usr/lib64/qt-3.3, SSH_AUTH_SOCK=/tmp/keyring-LiVncy/socket.ssh, OLDPWD=/home/trungvo/gradle-2.3, LIBGL_DRIVERS_PATH=/usr/local/lib/gallium, DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-9FkHHSyF0Z,guid=7c6139ab66bf88999c60bf4d0000013e, SHELL=/bin/bash, GNOME_KEYRING_PID=2685, GTK_RC_FILES=/etc/gtk/gtkrc:/home/trungvo/.gtkrc-1.2-gnome2, DESKTOP_SESSION=gnome, FLEX_HOME_4=/mnt/hgfs/CSI/Library/rhel5-64/Tools/flex_sdk_4.11, QTINC=/usr/lib64/qt-3.3/include, DISPLAY=:0.0, USER=trungvo, ANT_HOME=/mnt/hgfs/CSI/Library/rhel5-64/ant, GRADLE_OPTS=-Dorg.gradle.native=false, MESA_GLSL=opt,nopvert,nopfrag, HOME=/home/trungvo, HISTCONTROL=ignoredups, LESSOPEN=|/usr/bin/lesspipe.sh %s, MALLOC_TRIM_THRESHOLD_=128*1024, LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.tbz=01;31:*.tbz2=01;31:*.bz=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:, ORBIT_SOCKETDIR=/tmp/orbit-trungvo, LANG=en_US.utf8}
14:23:16.499 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Changing state to: STARTING
14:23:16.506 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Waiting until process started: command 'rpmbuild'.
14:23:16.516 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Changing state to: STARTED
14:23:16.517 [DEBUG] [org.gradle.process.internal.ExecHandleRunner] waiting until streams are handled...
14:23:16.517 [INFO] [org.gradle.process.internal.DefaultExecHandle] Successfully started process 'command 'rpmbuild''
14:23:16.545 [ERROR] [system.err] error: No compatible architectures found for build
14:23:16.569 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Changing state to: FAILED
14:23:16.569 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Process 'command 'rpmbuild'' finished with exit value 1 (state: FAILED)
14:23:16.570 [DEBUG] [org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter] Finished executing task ':buildSampleRpm'
14:23:16.571 [LIFECYCLE] [class org.gradle.TaskExecutionLogger] :buildSampleRpm FAILED

Did we miss to pass in the architecture in the command?

  • Please note that we do pass in --define ‘arch x86_64’
  • We did try to pass in the option --buildarch x86_64, but apparently, it’s the unknown option for our version of rpmbuild
  • If we execute the rpmbuild command directly from the terminal, it works just fine, however, as soon as we execute the rpmbuild in the gradle shell, things starting to break. That makes me to think that it’s properly we missed to passed in some configuration into the Gradle.project.exec
  • You can download the full sample source code from here:
    https://dl.dropboxusercontent.com/u/59660821/GradleRpmSample.zip
  • I’m running gradle on Centos 6.4
  • Let me know if there’s any other info I can provide

Have you tried the Nebula RPM plugin? https://plugins.gradle.org/plugin/nebula.os-package

There are some funny things in rpmArgs, the process will treat things like this as one argument – ' --define "sourcedir ."' when it should be two. You should try splitting those like – '--define', '"sourcedir ."'.

  • Thanks Sterling, I tried to split those ‘–define “blah”’ arguments to 2 arguments and it doesn’t seem to fix the problem.
  • I did think about using nebula.os-package however, according to their API they use Gradle DSL to construct rpm packages. It doesn’t offer a way for us to construct rpm package from spec files.
  • We have a huge amount of spec files, converting spec files logic to Gradle DSL is not an option for us at the moment.
  • I looked around and apparently scons/python is a preferred choice for building rpm packages from spec files, so I’m trying to use gradle to drive scons to build rpm from spec files with rpmbuild command
  • Little bit history, we’re mainly C/C++ shops so we’re currently using scons to build our system. However, we run into many problems with specifying dynamically generated dependency in scons for Java side. So we’re thinking of using Gradle as orchestration tool where it would drive scons to build C++ side, build Java side and dependency management.
  • It would be very nice if we could use gradle to build rpm packages from spec files through rpmbuild command line as our company have huge amount of spec files. Furthermore, it would also drive more Gradle adoption as I think most people use spec files to build rpm packages.

FYI, my colleague got it working by splitting the ‘–define blabh’ into separate arguments and remove any white spaces. Thank you very much for your help.

I ran into this forum and ran into a similar thing. And I just wanted to add.

If your rpmbuild command was like,
rpmbuild --quiet -bb 'SPECS/sample-rpm-spec.spec --define “rpmdir artifacts”

Then your args should like this,
def rpmArgs = [’–quiet’, ‘-bb’, ‘SPECS/sample-rpm-spec.spec’, ‘–define’, ‘rpmdir artifacts’]

Don’t do this…
def rpmArgs = [’–quiet’, ‘-bb’, ‘SPECS/sample-rpm-spec.spec’, ‘–define’, ““rpmdir artifacts””