2

I'm using jamplus to build a vendor's cross-platform project. On osx, the C tool's command line (fed via clang to ld) is too long.

Response files are the classic answer to command lines that are too long: jamplus states in the manual that one can generate them on the fly.

The example in the manual looks like this:

actions response C++
{
    $(C++) @@(-filelist @($(2)))
}

Almost there! If I specifically blow out the C.Link command, like this:

actions response C.Link
{
    "$(C.LINK)" $(LINKFLAGS) -o $(<[1]:C) -Wl,-filelist,@($(2:TC)) $(NEEDLIBS:TC) $(LINKLIBS:TC))
}

in my jamfile, I get the command line I need that passes through to the linker, but the response file isn't newline terminated, so link fails (osx ld requires newline-separated entries).

  1. Is there a way to expand a jamplus list joined with newlines? I've tried using the join expansion $(LIST:TCJ=\n) without luck. $(LIST:TCJ=@(\n)) doesn't work either. If I can do this, the generated file would hopefully be correct.
  2. If not, what jamplus code can I use to override the link command for clang, and generate the contents on the fly from a list? I'm looking for the least invasive way of handling this - ideally, modifying/overriding the tool directly, instead of adding new indirect targets wherever a link is required - since it's our vendor's codebase, as little edit as possible is desired.
Jamie
  • 7,022
  • 4
  • 19
  • 15
Epu
  • 595
  • 7
  • 18

2 Answers2

2

The syntax you are looking for is:

newLine = "
" ;

actions response C.Link
{
    "$(C.LINK)" $(LINKFLAGS) -o $(<[1]:C) -Wl,-filelist,@($(2:TCJ=$(newLine))) $(NEEDLIBS:TC) $(LINKLIBS:TC))
}

To be clear (I'm not sure how StackOverflow will format the above), the newLine variable should be defined by typing:

newLine = "" ;

And then placing the carat between the two quotes and hitting enter. You can use this same technique for certain other characters, i.e.

tab = "    " ;

Again, start with newLine = "" and then place carat between the quotes and hit tab. In the above it is actually 4 spaces which is wrong, but hopefully you get the idea. Another useful one to have is:

dollar = "$" ;

The last one is useful as $ is used to specify variables typically, so having a dollar variable is useful when you actually want to specify a dollar literal. For what it is worth, the Jambase I am using (the one that ships with the JamPlus I am using), has this:

SPACE = " " ;
TAB = " " ;
NEWLINE = "
" ;

Around line 28...

Steven Craft
  • 1,187
  • 10
  • 15
  • I see NEWLINE in my jamplus jambase also. Even though it's been more than a year ago, I'm excited to try this out. – Epu Apr 04 '16 at 21:44
  • I swapped in $(NEWLINE), and I can see the contents of the response file, as printed out by jamplus, are now separated correctly. You're awesome, Steven! This totally killed me. Updating yours to the answer. – Epu Apr 04 '16 at 22:10
0
  1. I gave up on trying to use escaped newlines and other language-specific characters within string joins. Maybe there's an awesome way to do that, that was too thorny to discover.

  2. Use a multi-step shell command with multiple temp files.

For jamplus (and maybe other jam variants), the section of the actions response {} between the curly braces becomes an inline shell script. And the response file syntax @(<value>) returns a filename that can be assigned within the shell script, with the contents set to <value>.

Thus, code like:

actions response C.Link
{
    _RESP1=@($(2:TCJ=#)#$(NEEDLIBS:TCJ=#)#$(LINKLIBS:TCJ=#))
    _RESP2=@()
    perl -pe "s/[#]/\n/g" < $_RESP1 > $_RESP2
    "$(C.LINK)" $(LINKFLAGS) -o $(<[1]:C) -Wl,-filelist,$_RESP2
}

creates a pair of temp files, assigned to shell variable names _RESP1 and _RESP2. File at path _RESP1 is assigned the contents of the expanded sequence joined with a # character. Search and replace is done with a perl one liner into _RESP2. And link proceeds as planned, and jamplus cleans up the intermediate files.

I wasn't able to do this with characters like :;\n, but # worked as long as it had no adjacent whitespace. Not completely satisfied, but moving on.

Epu
  • 595
  • 7
  • 18
  • Yeah, but this affects the C.Link command for all projects when using SubDirs, and it can break the other ones. Would be great to know, how can I apply this to exactly one target. – Epu Jan 23 '15 at 21:47
  • Ah. Adding any empty lists here (only `$2` is guaranteed to be assigned) breaks the entire thing. Rethinking. – Epu Jan 26 '15 at 17:19
  • I ended up replacing this with a temporary inline / heredoc script in the interpreted language of my choice, and invoking that. It wasn't pretty, but it handles all my corner cases now. – Epu Feb 03 '15 at 23:38