########################################################################
# 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
our @RCC; # List of compiled resource files
#
# 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
# There are two processing options
# Default : Proccess into a .cpp file
# and then compiled into a .obj file
# --Binary : Process directly into a .rcc file
# These are loaded at runtime by the QT application
# Also made available via the global @RCC varaible to assist packaging
#
# 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 = ();
my $csource;
my $buildDirName;
my $isBinary = ($SRC_ARGS{ $path } && grep (/^--Binary$/i, split( /$;/, $SRC_ARGS{$path} ) ) ) ? 1 : 0;
#
# The .qrc file will be converted into a cpp file
# Treat the .cpp file as a source file in its own right
#
if ($isBinary)
{
#
# Binary resource
# Treat it a bit like a program
# Put its name into an @RCC array to simplify packaging
# Tag it as a source file so that it can be packaged
my $oName = $obj . '.rcc';
$csource = '$(BINDIR)/' . $oName;
$buildDirName = '$(GBE_BINDIR)';
ToolsetGenerate($csource);
push @RCC, $oName;
Src ('*', $csource);
} else {
#
# Compiled resource
# Convert to a .cpp, which will then be made available
# Give the object a different name incase the user has a resource file and a
# program file of the same name.
#
$obj = 'qrc_' . $obj;
$csource = '$(OBJDIR)/' . $obj . '.cpp';
$buildDirName = '$(GBE_OBJDIR)';
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:
# FileName
#
# 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 ( )
{
if ( m~(.*)~ )
{
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)', $buildDirName );
if ($isBinary) {
$me->AddRecipe ( '$(XX_PRE)$(QT_RCCBIN)' );
} else {
$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;