bashrpmrpmbuildsoftware-packagingrpm-spec

Define Version with script in RPM spec file


I have an RPM Spec file, building on rhel7 with rpmbuild, where I would like to define the Version with a script.

I read here http://www.techrepublic.com/article/rpmproc-spec-file/ , That I can do this:

%define version 1.2

Version: %{version}

And here RPM spec file - Is it possible to dynamically populate a spec file variable , That I can define with a script:

%define whoami %(cmd)

So I tried to do this in my Spec File:

%define version %(echo "$(sed -n 's|^[ ]*appVersion = "\(.*\)"|\1|p' /fullfilepath/values.txt | sed 's/^\(.*\)-.*$/\1/')")

Version: %{version}  **Line 23**

But I get a

error: line 23: Empty tag: Version:

Things I have tested so far:

%define version %(echo "12") --basic script works ok, version becomes 12

//As a command straight in terminal
$ echo "$(sed -n 's|^[ ]*appVersion = "\(.*\)"|\1|p' /fullfilepath/values.txt | sed 's/^\(.*\)-.*$/\1/')"
//returns 1.2

These work well, So I have no idea what it could be thats causing it to fail. Any ideas what could be casuing it to fail when I call the same thing in define tag in spec file?

Update

I tried replacing the file name with the actual value so it looks like this

echo "$(sed -n 's|^[ ]*appVersion = "\(.*\)"|\1|p' <<< "appVersion = \"1.2-SNAPSHOT\"" | sed 's/^\(.*\)-.*$/\1/')"

That works when called in terminal but as a

%(echo "$(sed -n 's|^[ ]*appVersion = "\(.*\)"|\1|p' <<< "appVersion = \"1.2-SNAPSHOT\"" | sed 's/^\(.*\)-.*$/\1/')") 

but I still get the

Empty tag: Version: Error

Update 2

I tested a different more complex command then echo "12":

%define version %(echo "$(git log -1 | grep commit | awk -F"commit " '{print $2}' | cut -c1-8)")

This works ok too! Makes the version the 7 first digits of the commit hash.

Update 3

The mystery continues, I did a test to check if its the sed command thats the cause but the following command gives me 1.2 as the version

%define version %(echo "$( sed 's/.*= //' <<< "appVersion = 1.2" )")

If this command works but not my first one, then its got to be with something in my first command that only works when called directly in terminal and not in %(cmd). Getting closer!

Update 4

Ok so I seem to have isolated what it must be, curious, looks like it could be the -n or the s| | \1 |p syntax that rpmbuild doesn't like. I made a more simpler version of my original. Check it out:

#Error, doesn`t set version to 1.2
%define version %(echo "$( sed -n 's|^.*-\(-*\)|\1|p' <<< "foo-1.2" )") 

#Works ok! sets version to 1.2
%define version %(echo "$( sed 's/.*= //' <<< "appVersion = 1.2" )") 

Unfortunately though I don't think I can do anymore to isolate and figure out what the issue is. Theres nothing wrong with using a sed in the style of the second command but its still very interesting as to why the first command doesn't work.

Update 5

I have discovered that there is some deep issue here when working with any script inside %() with a spec file and rpmbuild. I tried using awk just to see what would happen and it too breaks! This goes way deeper then I initially thought, like discovering a conspiracy:

#In terminal it prints 1.2-SNAPSHOT, but in Spec it's an error 
%define version %(echo "$(awk '/appVersion /{ print $3 }' <<< "appVersion = \"1.2-SNAPSHOT\"" | tr -d \")")

sh: -c: line 0: unexpected EOF while looking for matching `)'
sh: -c: line 1: syntax error: unexpected end of file
error: line 23: Empty tag: Version:

Update 6

Good news and bad news for everyone, I found that rpm seems to be doing some of its own work in the backround and not showing what its doing, I finally found a command that gives different values when called through rpm:

%define version %(echo "$(awk '/midonetVersion /{ print $3 }' <<< "midonetVersion = \"5.1-SNAPSHOT\"")")
#In terminal it echos "5.1-SNAPSHOT" (literally wrapped in "" )
#When in spec it set version to 5.1-SNAPSHOT , rpmbuild is removing the ""

So now I made an adjustment and called this:

#echos "5.1 in terminal and sets version to 5.1 in spec
%define version %(echo "$(awk '/appVersion /{ print $3 }' <<< "appVersion = \"1.2-SNAPSHOT\"")"| cut -d'-' -f1)

So from looking at this, I think there maybe is a similar kind of behind the scenes parsing of the result of my first sed command from rpm. We will have our way rpm!

Final Update

A truce was made with rpm, I am going to use this command instead:

%define version %(echo "$(awk '/ appVersion =/{ print $3 }' /filepath/values.txt" | sed 's/\"//g' | cut -d'-' -f1)

It does the same thing as my first command and works inside specfile setting the version number correctly. If anyone has any guess as to why the first command wouldn't run I would be thrilled to read it. Peace!


Solution

  • You must be having a shell script that invokes rpmbuild command. You can use that script to compute version (or for that matter, any command that you are trying to use in rpm spec file).

    Change your original code,

    %define version %(echo "$(sed -n 's|^[ ]*appVersion = "\(.*\)"|\1|p' /fullfilepath/values.txt | sed 's/^\(.*\)-.*$/\1/')")
    Version: %{version}
    

    to,

    %define version _VERSION_
    Version: %{version}
    

    and sed _VERSION_ to its computed value in the shell script that calls rpmbuild (before invoking rpmbuild). After the actual spec contents are dumped to some file, pass on that generated file to rpmbuild in the same shell script.

    Here is a summary of the steps:

    Assuming you have a builder.sh shell script that calls rpmbuild, follow below steps:

    1. Update your spec file to have _VERSION_ placeholder string/macro as show above
    2. Move current rpm spec file to my_package_template.spec
    3. in builder.sh, run command(s) to get your version and save the version to a variable
    4. Use sed command on my_package_template.spec file to replace _VERSION_ by this computed version, and save the sed output to my_package.spec
    5. Pass my_package.spec to rpmbuild command.

    Repeat steps 1, 3 and 4 for replacing usage of any other shell commands inside your spec file.