Subversion Repositories DevTools

Rev

Rev 1150 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

########################################################################
# Copyright (C) 1998-2012 Vix Technology, All rights reserved
#
# Module name   : qt-builder.pm
# Module type   : Makefile system
# Compiler(s)   : Perl
# Environment(s): jats
#
# Description   : Provide JATS build support for the QT SDK
#                 This module hooks into the internals of JATS
#                 It tries to be generic, buts its not easy
#
#......................................................................#

require 5.008_002;
use strict;
use warnings;
use MakeEntry;

#
#   Global Varibales
#
our %SRC_DEPEND;                        # Source file dependencies
our %SRC_ARGS;                          # Source file arguments

#
#   Local variables
#
my $qt_package;                         # Ref to package containing QT
my %qt_used;                            # Track Used items
my @moc_defs;                           # Defines for MOC

#-------------------------------------------------------------------------------
# Function        : BEGIN
#
# Description     : Setup directive hooks
#                   Register to be told about source files that are QT specific
#
# Inputs          : None
#
# Returns         : None
#
BEGIN
{
    #
    #   Locate the QT package
    #   Done by looking for the include/QtGui directory
    #       If we don't find it then don't install the Qt hooks
    #       Generate a warning when Qt is 'Used'
    #       This allows for the building of packages that have Qt and Non-Qt parts
    #
    foreach my $entry ( getPackageList() )
    {
        foreach my $path ( $entry->getIncDirs(1) )
        {
            if ( -d "$path/QtGui" )
            {
                $qt_package = $entry;
                last;
            }
        }
    }

    #
    #   Qt not supported in this type of a build
    #   Just exist now. Will create an error if QtUses is activated
    #
    return
        unless ( $qt_package );


    #
    #   Define QT specfic rules.
    #   Will be found in the same directory as this file
    #
    Rules ( StripFileExt( __FILE__ ), 'qt.rul' );

    #
    #   Register interest in various types of source file
    #   Currently only header files are examined for MOC processing
    #
    RegisterSrcHook ('.qrc', \&src_hook_qrc );
    RegisterSrcHook ('.ui',  \&src_hook_ui );
    RegisterSrcHook ('.h',   \&src_hook_h );
    RegisterSrcHook ('.cpp', \&src_hook_cpp );
    RegisterSrcHook ('.ts',  \&src_hook_ts );

    # Register a function to be called just before we start to
    # generate makefiles. This will be used to process the data
    #
    RegisterMakefileGenerate (\&qtBuilder_Generate);

    #
    #   Files will be placed into the OBJDIR
    #   Ensure that the compiler searches this directory
    #
    AddIncDir( '*' , "\$(OBJDIR)", '--NoWarn' );
}

#-------------------------------------------------------------------------------
# Function        : QtUses
#
# Description     : User directive to provide information as to which parts of
#                   Qt are being used.
#
#                   Done this way for two reasons:
#                       1) Allow the Include path to be extended
#                          Qt has a lot of subdirs in 'include'
#                          Placing all of these in the include path
#                          slows down the compilation
#
#                       2) Allow JATS to provide a '--Uses' construct for
#                          programs and shared libraries taht provide a machine
#                          independent mechanism for adding the required libs
#
# Inputs          : $platforms          - Platform predicate
#                   @components         - Compoents to use
#
# Returns         : 
#
sub QtUses
{
    my ($platforms, @components) = @_;
    Debug( "QtUses: ",$platforms, @components );
    return if ( ! ActivePlatform($platforms) );

    Error ("Cannot find the Qt Base Package, or Qt is not supported", "on this platform") unless ( $qt_package );
    
    foreach my $component ( @components )
    {
        #
        #   Only do it once
        #
        next if ( exists $qt_used{$component} );
        $qt_used{$component} = 1;

        #
        #   Extend the header search path to include the required headers
        #
        my $dir;
        foreach my $path ( $qt_package->getIncDirs(2) )
        {
            if ( -d "$path/$component" )
            {
                $dir = "$path/$component";
                last;
            }
        }
        Error ("Qt component not supported: $component")
             unless ( $dir );
        AddIncDir ('*', '--NoWarn','--System', $dir );


################################################################################
#
#   Following code currently not active
#   There is no one-one relationship between QT include dirs and libraries
#
#   Dont know how Trolltech  do it. Might be hard coded
#
################################################################################
#
#        #
#        #   Extend a --Users(QT) definition to provide libraries for the user
#        #   There are problems
#        #       Under windows, some of the libraries have a 4 suffix
#        #   Need to determine the exact name of the library
#        #   Normally this knowledge is buried within the compiler/linker and
#        #   some JATS tools.
#        #
#        #   Algorithm:
#        #       Given a library name, determine if the file exists
#        #       under both windows and linux
#        #           If Unix - prefix with lib
#        #           If Unix - try shared-lib, static lib suffix
#        #           If Windows - try static lib suffix
#        #
#        my @prefix = ('', 'lib');
#        my @suffix = ($::so, $::a );
#        my $found;
#        HUNT:
#        foreach my $qtsuf ( '4', '' )
#        {
#            foreach my $suffix ( @suffix )
#            {
#                foreach my $prefix ( @prefix )
#                {
#                    my $cname = $prefix . $component . $qtsuf . '.' . $suffix;
#                    foreach my $path ( $qt_package->getLibDirs(2) )
#                    {
#                        if ( -f "$path/$cname" )
#                        {
#                            $found = $component . $qtsuf;
#                            last HUNT;
#                        }
#                    }
#                }
#            }
#        }
#
#        Error ("QT library component not supported: $component")
#            unless ( $found );
#
#        MakeIf::Libaries ( 'QT', '*', "-L$found");
################################################################################
    }
}

#-------------------------------------------------------------------------------
# Function        : AddMocFlags
#
# Description     : Provide a definition to the MOC file genorator AND the
#                   C / C++ compiler
#
# Inputs          : $platforms              - Standard platform args
#                   @defs                   - Flags passed to the Moc
#
# Returns         : Nothing
#
sub AddMocFlags
{
    my ($platforms, @args) = @_;
    Debug( "AddMocFlags: ",$platforms, @args );
    return if ( ! ActivePlatform($platforms) );

    #
    #   Save for later
    #
    push @moc_defs, @args;
}



#-------------------------------------------------------------------------------
# Function        : src_hook_qrc
#
# Description     : This function will be invoked when a .QRC file
#                   is encountered in the Src directive
#
#                   .qrc file are QT resource files
#                   These need to be processed into .cpp file
#                   and the .cpp file needs to be converted into an object file
#
# Inputs          : $path           - Source path
#                   $path           - Source file name
#                   $obj            - Base file name (no dir or ext)
#                   $ext            - Extension
#
# Returns         : 
#
sub src_hook_qrc
{
    Debug ("src_hook_qrc: @_");
    my ( $srcfile ,$path, $obj, $ext ) = @_;
    my @dlist = ();

    #
    #   The .qrc file will be converted into a cpp file
    #   Treat the .cpp file as a source file in its own right
    #
    $obj = 'qrc_' . $obj;
    my $csource = '$(OBJDIR)/' . $obj . '.cpp' ;
    GenerateSrcFile ( 1, $csource  );

    #
    #   The user may have specified some dependencies
    #   Create a list of these to be a part of the generated Rule
    #
    @dlist = split( /$;/, $SRC_DEPEND{$path} )
        if ( exists $SRC_DEPEND{$path} );

    #
    #   Parse the source file and extract dependencies
    #       The file is of a known XML format
    #       Depenedencies are not nested
    #       Implement a simple parser
    #
    #   Look for lines of the form:
    #       <file ....>FileName</file>
    #
    #   The source file may not acually exist. It may be symbolic
    #   If the file doesn't exist, then don't complain.
    #
    if ( -e $srcfile )
    {
        if (open (SF, '<', $srcfile ))
        {
            my $srcdir = StripFileExt( $srcfile );
            $srcdir .= '/' if ( $srcdir );
            while ( <SF> )
            {
                if ( m~<file.*>(.*)</file>~ )
                {
                    my $name = $1;
                    $name =~ s~([ ,])~\\$1~g;
                    push @dlist, "$srcdir$name";
                }
            }
            close SF;
        }
    }

    #
    #   Create a Rule to build this file
    #   Will be placed in the Rules section
    #
    my $var;
    my $me = MakeEntry::New (\$var, $csource );
#    $me->AddComment ("QT Resource Compiler: $path" );
    $me->AddDependancy ( $srcfile );
    $me->AddDependancy ( @dlist );
    $me->AddDependancy ( '$(SCM_MAKEFILE)' );
    $me->AddDependancy ( '$(GBE_OBJDIR)' );
    $me->AddRecipe     ( '$(XX_PRE)$(QT_RCC)' );
    $me->Print();

    ToolsetRule ( $var );
}

#-------------------------------------------------------------------------------
# Function        : src_hook_ui
#
# Description     : This function will be invoked when a .UI file
#                   is encountered in the Src directive
#
#                   .ui file are QT User Interface files
#                   These need to be processed into header files
#                   by the User Interface Compiler
#
# Inputs          : $path           - Source path
#                   $path           - Source file name
#                   $obj            - Base file name (no dir or ext)
#                   $ext            - Extension
#
# Returns         : 
#
sub src_hook_ui
{
    Debug ("src_hook_ui: @_");
    my ( $srcfile ,$path, $obj, $ext ) = @_;

    #
    #   Convert the UI file into a header file
    #   Place the header file in the OBJ directory
    #
    my $target = "\$(OBJDIR)/ui_$obj.h";
    GenerateSrcFile ( 1, $target  );

    #
    #   The user may have specified some dependencies
    #   Create a list of these to be a part of the generated Rule
    #
    my @dlist = split( /$;/, $SRC_DEPEND{$path} )
        if ( exists $SRC_DEPEND{$path} );
    
    #
    #   Create a Rule to build this file
    #   Will be placed in the Rules section
    #
    my $var;
    my $me = MakeEntry::New (\$var, $target );
#    $me->AddComment ("QT User Interface File: $path" );
    $me->AddDependancy ( $srcfile );
    $me->AddDependancy ( @dlist );
    $me->AddDependancy ( '$(SCM_MAKEFILE)' );
    $me->AddDependancy ( '$(GBE_OBJDIR)' );
    $me->AddRecipe     ( '$(XX_PRE)$(QT_UIC)' );
    $me->Print();

    ToolsetRule ( $var );
}

#-------------------------------------------------------------------------------
# Function        : src_hook_h
#
# Description     : This function will be invoked when a .h file
#                   is encountered in the Src directive
#
#                   If the file is flagged as --Moc then it will treated
#                   by the MOC processor
#
# Inputs          : $path           - Source path
#                   $path           - Source file name
#                   $obj            - Base file name (no dir or ext)
#                   $ext            - Extension
#
# Returns         : 
#
sub src_hook_h
{
    Debug ("src_hook_h: @_");
    my ( $srcfile ,$path, $obj, $ext ) = @_;

    #
    #   Only interested in files that are flagged as --Moc
    #
    return unless ( $SRC_ARGS{ $path } && grep (/^--Moc$/i, split( /$;/, $SRC_ARGS{$path} ) ) );

    #
    #   The file will be converted into a cpp file
    #   Treat the .cpp file as a source file in its own right
    #
    $obj = 'moc_' . $obj;
    my $csource = '$(OBJDIR)/' . $obj . '.cpp' ;
    GenerateSrcFile ( 1, $csource  );

    #
    #   The user may have specified some dependencies
    #   Create a list of these to be a part of the generated Rule
    #
    my @dlist = split( /$;/, $SRC_DEPEND{$path} )
        if ( exists $SRC_DEPEND{$path} );
    
    #
    #   Create a Rule to build this file
    #   Will be placed in the Rules section
    #
    my $var;
    my $me = MakeEntry::New (\$var, $csource );
#    $me->AddComment ("QT Meta Object Compiler: $path" );
    $me->AddDependancy ( $srcfile );
    $me->AddDependancy ( @dlist );
    $me->AddDependancy ( '$(SCM_MAKEFILE)' );
    $me->AddDependancy ( '$(GBE_OBJDIR)' );
    $me->AddRecipe     ( '$(XX_PRE)$(QT_MOC)' );
    $me->Print();

    ToolsetRule ( $var );
    
}

#-------------------------------------------------------------------------------
# Function        : src_hook_cpp
#
# Description     : This function will be invoked when a .cpp file
#                   is encountered in the Src directive
#
#                   If the file is flagged as --Moc then it will treated
#                   by the MOC processor
#
# Inputs          : $path           - Source path
#                   $path           - Source file name
#                   $obj            - Base file name (no dir or ext)
#                   $ext            - Extension
#
# Returns         : 
#
sub src_hook_cpp
{
    Debug ("src_hook_cpp: @_");
    my ( $srcfile ,$path, $obj, $ext ) = @_;

    #
    #   Only interested in files that are flagged as --Moc
    #
    return unless ( $SRC_ARGS{ $path } && grep (/^--Moc$/i, split( /$;/, $SRC_ARGS{$path} ) ) );

    #
    #   The file will be converted into a .moc file as shown in the QT doco
    #   Treat the .moc file as a source file in its own right
    #
    my $csource = '$(OBJDIR)/' . $obj . '.moc' ;
    GenerateSrcFile ( 1, $csource  );

    #
    #   The user may have specified some dependencies
    #   Create a list of these to be a part of the generated Rule
    #
    my @dlist = split( /$;/, $SRC_DEPEND{$path} )
        if ( exists $SRC_DEPEND{$path} );
    
    #
    #   Create a Rule to build this file
    #   Will be placed in the Rules section
    #
    my $var;
    my $me = MakeEntry::New (\$var, $csource );
#    $me->AddComment ("QT Meta Object Compiler: $path" );
    $me->AddDependancy ( $srcfile );
    $me->AddDependancy ( @dlist );
    $me->AddDependancy ( '$(SCM_MAKEFILE)' );
    $me->AddDependancy ( '$(GBE_OBJDIR)' );
    $me->AddRecipe     ( '$(XX_PRE)$(QT_MOC)' );
    $me->Print();

    ToolsetRule ( $var );
}

#-------------------------------------------------------------------------------
# Function        : src_hook_ts
#
# Description     : This function will be invoked when a .TS file
#                   is encountered in the Src directive
#
#                   .TS file are QT Translation Source Files
#                   These need to be processed into .qm files
#                   by the lrelease tool
#
# Inputs          : $path           - Source path
#                   $path           - Source file name
#                   $base           - Base file name (no dir or ext)
#                   $ext            - Extension
#
# Returns         : 
#
sub src_hook_ts
{
    Debug ("src_hook_ts: @_");
    my ( $srcfile ,$path, $base, $ext ) = @_;

    #
    #   Convert the TS file into a QM file
    #   Place the QM file in the BIN directory
    #
    my $target = "\$(BINDIR)/${base}.qm";
    GenerateSrcFile ( 1, $target  );

    #
    #   The user may have specified some dependencies
    #   Create a list of these to be a part of the generated Rule
    #
    my @dlist = split( /$;/, $SRC_DEPEND{$path} )
        if ( exists $SRC_DEPEND{$path} );
    
    #
    #   Create a Rule to build this file
    #   Will be placed in the Rules section
    #
    my $var;
    my $me = MakeEntry::New (\$var, $target );
    $me->AddComment ("QT Translation File: $path" );
    $me->AddDependancy ( $srcfile );
    $me->AddDependancy ( @dlist );
    $me->AddDependancy ( '$(SCM_MAKEFILE)' );
    $me->AddDependancy ( '$(GBE_OBJDIR)' );
    $me->AddRecipe     ( '$(XX_PRE)$(QT_TRANSLATE)' );
    $me->Print();

    ToolsetRule ( $var );

    #
    #   Append the generated file to a list
    #
    push( @::QT_PMFILES, "${base}.qm" );
}

#-------------------------------------------------------------------------------
# Function        : qtBuilder_Generate
#
# Description     : Insert definitions into the makefile
#                   Registered function to be called just before we start
#                   creating the makefile
#
# Inputs          : None
#
# Returns         : 
#
sub qtBuilder_Generate
{
    AddCFlags( '*', '--NoWarn', @moc_defs );
    Define ("# Definitions created by the AddMocFlags directive");
    Define ("MOC_FLAGS  =");
    foreach my $flag ( @moc_defs )
    {
        Define ("MOC_FLAGS +=" . $flag);
    }
}

1;