Target OS preprocessor macro

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Target OS preprocessor macro

mareq
I would like to conditionally execute parts of my code, depending on the
target OS. That means, that I need to define preprocessor macro (e.g.
BOOST_BUILD_TARGET_OS_LINUX), based on the value of <target-os> feature.

However, the only way how to do this, which is known to me by now is to
generate header file, containing appropriate #define directive and include
that header file into the sources. This is not very straightforward way, to
say the least.

Therefore, my question: What is the simplest way to add <define> property
into targets' property-set, which value (i.e. name of the preprocessor macro
being defined) is dependent on <target-os> property of the target in
question (e.g. <target-os>linux -> <define>BOOST_BUILD_TARGET_OS_LINUX,
<target-os>windows -> <define>BOOST_BUILD_TARGET_OS_WINDOWS, etc.).

Thanks.



--
View this message in context: http://boost.2283326.n4.nabble.com/Target-OS-preprocessor-macro-tp4635256.html
Sent from the Boost - Build mailing list archive at Nabble.com.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost-build
Reply | Threaded
Open this post in threaded view
|

Re: Target OS preprocessor macro

Vladimir Prus
On 05.09.2012 01:15, mareq wrote:

> I would like to conditionally execute parts of my code, depending on the
> target OS. That means, that I need to define preprocessor macro (e.g.
> BOOST_BUILD_TARGET_OS_LINUX), based on the value of <target-os> feature.
>
> However, the only way how to do this, which is known to me by now is to
> generate header file, containing appropriate #define directive and include
> that header file into the sources. This is not very straightforward way, to
> say the least.
>
> Therefore, my question: What is the simplest way to add <define> property
> into targets' property-set, which value (i.e. name of the preprocessor macro
> being defined) is dependent on <target-os> property of the target in
> question (e.g. <target-os>linux -> <define>BOOST_BUILD_TARGET_OS_LINUX,
> <target-os>windows -> <define>BOOST_BUILD_TARGET_OS_WINDOWS, etc.).

Hi,

the simplest way is to have this in your project requirements:

        <target-os>linux:<define>BOOST_BUILD_TARGET_OS_LINUX
        <target-os>windows:<define>BOOST_BUILD_TARGET_OS_WINDOWS

for every OS you need to support. It is possible to make this generic using indirect requirements:

        import feature ;
        rule add-os-define ( properties * )
         {
                local os = [ feature.get target-os : $(properties) ] ;
                return <define>BOOST_BUILD_TARGET_OS_$(os:U) ;
        }

        exe main : main.cpp : <conditional>@add-os-define ;

Hope this helps,
Volodya

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost-build
Reply | Threaded
Open this post in threaded view
|

Re: Target OS preprocessor macro

mareq
Hi,
thanks, that is exactly what I need (I never used <conditional> feature and I somewhat forgotten about it). There is one more problem, though. This is my implementation:

tools/config.jam:
import feature ;
import feature : feature ;

feature define-prefix : : free ;

rule define-target-os ( properties * )
{
  local define-prefix = [ feature.get-values define-prefix : $(properties) ] ;
  if ! $(define-prefix) {
    define-prefix = "" ;
  }
  local target-os = [ feature.get-values target-os : $(properties) ] ;
  return <define>$(define-prefix)TARGET_OS_$(target-os:U) ;
}

Jamroot:
import tools/config.jam ;

project /root
  : requirements
       <define-prefix>MY_PROJECT_
       <conditional>@tools/config.define-target-os
;

It seems that define-prefix property is just plain ignored (when I echo $(properties) variable inside define-target-os rule, it is not present there and thsu getting its value will return nothing as well). What am I doing incorrectly here?

Thanks for your help,
.mq.
Reply | Threaded
Open this post in threaded view
|

Re: Target OS preprocessor macro

Vladimir Prus
On 05.09.2012 11:14, mareq wrote:

> Hi,
> thanks, that is exactly what I need (I never used <conditional> feature and
> I somewhat forgotten about it). There is one more problem, though. This is
> my implementation:
>
> tools/config.jam:
>
>
> Jamroot:
>
>

The above does not have any content of files, nor there are attachments. Nothing is in source view of
your email either. Maybe, something ate content?

- Volodya

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost-build
Reply | Threaded
Open this post in threaded view
|

Re: Target OS preprocessor macro

mareq
Hi,
interesting, that is probably because I submitted it via Nabble - and embedded code into some tags to format it correctly, which might not work in e-mail (sorry for that, I did not realize it before). You should see that content in source of the (HTML) e-mail, and I am pasting it again here without formatting marks:

tools/config.jam:

import feature ;
import feature : feature ;

feature define-prefix : : free ;

rule define-target-os ( properties * )
{
  local define-prefix = [ feature.get-values define-prefix : $(properties) ] ;
  if ! $(define-prefix) {
    define-prefix = "" ;
  }
  local target-os = [ feature.get-values target-os : $(properties) ] ;
  return <define>$(define-prefix)TARGET_OS_$(target-os:U) ;
}


Jamroot:

import tools/config.jam ;

project /root
  : requirements
       <define-prefix>MY_PROJECT_
       <conditional>@tools/config.define-target-os
;


Thanks,
.mq.
Reply | Threaded
Open this post in threaded view
|

Re: Target OS preprocessor macro

Jurko Gospodnetić-2
   Hi.

   I just tried out your code out now. See comments below.


> import feature ;
> import feature : feature ;

   Stylistic comment: no need really to do 'import feature : feature ;'
here - thats really just an expensive way to shorten the name for the
rule already available as 'feature.feature'.


>    if ! $(define-prefix) {
>      define-prefix = "" ;
>    }

   This whole if construct can be simply be written as:
     'define-prefix ?= "" ;'.


> Jamroot:
>
> import tools/config.jam ;

   This import will not work as written here. You need to remove the
'.jam' suffix here and write it as 'import tool/config' ;'.


> project /root
>    : requirements
>         <define-prefix>MY_PROJECT_
>         <conditional>@tools/config.define-target-os
> ;

   Your Jamroot file does not contain any target definitions so using it
'as is' will not trigger the define-target-os rule.


   On the other hand, after adding a simple target to build in this
Jamroot file, this example shows that free properties are not passed to
indirect conditional rules.

   I do not know if this is intentional or a bug - perhaps someone else
can elaborate on that or you can do some more digging in the Boost Build
repository yourself.

   Code causing this is in the targets.jam module in the
common-properties rule. There all properties except the free ones are
passed on to the common-properties2 rule (which in turn calls
evaluate-requirements, which then calls the specified indirect
conditional rules, all in the same targets.jam module). There is a
comment in the common-properties rule mentioning something about this
being done as some sort of an optimization, so perhaps this is all just
an unfortunate consequence of that (i.e. a fixable bug).

   Hope this helps.

   Best regards,
     Jurko Gospodnetić


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost-build
Reply | Threaded
Open this post in threaded view
|

Re: Target OS preprocessor macro

mareq
Hi,

> > import feature ;
> > import feature : feature ;
>
>    Stylistic comment: no need really to do 'import feature : feature ;'
> here - thats really just an expensive way to shorten the name for the
> rule already available as 'feature.feature'.

Thanks, I was myself looking at it, thinking that it seems kind of strange, but I did not give it too much thought since it seems to work - calling feature.feature instead of importing feature : feature looks more natural indeed.

> >    if ! $(define-prefix) {
> >      define-prefix = "" ;
> >    }
>
>    This whole if construct can be simply be written as:
>      'define-prefix ?= "" ;'.

Good point as well.

>    On the other hand, after adding a simple target to build in this
> Jamroot file, this example shows that free properties are not passed to
> indirect conditional rules.
>
>    I do not know if this is intentional or a bug - perhaps someone else
> can elaborate on that or you can do some more digging in the Boost Build
> repository yourself.
>
>    Code causing this is in the targets.jam module in the
> common-properties rule. There all properties except the free ones are
> passed on to the common-properties2 rule (which in turn calls
> evaluate-requirements, which then calls the specified indirect
> conditional rules, all in the same targets.jam module). There is a
> comment in the common-properties rule mentioning something about this
> being done as some sort of an optimization, so perhaps this is all just
> an unfortunate consequence of that (i.e. a fixable bug).

Thank you for this pointer. I was looking into repository and the common-properties rule was added long long time ago (22. March 2004) in revision 22542 by vladimir_prus. Comment for the revision is "Improve the algorithm for computing build properties.". The only change (except comments and blanks) since then was on last line which now says return [ $($(key)).add-raw $(free) ] ; instead of result = [ ... ] ; However, this change is not present in version 1.49, which I am using and it does not seem to affect this behavior in any way (I tried to edit the file manually and the result is exactly the same - I do not recall really, I am no bjam expert, but isn't effect of those two commands exactly the same and therefore the change is only stylistic one?).

I will try to investigate the issue further, tomorrow, but anyway, any additional comments and/or advice would be much appreciated.

Thanks for help.
.mq.
Reply | Threaded
Open this post in threaded view
|

Re: Target OS preprocessor macro

mareq
After further investigation, it seems to be a bug. I created a ticket for it: https://svn.boost.org/trac/boost/ticket/7344

The question now is, whether it will be accepted and fixed - if it will be, I can patch my Boost.Build installation and live with my own patch until the problem is fixed in official release. However, if it will not be fixed for some reason, I need to find some reasonable workaround for the problem (obviously, I do not want to end up with patched version forever, since it is straight way to maintenance hell). Which of those two it will be?

.mq.
Reply | Threaded
Open this post in threaded view
|

Re: Target OS preprocessor macro

Jurko Gospodnetić-2
   Hi.

> After further investigation, it seems to be a bug. I created a ticket for it:
> https://svn.boost.org/trac/boost/ticket/7344
>
> The question now is, whether it will be accepted and fixed - if it will be,
> I can patch my Boost.Build installation and live with my own patch until the
> problem is fixed in official release. However, if it will not be fixed for
> some reason, I need to find some reasonable workaround for the problem
> (obviously, I do not want to end up with patched version forever, since it
> is straight way to maintenance hell). Which of those two it will be?

   I do believe this to be a bug, but I like for someone else (Volodya?
Steven?) to comment before actually working on the fix as neither of us
is well versed is this part of Boost Build's design and we could be
missing something here...

   And if it is a bug, and it bugs someone (which it obviously does ;-))
- it will get fixed. :-)

   Best regards,
     Jurko Gospodnetić


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost-build
Reply | Threaded
Open this post in threaded view
|

Re: Target OS preprocessor macro

Vladimir Prus
On 13.09.2012 10:41, Jurko Gospodnetić wrote:

>    Hi.
>
>> After further investigation, it seems to be a bug. I created a ticket for it:
>> https://svn.boost.org/trac/boost/ticket/7344
>>
>> The question now is, whether it will be accepted and fixed - if it will be,
>> I can patch my Boost.Build installation and live with my own patch until the
>> problem is fixed in official release. However, if it will not be fixed for
>> some reason, I need to find some reasonable workaround for the problem
>> (obviously, I do not want to end up with patched version forever, since it
>> is straight way to maintenance hell). Which of those two it will be?
>
>    I do believe this to be a bug, but I like for someone else (Volodya? Steven?) to comment before actually working on the fix as neither of
> us is well versed is this part of Boost Build's design and we could be missing something here...
>
>    And if it is a bug, and it bugs someone (which it obviously does ;-)) - it will get fixed. :-)

I would be scared to make this change ;-)

The key problem with the existing algorithm for computing properties is that:

- The 'default' mechanism for feature is not quite good -- i.e. if you have one compiler that is
   gcc for linux and another that is msvc for windows, then no set of default values for <toolset> and
   <target-os> will express the logic to pick one of those
- There's no way to have non-free features in usage requirements

Fixing that might involve different strategies, including setting some kind of hierarchy of properties
so that low-ranked properties can only be derived from higher-ranked properties. Allowing free features
to affect anything would make this approach impossible.

I suppose in this case we better solve the bigger problem first.

- Volodya

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost-build