Perl Scripting with DSS

From Texas Instruments Wiki
Jump to: navigation, search

Motivation/Overview

JavaScript is very rich and programmer-friendly, but Perl is probably still the most pervasive scripting language in use today. Giving programmers the ability to use DSS from Perl brings more customers onboard. This can be achieved by using the Perl Inline::Java module.

How does it work?

The perl Inline module has been around for many years. It lets perl developers write/leverage C code from within a perl environment. In the last several years, more language support has been added to the Inline module. Inline::Java was developed in 2001. With this we can access DSS Java classes in perl. A Java compiler is launched and the Java code is compiled. Then Perl asks the Java classes what public methods have been defined. These classes and methods are available to the Perl program as if they had been written in Perl. Is it efficient? Yes, the process of interrogating the Java classes for public methods occurs the first time you run your Java code. The namespace is cached, and subsequent calls use the cached version

Installation

The following are pre-requisites before installation of Inline::Java

Now you can install Inline::Java from CPAN. For more details on installing CPAN modules, see: [[1]]

Note:

  • If you use a proxy server or firewall, you may need to set the http_proxy environment variable (ex: set http_proxy=http://user:passwd@proxy.company.com:8008)
  • You may also need to set the JAVA_HOME environment variable to the install location of the JDK (ex: set JAVA_HOME=C:\Java\jdk1.6.0_45)

Ex: Installing Inline::Java via cpan from the command line with Strawberry Perl (assuming proxy configuration set or not needed):

> cpan
cpan> install Inline::Java

This brings in all the dependent modules (so be patient!)

What about Cygwin? Linux? Unix?

  • Also works fine. In addition, Cygwin JNI support got added in 0.52.

Environment Setup

NOTE: The follow steps below apply for Windows and CCSv6. The steps and paths used will vary with older CCS versions (CCSv4 and v5) and if using Linux.

Additional paths must be added to the PATH and CLASSPATH environment variables.

PATH: The following must be added to the PATH:

  • <INSTALL DIR>\ccsv6\ccs_base\DebugServer\packages\ti\dss\java;%PATH%
  • <INSTALL DIR>\ccsv6\ccs_base\DebugServer\bin;%PATH%
  • <INSTALL DIR>\ccsv6\ccs_base\common\bin;%PATH%
  • <INSTALL DIR>\ccsv6\ccs_base\common\uscif;%PATH%
  • <INSTALL DIR>\ccsv6\eclipse\plugins\com.ti.dvt.ofssymbolmanager_4.0.0;%PATH%
  • <INSTALL DIR>\ccsv6\eclipse\plugins\com.ti.dvt.tidisassembly_4.0.0\os\win32;%PATH%

CLASSPATH: The following needs to be added to CLASSPATH

  • <INSTALL DIR>\ccsv6\DebugServer\packages\ti\dss\java\dss.jar
  • <INSTALL DIR>\ccsv6\dvt\scripting\dvt_scripting.jar

This can be done manually or automated by a batch file. An example batch file (setpath.bat) is provided in the 'perl_inlinejava' example folder (found in '<INSTALL DIR>\ccsv6\ccs_base\scripting\examples\DebugServerExamples\perl_inlinejava'). Simply update the paths for DSS_ROOT and PERL_INLINE_JAVA_J2SDK.

@echo off
REM
REM File: setpath.bat
REM
REM This batch file will set up the environment to run DSS with Perl
REM Inline::Java. Contents of this batch file must be modified to match the
REM user's environment
REM

REM ============================================================================
REM Modify these paths to match the user's environment.

REM Root DSS install location
set DSS_ROOT=C:\ti\ccsv6

REM Root JDK install location
set PERL_INLINE_JAVA_J2SDK=C:\Java\jdk1.6.0_45

REM ============================================================================

REM Set PATH
set PATH=%DSS_ROOT%\ccs_base\DebugServer\packages\ti\dss\java;%PATH%
set PATH=%DSS_ROOT%\ccs_base\DebugServer\bin;%PATH%
set PATH=%DSS_ROOT%\ccs_base\common\bin;%PATH%
set PATH=%DSS_ROOT%\ccs_base\common\uscif;%PATH%
set PATH=%DSS_ROOT%\eclipse\plugins\com.ti.dvt.ofssymbolmanager_4.0.0;%PATH%
set PATH=%DSS_ROOT%\eclipse\plugins\com.ti.dvt.tidisassembly_4.0.0\os\win32;%PATH%

REM Set CLASSPATH
set CLASSPATH=%CLASSPATH%;%DSS_ROOT%\ccs_base\DebugServer\packages\ti\dss\java\dss.jar;%DSS_ROOT%\ccs_base\dvt\scripting\dvt_scripting.jar

Using Inline::Java

To use Inline::Java with DSS:

  • Tell Inline::Java to explicitly ‘STUDY’ main DSS class (ScriptingEnvironment) so we can use it from Perl
  • Turn on AUTOSTUDY which makes Inline::Java automatically study unknown classes as it encounters them
  • Proxy Java's importPackage() by assigning a new namespace TraceLevel to the fully scoped package name so we can then use the shorter namespace $TraceLevel::ALL instead of $DSS_SCRIPTING::com::ti::ccstudio::scripting::environment::TraceLevel::ALL
  • Enable access to the ScriptingEnvironment Java class constructor

For reuse and usability purposes, this functionality has been added to a Perl module (DSS_SCRIPTING.pm) which is provided with DSS (in the 'perl_inlinejava' example folder).

#=============================================================================
# POD Documentation First ...
#=============================================================================
 
=head1 NAME
 
DSS_SCRIPTING.pm
 
=head1 SYNOPSIS
 
Perl module for using Debug Server Scripting. Leverages Inline::Java to
interface with DSS's Java classes
 
=head1 USAGE
 
   use DSS_SCRIPTING;
 
=head1 DESCRIPTION
 
Perl module for using Debug Server Scripting. Leverages Inline::Java to
interface with DSS's Java classes
 
Main purpose is to hide the funky details of 'STUDY' and 'CLASSPATH'
that perl users dont need to know.
 
This module lets perl users leverage the Scripting package to call the core
APIs. In addition we also use config option 'AUTOSTUDY' which brings in all
other DSS Java classes we need to work with.
 
=head1 FUNCTIONS DEFINED
 
Nothing - no 'wrappers' required at present
 
=cut
 
#=============================================================================
# Code starts here ...
#=============================================================================
 
package DSS_SCRIPTING;
 
use strict;
use warnings;
 
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw();
 
#
# Base Java CLASSPATH is set as an environment variable and must have at least
# <myDssdir>/scripting/lib/dss.jar in it
#
 
#
# Bring in the Java classes from DSS that we need.
# AUTOSTUDY helps in not requiring us to list out all classes we need
# individually. For example openSession() returns a DebugSession class
# which Inline::Java automatically 'studies' by virtue of AUTOSTUDY.
#
# Note, however that we *must* (a) STUDY 1 class to guide AUTOSTUDY's
# context (b) explicitly specify the TraceLevel class since we
# explicitly use its member data (ie its context is not returned by
# a TraceLevel() API like the other classes)
#
use Inline  ( Java  => 'STUDY',
             STUDY => ['com.ti.ccstudio.scripting.environment.ScriptingEnvironment',
                       'com.ti.ccstudio.scripting.environment.TraceLevel',
                       'java.lang.System',
                      ],
             AUTOSTUDY => 1,
#             DEBUG => 5,
           );
 
#
# Our perl proxy for Java's importPackage(). We assign a new namespace TraceLevel
# to the fully scoped package name so we can then use the shorter namespace
# $TraceLevel::ALL instead of
# $DSS_SCRIPTING::com::ti::ccstudio::scripting::environment::TraceLevel::ALL
# Internally this creates a TraceLevel symbol table which holds typeglobs
# to each of the class fields.
#
BEGIN {
    %{TraceLevel::} = %{DSS_SCRIPTING::com::ti::ccstudio::scripting::environment::TraceLevel::};
}
 
# enable access to the DebugserverEnvironment Java class constructor
sub new {
    my $class = shift;
    return DSS_SCRIPTING::com::ti::ccstudio::scripting::environment::ScriptingEnvironment->instance();
}
 
1;

Users can add the path to DSS_Scripting.pm to their package path so it can be referenced for anywhere (can add the below to the end of the setpath.bat file).

DSS_Scripting.pm then can be leveraged in the Perl script by:

# import module abstracting the DSS class details
use DSS_SCRIPTING;
 
# call the DSS class constructor(s) we need to create our scripting environment object
my $dss = new DSS_SCRIPTING();

And with the main scripting object, the rest of the DSS APIs are available for use:

# Create a log file to log script execution
$dss->traceBegin("dssScriptLog.xml", "DefaultStylesheet.xsl");
 
# The default timeout is 'infinite'.  Set ours to something shorter, 10s
$dss->setScriptTimeout(10000);
 
# Make the log and console file really verbose
$dss->traceSetConsoleLevel($TraceLevel::INFO);
$dss->traceSetFileLevel($TraceLevel::ALL);
 
# Open a debug session
my $debugServer = $dss->getServer("DebugServer.1");
...

Example

An example perl script (dss_simple.pl) is provided in 'perl_inlinejava' examples folder. The script takes an outfile to run and ccxml setup file as its parameters:

> perl dss_simple.pl ..\..\C64\interpreter\Debug\interpreter.out ..\..\C64\tisim_c64xpcpube.ccxml

Error Handling

  • Inline::Java >= v0.31 lets you catch exceptions in perl as objects when they are thrown from Java, using the regular Perl exception tools: eval and $@.
  • There are many good reasons for using exception handling. One reason might be in running 1000 tests on 1000 different .out files - if one of the .out files is misspelled or passed incorrectly, you might not want to kill the entire script. Instead you might want to catch the exception and simply warn the user indicating which file was problematic.
#
# Load the program from the out file.
# Example of how to handle Java exceptions in perl with Inline::Java
# This is Perl's equivalent of Java try-catch
#
eval { $tgt->{memory}->loadProgram($out_file); };
if ($@) {
     die "$out_file does not exist! $!";
}

Performance

When you use Inline::Java, the Java compiler (javac) is launched and the DSS Java code is compiled. Then Perl asks the Java classes what public methods have been defined. The process of interrogating the Java classes for public methods occurs the first time you run your Java code. The namespace is cached, and subsequent calls use the cached version - bottom line is there's an initial 1-2sec hit but then calls to the methods are near identical to calls from Javascript directly.

  • Inline::Java now also provides a JNI extension that allows you to load the JVM as shared object instead of running it as a separate process

Known Issues

  • If CCS is installed in a path with spaces in it (like "C:\Program Files\Texas Instruments"), there may be an issue running the perl example (dss_simple.pl) from within the directory. This can be worked around by changing the working directory to a path without spaces.