######################################################################## # 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;