Using the install rule with a pre-built library

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Using the install rule with a pre-built library

Peter Fry
Hi everyone,

I'm trying to build an executable project on RedHat EL6, using an install rule to deploy it's executable to an artefacts directory. Since it requires another project's shared library to execute, I would also like to use an install rule to deploy the pre-built shared library into my project's artefacts folder. In case it's material, I'm using Boost.Build 2011.12-svn.

I've found that if I set-up the pre-built library using the <file> feature, it works as expected. However, when I change to the use <name> and <search>, it doesn't copy the file.

This will (hopefully) make more sense with an example. Here's a cut-down and contrived version, to demonstrate what I'm trying to do.

The pre-built library is configured in /some_source_location/project1/jamroot:

lib MyLib_Works : : <file>some/path/to/libMyLib.so <link>shared;
lib MyLib_Fail : : <name>MyLib <search>some/path/to <link>shared;

The project I'm trying build is defined in /another_source_location/project2/jamroot:

use-project /project1 : /some_source_location/project1 ;
exe MyApp : [ glob *.cpp ] ;
install MyApp-install : MyApp /project1//MyLib_Works : <location>/some/deploy/path ;

This works fine, however if I changed MyLib_Works to MyLib_Fail, it doesn't copy the file.

I presume it's because it's not converted MyLib into the platform specific libMyLib.so?

I would like to use the <name> and <search> version, since I use a <conditional> rule to generate the search path depending upon the variant and address-model. I would also like to have bjam turn the name into a platform-specific one (i.e. libMyLib.so on Linux, MyLib.dll on Windows), rather than hard-code it.

Anyone have any ideas?

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

Re: Using the install rule with a pre-built library

Jurko Gospodnetić-2
   Hi.

> I've found that if I set-up the pre-built library using the <file> feature,
> it works as expected. However, when I change to the use <name> and <search>,
> it doesn't copy the file.

   I was just looking into how to define a prebuilt lib target having a
differently named import & executable library files and ran into this
issue myself. :-)

   The best workaround I've found so far, without delving into the Boost
Build sources themselves and making tweaks there, goes something like this:

> local dllFolder = "D:/Libraries/WxWidgets/wxWidgets-2.9.4/lib/vc_dll_staticRTL_unicode_PKE_msvc-9.0" ;
> lib test-dll : : <link>shared <file>$(dllFolder)/wxbase294ud_vc_PKE.dll ;
> lib test : :
>     <link>shared:<dependency>test-dll
>     <name>wxbase29ud
>     <search>$(dllFolder) ;
> install oklahoma : test : <install-dependencies>on <location>BBB ;

   This defines a prebuilt library target test which, on Windows, gets
resolved to import library wxbase29ud.lib and wxbase294ud_vc_PKE.dll
DLL. It installs the library file correctly - DLL when asked to use the
library as a DLL, and nothing when asked to use it as a static library.

   It also correctly links in the import library when you create an exe
from the test target with link=shared.

   Not quite happy with the solution so I'm going to dig some more, but
it does get the ball rolling. :-)

   Problems with this solution:
     - when you say you want to install the prebuilt library you also
need to explicitly tell the install rule to install the related
dependencies or it will not collect the DLL file.
     - you need to spell out the target folder & file location in
multiple places (can be remedied by using indirect conditional rules
though and thus having the values calculated in a single location)

   If anyone has any better suggestions, I'd be glad to hear them...

   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: Using the install rule with a pre-built library

Peter Fry
I ended up solving my problem by generating the <file> feature using a rule, which borrows the same bjam utilities that are used to generate platform-specific library names. It's not pretty, but it got me there.

In case it helps anyone else, here's an example of how to expose a pre-built library, which you can both link to, and also deploy using an install rule:

import property-set ;
import type ;

# This rule generates the fully qualified path based upon the address model and variant
rule MYLIB_FILE ( properties * )
{
    local my_props = [ property-set.create $(properties) ] ;
    local prefix = [ type.generated-target-prefix SHARED_LIB : $(my_props) ] ;
    local name = MyLib ;
    local suffix = [ type.generated-target-suffix SHARED_LIB : $(my_props) ] ;
    
    local result = <file>some/path/to/ ;
        
    if <address-model>32 in $(properties)
    {
        result = $(result)/x86 ;
    }
    else if <address-model>64 in $(properties)
    {
        result = $(result)/x64 ;
    }
    
    if <variant>debug in $(properties)
    {
        result = $(result)/debug ;
    }
    else if <variant>release in $(properties)
    {
        result = $(result)/release ;
    }
    result = $(result)/$(prefix)$(name).$(suffix) ;
    return $(result) ;
}

lib MyLib : : <conditional>@MYLIB_FILE <link>shared ;

Obviously it can be tweaked to generate a different filename, depending upon the address model and variant, instead of a path.
Reply | Threaded
Open this post in threaded view
|

Re: Using the install rule with a pre-built library

Jurko Gospodnetić-2
   Hi.

> I ended up solving my problem by generating the <file> feature using a rule,
> which borrows the same bjam utilities that are used to generate
> platform-specific library names. It's not pretty, but it got me there.

   Are you sure your solution works correctly when you attempt to build
an exe using your target as a source? Does it link to the correct import
library? I remember it did not when I tried setting the <file> rule
directly...

   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: Using the install rule with a pre-built library

Jurko Gospodnetić-2
   Hi.

>> I ended up solving my problem by generating the <file> feature using a
>> rule,
>> which borrows the same bjam utilities that are used to generate
>> platform-specific library names. It's not pretty, but it got me there.
>
>    Are you sure your solution works correctly when you attempt to build
> an exe using your target as a source? Does it link to the correct import
> library? I remember it did not when I tried setting the <file> rule
> directly...

   Ok, research results so far...

   Your code, as posted, will do the wrong thing here:

> exe aaa : aaa.cpp MyLib : <link>shared ;

   and will not link the aaa.exe to MyLib's import library


   My solution can be improved a bit like this, to get the same
end-results as before, but with only one target:

> rule wxWidgets-lib ( name : dllFolder : libName : dllName )
> {
>     lib $(name) : :
>         <link>shared:<file>$(dllFolder)/$(dllName).dll
>         <link>shared:<file>$(dllFolder)/$(libName).lib
>         <name>$(libName) <search>$(dllFolder) ;
> }
> local dllFolder = "D:/Libraries/WxWidgets/wxWidgets-2.9.4/lib/vc_dll_staticRTL_unicode_PKE_msvc-9.0" ;
> wxWidgets-lib test : $(dllFolder) : wxbase29ud : wxbase294ud_vc_PKE ;

   You can improve the lib/dll prefix/suffix generation code using an
indirect conditional property, of course.

   This gets the following effects:
     - when linking to an exe with <link>static - links with the static
library $(dllFolder)/$(libName).lib.
     - when linking to an exe with <link>shared - links with the static
import libarary $(dllFolder)/$(libName).lib (can easily be modified to
use differently named regular static library and import library, but I
did not require this)
     - when installing an exe with this lib listed as a source using
<link>static - no lib files get installed, independent of any additional
install properties.
     - when installing an exe with this lib listed as a source using
<link>shared, and you tell it <install-dependencies>on - you will get
both the DLL file & the import library installed, but you can control
this by setting <install-type> properties, e.g. list SHARED_LIB and not
LIB - to get only the DLL file installed, and not the import library.

   Still messy, but getting better...

   I believe the whole mess stems from the fact that it is not clear
what it means to 'install a prebuilt library'. :-) If it is a static
library - it might mean 'do nothing' (since the library has supposedly
been used when compiling some product) or it might mean 'copy'. If it is
a shared library - things get even more complicated as it might mean: do
nothing, copy the import library, copy the DLL file or copy both the
import library and the DLL file.

   The current install rule explicitly skips SEARCHED_LIB targets (the
ones you get when you use the lib rule without <file> property and with
either a <name> or <search> property specified) when choosing what
dependencies to select. It does install STATIC_LIB targets though.

   The current Boost Build implementation most likely grew out of the
standard Linux-style file system organization where using
application-private shared libraries stored in some application specific
folder is not the norm and instead, all libraries get installed in some
central location like /usr/local/lib that is always automatically added
to the library search path. Then there is never any need to install
prebuilt libraries as they are always expected to have already been
installed into those folders by their build or installation system.

   It could be redesigned and implemented a bit differently, but someone
would need to step up for that and lead a design discussion, prepare a
working prototype, defend the design, deal with all the 'you idiot! you
broke XYZ!' flames :-P, deal with any backward compatibility issues,
especially those related to building existing Boost libraries, and then
get the whole thing committed... :-)

   For me, the current workaround seems good enough for now. I can
package it up locally as a well commented implementation detail, add a
few tests for it, and it allows me to automatically install prebuilt DLL
targets if I want to and still easily switch between using static or
shared libraries in our products.

   Hope this helps.

   Best regards,
     Jurko Gospodnetić

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