Well here it is. The latest and greatest. Making its first appearance in POD, the "getting started" guide. There is a lot of work to do on it. There are sections that read like bad notes. But some might find this realease of use.

And in my tinkering around, I compile a lot. I have also added this handy little perl script that helps.

I only know that it works on win32 (XP). I could get it working on linux if anyone is interested.

Extensions are in win32 speak. But it uses Config.pm so it should be somewhat easy to make work for linux if it already does not. Here is a summary of what it does.

perl ecomp.pl -s dir
This builds a static libparrot.lib in the specified dir

perl ecomp.pl -d dir
This builds a dynamic libparrot.lib and libparrot.dll in the specified dir

perl ecomp.pl -o dir/test
this will compile dir/test.c into dir/test.obj (leave off all file extensions)

perl ecomp.pl -b dir/test
this will compile and link dir/test.c into dir/test.exe (leave off all file extensions). Handy when you just want to run something without the fuss.

perl ecomp.pl -link dir/test
this will link dir/test.obj with other parrot obj files to create dir/test.exe

perl ecomp.pl -liblink dir/test libdir/lib
this will link dir/test.obj with libdir/lib.lib (use libparrot for lib)

I think I know the answer, but is there a reason why in Config.pm 'so' maps to '.dll' and 'ar' only maps to 'lib' with no dot? Does it have to do with 'hello.lib' for windows and 'libhello.a' for linux?

Thanks,
Erik

=head1 TITLE

Getting started with parrot

    Version: 0.4
    Status:  POD DRAFT
    Last Revision:  19 October 2002
    Maintained By:  Erik Lechak <[EMAIL PROTECTED]>

=head1 Introduction

=head2 Overview

This is the HOWTO for becoming a Parrot developer.  It will outline the steps that 
will lead you to contributing to the Parrot community.  I will start with the most 
basic material to ensure that anyone that would like to help can be brought up to 
speed.

I am writing this as I learn the ropes as well.  So hopefully I have some insight into 
the learning process.  This document should also grow and become more useful as I grow 
more useful to the Parrot community.  Although, writing a document about what you 
learn makes learning take a lot longer.

=head2 Why would I want to help?

There are a number of great reasons to help with Parrot.  Several languages are slated 
to compile down to Parrot ByteCode (PBC).  Perl, Python, and Java are just a few.  I 
imagine that the list will continue to grow as Parrot does.  The Parrot elevator (or 
cage) is close to the ground floor and it is waiting for developers to get on.  This 
is a great chance to learn from some of the best programmers around.  The chance to 
help merge the strengths and user bases of these languages is a great opportunity.

Students looking for a great place to find a computer science project, should look no 
further than Parrot.  There are many different areas in Parrot to choose from.  From 
language development to garbage collection,  Parrot provides a fertile ground for 
project ideas.

If you have never worked on a open source project before, Parrot offers a great way to 
start.  Working in some corporate environments can discourage creative thinking and 
novel approaches to software design and development.  Working on an Open source 
project introduces you to an entirely different approach. 

There are millions of other reasons to help with Parrot, but I will just mention one 
more.  Your ego.  Just imagine when in a few years you go on an interview and they ask 
you if you know Perl or Python and you can say "Yep, I helped write the interpreter."  
How cool would that be?

=head1 First Steps

OK, let's start with some baby steps.  You are sitting at work surfing the web or your 
a student trying to come up with an idea for a computer science project.  You stumble 
across Parrot and want to learn more. Where do you go from here?  Well Here are some 
of the first steps in gaining an understanding of what Parrot is, where it is heading, 
and how you can help.

Browse through www.parrotcode.org (see 'http://www.parrotcode.org').  This is Parrot's 
home.  You can find just about all the documentation for Parrot here.  One of the best 
introductions to Parrot is the Parrot FAQ (see 
'http://www.parrotcode.org/docs/faq.pod.html').  It is an easy to read and 
entertaining executive summary of Parrot.  Most of the documentation is in the 'great 
reference material' category not the 'Parrot for dummies' category.  Once you get 
better acquainted with Parrot, the documentation makes more sense.  Remember that 
Parrot is a dynamic project, and that includes its documentation.  Things are changing 
and being added all the time.

Another great document to get you started with Parrot is the Parrot Primer (see 
'http://www.parrotcode.org/docs/intro.pod.html'). Be aware that this document is a 
little dated (as of this release of this document).

Read the Perl 6/Parrot Mailing List Summaries (see 
'http://dev.perl.org/perl6/list-summaries/') (the newest ones can be found at perl.com 
(see 'http://www.perl.com')). Piers Cawley does a great job of summarizing the goings 
on in the group.  He even suppresses some of the technobabble.  Although he seems to 
portray me as being fixated on not liking pod.  Or maybe its just me being fixated on 
not liking pod.

The perl6-internals mailing list (see 
'http://archive.develooper.com/perl6-internals@;perl.org/') is the group that will be 
most interesting to us (because we are talking about Parrot, not because Perl6 is not 
interesting).  You can browse through the list just to get an idea of what Parrot 
development sound like.  If you are new to Parrot don't spend too much time here 
trying to read and comprehend the mailing list.  Most of the talk is about the 
internal components, and since you are new to Parrot, It will make very little sense. 

So now let's get your machine ready.  So that you can download and start playing with 
Parrot.

=head1 What Do I Need to Get Started

=head2 Required Tools

If you program in C and Perl, you already have the tools you need to build Parrot.  
This is the list of the tools that are required to do anything with parrot:

=over 4

=item *

An ANSI (??89 or 99??)I<C> compiler

=item *

a version of I<make>

=item *

I<Perl> 5.005_03 or up

=back

It goes without saying that since Parrot is being developed in C that you need a C 
compiler.  If you have a C compiler and use it, chances are a version of make is also 
installed on your machine.  There are several C compilers to choose from.  Here are 
the listings of Parrot friendly C compilers for various operating systems:

=over 4

=item *

Linux

=over 4

=item *

gnu gcc

=back

=item *

Windows

=over 4

=item *

Microsoft's Visual C++

=item *

mingw

=item *

cygwin + gnu gcc

=back

=item *

Macintosh

=over 4

=item *

????

=back

=back

Make is a tool that directs the build of parrot.  On windows machines using VC++, the 
utility is called 'nmake' and is installed with VC++.  The manual for gnu make is here 
(see 'http://www.gnu.org/manual/make/html_node/make_toc.html').

Cygwin is a unix type environment that runs on Windows.  It allows you to use many of 
the gnu unix tools and can support X.

Perl is currently an integral part of the build process.  There is some talk that it 
will be slowly be replace by Parrot bootstrapping itself into a full build.  Perl is 
used up front in the configuration process.  It is used to generate C code from ops 
and pmc files. Most if not all of the Parrot utility programs are written in Perl.  
And the list goes on.  You can get the latest and greatest Perl and a ton of neat 
modules at CPAN (see 'http://www.cpan.org').  If you want a pre built binary version 
of Perl for Win32 go to ActiveState (see 'http://www.activestate.com'). 

Perl is also required for some of the languages that come with the parrot 
distribution.  See the L<included languages|"Included Languages"> section below.

=head2 Important Tools

These are some tools that are not required to build or run Parrot, but if you plan on 
doing any development work, they are necessary:

=over 4

=item *

cvs

=item *

diff

=item *

your favorite text editor

=back

CVS is the 'Concurrent Versions System'.  It is the source code control system that 
this project and the majority of other open source projects employ.  CVS information 
and applications can be found at www.cvshome.org (see 'http://www.cvshome.org').  If 
you are using windows go to www.wincvs.org (see 'http://www.wincvs.org') for a client 
that will work on your machine.   There is a source code repository on cvs.perl.org.  
This is where the developers check the source code out of, and after modifying it, 
check it back into.  Look L<here|"Getting the Parrot Source Code"> for a quick intro 
to cvs.  You can get the cvs manual here (see 'http://www.cvshome.org/docs/manual').

Diff is a utility useful in determining the differences between two files.  It is also 
used to generate patches that can be applied to the Parrot repository.

=head2 Useful Tools

Here are some other utilities that may come in handy.  They are not mandatory for 
building Parrot, but they are handy to have around:

=over 4

=item *

pod2text

=item *

pod2html

=item *

perldoc

=item *

grep

=item *

patch

=back

The utilities I<pod2text> and I<pod2html> transform the documentation provided with 
parrot into easier to read formats.  They are provided with your Perl distribution.  
The parrot documentation comes in a format developed by the perl community called POD 
(Plain Old Documentation).  Running these scripts on the POD file (or Perl script) of 
you choice will transform it into either text or html (respectively).  See below for 
the calling syntax.

Grep is a tool that the unix community is familiar with, but windows users may not 
recognize it.  Grep locates occurrences of patterns in a file, or set of files.  It 
comes in handy when you just can't find where that structure is defined or the place 
where that function is used.

=head2  Language Development Tools

If you plan on working on or building your own language for Parrot, these tools may 
come in handy.  IMCC development (see ??????) requires lex and yacc.

=over 4

=item *

Parse::RecDescent

=item *

lex/flex

=item *

yacc/bison

=back

Lex is a tokenizer.  A tokenizer takes a stream of characters and cuts them up into 
recognizable chunks called tokens.  For example the string of characters you are 
currently reading can be broken into meaningful chunks called words.

Yacc takes the tokens supplied by lex and looks for recognizable patterns in the 
tokens.  When it recognizes a pattern, it performs a specified function.  To continue 
the analogy started above, the words are linked together to form a sentence which is 
(I hope) a coherent thought.

Parse::RecDescent is a module for Perl.  It is like lex and yacc mixed into one 
creature.  You could use this module to create a language for Parrot or use it to 
learn the basics of what lex and yacc provide.  This was just a brief description of 
lex, yacc and recursive descent parsing.  For a more detailed description of these 
programs and concepts see ?????

Now your machine is ready for Parrot.  So we need to get the code.

=head1 Getting the Parrot Source Code

You can get instructions that might be more up to date for downloading the Parrot 
source code from www.parrotcode.org (see 'http://www.parrotcode.org') in the 'How to 
get the code' section.

=over 4

=item *

B<Browse the CVS Repository:>

If you're just interested in browsing the CVS repository without downloading anything, 
a few interfaces exist.

=over 4

=item *

cvs.perl.org/cvsweb/parrot/ (see 'http://cvs.perl.org/cvsweb/parrot/')

=item *

cvs.perl.org/viewcvs/parrot/ (see 'http://cvs.perl.org/viewcvs/parrot/')

=back

=item *

B<Download Snapshot of the CVS Repository:>

The easiest solution is to grab the most recent snapshot of the Parrot CVS repository. 
It's a tar-gzipped download of a recent checkout of Parrot, updated every six hours. 
You can find it here:

=over 4

=item *

cvs.perl.org/snapshots/parrot/parrot-latest.tar.gz (see 
'http://cvs.perl.org/snapshots/parrot/parrot-latest.tar.gz')

=back

=item *

B<Use CVS to get the code>

Even better is the option to use CVS, which gets you the very latest copy of the 
Parrot distribution. The procedure for this is:

=over 4

=item *

Install cvs on your machine (make sure the cvs executable is in your path).

=item *

Tell cvs where to find the Parrot repository and log in to it.  The environment 
variable CVSROOT holds the location of the repository. Here are a few shell scripts to 
use so you don't have to retype this all the time:

=over 4

=item *

Batch script for Windows

=over 4

  set HOME=C:                                            
  set USERPROFILE=C:                                     
  set CVSROOT=:pserver:[EMAIL PROTECTED]:/cvs/public
  cvs login

=back

=item *

Bash script file for Linux: *untested*

 export CVSROOT=:pserver:[EMAIL PROTECTED]:/cvs/public
 cvs login

=back

=item *

Run the appropriate script above for your system.  Hit the enter key when is asks you 
for you password.

=item *

If you want to create a new instance of the source code on your machine, you need to 
check the source code out of the Parrot repository.  If you have already checked out 
the copy you only need to update it, so skip to the next item.

To check out the parrot source code go to the directory where you want the parrot root 
directory to be created, then type:

  cvs co 

=item *

You only have to check out the source code once.  From now on you can just sync the 
version on your machine with the repository.  The following command is recursive so it 
will update the current directory and all the lower directories.  To update your 
version, I<cd> into the Parrot root directory and type:

 cvs update -dP

=back

=back

CVS has a ton of commands.  Checkout and update have many flags. Please read the cvs 
manual (see 'http://www.cvshome.org/docs/manual') for more details and capabilities.

=back

You are now the proud owner of copy of Parrot.  Let's take a look at what you have.

=head1 Contents of the Distribution

=over 4

=item *

chartypes

=item *

L<classes|"PMCs">  - pmc directory

=item *

L<config|"Configuring Parrot"> - data for Configure.pl

=item *

L<docs|"Documentation"> - POD documentation for Parrot

=item *

editor - Nice plugins for emacs and vi

=item *

encodings

=item *

examples

=item *

icu

=item *

include - Parrot C header files

=item *

io

=item *

jit - Just In Time "compiler" 

=item *

L<languages|"Included Languages"> - Current set of languages that support Parrot

=item *

lib - Perl module library

=item *

LICENSES - Parrot's license files

=item *

L<t|"Testing"> - All of the code test for I<make test>

=item *

tools

=item *

types

=item *

MANIFEST - list of files in the parrot distribution

=item *

README - first thing you should read after downloading Parrot

=item *

vtable.tbl - virtual functions supported by PMCs

=item *

*.pl - executable perl scripts

=item *

*.ops - opcode functions

=back

=head2 Executable Scripts

=item parrot

   assemble.pl   - compiles parrot assembly code (.pasm) into parrot bytecode 
(packfiles)
   Configure.pl  - first step in the Parrot build process
   disassemble.pl - transforms packfiles into assembly code (.pasm)
   jit2h.pl
   make.pl - perl "make" program that will build Parrot
   ops2c.pl - translates opcode files (.ops) into C code
   ops2cgc.pl
   ops2pm.pl
   optimizer.pl - performs optimization techniques on parrot assembly code file (.pasm)
   pbc2c.pl - generates the equivalent C code of parrot byte code (packfile)
   vtable_h.pl - generates parrot/include/vtable.h C header file   

=item parrot/t

   harness - runs the parrot tests (i.e.  'perl t/harness t/src/basic.t')

=item parrot/classes

   genclass.pl - generates a blank PMC template
   pmc2c.pl    - creates a C file based on the .pmc file

=item parrot/tools/dev

   check_source_standards.pl - looks for violations of coding standards
   genrpt.pl
   lib_deps.pl
   maincheck.pl  - verifies the contents of the distribution with the MANIFEST file
   parrot_coverage.pl
   run_indent.pl


=item parrot/types

   bignum_atest.pl
   bignum_test.pl

=head1 Connecting with the Parrot community

I couldn't decide whether to put this section before or after I show you how to 
compile Parrot.  It probably should go after, but for now it is here.  Just in case 
Parrot will not compile on your machine, I want you to be able to contact the Parrot 
community to get some help.

Now might be a good time to think about how you can help with Parrot.  Where do you 
skills lie?  How much time can you devote to the project?  This document will try to 
touch on several different ways to help with Parrot.  Here are some of them:

=over 4

=item *

Help with the documentation

=item *

Code development

=item *

Write a Language that compiles to PBC

=item *

Testing

=item *

Others??? (raise funds, buy a developer a pizza, ...)

=back

=head2 perl6-internals mailing list

The first step is looking at the mailing list.  The web interface to the mailing list 
archive is at perl6-internals mailing list archive (see 
'http://archive.develooper.com/perl6-internals@;perl.org/').  You can subscribe to the 
mailing list by sending a blank email to [EMAIL PROTECTED] (see 
'mailto:perl6-internals-subscribe@;perl.org').  After you mail in the subscription 
request, an email with a set of instructions will be sent to you automatically.  When 
you receive that email, It will ask you to reply to it to ensure that you want to 
subscribe to the mailing list.  This protects you from nefarious netizens that want to 
get you involved in Parrot without your consent.

If you want to ask a question or post something to the mailing list send an email 
containing your message to [EMAIL PROTECTED] (see 
'mailto:perl6-internals@;perl.org').  This will put your message in the root of the 
mailing list archive.  If you want your message to be a reply to a previous message, 
go to the message you want to reply to and hit the 'reply' button.  Then type your 
reply in.  And that's all there is to it.

Before we get to Compiling and trying out Parrot, let just go over some of the 
documentation.

=head1 Documentation

As with most programs the best place to start when you download anything is with the 
README file (in the parrot root directory).  It cuts right through the small talk and 
quickly gets you up and running.

The Parrot documentation is in the parrot/docs directory.  This is the current makeup 
of the parrot documentation directories:

=over 4

=item parrot/docs

=over 4

This is where parrot concepts are explained, or miscellaneous topics are documented.

=back

=item parrot/docs/dev

=over 4

This directory contains documents that describes the content and the functionality of 
individual source files.  These files describe the implementation.  The name of the 
document should match the name of the source code file that it describes.

=back

=item parrot/docs/pdds

=over 4

This directory contains the parrot design documents.  The design documents are a great 
place to get an overview of the direction parrot is heading.

=back

=back

The documentation provided with parrot is written in pod.  Pod is an embeddable 
documentation syntax for perl. See L<A brief introduction to pod> for more details.

=head2 Translating Pod

If you are having difficulty reading the documentation in pod and you have perl, you 
already have the tools to format pod into simple text or HTML:

=over 4

=item *

Transform pod into a text file

   pod2text file.pod > file.txt


=item *

Transform pod into an html file

   pod2html file.pod > file.html

=back

Some of the documentation for Parrot is embedded in the source code.  During a build, 
this information is extracted and placed in the documentation directories.  This keeps 
the documentation and the source code in sync (or it makes it simpler to keep things 
in sync).  The code that extracts the pod from the source is in parrot/docs/Makefile 
(this Makefile does not exist before you build parrot).  The following is one of the 
rules in parrot/docs/Makefile that creates a document from source (see ???? for a 
description of I<make rules>):

     core_ops.pod: ../core.ops  
            perldoc -u ../core.ops > core_ops.pod 

=head2 A brief introduction to pod

A more complete document about pod can be viewed by typing this at the command prompt 
(if you have perl installed):

    perldoc perlpod

Pod is a commenting style/language for Perl.  Its purpose is similar to that of 
javadoc.  Pod comments can be embedded into Perl code or stand on their own in a 
separate file.  If a file contains just pod, the standard file extension is .pod (as 
in 'document.pod').

To start a pod comment an equal sign (=) must be the first character of a line 
followed directly by a pod command. After the command is the content.  The content 
varies based on the command.  The pod '=cut' will end a pod section. For example:


     =head1 NAME
                             
     This is what pod looks like
                             
     =cut 


The blank lines are mandatory.  In pod 'head1' declares a major heading.  If you ran 
this pod through I<pod2text>, you would get something like:

    NAME                               
         This is what pod looks like   

The following list shows the pod commands and gives a brief description of them:

    head1 [heading name] -  Major heading
    head2 [heading name] -  Less Major heading
    head3 [heading name] -  Even less Major heading
    over  [number of spaces to indent] - Indented section( starts items).
    item  [*,number,name] - This is a list item.
    for [format]          - Formatter specific line
    begin [format]        - Formatter specific section
    end                   - Ends a formatter specific section
    back                  - This ends an over section of pod.
    cut                   - Terminates the current section of pod.

You may have as many pod sections that you want in a single file.  Pod section do not 
nest ('over' section can nest).  Once a '=cut' is reached all pod is turned off until 
another section is started.

Pod also allows you to emphasize or give special treatment to text.  Pod sequences are 
used for this purpose.  When the pod is translated into another format, the sequence 
information might not look the same.  The way that the translated text appears is the 
job of the pod formatter.  For example if in pod you specify that hello be bold, and 
you translate the pod via pod2text, the result will be *hello*.  However, translating 
the same pod into html will result in <B>hello</B>

The following list describes the sequences and their functions:

   B - Bold
   I - Italics
   C - Code, put this around a block of code.
   S - ???
   L - Make a link
   Z - Nothing
   E - Escape the character

OK.  Enough about POD and documentation let get the show on the road.

=head1 Compiling

=head2 The very basics

=over 4

=item *

I<cd> to your parrot directory and run I<Configure.pl> (or perl Configure.pl on a 
Windows machine).  This script performs a number of tests and configures parrot for a 
build on your machine (see Configuring Parrot below).  The main result from running 
I<Configure.pl> is the generation of Makefiles. 

    cd parrot 
    perl Configure.pl 

=item *

Run I<make> to compile everything and build parrot (I<nmake> with VC++).

    make

=item *

Run I<make test> to run the test suite and verify that everything works on your 
system.  (Note: I found that if I ran the tests in a path where there were spaces, 
some of the tests failed.  This may have been fixed)

    make test

=back

=head2 Configuring Parrot

The main task of Configure.pl is to run a series of small perl scripts that perform 
the individual steps of prepping Parrot for a build. Here are some of the functions of 
Configure.pl:

=over 4

=item *

Determine information about your compiler and linker

=item *

Gather information about your OS

=item *

Run several test to determine ???? a bunch of stuff

=item *

Build Makefiles

=item *

Build documentation from source code (actually pod)

=item *

Translate pmc files into c files.

=item *

Translate ops files into c files.

=back

The scripts are in the parrot/config directory. This is a brief description of the 
directories:

=over 4

=item config/

Root directory for configuration data used by Configure.pl

=item config/init

Scripts that set compiler and linker options

=item config/init/hints

OS dependant variables stored here

=item config/inter

=item config/auto

Scripts that automatically detect correct settings

=item config/auto/*

Auxiliary files needed by auto scripts

=item config/gen

These scripts generate other files (like Makefiles and some 

=item config/gen/*

Auxiliary files needed by gen scripts

=back

Just because a file appears in the config directory does not mean that it will be 
used.  The perl module parrot/lib/Parrot/Configure/RunStepsHere.pm contains a list of 
the scripts to run.  To run an additional script during configuration just add the 
scripts to the list.  The scripts run in the order that they are listed.  Here is an 
abbreviated list from RunStepsHere.pm just so you will know where to look (the ... 
means that I removed some scripts to save space.  Don't put ... in the list):

=over 4

    # EDIT HERE TO ADD NEW TESTS
    @steps=qw(                  
       init/manifest.pl         
       init/data.pl             
       init/miniparrot.pl       
       init/hints.pl            
       ...                      
       );                       

=back

As of the last version of this document, these are the scripts that Configure.pl runs:

   * init/manifest.pl
         ensures all files listed in manifest are present
         includes: ExtUtils/Manifest(perl standard lib)

   * init/data.pl
         gets data about compiler, linker, make util
         includes: parrot/lib/Parrot/Configure/Step;

   * init/miniparrot.pl 
         Should we build miniparrot????

   * init/hints.pl
         customizes some configuration data based on the platform. 
         An addendum to init/data.pl???

   * init/debug.pl 
         enables debugging

   * inter/progs.pl
         another step that deals with getting compiler and linker options

   * inter/types.pl
         customizes the size of the different parrot types (intval floatval and 
         pcode)

   * inter/ops.pl
         determine the ops files that should be compiled into parrot.  Looks
         like all ops files but one named vtable.ops (that I don't have in my
         distribution) are used.

   * inter/exp.pl
         experimental networking ??????

   * inter/pmc.pl
         What pmc files should be included in the build. All of the pmcs in
         the parrot/classes directory

   * auto/alignptrs.pl
   * auto/headers.pl
   * auto/sizes.pl
   * auto/stackdir.pl
   * auto/byteorder.pl
   * auto/pack.pl
   * auto/format.pl
   * auto/gcc.pl
   * auto/jit.pl
   * auto/funcptr.pl
   * auto/cgoto.pl
   * gen/config_h.pl
   * gen/config_pm.pl
        generates the super helpful lib/Parrot/Config.pm.  This module
        lists all of the machine dependent variables and gives them a 
        non-system dependent hash entry.
        
   * gen/makefiles.pl
        generates the main Makefile, the documentation Makefile, the pmc 
        makefile (in the classes directory), and the Makefiles for the various 
        languages included with Parrot.

   * gen/myconfig.pl
   * gen/platform.pl
   * gen/libparrot_def.pl
        Takes the data from libparrot_def/libparrot_def.in and creates the 
        libparrot.def file.  This file is used in Win32 to create the 
        libparrot dll.
   * gen/core_pmcs.pl

=head2 Making Parrot

After configuring Parrot you are ready to take the largest step so far.  You are going 
to build Parrot.  For such a daunting and important step, It is kind of anticlimactic 
that all it takes is:

    make

Or for Windows with VC++:

    nmake

That's it.  Just type I<make> at the command prompt and you can sit back and watch in 
amazement as Parrot is built.(Or you can go to the fridge.)

=head2 Other Make targets

This is a brief description of some of the other targets in the Makefile.  A target in 
a makefile is something that you can run by typing:

    make target

The following is a list of targets provided by the generated file Makefile:

=over 4

=item *

shared    - creates the parrot shared library (.so or .dll)

=item *

test      - runs the parrot tests

=item *

quicktest - runs the parrot tests (only if test has already been run)

=item *

clean     - removes files built during the make process

=item *

realclean - removes files built during make and Configure.pl process

=back

=head2 Compliling Notes

In a utopian world I<make> would build everything.  And everything would work.  
However, it is often necessary to build the libraries, objects, and executables 
yourself.  If for no other reason than to satisfy your own curiosity about how the 
process works.

The first step in figuring out how the build process works is to look at the Makefile. 
 If you are familiar with Makefiles, it is all you need to know to piece together a 
command line that will build whatever you want.

Different platforms (Linux, Win32, ...) support different tools and the same tools on 
different machines can have different names.  For example, a C compiler can be I<gcc>, 
I<cc>, or I<cl> and building a library could require something called I<ar> or 
I<link>.  The configureation process builds a Makefile that decouples the build syntax 
from the machine type and the software installed.  It does this by creating variables 
that remove the machine and software dependence. Then throughout the remainder of the 
Makefile only the variables are used.  Another file is built with these variables.  It 
is lib/Parrot/Config.pm.  The majority of variables found in the Makefile have the 
same name in the Config.pm file, but they are in lower case (a few variables do 
differ).

Instead of going through the process of trying to figure out what the command line 
should be to build Parrot's pieces, you can use the Config.pm file to help you 
accomplish this.

An example of the use of the Config.pm module is in the parrot/lib/Parrot/Test.pm 
module.  Here is an excerpt (Note that the code may change so the examples may not 
match the code exactly):

    _run_command("$PConfig{cc} $PConfig{ccflags} -I./include -c 
$PConfig{cc_o_out}$obj_f $source_f", 'STDOUT' => $build_f, 'STDERR' => $build_f);  
    _run_command("$PConfig{link} $PConfig{linkflags} $obj_f $PConfig{ld_out}$exe_f 
blib/lib/libparrot$PConfig{a} $PConfig{libs}", 'STDOUT' => $build_f, 'STDERR' => 
$build_f);

The following is a pseudo-perlscript that demonstrates how lib/Parrot/Config.pm can be 
used to remove the OS specific nature of building:

    use lib "c:/parrot/lib";                                                           
                                                          
    use Parrot::Config;                                                                
                                                          

    ##Find the object files
    my $o_ext = $PConfig{'o'};
    my @o_files=();

    push(@o_files,  glob( "*$o_ext" ) );             #root objects
    push(@o_files,  glob( "classes/*$o_ext" ) );     #pmc objects
    push(@o_files,  glob( "encodings/*$o_ext" ) );   #encoding objects
    push(@o_files,  glob( "chartypes/*$o_ext" ) );   #chartype objects
    push(@o_files,  glob( "io/*$o_ext" ) );          #io objects

    @o_files = grep (!/test_main/ , @o_files); #remove the obj with function main
    my $o_files = join (" " , @o_files);       #join into a string

    ##Builds a static library (tested on Win32 system)                                 
                                                          
    `$PConfig{ld} -lib  $PConfig{ld_out}libparrot$PConfig{ar} $o_files`;               
                                                          

    ##Builds a dynamic library                                                         
                                                          
    `$PConfig{ld} $PConfig{ld_shared} $PConfig{ld_shared_flags} $PConfig{ldflags} 
$PConfig{ld_out}libparrot$PConfig{so} $o_files $PConfig{libs}`;

    ##Compile Parrot                                                                   
                                                          
    `$PConfig{cc} $PConfig{ccflags} -I./include -c $PConfig{cc_o_out}OUTNAME SOURCE`;

    ##Link with dynamic library (note: in win32 libparrot.dll need to be in path)
    `$PConfig{link} $PConfig{linkflags} $o_files $PConfig{ld_out}$exe_f 
blib/lib/libparrot$PConfig{a} $PConfig{libs}`;                           

    ##Link with object files                                                           
                                                          
    `$PConfig{link} $PConfig{ld_out}OUTPUT.exe $PConfig{linkflags} OBJECTFILES 
OUTPUT.obj $PConfig{libs}`;                                       

=head1 Testing

=over 4

=item t/

the test directory

=item t/src

tests for embedding and building parrot (C code tests)

=item t/op

tests for all of the opcodes

=item t/pmc

pmc specific tests

=back

Testing sounds like it may be a boring subject.  But this is actually a great place to 
take a look at the current functionality of Parrot.  Whenever someone adds some sort 
of capability to Parrot, a test is also installed that will test that funtionality.  
For those people that learn faster from code examples, the test (t) directory is your 
encyclopedia.

Automated testing is conducted by the perl script t/harness.  You can run individual 
test using harness like this (do this from the parrot root directory):

    perl t/harness t/src/basic.t

This will run all of the tests in the t/src/basic.t file.  A file with a ".t" 
extention is a test file.  You can replace basic.t with any other test file or write 
your own tests and run them.  This is a great way to try out the capabilities of 
Parrot and have the compilation and execution of your test automated.

There are a number of "testing functions" that can be employed by t/harness.  These 
functions are located inside of the test files (.t) and provide information to harness 
about how to run the tests.

   output_is   - code is Parrot opcode, output must match expected output
   output_isnt
   output_like
   c_output_is - code is in C, output must match expected output
   c_output_isnt
   c_output_like

If you are unfamiliar with Perl, the test files' syntax might look a little awkward 
(especially the '<<' in some subroutines arguments).  So I will walk through an 
example.

    1  use Parrot::Test tests => 2;                                              
    2                                                                            
    3  output_is(<<'CODE', '1', "print 1");                                      
    4   print   1                                                                    
    5   end                                                                        
    6  CODE                                                                      
    7                                                                            
    8  output_is(<<'CODE', <<OUTPUT, "print string with embedded newline");|
    9       print "Parrot flies\n"                                               
   10       end                                                                 
   11  CODE                                                                     
   12  Parrot flies                                                             
   13  OUTPUT                                                                   

The line numbers up front are there so I can refer to the lines.  They are not 
actually in the files.  Line 1 shows how many tests this file contains.  In this 
example there are two tests (I<tests => 2>).

The tests follow the following syntax:

    output_is(test_source_code , expected_output , test_name);

The first argument to the subroutine I<output_is> is a string that contains the source 
code that makes up the test.  The second argument is the result that constitutes a 
passed test.  The third argument is the name of the test.

The first test in the example starts on line 3.  Let me translate line 3 into english 
and it might clear up some things.

    Run a test called 'print 1'.  The test consists of the code from the following 
lines up to but not including the word 'CODE'.  The output of the test should be '1' 
to pass.  Any other value is a failure.                                

The << (for here) operator is a handy Perl operator that provides a way of specifying 
a string that can contain several lines and a lot of text in a pleasent syntax.  The 
<<'CODE' will be replace with the text following the current line up to but not 
including the word CODE.   The text that replaces that statement will be single quoted 
as specified by the single quotes around the word CODE. 

Lines 8-13 show a slightly more complicated use of the 'for here' operator.  Both the 
source code and the expected value are specified by the 'for here' operator.  The test 
code goes up to the word CODE.  The expected output of the test starts the line after 
CODE and up to but not including the word OUTPUT.  Which is a long way of saying 
"Parrot files".

If you are interested in more feature and the internals of the testing environment see 
parrot/lib/Parrot/Test.pm and parrot/lib/Test/Builder.pm.

=head2 TODOs

Every once in a while you will see an area of a test blocked off so that a particular 
operating system will skip the test.  In this example Win32 is excluded from this test:

    TODO: {                                                          
       local $TODO="t/src doesn't work on Windows" if $^O =~ /Win32/;
       $TODO=$TODO;  #warnings                                       
       ...                                                            
       ...                                                            
       ...                                                            
    }                                                                

=head1 Developing

=head2 Common CVS

Just some notes!!

    cvs co
    cvs ci 
    cvs update -dP
    cvs diff

=head2 Patches

=head3 I've developed a patch. What should I do with it?

There's a lot of traffic that goes through the mailing list, and it's quite possible 
that if you send patches directly to the mailing list, they will get lost in the 
mailboxes of those with commit access.

As such, a better solution would be to submit your patch to RT, the request tracker 
system that maintains bugs and patches for the Parrot project. To visit RT, go here: 
http://bugs6.perl.org/

Or if you want to submit a patch, send an email to [EMAIL PROTECTED] with the 
moniker [PATCH] (including the brackets) at the start of the subject so that it can be 
appropriately tagged in the RT system. Please note that you do I<not> have to CC 
[EMAIL PROTECTED] when reporting a bug. The RT system will correctly handle 
that on its own.

A listing of the pending patches can be found here:

http://www.parrotcode.org/openpatches

=head3 I've found a bug, what now?

Well, if you know enough about the bug that you can fix the problem, please do so. 
Then you can create a patch and submit it to the list, with a better chance of your 
bug getting attention. If you're not able to solve it on your own, we're still 
interested in seeing what the problem is, and hopefully helping to resolve it. To 
report a bug, email [EMAIL PROTECTED] with a brief description of your bug in 
the subject. For more information about the bug management system, see the previous 
question.

=head3 How to submit a patch

These are the steps to submit a patch:

=over 4

=item 1

do a I<cvs update -dP>

=item 2

do a I<cvs diff -u> of the file(s) you want to patch (note: Win32 users will probably 
need -ub)

=item 3

redirect the output to a file (any name will do, .patch extension is conventional)

=item 4

create a new email message

=item 5

set the recipient to: [EMAIL PROTECTED] (note there's no need to CC the 
mailing list, it will find its way to it)

=item 6

pre pend [PATCH] to the subject

=item 7

be very, very informative about what you're doing, both in the subject line and the 
message body

=item 8

attach the patch file you generated in step 2 (DON'T paste the content in the body, 
attach the file!)

=item 9

send and wait patiently.

=back

=head1 Parrot Internals

It's time to look at some of the types you will encounter in the Parrot code.  One of 
the first places you should look when you start working on the internals of Parrot is 
F<'include/parrot/config.h'>.  This file is generated when you run Configure.pl.  This 
header file defines all of the main types and a lot of other bits and pieces that are 
used throghout Parrot.

=head2 Common types

=over 4

=item *

INTVAL

       An integer value.  See include/parrot/config.h for typedef.

=item *

FLOATVAL

       A float value.  See include/parrot/config.h for typedef.

=item *

L<PMC|"PMCs">

       A low level Parrot object.  See pmc.h and the PMC section below.

=item *

L<STRING|"STRINGs">

       Parrots String object.  See string.h and string_funcs.h for details.

=item *

DPOINTER

       A pointer (of type void *)

=item *

L<VTABLE|"VTABLE">

       A pointer to a table of functions.  See vtable.h.

=back

=head2 Lingo for this section

This section is huge and can be confusing.  In order to keep things clear I will refer 
to things in a shortened version than what you might find in the code.  This will make 
things clearer as you read this section.

If you see slashes surrounding a word that means see this file for the code.  For 
example, /interpreter.c/ means look in the file interpreter.c for the definition of 
the function or variable I am speaking about.

I am not going to give paths for the files I refer you to in this section.   I would 
be typing all night and all of the extra characters will just confuse the issue.  So 
if I refer you to a '.c' file it is either in the parrot root directory or in the 
classes/ directory.  If I refer you to a '.h' file it is in the include/parrot/ 
directory or in the classes/ directory.  Any other extension is usualy in the parrot 
root directory.  If it is not, I will give the directory it is in.  This is where grep 
comes in handy.  If you do not have grep get a copy and learn to use it.

    grep Parrot_new *.c  - this will look through all of the .c files for Parrot_new

There are many different types of PMCs.  And the number is ever increasing as Parrot 
is developed.  Each PMC types have two different names.  The first is the easy name 
that people refer to them as (i.e. PerlInt).  The second name is actualy an 
enumeration that C understands.  C does not have the nice object oriented symantics 
that Object oriented languages do.  In Parrot the PMC objects' types are defined by an 
enumeration (see core_pmcs.h for the enumeration definition).  Or at least to create 
the PMC object you need to specify what PMC type by its enumeration.  The enumerations 
look like I<enum_class_PMCTYPE>.  For example, in the classes/ directory there is a 
PerlHash.pmc file.  This means that there is a PerlHash pmc type.  Inside of the C 
code that type would be refered to as enum_class_PerlHash. Here is a line of C code 
that creates a new PerlInt pmc.  Note the enum_class_PerlInt as the final argument:

    pmc=pmc_new(interpreter, enum_class_PerlInt);

I will abbreviate some of the funtion definitions into a pseudo c-like syntax.  This 
is to save on wrist wear and tear.  But I will also try to point you to the file that 
the function is defined or used in with the slash syntax described earlier.

=head2 The Interpreter

The struct Parrot_Interp is an interpreter object.  Here is the code to create an 
interpreter:

    1 #include "parrot/parrot.h"
    2 #include "parrot/embed.h"
    3 int main(int argc, char* argv[]) {
    4     struct Parrot_Interp * interpreter;
    5     interpreter = Parrot_new();
    6 }

Line 2 includes embed.h.  This file contains the declaration for Parrot_new().  Line 4 
declares the variable I<interpreter> as a Parrot interpreter.  Line 5 creates the 
interpreter.  That's it.  Kind of a boring program, but it's good to start small.

Let's take a more detailed look at what Parrot_new does:

  Parrot_new /embed.c/
      init_world /global_setup.c/
         string_init
         parrot_initialize_core_pmcs
         Parrot_base_classname_hash = pmc_new(NULL,PerlHash)
         Parrot_register_coer_pmcs(Parrot_base_classname_hash)
      make_interpreter
         creates interpreter
         initializes variables in interpreter
         mem_setup_allocator(interpreter)
         Perl_stash = mem_sys_allocate
         Perl_stash->stash_hash = pmc_new(PerlHash)
         initialize register chunks
         initialize registers


=head2 Memory management types

Sorry, Just some notes for now.

  Parrot_Interp   /interpreter.h/
  Stash           /resources.h/
  Arena           /resources.h/
  Memory_Pool     /resources.h/
  Memory_Block    /resources.h/
  Small_Object_Pool   /smallobjects.h/
  Small_Object_Arena  /smallobjects.h/
  Parrot_Context  /interpreter.h/
  SYNC
  VTABLE
  Buffer          /resources.h/

=head2 PMCs

Parrot Magic Cookies (PMC).  This is the meat and potatoes of Parrot (or beans and 
rice if you are a vegetarian).  PMCs are the low level objects in Parrot.

Every PMC in Parrot has a set of functions that must be defined for it.  This set of 
mandatory funtions can be seen in the F<vtable.tbl> file. See the L<VTABLE> section 
below for more detail.

See F<docs/vtables.pod> for a more detailed description on how to create a PMC.  

The following list details the contents of the PMC struct:

    VTABLE *vtable
    INTVAL flags
    DPOINTER *data
    UnionVal cache
    SYNC *synchronize
    PMC *next_for_GC

=head3 creating a pmc

Now we know what is in a PMC.  So lets find out how to instanciate one.  The first 
thing you need to know is what kind of PMC do you want to create.  A quick glance and 
the F<classes/> directory will tell you what you have to choose from.  You can also 
look in the file F<inclue/parrot/core_pmcs.h> and that will list the complete 
enumeration name of the PMC type.

Once you know what type you want to create the name of the type is in the following 
form
  
  enum_class_PMCNAME

The following functions allow you to create the new PMC objects:

=over 4

=item *

pmc_new(interpreter, type)

=item *

pmc_new_noinit( interpreter, type , size)

=item *

pmc_new_sized(interpreter, type, size)

=item *

pmc_new_sized_pmc(interpreter, type, pmc)

=back

Allright enough talk, let's write some code that does something.  Well it doesn't do 
much but at least it's code.  The following C code creates a Parrot interpreter and 
creates a PerlInt PMC:

     1   #include "parrot/parrot.h"
     2   #include "parrot/embed.h"
     3
     4   int main(int argc, char* argv[]) {
     5      int dummy_var;
     6      PMC *pmc;
     7   
     8      struct Parrot_Interp * interpreter;
     9      interpreter = Parrot_new();
    10
    11      pmc=pmc_new(interpreter, enum_class_PerlInt);
    12      pmc->vtable->set_integer_native(interpreter, pmc, 1);               
    13   }

A closer look at what pmc_new does:

  pmc_new
    new_pmc_header
    pmc->vtable=Parrot_base_vtables[type]
    pmc->vtable->init(interpreter,pmc)

=head3 pmc flags
   
   0 - for use by pmc author
   1 - for use by pmc author
   2 - for use by pmc author
   3 - for use by pmc author
   4 - for use by pmc author
   5 - for use by pmc author
   6 - for use by pmc author
   7 - for use by pmc author
   8 - Set if the PMC has a destroy method that must be called
   9 - ??????
  10 - Set to true if the PMC data pointer points to something that
       looks like a string or buffer pointer 
  11 - Set to true if the data pointer points to a PMC
  12 - Set to true if the PMC has a private GC function. For PMCs the
       GC system can't snoop into
  13 - Set to true if the PMC has a custom mark routine
  14 - Are we live
  15 - Are we on the free list
  16 - Our refcount
  17 - Our refcount
  18 - Constant flag

=head3 data

=head2 VTABLE

Every PMC type has its own vtable.  A vtable defines the functional capabilities of a 
PMC.  After building Parrot (or running pmc2c.pl), you can view all of the functions 
available to a PMC type by looking at the I<pmctype>.c file (like PerlInt.c).  

For example if you are interested in the PerlHash PMC type, look in the PerlHash.c 
file.  At the end of the file you will see a function called 
I<Parrot_PerlHash_class_init>.  If you were interested in PerlArray look int the 
PerlArray.c file for a function called I<Parrot_PerlArray_class_init>.  I think you 
get the point.  In this funciton a _vtable struct named temp_base_vtable defines the 
vtable.


  1void Parrot_DemoPMC_class_init (int entry) {
  2  
  3  struct _vtable temp_base_vtable = {
  4      NULL,
  5      enum_class_DemoPMC,
  6      ...
  7      ...
  8      ...
  9      Parrot_DemoPMC_substr_str_keyed,
 10      Parrot_ParentPMC_substr_str_keyed_int,
 11      Parrot_default_invoke
 12      };
 13   
 14    Parrot_base_vtables[entry] = temp_base_vtable;
 15  }


The vtable or VTABLE type is a struct that contains pointers to all of the functions 
in F<vtable.tbl>.  The VTABLE type is defined in F<include/parrot/vtable.h>.  Actually 
struct _vtable is defined there.  It is typedef'd into VTABLE in F<config.h>.   

Need to talk about inheritence and the syntax used in a .pmc file.

=head2 STRINGs

Just some notes for now!!

  #define STRING struct parrot_string_t
  typedef struct parrot_string_t String;

=head3 String internals

  struct parrot_string_t {
    void *bufstart;
    UINTVAL buflen;
    UINTVAL flags;
    UINTVAL version;
    UINTVAL bufused;
    void *strstart;
    UINTVAL strlen;
    const ENCODING *encoding;
    const CHARTYPE *type;
    INTVAL language;
  };

  typedef struct {
            void *bufstart;
            UINTVAL buflen;
            UINTVAL flags;
            UINTVAL version;
   } Buffer;

=head3 String flags

    0  can be used by programmer
    1  can be used by programmer
    2  can be used by programmer
    3  can be used by programmer
    4  can be used by programmer
    5  can be used by programmer
    6  can be used by programmer
    7  can be used by programmer
    8  The contents of the buffer can't be moved by the GC
    9  Marks the contents as coming from a non-Parrot source
   10  Mark the buffer as pointing to system memory 
   11  Mark the contents as Copy on write 
   12  Private flag for the GC system. Set if the buffer's in use as far as the GC's 
concerned
   13  Mark the bufffer as needing GC
   14  Mark the buffer as on the free list 
   15  This is a constant--don't kill it!
   16  For debugging, report when this buffer gets moved around
   17  Generation in the GC pools
   18  Generation in the GC pools
   19  Buffer header has a strstart which needs to be updated with bufstart

=head3 String functions

Just notes!!

   INTVAL string_compute_strlen(STRING *)
   STRING *string_concat(interpreter, STRING *, STRING *, UINTVAL)
   STRING *string_append(interpreter, STRING *, STRING *, UINTVAL)
   STRING *string_repeat(interpreter, const STRING *, UINTVAL,STRING **)
   STRING *string_chopn(STRING *, INTVAL)
   STRING *string_substr(struct Parrot_Interp *, STRING *, INTVAL, INTVAL, STRING **)
   STRING *string_replace(struct Parrot_Interp *, STRING *, INTVAL, INTVAL, STRING *, 
STRING **)
   INTVAL string_compare(struct Parrot_Interp *, STRING *, STRING *)
   INTVAL string_bool(const STRING *)
   const char *Parrot_string_cstring(const STRING *)
   STRING *string_set(struct Parrot_Interp *, STRING *, STRING *)

   UINTVAL string_length(const STRING *);
   INTVAL string_ord(const STRING *, INTVAL idx);
   FLOATVAL string_to_num(const STRING *);
   INTVAL string_to_int(const STRING *);
   STRING *string_from_int(struct Parrot_Interp *, INTVAL i);
   STRING *string_from_num(struct Parrot_Interp *, FLOATVAL f);
   STRING *string_grow(struct Parrot_Interp *, STRING *s, INTVAL addlen);
   void string_destroy(STRING *);
   STRING *string_make(struct Parrot_Interp *, const void *buffer,
                            UINTVAL buflen, const ENCODING *, UINTVAL flags,
                            const CHARTYPE *);
   STRING *string_copy(struct Parrot_Interp *, STRING *);
   STRING *string_transcode(struct Parrot_Interp *, STRING *src,
                                 const ENCODING *, const CHARTYPE *,
                                 STRING **dest_ptr);
   void string_init(void);
   INTVAL string_index(const STRING *, UINTVAL idx);
   const char *string_to_cstring(struct Parrot_Interp *, STRING *);


=head1 Included Languages

Sorry, less than just notes!!

=over 4

=item *

BASIC

=item *

cola

=item *

forth

=item *

jako

=item *

miniperl

=item *

Ruby

=item *

Scheme

=back

=head1 Other Resources

=over 4

=item *

Tinderbox

=over 4

The tinderbox consists of two dozen or so computers running various OS and platform 
configurations, downloading the latest Parrot distribution every few hours and running 
the test suite to verify that it works on that given combination of software and 
hardware.

To view the results of the tinderbox system, check out:

http://tinderbox.perl.org/tinderbox/bdshowbuild.cgi?tree=parrot

=back

=item *

Test Coverage Results

=over 4

The Parrot test suite is intended to test all aspects of Parrot's code. You can see 
how successful we are at this goal by checkout the test coverage. It gives line, 
branch, and call coverage percentages on a per-file or per-function breakdown. Find it 
here:

http://www.hitchhiker.org/parrot_coverage/

=back

=item *

Bonsai

=over 4

Bonsai is a cvs tree control tool to monitor the status of cvs trees. Whenever a check 
in occurs, bonsai adds that person to the "hook," a list of those responsible for the 
current state of the tree (this should be cleared whenever we know that things are 
working for sure). Users can then run queries to find out who has changed what files 
and access their check in comments in addition to generating diffs.

=item *

Query

http://tinderbox.perl.org/bonsai/cvsqueryform.cgi?cvsroot=/home/tinder/perlcvs&module=parrot

=item *

Browse

http://tinderbox.perl.org/bonsai/rview.cgi?cvsroot=/home/tinder/perlcvs&dir=parrot&module=parrot

=back

=back

=head1 FAQ

=head1 Unsolved Mysteries

=over 4

=item *

How do you add methods to a pmc?

=item *

How do you call the methods in a pmc?

=item *

For interpreter threads will there be more than one interpreter (Parrot_new), and if 
so will init_world run more than once (looks like it should, but its name makes it 
sound like it should not)?

=item *

What is a register chunk, and why would I want my registers chunky?

=back

=cut














use lib "lib";
use Parrot::Config;

#so -> .dll
#ar -> lib    why no dot???
#


##############################################
# Global Vars

$main = "test_main.c"; #where is the function main 
##############################################

if ($ARGV[0] eq "-d"){   #compile a dynamic linked lib
  $o_files = collectObjectFiles();
  
  if (! -e "$ARGV[1]/"){
     mkdir "$ARGV[1]/";
  }
  
  makeSharedLib("$ARGV[1]/",$o_files);
  
}elsif ($ARGV[0] eq "-s"){   # build static library
  
  $o_files = collectObjectFiles();

  makeStaticLib("$ARGV[1]/",$o_files);
  

}elsif ($ARGV[0] eq "-o"){   # compile to object file
  
  $o_files = collectObjectFiles();

       #  source
  compile($ARGV[1]);

}elsif ($ARGV[0] eq "-liblink"){
    $o_files = collectObjectFiles();
    liblink($ARGV[1], $ARGV[2], $o_files);
}elsif ($ARGV[0] eq "-link"){
    $o_files = collectObjectFiles();
    objlink($ARGV[1], $o_files);
}elsif ($ARGV[0] eq "-b"){

  $o_files = collectObjectFiles();
  compile($ARGV[1]);
  objlink($ARGV[1], $o_files);
}else{
   print "Usage:\n";
   print " Easy compiler for parrot. Do not put any file\n";
   print " extentions on the filenames when issuing commands.\n";
   print " It figures out extentions itself for cross platform compatability\n";
   print " examples below have win32 extentions.\n";
   print "  ecomp.pl -b dir/test    ---builds test.exe from test.c\n";
   print "  ecomp.pl -o dir/test    ---makes test.obj from test.c\n";
   print "  ecomp.pl -s dir/        ---makes static libparrot.lib\n";
   print "  ecomp.pl -d dir/        ---makes dynamic libparrot.dll\n";
   print "  ecomp.pl -link dir/test ---links objects into test.exe\n";
   print "  ecomp.pl -liblink dir/test libdir/lib ---links with library\n";
}

exit();


#link objects into executable
sub objlink{
   my $object = shift;
   my $o_files=shift;
   
   my $output = $object . $PConfig{'exe'} ;
   $object = $object . $PConfig{'o'} ;
   
   $o_files = $object . " " . $o_files;
   
   my $cmd = "$PConfig{link} $PConfig{ld_out}$output $PConfig{linkflags} $o_files 
$PConfig{libs}";
   run($cmd);
}


#link with library
sub liblink{
   my $object = shift;
   my $lib= shift;
   my $output = $object . $PConfig{'exe'} ;
   $object = $object . $PConfig{'o'} ;
   my $cmd = "$PConfig{link} $PConfig{linkflags} $object $PConfig{ld_out}$output 
$lib$PConfig{a} $PConfig{libs}";
   run($cmd);
}


# gets all of the pertinent object files
sub collectObjectFiles{
        my $o_ext = $PConfig{'o'};
        my @o_files=();

        push(@o_files,  glob( "*$o_ext" ) );             #root objects
        push(@o_files,  glob( "classes/*$o_ext" ) );     #pmc objects
        push(@o_files,  glob( "encodings/*$o_ext" ) );   #encoding objects
        push(@o_files,  glob( "chartypes/*$o_ext" ) );   #chartype objects
        push(@o_files,  glob( "io/*$o_ext" ) );          #io objects

        @o_files = grep (!/test_main/ , @o_files);

        my $o_files = join (" " , @o_files);
        return $o_files;
}

#compile to object
sub compile{
   my $source = shift;
   my $output = $source . $PConfig{'o'};
   $source = $source . ".c";
   my $cmd = "$PConfig{cc} $PConfig{ccflags} -I./include -c $PConfig{cc_o_out}$output 
$source";
   run($cmd);
}

#makes a static library.
#Don't have the .h info yet
sub makeStaticLib{
   my $location = shift;
   my $o_files=shift;
              #Windows dependent see -lib below
   my $cmd = "$PConfig{ld} -lib  $PConfig{ld_out}$location/" . "libparrot.$PConfig{ar} 
$o_files\n";
   run($cmd);
}



#makes a shared library
sub makeSharedLib{
   my $location = shift || ".";
   my $o_files=shift;
   my $cmd = "$PConfig{ld} $PConfig{ld_shared} $PConfig{ld_shared_flags} 
$PConfig{ldflags} $PConfig{ld_out}$location/libparrot$PConfig{so} $o_files 
$PConfig{libs}\n";
   run($cmd);
}


# Run the command and print result
sub run{
  my $cmd = shift;
  print "$cmd\n";
  $out = `$cmd`;
  print "$out\n";
}

Reply via email to