Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Artifact ID: | 94bcf5d5f19912194a3cd51dfdd631818e7a5b8d |
---|---|
Page Name: | Practcl Retrofit |
Date: | 2016-06-24 16:21:49 |
Original User: | hypnotoad |
Next | 10383a362fb2df0f101e9f49f8453201ba23031f |
For existing projects, which already have an established Makefile system this may not be practical or desired. So for our first example we will provide a minimal shim to allow make to invoke practcl.
The example here is a stylized version of the build system for odielib(http://fossil.etoyoc.com/fossil/odielib). Bits have been edited for clarity, and may vary slightly from the production code.
# Minimal make.tcl with a single target
set CWD pwd
set ::project(builddir) $::CWD
set ::project(srcdir) file dirname [file normalize [info script]]
set ::project(sandbox) file dirname $::project(srcdir)
if {file exists [file join $CWD .. tclconfig practcl.tcl]} {
source file join $CWD .. tclconfig practcl.tcl
} else {
source file join $SRCPATH tclconfig practcl.tcl
}
array set ::project :practcl::config.tcl $CWD
::practcl::library create LIBRARY array get ::project
LIBRARY source file join $::project(srcdir) library.ini
LIBRARY implement $::project(builddir)
set fout open pkgIndex.tcl w
puts $fout "
#
# Tcl package index file
#
"
puts $fout LIBRARY package-ifneeded
close $fout
This make script has no options, not targets, and only has a single task which will: * Read our practcl build rules (in the library.ini file) * generate a *PKGNAME*.mk file (which is a supplementary list of instructions for the Makefile) * generate the pkgIndex.tcl file (which will notifies Tcl about the package and how to load it.)
The *library.ini* contains instructions for the *LIBRARY* object. For this package it looks like:
set SRCPATH file normalize [my define get srcdir]
my add file join $SRCPATH cmodules btree module.ini my add file join $SRCPATH cmodules odieutil module.ini my add file join $SRCPATH cmodules geometry module.ini
my define add public-include <tcl.h> my define add public-include <assert.h> my define add public-include <stdio.h> my define add public-include <stdlib.h> my define add public-include <string.h> my define add public-include <math.h> my define add include_dir my define get builddir
You will note the "my" in front of many statements. This is because the script is actually invoked within the namespace of a TclOO object. This object is the master controller for the project.
The *add* method introduces a new subordinate object. In this case we have added three modules, which themselves will be objects. The add method has an auto-dectection algorithm to pair the appropriate class for a new subordinate by file extension. If we want more control we could have specified:
my add class module filename file join $SRCPATH cmodules btree module.ini
Modules, in turn, can have subordinates.
The btree module is straightforward:
set here file dirname [file normalize [info script]] my add file join $here tree.tcl
The tree.tcl(http://fossil.etoyoc.com/fossil/odielib/info/822483fd556b93ba17510c8bbe1a6c5c40d3946b?txt=1&ln=0) file, in turn defines data structures and functions we want available within our library. That file contains a stream of commands along the lines of:
my c_structure Tree { /* A complete binary tree is defined by an instance of the following ** structure */ int (*xCompare)(const void*, const void*); /* Comparison function */ void *(*xCopy)(const void*); /* Key copy function, or NULL */ void (*xFree)(void*); /* Key delete function */ struct TreeElem *top; /* The top-most node of the tree */ };
And
my c_function {static void TreeClearNode(TreeElem *p, void (*xFree)(void*))} { /* Delete a single node of the binary tree and all of its children */ if( p==0 ) return; if( p->left ) TreeClearNode(p->left, xFree); if( p->right ) TreeClearNode(p->right, xFree); if( xFree ){ xFree(p->key); } Tcl_Free((char *)p); }
Methods also exist for injecting arbitrary block of C code into specific places in the resulting C file, defining Tcl commands, and building OO classes.
Source files can also be read in from pure C:
my add file join $here md5.c
or
my add class csource initfunc Md5_Init filename file join $here md5.c