4

I am trying to set the rpath in my spec file with a statement like

export LDFLAGS="-Wl-rpath=$ORIGIN/../lib"

But I can't correctly escape "$ORIGIN". I need the command to gcc to contain the string "$ORIGIN", not expand it anywhere along the line. I tried

\\\$ORIGIN
$$ORIGIN
\$\$ORIGIN
\\$\\$ORIGIN
\\\\\\$ORIGIN
\\\\\\\\$ORIGIN

and a few others with no success. What's the right sequence of escape characters?

pythonic metaphor
  • 10,296
  • 18
  • 68
  • 110
  • 1
    How are you determining that it isn't working correctly? What are you expecting to happen exactly? Where is the value of `ORIGIN` supposed to be coming from in the first place? – Etan Reisner Jul 10 '14 at 19:04
  • 1
    @Etan on linux, having "$ORIGIN" in your rpath has special meaning. So I don't want to expand the `ORIGIN` variable, I want the rpath to contain the literal string "$ORIGIN". You can run `chrpath` on the resulting executable to see what the rpath was set to, and none of those set it to the right string (though in reality, I look at the build commands as they scroll by and see that it's not right) – pythonic metaphor Jul 10 '14 at 19:11
  • Huh. I was not previously aware of that. That's nifty. I assume then that all of those various options ended up expanding the variable to an empty string? – Etan Reisner Jul 10 '14 at 19:17
  • They did various things. Some expanded to "RIGIN" some expanded to nothing, some put numbers there. That last one was mysterious to me! – pythonic metaphor Jul 10 '14 at 19:19
  • 1
    Ah, right, this is going to be passed through make at some point so it needs to make it through there unscathed. I don't think rpm is actually doing anything to it (though you should be able to check that via the script that rpm uses to build the package if you don't clean it up). You should single quote the assignment first off so the shell doesn't expand the variable on you, then you might need $$ to escape through make correctly but I'm not sure. – Etan Reisner Jul 10 '14 at 19:23
  • I have to double quote the assignment because in my actual rpm, I do need shell expansion of some other parts of `LDFLAGS`. But, yeah, I need to escape around the shell (why I tried escaping the `$`) and make (why I tried using double `$`) and I can't quite wrap my mind around how to do it. – pythonic metaphor Jul 10 '14 at 19:29
  • You can alternate quotes for different parts of the assignment. So `="..."'$ORIGIN'"..."` and that might help. I need to think about the pieces involved here a bit more though – Etan Reisner Jul 10 '14 at 20:31
  • Thank you for asking this question. I ran into the same problem a few weeks ago, but I ended up solving it by hard-coding the full RPATH (using a specfile macro to get the proper lib dir), rather than by using the `$ORIGIN` string. This solution won't work for relocatable packages and a few other situations. – jayhendren Jul 30 '14 at 20:34

2 Answers2

1

Alright. I did some quick testing and I believe I figured out what you need to do.

Try using one of the following:

export LDFLAGS="-Wl,-rpath=\\$\$ORIGIN/../lib"

or

export LDFLAGS="-Wl,-rpath="'\$$ORIGIN'"/../lib"
Etan Reisner
  • 77,877
  • 8
  • 106
  • 148
  • 1
    I tried this and I got "RIGIN" instead of "$ORIGIN" – pythonic metaphor Jul 14 '14 at 17:39
  • @pythonicmetaphor Hm... How exactly are you using that line in your spec file and that variable in your makefile? – Etan Reisner Jul 14 '14 at 17:42
  • in the `%build` section I set some environment variables `export VAR=blah;` for a few things and then call configure and make. The configure script and resulting make file are standard gnu release stuff; they use `LDFLAGS` in the usual way. – pythonic metaphor Jul 14 '14 at 18:56
  • @pythonicmetaphor You could try `"..."'\$$\$$ORIGIN'"..."` but that's mostly a guess. I'd need to find a simple autotools project to test with to see if that works and I don't have one offhand. The versions in my answer work with a tiny custom makefile so I'm a bit confused. – Etan Reisner Jul 15 '14 at 19:09
1

I managed to figure this one out. I used curl-7.19.7 for testing. From the command line, the following was sufficient to get make to pass $ORIGIN through to the compiler:

export LDFLAGS='-Wl,-rpath=\$$ORIGIN/../lib'
./configure --prefix=/tmp/curl
make
make install

and I verified using readelf --dynamic /tmp/curl/bin/curl.

However, from a specfile, I needed to escape the backslash an extra time. Here is what worked from the %build section of the specfile for me:

%define ldflags LDFLAGS='-Wl,-rpath=\\$$ORIGIN/../lib'
%configure --enable-shared %{ldflags}
make %{?_smp_mflags}

To verify, here is the output from readelf:

[faceplant ~/rpmbuild/specs]% readelf --dynamic ../buildroot/sis-curl-7.19.7-2.el6.x86_64/usr/local/curl-7.19.7/bin/curl

Dynamic section at offset 0x1c028 contains 26 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libcurl.so.4]
 0x0000000000000001 (NEEDED)             Shared library: [libssl.so.1.0.0]
 0x0000000000000001 (NEEDED)             Shared library: [libcrypto.so.1.0.0]
 0x0000000000000001 (NEEDED)             Shared library: [librt.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libz.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000f (RPATH)              Library rpath: [$ORIGIN/../lib:/usr/local/curl-7.19.7/lib]
 0x000000000000000c (INIT)               0x401b98
 0x000000000000000d (FINI)               0x40b2f8
 0x000000006ffffef5 (GNU_HASH)           0x400260
 0x0000000000000005 (STRTAB)             0x400cb0
 0x0000000000000006 (SYMTAB)             0x4002c0
 0x000000000000000a (STRSZ)              1229 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000015 (DEBUG)              0x0
 0x0000000000000003 (PLTGOT)             0x61c220
 0x0000000000000002 (PLTRELSZ)           2160 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x401328
 0x0000000000000007 (RELA)               0x4012c8
 0x0000000000000008 (RELASZ)             96 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffe (VERNEED)            0x401258
 0x000000006fffffff (VERNEEDNUM)         2
 0x000000006ffffff0 (VERSYM)             0x40117e
 0x0000000000000000 (NULL)               0x0

As you can see, $ORIGIN/../lib made it into the RPATH field unscathed.

Hopefully this works for you.

(P.S. please ignore the /usr/local/<package>-<version> prefixes. This is just a packaging method I've been experimenting with in order to meet some packaging needs for my organization.)

jayhendren
  • 4,286
  • 2
  • 35
  • 59