Rev 369 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#! perl######################################################################### Copyright (C) 2006 ERG Limited, All rights reserved## Module name : jats_buildlinux.pl# Module type : Makefile system# Compiler(s) : n/a# Environment(s): jats## Description : A utility to assist in building Linux Device Driver# This script implemenst the runtime functionality of the# MakeLinuxDriver directive## Usage:##......................................................................#require 5.006_001;use strict;use warnings;use Cwd;use FileUtils;use JatsSystem;use JatsError;use ArrayHashUtils;use File::Path;use File::Copy;use Getopt::Long;use Pod::Usage; # required for help support## Initialise and configure some of the used packages#ErrorConfig( 'name' => 'BuildLinuxDriver' );SystemConfig ( 'ExitOnError' => 1);InitFileUtils();## Global variables#my $VERSION = "1.0.0"; # Update thismy $opt_debug = $ENV{'GBE_DEBUG'}; # Allow global debugmy $opt_verbose = $ENV{'GBE_VERBOSE'}; # Allow global verbosemy $opt_help = 0;my $opt_manual = 0;my $opt_output;my $opt_kernel;my $opt_gcc_path;my $opt_arch;my @opt_source;my $opt_driver;my $opt_leavetmp;my $opt_show_cmds;my $opt_type = 'P';my $opt_platform;my @opt_defs;my @opt_incdirs;## Extract arguments#my $result = GetOptions ("help+" => \$opt_help, # flag, multiple use allowed"manual" => \$opt_manual, # flag, multiple use allowed"verbose+" => \$opt_verbose, # flag, multiple use allowed"Output=s" => \$opt_output,"GccPath=s" => \$opt_gcc_path,"Arch=s" => \$opt_arch,"Driver=s" => \$opt_driver,"LeaveTmp:s" => \$opt_leavetmp,"Verbose:s" => \$opt_show_cmds,"Type=s" => \$opt_type,"Platform=s" => \$opt_platform,"Define=s" => \@opt_defs,"Define=s" => \@opt_defs,"Incdir=s" => \@opt_incdirs,);## Process help and manual options#pod2usage(-verbose => 0, -message => "Version: $VERSION") if ($opt_help == 1 || ! $result);pod2usage(-verbose => 1) if ($opt_help == 2 );pod2usage(-verbose => 2) if ($opt_manual || ($opt_help > 2));#pod2usage(-verbose => 0, -message => "Version: $VERSION") if ( $#ARGV >= 0 );## Sanity Test user input#Error ("No Output File specified") unless ( $opt_output );## Locate the Kernel Headers# This will be provided by one of the external packages# Paths to the packages will be in @opt_incdirs# Look for a dir ectory with a 'Makefile' - use the first one#my $KERNELDIR;foreach ( @opt_incdirs ){my $test_dir = $_ . '/' . $opt_platform;next unless ( -d $test_dir );next unless ( -f $test_dir . '/Makefile' );$KERNELDIR = $test_dir;}Error ("Could not find the Kernel Headers","Need a package that contains include/$opt_platform/Makefile") unless ( $KERNELDIR );## Calculate required bits# The generated file. Based on the name of the desired output file and the# source path.#my $gen_file = StripDir($opt_output);## Cross-compiler toolchain root# Based on GccPath, remove the gcc bit#my $CROSS_COMPILE = $opt_gcc_path;$CROSS_COMPILE =~ s~-gcc$~-~;## The required architecture#my $ARCH;$ARCH = 'arm' if ( $opt_arch =~ m/arm/i );$ARCH = 'i386' if ( $opt_arch =~ m/i386/i );$ARCH = 'powerpc' if ( $opt_arch =~ m/powerpc/i );Error ("Cannot determine architecture") unless ( $ARCH );## Source files# These may be comma seperated. Expand the array#@opt_source = @ARGV;Error ("No source files specified" ) unless ( @opt_source );## Must have a nice name for the driver#Error ("No driver name specified") unless ( $opt_driver );Message "======================================================================";Message "Build Linux Device Driver using the native build method";Message " Driver : $opt_driver";Message " Arch : $ARCH";Message " Type : $opt_type";Message " Output : $opt_output";Message " Platform : $opt_platform";Message " Cross Compiler : $CROSS_COMPILE";Message " Kernel Headers : $KERNELDIR";Message " Source : @opt_source";foreach ( @opt_defs ){Message " Define : $_";}foreach ( @opt_incdirs ){Message " Incdir : $_";}Message "======================================================================";## Convert the list of source files into object files# Needed for cleaning#my @obj_files = map { $_ =~ s~\.\w+$~.o~; $_ } @opt_source;## Clean any existing build artifacts# The build options to place things in a different diractory are broken.# We must be able to build for multiple targets without confusion so we# clean, then build, then copy out the bits we need.clean();## Generate a Makefile for use by the driver Builder# This encapsulates the complete driver build mechanism#create_makefile();## Remove some 'make' environment variables# The JATS make and the PACKAGE make must not know about each other#foreach my $var (qw ( MAKE MAKEFLAGS MAKEOVERRIDES MAKELEVEL MAKE_MODECC CXX CPP EXTRA_CFLAGS CFLAGS ASFLAGS LDFLAGSDEBFLAGS LDDINC DEBUG KERNELRELEASE LDDINC)){delete $ENV{$var};}## Build up the make command# Create an array of arguments - Don't need to escape funny bits#my @make_args = ();push @make_args, "ARCH=$ARCH";push @make_args, "CROSS_COMPILE=$CROSS_COMPILE";push @make_args, "KERNELDIR=$KERNELDIR";push @make_args, "-f", "Kbuild";push @make_args, "V=1" unless ( $opt_show_cmds );System ( 'make', @make_args );Error ("Generated output module file not found: $gen_file") unless ( -f $gen_file );copy ( $gen_file, $opt_output ) || Error ("Cannot copy output file: $opt_output");clean() unless $opt_leavetmp;Message "Script complete";exit 0;#-------------------------------------------------------------------------------# Function : create_makefile## Description : Generate a makefile called Kbuild# This will be used by the kernel builder to do the hard work## The makefile is created via a template embedded in this file## Inputs : None## Returns : Creates a file called Kbuild#sub create_makefile{## Create variables for the data that will be substituted#my $driver_line = "obj-m := $opt_driver.o";my $file_list = "${opt_driver}-objs := @obj_files";my $debug_line = "DEBUG = y";$debug_line = "# " . $debug_line unless ( $opt_type eq 'D' );my $filename = "Kbuild";unlink ($filename);open (KBUILD, ">", $filename ) || Error ("Cannot generate file: $filename");while ( <DATA> ){$_ =~ s~\s+$~~;## Replace the entire line#$_ = $debug_line if ( m~__DEBUG_LINE__~ );$_ = $driver_line if ( m~__DEVICE_NAME__~ );$_ = $file_list if ( m~__FILE_LIST__~ );last if ( m~__END__~ );if ( m~__DEFINES__~ ){print KBUILD "# User definitions\n";foreach my $line ( @opt_defs ){print KBUILD "EXTRA_CFLAGS += -D$line\n";}print KBUILD "# End of User definitions\n";next;}if ( m~__INCDIR__~ ){print KBUILD "# Search Include Directories\n";foreach my $line ( @opt_incdirs ){if ( ! -d $line ){Verbose("Incdir does not exist: $line");next;}if ( $line =~ m~^/~ ){print KBUILD "EXTRA_CFLAGS += -I$line\n";}else{print KBUILD "EXTRA_CFLAGS += -I\$(PWD)/$line\n";}}print KBUILD "# End of User Include Directories\n";next;}print KBUILD "$_\n";}close (KBUILD);}#-------------------------------------------------------------------------------# Function : clean## Description : Clean up build artifacts# Need to remove stuff that we build as the the kernel builder# doesn't handle multiple platforms## Inputs : Globals: @obj_files## Returns : Nothing#sub clean{foreach my $files (qw (*.o *~ core .depend .*.cmd *.ko *.mod.c Kbuild ), @obj_files ){unlink ( glob ( $files ));}rmtree ( '.tmp_versions' );}__DATA__## This is a generated file# Do not edit or check into version control################################################################################# Comment/uncomment the following line to disable/enable debuggingDEBUG = y __DEBUG_LINE____DEFINES____INCDIR__# Add your debugging flag (or not) to EXTRA_CFLAGSifeq ($(DEBUG),y)DEBFLAGS = -O -g -DDEV_DEBUG # "-O" is needed to expand inlineselseDEBFLAGS = -O2endifEXTRA_CFLAGS += $(DEBFLAGS)EXTRA_CFLAGS += -I$(LDDINC)ifneq ($(KERNELRELEASE),)# call from kernel build systemllcd-objs := __FILE_LIST__obj-m := __DEVICE_NAME__elseKERNELDIR ?= "-- Must be defined by calling makefile"PWD := $(shell pwd)modules:$(MAKE) -C $(KERNELDIR) M=$(PWD) LDDINC=$(PWD)/../include modulesendifdepend .depend dep:$(CC) $(EXTRA_CFLAGS) -M *.c > .dependifeq (.depend,$(wildcard .depend))include .dependendif__END__#-------------------------------------------------------------------------------# Documentation#=pod=for htmltoc MAKEUTIL::=head1 NAMEjats_buildlinux - Build a Linux Device Driver=head1 SYNOPSISperl jats_buildlinux [options] source_files+Options:-help - brief help message-help -help - Detailed help message-man - Full documentation-Output=path - Path to the output file-Kernel=path - Path to the Kernel Headers-GccPath=path - Path to the gcc compiler to use-Arch=name - Architecture name-Driver=name - Base name of the driver to build-LeaveTmp=num - Leave tmp files after build-Verbose=num - Verbose command output-Type=[P|D] - Type of build-Platform=name - Target Platform-Define=text - Definitions to pass to compiler-Incdir=path - Extend the header file search path=head1 OPTIONS=over 8=item B<-help>Print a brief help message and exits.=item B<-help -help>Print a detailed help message with an explanation for each option.=item B<-man>Prints the manual page and exits.=back=head1 DESCRIPTIONThis program is used internally by Jats to implement the body of the MakeLinuxDriverdirective. The command is not intended to be called by the user.=head1 EXAMPLEMakeLinuxDriver ('*', 'llcd.ko','--KernelPackage=linux_kernel_headers', @CSRCS );=cut