Boost logo

Boost-Build :

From: Klaus Nowikow (e8827661_at_[hidden])
Date: 2006-08-03 04:12:03


Some time ago, I started a thread about an XPIDL tool, see
http://article.gmane.org/gmane.comp.lib.boost.build/13076

(For those who do not know XPIDL: its the compiler for the
Interface Description Language created and used by the Mozilla
project -- Cross-Platform IDL)

I now just took Alexey Pakhunov's midl.jam and changed it to
handle xpidl files -- see the attached file xpidl.jam. Feel free
to use or change it or add it to the BBv2 distribution if
you think it's good enough.

There is only one problem: when used with the MSVC toolset it
clashes with midl.jam, because msvc.jam imports midl.jam.
Both midl and xpidl register a new type IDL, and both add a
generator to create other files from an *.idl file. I can't
think of any solution to that besides not importing midl.jam
from msvc.jam. Any ideas?

--
Klaus

# Copyright (c) 2006 Klaus Nowikow.
# Large portions of the code taken from midl.jam, Copyright (c) 2005 Alexey Pakhunov.
#
# Use, modification and distribution is subject to the Boost Software
# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
# http://www.boost.org/LICENSE_1_0.txt)

# Mozilla Cross-Platform Interface Definition Language (XPIDL) related routines,
# using code from midl.jam

import common ;
import generators ;
import feature : feature get-values ;
import os ;
import scanner ;
import toolset : flags ;
import type ;

rule init ( )
{
}

type.register IDL : idl ;
type.register XPTYPELIB : xpt : H ;
type.register JAVA : java ;

# Register scanner for XPIDL files
class xpidl-scanner : scanner
{
    import path property-set regex scanner type virtual-target ;
    
    rule __init__ ( includes * )
    {
        scanner.__init__ ;
    
        self.includes = $(includes) ;

        # List of quoted strings
        self.re-strings = "[ \t]*\"([^\"]*)\"([ \t]*,[ \t]*\"([^\"]*)\")*[ \t]*" ;

        # 'import' and 'importlib' directives
        self.re-import = "import"$(self.re-strings)"[ \t]*;" ;
        self.re-importlib = "importlib[ \t]*[(]"$(self.re-strings)"[)][ \t]*;" ;

        # C preprocessor 'include' directive
        self.re-include-angle = "#[ \t]*include[ \t]*<(.*)>" ;
        self.re-include-quoted = "#[ \t]*include[ \t]*\"(.*)\"" ;
    }

    rule pattern ( )
    {
        # Match '#include', 'import' and 'importlib' directives
        return "((#[ \t]*include|import(lib)?).+(<(.*)>|\"(.*)\").+)" ;
    }

    rule process ( target : matches * : binding )
    {
        local included-angle = [ regex.transform $(matches) : $(self.re-include-angle) : 1 ] ;
        local included-quoted = [ regex.transform $(matches) : $(self.re-include-quoted) : 1 ] ;
        local imported = [ regex.transform $(matches) : $(self.re-import) : 1 3 ] ;
        local imported_tlbs = [ regex.transform $(matches) : $(self.re-importlib) : 1 3 ] ;

        # CONSIDER: the new scoping rule seem to defeat "on target" variables.
        local g = [ on $(target) return $(HDRGRIST) ] ;
        local b = [ NORMALIZE_PATH $(binding:D) ] ;

        # Attach binding of including file to included targets.
        # When target is directly created from virtual target
        # this extra information is unnecessary. But in other
        # cases, it allows to distinguish between two headers of the
        # same name included from different places.
        local g2 = $(g)"#"$(b) ;

        included-angle = $(included-angle:G=$(g)) ;
        included-quoted = $(included-quoted:G=$(g2)) ;
        imported = $(imported:G=$(g2)) ;
        imported_tlbs = $(imported_tlbs:G=$(g2)) ;

        local all = $(included-angle) $(included-quoted) $(imported) ;

        INCLUDES $(target) : $(all) ;
        DEPENDS $(target) : $(imported_tlbs) ;
        NOCARE $(all) $(imported_tlbs) ;
        SEARCH on $(included-angle) = $(self.includes:G=) ;
        SEARCH on $(included-quoted) = $(b) $(self.includes:G=) ;
        SEARCH on $(imported) = $(b) $(self.includes:G=) ;
        SEARCH on $(imported_tlbs) = $(b) $(self.includes:G=) ;
        
        scanner.propagate
            [ type.get-scanner CPP : [ property-set.create $(self.includes) ] ] :
            $(included-angle) $(included-quoted) : $(target) ;

        scanner.propagate $(__name__) : $(imported) : $(target) ;
    }
}

scanner.register xpidl-scanner : include ;
type.set-scanner IDL : xpidl-scanner ;

flags xpidl.compile.idl INCLUDES <include> ;

generators.register-c-compiler xpidl.compile.idl : IDL : XPTYPELIB H JAVA CPP ;

TOUCH_FILE = [ common.file-touch-command ] ;

actions compile.idl
{
    xpidl -m typelib -I$(INCLUDES) -w -e $(<[1]:W) $(>:W)
    xpidl -m header -I$(INCLUDES) -w -e $(<[2]:W) $(>:W)
    xpidl -m java -I$(INCLUDES) -w -e $(<[3]:W) $(>:W)
        $(TOUCH_FILE) $(<[4]:W)
}


Boost-Build list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk