practcl - The Practcl Module
The Practcl module is a tool for integrating large modules for C API Tcl code that requires custom Tcl types and TclOO objects.
The concept with Practcl is that is a single file package that can assist any tcl based project with distribution, compilation, linking, VFS preparation, executable assembly, and installation. Practcl also allows one project to invoke the build system from another project, allowing complex projects such as a statically linked basekit to be assembled with relative ease.
Practcl ships as a single file, and aside from a Tcl 8.6 interpreter, has no external dependencies.
Making a practcl project
Concatenate a file
Strip the global comments from tcl code. Used to prevent the documentation markup comments from clogging up files intended for distribution in machine readable format.
Append a line of text to a variable. Optionally apply a string mapping.
Generate a proc if no command already exists by that name
A command to do nothing. A handy way of negating an instruction without having to comment it completely out. It's also a handy attachment point for an object to be named later
Drop in a static copy of Tcl
Build a zipfile. On tcl8.6 this invokes the native Zip implementation on older interpreters this invokes zip via exec
Dictionary sort a key/value list. Needed because pre tcl8.6 does not have lsort -stride 2
Returns a dictionary describing the local operating system. Fields return include:
download - Filesystem path where fossil repositories and source tarballs are downloaded for the current user
EXEEXT - The extension to give to executables. (i.e. .exe on windows)
fossil_mirror - A URI for a local network web server who acts as a fossil repository mirror
local_install - Filesystem path where packages for local consumption by the current user are installed
prefix - The prefix as given to the Tcl core/TEA for installation to local_install in ./configure
sandbox - The file location where this project unpacks external projects
TEACUP_PROFILE - The ActiveState/Teacup canonical name for this platform (i.e. win32-ix86 macosx10.5-i386-x86_84)
TEACUP_OS - The local operating system (windows, macosx, openbsd, etc). Gives the same answer as tcl.m4, except that macosx is given as macosx instead of Darwin.
TEA_PLATFORM - The platform returned by uname -s-uname -r (on Unix), or "windows" on Windows
TEACUP_ARCH - The processor architecture for the local os (i.e. ix86, x86_64)
TEACUP_ARCH - The processor architecture for the local os (i.e. ix86, x86_64)
teapot - Filesystem path where teapot package files are downloaded for the current user
userhome - File path to store localized preferences, cache download files, etc for the current user
This command uses a combination of local checks with Exec, any tclConfig.sh file that is resident, autoconf data where already computed, and data gleaned from a file named practcl.rc in userhome. The location for userhome varies by platform and operating system:
Windows: ::env(LOCALAPPDATA)/Tcl
Macos: ~/Library/Application Support/Tcl
Other: ~/tcl
A transparent call to ::practcl::read_configuration to preserve backward compadibility with older copies of Practcl
Detect local platform. This command looks for data gleaned by autoconf or autosetup in the path specified, or perform its own logic tests if neither has been run. A file named config.site present in the location indicates that this project is cross compiling, and the data stored in that file is used for the compiler and linker.
This command looks for information from the following files, in the following order:
config.tcl - A file generated by autoconf/configure in newer editions of TEA, encoded as a Tcl script.
config.site - A file containing cross compiler information, encoded as a SH script
::env(VisualStudioVersion) - On Windows, and environmental value that indicates MS Visual Studio is installed
This command returns a dictionary containing all of the data cleaned from the sources above. In the absence of any guidance this command returns the same output as ::practcl::local_os. In this mode, if the environmental variable VisualStudioVersion exists, this command will provide a template of fields that are appropriate for compiling on Windows under Microsoft Visual Studio. The USEMSVC flag in the dictionary is a boolean flag to indicate if this is indeed the case.
Try to load a package, and failing that retrieve tcllib
Return the string to pass to ./configure to compile the Tcl core for the given OS.
windows: --with-tzdata --with-encoding utf-8
macosx: --enable-corefoundation=yes --enable-framework=no --with-tzdata --with-encoding utf-8
other: --with-tzdata --with-encoding utf-8
Read a stylized key/value list stored in a file
Converts a XXX.sh file into a series of Tcl variables
A simpler form of read_sh_file tailored to pulling data from (tcl|tk)Config.sh
A simpler form of read_sh_file tailored to pulling data from a Makefile
Append arguments to a buffer The command works like puts in that each call will also insert a line feed. Unlike puts, blank links in the interstitial are suppressed
Search for the pattern pattern amongst $files
Calculate a relative path between base and dst
Example:
::practcl::file_relative ~/build/tcl/unix ~/build/tcl/library > ../library
Record an event in the practcl log
Return true if the pkgindex file contains any statement other than "package ifneeded" and/or if any package ifneeded loads a DLL
Helper function for ::practcl::pkgindex_path
Index all paths given as though they will end up in the same virtual file system
Delete the contents of d2, and then recusively Ccopy the contents of d1 to d2.
Recursively copy the contents of d1 to d2
Install a module from MODPATH to the directory specified. dpath is assumed to be the fully qualified path where module is to be placed. Any existing files will be deleted at that path. If the path is symlink the process will return with no error and no action. If the module has contents in the build/ directory that are newer than the .tcl files in the module source directory, and a build/build.tcl file exists, the build/build.tcl file is run. If the source directory includes a file named index.tcl, the directory is assumed to be in the tao style of modules, and the entire directory (and all subdirectories) are copied verbatim. If no index.tcl file is present, all .tcl files are copied from the module source directory, and a pkgIndex.tcl file is generated if non yet exists. I a folder named htdocs exists in the source directory, that directory is copied verbatim to the destination.
Trigger build targets, and recompute dependencies
Internals:
::practcl::LOCAL make trigger {*}$args foreach {name obj} [::practcl::LOCAL make objects] { set ::make($name) [$obj do] }
Calculate if a dependency for any of the arguments needs to be fulfilled or rebuilt.
Internals:
::practcl::LOCAL make depends {*}$args
Declare a build product. This proc is just a shorthand for ::practcl::LOCAL make task $name $info $action
Registering a build product with this command will create an entry in the global array, and populate a value in the global array.
Internals:
set obj [::practcl::LOCAL make task $name $info $action] set ::make($name) 0 set filename [$obj define get filename] if {$filename ne {}} { set ::target($name) $filename }
{ set authors { {John Doe} {jdoe@illustrious.edu} {Tom RichardHarry} {tomdickharry@illustrius.edu} } # Create the object ::practcl::doctool create AutoDoc set fout [open [file join $moddir module.tcl] w] foreach file [glob [file join $srcdir *.tcl]] { set content [::practcl::cat [file join $srcdir $file]] # Scan the file AutoDoc scan_text $content # Strip the comments from the distribution puts $fout [::practcl::docstrip $content] } # Write out the manual page set manout [open [file join $moddir module.man] w] dict set args header [string map $modmap [::practcl::cat [file join $srcdir manual.txt]]] dict set args footer [string map $modmap [::practcl::cat [file join $srcdir footer.txt]]] dict set args authors $authors puts $manout [AutoDoc manpage {*}$args] close $manout }
Tool for build scripts to dynamically generate manual files from comments in source code files
Methods
Process an argument list into an informational dict. This method also understands non-positional arguments expressed in the notation of Tip 471 https://core.tcl-lang.org/tips/doc/trunk/tip/479.md.
The output will be a dictionary of all of the fields and whether the fields are positional, mandatory, and whether they have a default value.
Example:
my argspec {a b {c 10}} > a {positional 1 mandatory 1} b {positional 1 mandatory 1} c {positional 1 mandatory 0 default 10}
Convert a block of comments into an informational dictionary. If lines in the comment start with a single word ending in a colon, all subsequent lines are appended to a dictionary field of that name. If no fields are given, all of the text is appended to the description field.
Example:
my comment {Does something cool} > description {Does something cool} my comment { title : Something really cool author : Sean Woods author : John Doe description : This does something really cool! } > description {This does something really cool!} title {Something really cool} author {Sean Woods John Doe}
Process an oo::objdefine call that modifies the class object itself
Process an oo::define, clay::define, etc statement.
Process a statement for a clay style class method
Process a statement for a tcloo style object method
Process a proc statement
Reset the state of the object and its embedded coroutine
Main body of the embedded coroutine for the object
Generate the manual page text for a method or proc
Generate the manual page text for a class
Generate the manual page text for the commands section
Generate the manual page. Returns the completed text suitable for saving in .man file. The header argument is a block of doctools text to go in before the machine generated section. footer is a block of doctools text to go in after the machine generated section. authors is a list of individual authors and emails in the form of AUTHOR EMAIL ?AUTHOR EMAIL?...
Scan a block of text
Scan a file of text
Ancestor-less class intended to be a mixin which defines a family of build related behaviors that are modified when targetting either gcc or msvc
Class Methods
Perform the selection for the toolset mixin
Methods
find or fake a key/value list describing this project
Compute the location where the product will be built
Return where the Makefile is located relative to srcdir. For this implementation the MakeDir is always srcdir.
Read information about the build process for this package. For this implementation, data is sought in the following locations in the following order: config.tcl (generated by practcl.) PKGConfig.sh. The Makefile
If the Makefile needs to be consulted, but does not exist, the Configure method is invoked
method DEFS This method populates 4 variables: name - The name of the package version - The version of the package defs - C flags passed to the compiler includedir - A list of paths to feed to the compiler for finding headers
Invoke critcl in an external process
ancestors: practcl::toolset
Methods
Detect what directory contains the Makefile template
Produce a static or dynamic library
Produce a static executable
ancestors: practcl::toolset
Methods
MSVC always builds in the source directory
Do nothing
Detect what directory contains the Makefile template
ancestors: practcl::metaclass
A build deliverable object. Normally an object file, header, or tcl script which must be compiled or generated in some way
Methods
Dynamic blocks do not generate their own .c files, instead the contribute to the amalgamation of the main library file
Methods
Parser functions
Alias to classic name
Alias to classic name
Module interactions
Practcl internals
Generate code that provides implements Tcl API calls
Generate code that runs when the package/module is initialized into the interpreter
Once an object marks itself as some flavor of dynamic, stop trying to morph it into something else
A deliverable for the build system
Class Methods
Methods
Populate const static data structures
Generate code that provides subroutines called by Tcl API methods
Generate code that provides implements Tcl API calls
This methods generates any Tcl script file which is required to pre-initialize the C library
Methods called by the master project
Methods called by the toolset
ancestors: practcl::product
A product which generated from a C header file. Which is to say, nothing.
Methods
ancestors: practcl::product
A product which generated from a C source file. Normally an object (.o) file.
Methods
ancestors: practcl::product
A product which is generated from a compiled C library. Usually a .a or a .dylib file, but in complex cases may actually just be a conduit for one project to integrate the source code of another
Methods
ancestors: practcl::dynamic practcl::product
A product which is generated from C code that itself is generated by practcl or some other means. This C file may or may not produce its own .o file, depending on whether it is eligible to become part of an amalgamation
Methods
ancestors: practcl::dynamic practcl::product
A binary product produced by critcl. Note: The implementation is not written yet, this class does nothing.
ancestors: practcl::object practcl::product.dynamic
In the end, all C code must be loaded into a module This will either be a dynamically loaded library implementing a tcl extension, or a compiled in segment of a custom shell/app
Variable
Methods
Return a dictionary of all handles and associated objects
Return the object associated with handle name
Reset all deputy objects
Exercise the triggers method for all handles listed
Exercise the check method for all handles listed
Return the file name of the build product for the listed handle
Return a list of handles for object which return true for the do method
For each target exercise the action specified in the action definition if the do method returns true
This methods generates the contents of an amalgamated .c file which implements the loader for a batch of tools
This methods generates the contents of an amalgamated .h file which describes the public API of this module
ancestors: practcl::module
A toplevel project that is a collection of other projects
Methods
Compile the Tcl core. If the define tk is true, compile the Tk core as well
Exercise the methods of a sub-object
ancestors: practcl::project
A toplevel project that produces a library
Methods
Backward compadible call
Create a "package ifneeded" Args are a list of aliases for which this package will answer to
ancestors: practcl::library
A toplevel project that produces a self-contained executable
Methods
Standalone class to manage code distribution This class is intended to be mixed into another class (Thus the lack of ancestors)
Class Methods
Methods
ancestors: practcl::distribution
A file distribution from zip, tarball, or other non-scm archive format
Class Methods
Methods
ancestors: practcl::distribution
A file distribution based on fossil
Class Methods
Check for markers in the metadata
Check for markers in the source root
Methods
Clone the source
ancestors: practcl::distribution
A file distribution based on git
Class Methods
Methods
ancestors: practcl::module
A subordinate project
Methods
Install project into the local build system
Methods for packages/tools that can be downloaded possibly built and used internally by this Practcl process Load the facility into the interpreter
Return a file path that exec can call
Install the tool into the local environment
Do whatever is necessary to get the tool into the local environment
Check if tool is available for load/already loaded
ancestors: practcl::subproject practcl::library
A project which the kit compiles and integrates the source for itself
Methods
ancestors: practcl::subproject
A subordinate binary package
Methods
ancestors: practcl::subproject.binary
A subordinate TEA based binary package
ancestors: practcl::subproject.binary practcl::library
A subordinate C library built by this project
Methods
ancestors: practcl::subproject.binary
A subordinate external C library
Methods
This document, and the package it describes, will undoubtedly contain bugs and other problems. Please report such in the category practcl of the Tcllib Trackers. Please also report any ideas for enhancements you may have for either package and/or documentation.
When proposing code changes, please provide unified diffs, i.e the output of diff -u.
Note further that attachments are strongly preferred over inlined patches. Attachments can be made by going to the Edit form of the ticket immediately after its creation, and then using the left-most button in the secondary navigation bar.
TclOO
Copyright © 2016-2018 Sean Woods <yoda@etoyoc.com>