warkda rrior | 2 Dec 2008 03:14
Picon

Compiling the same file with different flags for different targets

Hi,

I would like to create one Jamfile, which has two targets that share one
source file. This source file must be compiled with different compiler
flags depending on the target.

Basically, I'd like to have a Jamfile as follows:

----
CC = gcc ;
LINK = gcc ;

Main test1 : test1.c lib.c ;

Main libtest.so : lib.c ;
   CCFLAGS on lib.o = -fPIC ;
   LINKFLAGS on libtest.so = -shared ;

Main test2 : test2.c ;
   LINKFLAGS on test2 = -Xlinker -rpath -Xlinker . -L . -l test ;
----

such that the file lib.c is compiled with the option "-fPIC" when it is
to be linked into the target libtest.so and without that option for the
target test1.

I can certainly do this with two Jamfiles. Is there a way to do this
with one Jamfile? It seems that CCFLAGS is defined once for the whole
file (i.e., setting CCFLAGS multiple times does not matter).

(Continue reading)

Craig Allsop | 5 Dec 2008 01:25
Picon

Re: Compiling the same file with different flags for different targets

OR

SOURCE_GRIST is used to distinguish between different versions of the
same source but different flags/options. LOCATE_TARGET is used to
place the different versions with the same names into different output
directories and avoid conflict.

Just set them in a scope for each Main so that jam knows that there
are two versions of lib.o with different flags. Jam has a rule
ObjectCcFlags for setting flags. You can put it one jamfile if you
desire...

SubDir TOP blah blah blah ;

{
  local SOURCE_GRIST = $(SOURCE_GRIST) static ;
  local LOCATE_TARGET = $(LOCATE_TARGET) static ;
  Main test1 : test1.c lib.c ;
}

{
  local SOURCE_GRIST = $(SOURCE_GRIST) shared ;
  local LOCATE_TARGET = $(LOCATE_TARGET) shared ;
  Main libtest.so : lib.c ;
  ObjectCcFlags lib.c : -fPIC ;
  LINKFLAGS on libtest.so = -shared ;
}

Next you'll want debug and release configurations too, it's all more
of the same really. Stick it all in a loop and call it for every
(Continue reading)

Diane Holt | 5 Dec 2008 05:56
Picon

Re: Compiling the same file with different flags for different targets

You'd really recommend putting all that in each Jamfile rather than writing a couple of rules and having:

SubDir TOP blah blah blah ;

SharedLib libtest : lib.c ;
Main libtest : lib.c ;

Personally, I prefer not to have the Jamfiles as simple as possible, so they're easier for developers to work with.

As for debug v. release, I handle that sort of thing (along with many others) in config files, and build specific to the selected configuration (ie., the Jamfiles don't deal with any of that -- they're the same for whatever configuration I'm building).

Diane

On Thu, Dec 4, 2008 at 4:25 PM, Craig Allsop <cjamallsop <at> gmail.com> wrote:
OR

SOURCE_GRIST is used to distinguish between different versions of the
same source but different flags/options. LOCATE_TARGET is used to
place the different versions with the same names into different output
directories and avoid conflict.

Just set them in a scope for each Main so that jam knows that there
are two versions of lib.o with different flags. Jam has a rule
ObjectCcFlags for setting flags. You can put it one jamfile if you
desire...

SubDir TOP blah blah blah ;

{
 local SOURCE_GRIST = $(SOURCE_GRIST) static ;
 local LOCATE_TARGET = $(LOCATE_TARGET) static ;
 Main test1 : test1.c lib.c ;
}

{
 local SOURCE_GRIST = $(SOURCE_GRIST) shared ;
 local LOCATE_TARGET = $(LOCATE_TARGET) shared ;
 Main libtest.so : lib.c ;
 ObjectCcFlags lib.c : -fPIC ;
 LINKFLAGS on libtest.so = -shared ;
}

Next you'll want debug and release configurations too, it's all more
of the same really. Stick it all in a loop and call it for every
different combination so you can build all the flavours at the same
time.

Craig.


On Tue, Dec 2, 2008 at 12:14 PM, warkda rrior
_______________________________________________
jamming mailing list  -  jamming <at> perforce.com
http://maillist.perforce.com/mailman/listinfo/jamming

_______________________________________________
jamming mailing list  -  jamming <at> perforce.com
http://maillist.perforce.com/mailman/listinfo/jamming
Craig Allsop | 5 Dec 2008 07:17
Picon

Re: Compiling the same file with different flags for different targets

On Fri, Dec 5, 2008 at 2:56 PM, Diane Holt <holt.diane <at> gmail.com> wrote:
> You'd really recommend putting all that in each Jamfile rather than writing
> a couple of rules and having:

No no, my 'OR' was in relation to making use of jam's SOURCE_GRIST,
LOCATE_TARGET & ObjectCcFlags features, not the expanding of each
configuration in the Jamfile vs your suggestion - I think that's where
the confusion is.

Craig.
_______________________________________________
jamming mailing list  -  jamming <at> perforce.com
http://maillist.perforce.com/mailman/listinfo/jamming

Mihai Christodorescu | 10 Dec 2008 18:44
Picon

Re: Compiling the same file with different flags for different targets


Thank you for all your help. By the time I saw Craig's reply, I had
already cooked up a solution based on Diane's suggestion. Here's what I
ended up doing:

---[ new rules (in Jamrules) ]---
SUFSHLIB = .so ;
SUFSHOBJ = .slo ;

rule SharedLibrary
{
   SharedLibraryFromObjects $(<) : $(>:S=$(SUFSHOBJ)) ;
   SharedObjects $(>) ;
}

rule SharedLibraryFromObjects
{
   local _s _t ;

   # Add grist to file names
   # Add suffix to exe

   _s = [ FGristFiles $(>) ] ;
   _t = [ FAppendSuffix $(<) : $(SUFSHLIB) ] ;

   # so 'jam libfoo' works when it's really libfoo.so

   if $(_t) != $(<)
   {
      Depends $(<) : $(_t) ;
      NotFile $(<) ;
   }

   # make compiled sources a dependency of target
   Depends shared : $(_t) ;
   Depends $(_t) : $(_s) ;
   MakeLocate $(_t) : $(LOCATE_TARGET) ;

   Clean clean : $(_t) ;

   LINKFLAGS on $(_t) = $(CCFLAGS) -shared ;
   Link $(_t) : $(_s) ;
}

rule SharedObjects
{
   local _i ;

   for _i in [ FGristFiles $(<) ]
   {
      CCFLAGS on $(_i:S=$(SUFSHOBJ)) += -fPIC -fvisibility=hidden ;
      Object $(_i:S=$(SUFSHOBJ)) : $(_i) ;
      Depends obj : $(_i:S=$(SUFSHOBJ)) ;
   }
}

rule SharedObjectCcFlags
{
   CCFLAGS on [ FGristFiles $(<:S=$(SUFSHOBJ)) ] += $(>) ;
}

rule InstallSharedLibrary
{
   local _t = [ FAppendSuffix $(>) : $(SUFSHLIB) ] ;
   InstallInto $(<) : $(_t) ;
   MODE on $(_t:G=$(INSTALLGRIST)) = $(EXEMODE) ;
}
---------------------------------

As you can probably tell, they are pretty much blatant ripoffs of the
corresponding Jambase rules without the word "shared" in them.

With these new rules, I can do the following in my Jamfile (based on the
example of my original query):

---------------------------------
CC = gcc ;
LINK = gcc ;

Main test1 : test1.c lib.c ;

SharedObjectCcFlags lib.c : -DIS_LIB ;
SharedLibrary libtest : test1.c lib.c ;

InstallSharedLibrary /some_place_safe/lib : libtest ;

LINKFLAGS on test2$(SUFEXE) = -Xlinker -rpath
                              -Xlinker /some_place_safe/lib
                              -L /some_place_safe/lib -l test ;
Main test2 : test2.c ;
---------------------------------

Regards,

Mihai
_______________________________________________
jamming mailing list  -  jamming <at> maillist.perforce.com
http://maillist.perforce.com/mailman/listinfo/jamming

Craig Allsop | 11 Dec 2008 05:07
Picon

Re: Compiling the same file with different flags for different targets

Nice work.

Small mistake here, you don't want CCFLAGS on LINKFLAGS:

LINKFLAGS on $(_t) = $(CCFLAGS) -shared ;

My view on all this is that you didn't need to duplicate the source,
another way to skin the cat is to wrap them and use the power of
'local' to push your changes....

rule SharedLibrary
{
  local SUFOBJ = .slo ;
  SharedLibraryFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
  Objects $(>) ;
}

rule SharedLibraryFromObjects
{
  local SUFEXE = .so ;
  MainFromObjects $(<) : $(>) ;
  LINKFLAGS on $(_t) += -shared ;
}

rule SharedObjects
{
  local SUFOBJ = .slo ;
  Objects $(<) ;
  SharedObjectCcFlags $(<) : -fPIC -fvisibility=hidden ;
}

Then once you get your head around that, you can push a whole stack of
variables in one statement with jam's built in 'on' syntax. i.e. you
setup everything beforehand like:

SUFOBJ on shared = .slo ;
SUFEXE on shared = .so ;
CCFLAGS on shared =  -fPIC -fvisibility=hidden ;

Then when you need these just call the 'on' command...

rule SharedObjects
{
   on shared
   {
      # in this scope everything set on shared-config is imported
      Objects $(<) ;

      # this is now done by the original Objects so don't need it...
      #ObjectCcFlags $(<) : -fPIC -fvisibility=hidden ;
   }

   # here everything is back to the way it was
}

So now you've seen what you can do above, you don't need to make any
Shared* rules at all. So instead of...

Main test1 : test1.c lib.c ;
SharedObjectCcFlags lib.c : -DIS_LIB ;
SharedLibrary libtest : test1.c lib.c ;
InstallSharedLibrary /some_place_safe/lib : libtest ;

... after the 3 setup definitions above just use the same normal rules
and your jamfile becomes...

Main test1 : test1.c lib.c ;

on shared
{
  ObjectCcFlags lib.c : -DIS_LIB ;
  Main libtest : test1.c lib.c ;
  InstallBin /some_place_safe/lib : libtest ;
}

Now think about this...

types = static shared ;
flavour = release debug ;

for config in $(types)!$(flavour)
{
  on $(config)
  {
    Main libtest : test1.c lib.c ;
  }
}

Or make a rule to encapsulate the loop....

rule On configs
{
  local config ;
  for config in $(configs)
  {
    on $(config) $(>[1]) $(>[2-]) : $(3) ;
  }
}

Now your jamfile might look like this...

allcfgs = $(types)!$(flavour) ; # put in jamrules

On $(allcfgs) Main test : test1.c lib.c ;
On shared!$(flavour) ObjectCcFlags lib.c : -DIS_LIB ;
On $(types)!debug ObjectCcFlags lib.c : -D_DEBUG ;
On $(types)!release ObjectCcFlags lib.c : -DNDEBUG ;

Our version of On uses a friendly syntax with slashes for example:

"pc/xb release/debug" would expand to: pc!release pc!debug xb!release xb!debug

If you want different suffix on your outputs, replace just
FAppendSuffix, e.g. it might add _xr for xbox release or _pd for pc
debug, etc. again based on some variable you set for that
configuration combination.

I could go on but where shall I stop? The point is that the standard
set of rules are quite capable of doing much more than I think people
perceive them to.

Craig.

On Thu, Dec 11, 2008 at 3:44 AM, Mihai Christodorescu
<announcements.for.warkdarrior <at> gmail.com> wrote:
>
> Thank you for all your help. By the time I saw Craig's reply, I had
> already cooked up a solution based on Diane's suggestion. Here's what I
> ended up doing:
>
_______________________________________________
jamming mailing list  -  jamming <at> maillist.perforce.com
http://maillist.perforce.com/mailman/listinfo/jamming

Diane Holt | 5 Dec 2008 05:57
Picon

Re: Compiling the same file with different flags for different targets

> Personally, I prefer not to have the Jamfiles as simple as possible...

Of course, I meant "to have", not "not to have" :P

Diane

_______________________________________________
jamming mailing list  -  jamming <at> perforce.com
http://maillist.perforce.com/mailman/listinfo/jamming
Craig Allsop | 5 Dec 2008 07:08
Picon

Re: Compiling the same file with different flags for different targets

Hi.

I just wanted to give the person the exact details needed to make it
work because it's not always clear to someone when you say write a
rule, but they may not understand the inner jam workings so don't
really know what they should put in that rule.

I do agree with you that a rule to simplify the jamfile is worthwhile.
We, like you, also have all our configurations in one place and we
generally only need one "Main" per jamfile too.

:)
Craig.

On Fri, Dec 5, 2008 at 2:57 PM, Diane Holt <holt.diane <at> gmail.com> wrote:
>> Personally, I prefer not to have the Jamfiles as simple as possible...
>
> Of course, I meant "to have", not "not to have" :P
>
> Diane
>
_______________________________________________
jamming mailing list  -  jamming <at> perforce.com
http://maillist.perforce.com/mailman/listinfo/jamming

Diane Holt | 2 Dec 2008 05:12
Picon

Re: Compiling the same file with different flags for different targets

You should write SharedLibrary and SharedObjects rules, and set your compile and link flags that way. You should also give your shared objects a different suffix, to distinguish them from regular .o's and so you can set your flags on them. (I suppose you could build them out to a different subdir, or grist them differently, but a different suffix seems easier to me.)

Diane

On Mon, Dec 1, 2008 at 6:14 PM, warkda rrior <announcements.for.warkdarrior <at> gmail.com> wrote:
Hi,

I would like to create one Jamfile, which has two targets that share one
source file. This source file must be compiled with different compiler
flags depending on the target.

Basically, I'd like to have a Jamfile as follows:

----
CC = gcc ;
LINK = gcc ;

Main test1 : test1.c lib.c ;

Main libtest.so : lib.c ;
  CCFLAGS on lib.o = -fPIC ;
  LINKFLAGS on libtest.so = -shared ;

Main test2 : test2.c ;
  LINKFLAGS on test2 = -Xlinker -rpath -Xlinker . -L . -l test ;
----

such that the file lib.c is compiled with the option "-fPIC" when it is
to be linked into the target libtest.so and without that option for the
target test1.

I can certainly do this with two Jamfiles. Is there a way to do this
with one Jamfile? It seems that CCFLAGS is defined once for the whole
file (i.e., setting CCFLAGS multiple times does not matter).


Thanks,

Mihai

--
_______________________________________________
jamming mailing list  -  jamming <at> perforce.com
http://maillist.perforce.com/mailman/listinfo/jamming

_______________________________________________
jamming mailing list  -  jamming <at> perforce.com
http://maillist.perforce.com/mailman/listinfo/jamming

Gmane