diff --git a/doc/changes/changes45.xml b/doc/changes/changes45.xml index d28bef520c..539b8dabc6 100644 --- a/doc/changes/changes45.xml +++ b/doc/changes/changes45.xml @@ -627,7 +627,7 @@ In addition, there is now a better error management if package loading fails for packages that use the new functionality to log package loading messages (see -and the rest of the Chapter +and the rest of the Chapter which documents how to use ⪆ packages), and package authors are very much encouraged to use these logging facilities.

diff --git a/doc/ref/gappkg.xml b/doc/ref/gappkg.xml index 140d2ef816..7fc1fd7bdd 100644 --- a/doc/ref/gappkg.xml +++ b/doc/ref/gappkg.xml @@ -1,15 +1,5 @@ - - - - - - - - - - - -Using GAP Packages + +Using and Developing GAP Packages package The functionality of ⪆ can be extended by loading ⪆ @@ -27,26 +17,37 @@ integrated into the ⪆ help system. All ⪆ users who develop new code are invited to share the results of their efforts with other ⪆ users by making the code and its documentation available in form of a package. -Information how to do this is available from the ⪆ Web pages +Information how to do this is available from the ⪆ website (https://www.gap-system.org) and in the ⪆ package Example (see https://www.gap-system.org/Packages/example.html). +

There are possibilities to get a package distributed together with ⪆ and it is possible to submit a package to a formal refereeing process.

-In this chapter we describe how to use existing packages. +In this chapter we first describe how to use existing packages, +and then provide guidelines for writing a ⪆ package.

Installing a GAP Package -Before a package can be used it must be installed. With a standard -installation of ⪆ there should be all currently redistributed with -⪆ packages already available. But since ⪆ packages are released -independently of the main ⪆ system it may be sensible to upgrade -or install new packages between upgrades of your ⪆ installation. +Before a package can be used it must be installed. A standard installation +of ⪆ already contains all ⪆ packages currently redistributed with +⪆. This set of packages is checked for compatibility +with the system and other packages during release preparation. Most of +the packages can be used immediately, but some of them may require further +installation steps such as compilation or installing additional software +to satisfy their dependencies. Most of the packages that require compilation +can be compiled in a single step by changing to the pkg directory of +your ⪆ installation and calling the ../bin/BuildPackages.sh script. +

+Also, since ⪆ packages are released independently of the main ⪆ system, +sometimes it may be useful to upgrade or install new packages between +upgrades of your ⪆ installation, e.g. if a new version of a package adds +new capabilities or bug fixes that you need.

A package consists of a collection of files within a single directory that must be a subdirectory of the pkg directory in one of the @@ -73,10 +74,20 @@ be able to use some or all external binaries. automatic loading of GAP packages disable automatic loading -Some ⪆ packages are prepared for automatic loading, -that is they will be loaded automatically with ⪆, -others must in each case be separately loaded by a call to -. +If a package is not loaded, it may be loaded using +the function . +

+Some ⪆ packages are loaded automatically with ⪆. Those belong to +two categories: packages which are needed to start ⪆ (as of this writing, +the only such package is &GAPDoc;; their list is contained in +GAPInfo.Dependencies.NeededOtherPackages), and packages which are +loaded during ⪆ startup by default. The latter list may be obtained by +calling UserPreference("PackagesToLoad") and is customisable as +described in Section . +

+While &GAP; will not start if any of the packages from the former group is +missing, loading of the packages from the latter group may be suppressed by +using the -A command line option (see ). <#Include Label="LoadPackage"> <#Include Label="SetPackagePath"> @@ -91,7 +102,12 @@ others must in each case be separately loaded by a call to Functions for GAP Packages The following functions are mainly used in files contained in a -package and not by users of a package. +package and not by users of a package. They are needed to organise +reading package files into &GAP; in the right order, performing +maintenance tasks like building documentation and running package +tests, checking package dependencies, etc. +You will find further information about their use in Section + and subsequent sections. <#Include Label="ReadPackage"> <#Include Label="TestPackageAvailability"> @@ -161,9 +177,8 @@ no effect, even if the file on disk has changed. Each package has the file PackageInfo.g which contains meta-information about the package (package name, version, author(s), relations to other packages, -homepage, download archives, banner, etc.). This file is used by the package -loading mechanism and also for the distribution of a package to other -users. +homepage, download archives, etc.). This file is used by the package +loading mechanism and also for the redistribution of a package with &GAP; <#Include Label="ValidatePackageInfo"> @@ -173,5 +188,1996 @@ users.

- +
+Guidelines for Writing a GAP Package + +The remaining part of this chapter explains the basics +of how to write a &GAP; package so that it integrates properly into &GAP;. +

+ +There are two basic aspects of creating a &GAP; package. +

+ +First, it is a convenient possibility to load additional functionality into +&GAP; including a smooth integration of the package documentation. Second, +a package is a way to make your code available to other &GAP; users. +

+ +Moreover, the &GAP; Group may provide some help with redistributing your +package via the &GAP; website after checking if the +package provides some new or improved functionality which looks interesting +for other users, if it contains reasonable documentation, and if it seems +to work smoothly with the &GAP; library and other distributed packages. In +this case the package can take part in the &GAP; distribution update +mechanism and becomes a deposited package. +

+ +Furthermore, package authors are encouraged to check if the package would +be appropriate for the refereeing process and submit it. If the +refereeing has been successful, the package becomes an accepted package. +Check out https://www.gap-system.org/Packages/Authors/authors.html +on the &GAP; website for more details. +

+ +Below we start with a description how the directory structure of a +&GAP; package should be constructed and then add remarks on certain aspects +of creating a package, some of these only apply to some packages. Finally, +we provide guidelines for the release preparation and its distribution. +

+ +

+ + +
+Structure of a GAP Package + +home directory +A &GAP; package should have an alphanumeric name (packagename, say); +mixed case is fine, but there should be no whitespace characters. +All files of a &GAP; package packagename must be collected in a +single directory packagedir, where packagedir should be +just packagename optionally converted to lowercase and optionally +followed by the package version (with or without hyphen to separate the +version from packagename). +Let us call this directory the home directory of the package. +

+To use the package with &GAP;, the directory packagedir must +be a subdirectory of a pkg directory in (one of) the &GAP; root +directories (see ). +For example, if &GAP; is installed in /usr/local/gap4 then the +files of the package MyPack may be placed in the directory +/usr/local/gap4/pkg/mypack. + +The directory packagedir preferably should have the following +structure (below, a trailing / distinguishes directories from +ordinary files): +

+\newpage + +

+ +This layout of directories and files may be created manually, or automatically +using the tool called PackageMaker, +available at https://github.com/gap-system/PackageMaker. The +PackageMaker asks several questions about the intended +package and then creates a new directory for it and populates it with all +the files needed for a basic package. +

+ +Packages that contain some code that requires compilation will usually have +it in the src subdirectory. They may also have extra files such as +configure, Makefile.in etc. that automate the build procedure. + +There are three file names with a special meaning in the home +directory of a package: PackageInfo.g and init.g +which must be present, and read.g which is optional. +

+ +On the other hand, the names of CHANGES, LICENSE and +README files are not strictly fixed. They may have extensions +.txt or .md, and instead of LICENSE one could use +e.g. COPYING or GPL for packages distributed under the +GNU General Public License, or use HISTORY instead of CHANGES. +

+ +We now describe the above files and directories in more details: +

+ + + + +README + +README + +The filename may optionally have an extension, e.g. .txt or .md. +

+This should contain how to get it instructions (covering the +way of getting it with the &GAP; distribution and from the &GAP; website, +if applicable), as well as installation instructions and names +of the package authors and their email addresses. These installation +instructions should be repeated or referenced from the package's +documentation, which should be in the doc directory +(see ). +Authors' names and addresses should be repeated both in the package's +documentation and in the PackageInfo.g (see below). + + + +CHANGES + +For further versions of the package, it will be also useful to have a +CHANGES file that records the main changes between versions +of the package. +

+The filename may optionally have an extension, e.g. .txt or .md. + + + +LICENSE + +The file which explains conditions on which the package is distributed. +

+We advise all package authors to make clear in the documentation of their +package the basis on which it is being distributed to users. Technically, +this is the terms of the license which you give the users to copy, modify +and redistribute your software (of which you presumably own the copyright) +for their purposes. +

+&GAP; itself is distributed under the GNU General Public License version 2, +a popular free software license which allows users to redistribute it +freely under the same terms, and requires that any software which +incorporates &GAP; (technically, any derived work) also be distributed +under those terms. We would encourage you to consider the GPL for your +packages, but you might wish to be more restrictive (for instance +forbidding redistribution for profit) or less restrictive (allowing +your software to be incorporated into commercial software). +

+The filename may optionally have an extension, e.g. .txt or .md. +Some packages also use different filenames, like COPYING. + + +configure, Makefile.in + +These files are typically only used by packages which have a non-&GAP; component, +e.g. some C code (the files of which should be in the src +directory). The configure and Makefile.in files of the +Example package provide prototypes (or they may be created +using the PackageMaker mentioned above). The configure +file typically takes a path path to the &GAP; root directory as argument +and uses the value assigned to GAParch in the file sysinfo.gap, +created when &GAP; was compiled to determine the +compilation architecture, inserts this in place of the string @GAPARCH@ +in Makefile.in and creates a file Makefile. When make is +run (which, of course, reads the constructed Makefile), a directory +bin (if necessary) and subdirectories of bin with the path equal +to the string assigned to GAParch in the file sysinfo.gap should +be created; any binaries constructed by compiling the code in src should +end up in this subdirectory of bin. + + + +PackageInfo.g + +PackageInfo.g +Every &GAP; package must have a PackageInfo.g +file which contains meta-information about the package (package name, version, +author(s), relations to other packages, homepage, download archives, etc.). +This information is used by the package loading mechanism and also for +the redistribution of a package with &GAP;. The Example package's +PackageInfo.g file is well-commented and can be used as a +prototype (see also for further details). +It may also be created using the PackageMaker mentioned above. + + + +init.g, read.g + +init.g +read.g +A &GAP; package must have a file init.g. +Typical init.g and read.g files should normally consist +entirely of commands (and possibly +also commands) for reading further files +of the package. If the declaration and implementation parts of +the package are separated (and this is recommended), there should be a +read.g file. +The declaration part +of a package consists of function and variable name declarations and +these go in files with .gd extensions; these files are read in via +ReadPackage commands in the init.g file. The implementation part +of a package consists of the actual definitions of the functions and +variables whose names were declared in the declaration part, and +these go in files with .gi extensions; these files are read in via +ReadPackage commands in the read.g file. The reason for following the +above dichotomy is that the read.g file is read after the init.g +file, thus enabling the possibility of a function's implementation to +refer to another function whose name is known but is not actually defined +yet (see +below for more details). +

+The &GAP; code (whether or not it is split into declaration and +implementation parts) should go in the package's lib directory +(see below). + + +doc + +GAPDoc format +This directory should contain the package's documentation, written in an +XML-based documentation format supported by the &GAP; package &GAPDoc; +(see ) +which is used for the &GAP; documentation itself. +

+The Example package's documentation (see its doc +directory) may be used as a prototype. It consists of the master file +main.xml, further .xml files for manual chapters (included in +the manual via Include directives in the master file) and the &GAP; +input file ../makedocrel.g which generates the manuals. +Generally, one should also provide a manual.bib Bib&TeX; database +file or an xml file in the BibXMLext format (see +). +

+ +One could also use the AutoDoc which simplifies writing +documentation by generating most of the &GAPDoc; code automatically. + + +lib + +This is the preferred place for the &GAP; code of the package, i.e. the +.g, .gd and .gi files (other than PackageInfo.g, +init.g and read.g). For some packages, the directory gap +has been used instead of lib; lib has the advantage that it is +the default subdirectory of a package directory searched for by the + command. + + +src + +If the package contains non-&GAP; code, e.g. C code, then this source +code should go in the src directory. If there are .h +include files you may prefer to put these all together in a separate +include directory. There is one further rule for the location of kernel +library modules or external programs which is explained in + below. + + +tst + +It is highly recommended that a package should have test files, which then +should go in the tst directory. For a deposited package, a test file +with a basic test of the package (for example, to check that it works as +expected and/or that the manual examples are correct) may be specified in the +PackageInfo.g to be included in the &GAP; standard test suite +and run as a part of the &GAP; release preparation. +More specific and time consuming tests are not supposed to be a part of the +&GAP; standard test suite but may be placed in the tst directory +with further instructions on how to run them. +See Section about the requirements +to the test files formats and further recommendations. + + + + +All other files can be organised as you like. But we suggest that you +have a look at existing packages and use a similar scheme, for +example, put examples in the examples subdirectory, data +libraries in extra subdirectories, and so on. +

+Sometimes there may be a need to include an empty directory in the +package distribution (for example, as a place to store some data that +may appear at runtime). In this case package authors are +advised to put in this directory a short README file describing +its purpose to ensure that such directory will be included in the +redistribution. +

+Concerning the &GAP; code in packages, it is recommended to use only +documented &GAP; functions, see . +In particular if you want to make your package available to other &GAP; users +it is advisable to avoid using obsolete variables +(see ). To test that +the package does not use obsolete variables you can set the ReadObsolete +component in your gap.ini file to false (see +) or start &GAP; with -A -O command line +options (note that this may also cause problems with loading other +packages that use obsolete variables). + +

+ + +
+Writing Documentation and Tools Needed + +If you intend to make your package available to other users it is +essential to include documentation explaining how to install and use your +programs. +

+Concerning the installation you should produce a README file which +gives a short description of the purpose of the package and contains +proper instructions how to install your package. Again, check out some +existing packages to get an idea how this could look like. +

+Documentation for &GAP; package should be prepared in an XML-based +documentation format that is defined in and can be used with the &GAPDoc; +package (see ). +

+There should be at least a text version of your documentation provided for use +in the terminal running &GAP; and some nicely printable version in +.pdf format. +Many &GAP; users like to browse the documentation in HTML format +via their Web browser. As a package author, you are not obliged +to provide an HTML version of your package manual, + +but if you use the &GAPDoc; package you should have no trouble in producing one. +

+Moreover, using the +&GAPDoc; package, it is also possible to produce HTML version of the +documentation supporting MathJax (http://www.mathjax.org/) +for the high quality rendering of mathematical symbols while viewing +it online. For example, if you are viewing the HTML version of the manual, +compare how this formula will look with MathJax turned on/off: + +[ \chi, \psi ] = \left( \sum_{{g \in G}} \chi(g) \psi(g^{{-1}}) \right) / |G|. + +

+The manual of the Example package is written in the &GAPDoc; format, +and commands needed to build it are contained in the file makedocrel.g +(you don't need to re-build the manual since it is already included in the package). +You will also need to have certain &TeX; tools installed: to produce manuals in +the .pdf format, you need pdflatex. +

+In principle it is also possible to use alternative documentation +systems. Historically, there is one such &TeX;-based system, +which predates &GAPDoc;, and which is still in use by several packages. +However, we do not recommend using it for new packages. +

+ + + +
+An Example of a GAP Package + +We illustrate the creation of a &GAP; package by an example of a very basic package. +

+Create the following directories in your home directory: +.gap, .gap/pkg and .gap/pkg/test. +Then inside the directory .gap/pkg/test create an empty file +init.g, and a file PackageInfo.g with the following contents: +

+ +

+This file declares the &GAP; package with name test in version 1.0. +The package documentation consists of one autoloaded book; the SixFile +component is needed by the &GAP; help system. Package dependencies (picked +for the purposes of this example) require at least &GAP; 4.9 and &GAPDoc; +package at version at least 1.6, and these conditions will be checked when the +package will be loaded (see ). +Since there are no requirements that have to be tested, +AvailabilityTest just uses . +

+Now start &GAP; (without using the -r option) and the .gap +directory will be added to the &GAP; root directory to +allow &GAP; to find the packages installed there +(see ). +

+ LoadPackage("test"); +true +]]> +

+This &GAP; package is too simple to be useful, but we have succeeded +in loading it via , satisfying all specified +dependencies. + +

+ + + +
+File Structure + +Package files may follow the style used for the &GAP; library. +Every file in the &GAP; library starts with a header that lists the +filename, copyright, a short description of the file contents and the +original authors of this file, and ends with a comment line #E. +Indentation in functions and the use of decorative spaces in the code +are left to the decision of the authors of each file. Global (i.e. +re-used elsewhere) comments usually are indented by two hash marks and +two blanks, in particular, every declaration or method or function +installation which is not only of local scope is separated by a header. +

+Facilities to distribute a document over several files +to allow the documentation for parts of some code to be stored in +the same file as the code itself are provided by the &GAPDoc; package (see +). +The same approach is demonstrated by the Example package. +E.g. example/doc/example.xml has the statement +<#Include Label="ListDirectory"> +and example/lib/files.gd contains + +## +## +## +## +## lists the files in directory dir (a string) +## or the current directory if called with no arguments. +## +## +## <#/GAPDoc> +DeclareGlobalFunction( "ListDirectory" ); +]]> +This is all put together in the file example/makedocrel.g which +builds the package documentation, calling + with +locations of library files containing parts of the +documentation. +

+Alternatively, one could use the AutoDoc, which simplifies +writing documentation by generating most of the &GAPDoc; code automatically. +The equivalent of the fragment of the code above for AutoDoc +would look like +dir (a string) +#! or the current directory if called with no arguments. +DeclareGlobalFunction( "ListDirectory" ); +]]> +

+ + + + +
+Creating the PackageInfo.g File +ValidatePackageInfo +While the minimalistic PackageInfo.g file described in + is enough to let &GAP; +load the package, and check all specified dependencies, it is +actually missing many extra fields which become relevant if you want to +distribute your package: they contain lists of authors and/or maintainers +including contact information, URLs of the package archives and README files, +status information, text for a package overview webpage, and so on. All +these details are required for a package to be redistributed with &GAP;. +

+The command can be used to get a quick idea about which +fields are missing: + ValidatePackageInfo("PackageInfo.g"); +#E component `Subtitle' must be bound to a string +#E component `Date' must be bound to a string of the form `dd/mm/yyyy' +#E component `ArchiveURL' must be bound to a string started with http://, https:// or ftp:// +#E component `ArchiveFormats' must be bound to a string +#E component `Status' must be bound to one of "accepted", "deposited", "dev", "other" +#E component `README_URL' must be bound to a string started with http://, https:// or ftp:// +#E component `PackageInfoURL' must be bound to a string started with http://, https:// or ftp:// +#E component `AbstractHTML' must be bound to a string +#E component `PackageWWWHome' must be bound to a string started with http://, https:// or ftp:// +#E component `ArchiveURLSubset' must be bound to a list of strings denoting relative paths to readable files or directories +#E component `HTMLStart' must be bound to a string denoting a relative path to a readable file +#E component `PDFFile' must be bound to a string denoting a relative path to a readable file +#E component `SixFile' must be bound to a string denoting a relative path to a readable file +#E component `LongTitle' must be bound to a string +false +]]> +

+We suggest to create a PackageInfo.g file for your package by +copying the one in the Example package, distributed +with &GAP;, or using the PackageMaker +(https://github.com/gap-system/PackageMaker), and then adjusting +it for your package. Within &GAP; you can look at this template file for a +list and explanation of all recognised entries by + +

+Instead of populating the rest of the PackageInfo.g by hands, +you can also create a basic &GAP; package with the help of the +tool called PackageMaker, available at +https://github.com/gap-system/PackageMaker. The +PackageMaker asks several questions about the intended +package and then creates a new directory for it and populates it with all +the files needed for a basic package. + +

+ + + + +
+Functions and Variables and Choices of Their Names + +In writing the &GAP; code for your package you need to be a little +careful on just how you define your functions and variables. +

+Firstly, in general one should avoid defining functions and variables +via assignment statements in the way you would interactively, e.g. +

+ Squared := x -> x^2;; +gap> Cubed := function(x) return x^3; end;; +]]> +

+The reason for this is that such functions and variables are easily +overwritten and what's more you are not warned about it when it happens. +

+To protect a function or variable against overwriting there is the +function , +or alternatively (and equivalently) you may define a global +function via a +and pair +or a global variable via a +and pair. There are also operations +and their methods, and related objects like attributes and filters which +also have Declare... and Install... pairs. +

+Secondly, it's a good idea to reduce the chance of accidental +overwriting by choosing names for your functions and variables that begin +with a string that identifies it with the package, e.g. some of the +undocumented functions in the Example package begin with Eg. This is +especially important in cases where you actually want the user to be able +to change the value of a function or variable defined by your package, +for which you have used direct assignments (for which the user will +receive no warning if she accidentally overwrites them). It's also +important for functions and variables defined via BindGlobal, +DeclareGlobalFunction/InstallGlobalFunction and +DeclareGlobalVariable/InstallValue, in order to avoid name clashes +that may occur with (extensions of) the &GAP; library and other +packages. +

+local namespace +Additionally, since &GAP; 4.5 a package may place global variables into +a local namespace as explained in + in order to avoid +name clashes and preserve compatibility. This new feature +allows you to define in your package global variables with the identifier +ending with the @ symbol, e.g. xYz@. Such variables may be used +in your package code safely, as they may be accessed from outside the package +only by their full name, i.e. xYz@YourPackageName. This helps to prevent +clashes between different packages or between a package and the &GAP; library +because of the same variable names. + +

+On the other hand, operations and their methods (defined via +, + etc. pairs) +and their relatives do not need this consideration, as they +avoid name clashes by allowing for more than one method +for the same-named object. +

+To demonstrate the definition of a function via a +DeclareOperation/InstallMethod pair, +the method was included in the Example package; +Recipe( FruitCake ); gives a method for making a +fruit cake (forgive the pun). +

+Thirdly, functions or variables with SetXXX or HasXXX names +(even if they are defined as operations) should be avoided as these may +clash with objects associated with attributes or properties (attributes +and properties XXX declared via the DeclareAttribute and +DeclareProperty commands have associated with them testers of form +HasXXX and setters of form SetXXX). +

+Fourthly, it is a good idea to have some convention for internal +functions and variables (i.e. the functions and variables you don't +intend for the user to use). For example, they might be entirely +CAPITALISED. +

+Additionally, there is a recommended naming convention that the &GAP; core +system and &GAP; packages should not use global variables starting in the +lowercase. This allows to reserve variables with names starting in lowercase +to the &GAP; user so they will never clash with the system. It is extremely +important to avoid using for package global variables very short names +started in lowercase. For example, such names like cs, exp, +ngens, pc, pow which are perfectly fine for local +variables, should never be used for globals. Additionally, the package must +not have writable global variables with very short names even if they are +starting in uppercase, for example, C1 or ORB, since they +also could be easily overwritten by the user. +

+It is a good practice to follow naming conventions used in &GAP; as +explained in and +, which +might help users to memorize or even guess names of functions +provided by the package. +

+Finally, note the advantage of using +DeclareGlobalFunction/InstallGlobalFunction, +DeclareGlobalVariable/InstallValue, etc. pairs (rather than +BindGlobal) to define functions and variables, which allow the package +author to organise her function- and variable- definitions in any order +without worrying about any interdependence. The Declare... statements +should go in files with .gd extensions and be loaded by ReadPackage +statements in the package init.g file, and the Install... definitions +should go in files with .gi extensions and be loaded by ReadPackage +statements in the package read.g file; this ensures that the .gi +files are read after the .gd files. All other package code should go +in .g files (other than the init.g and read.g files themselves) and +be loaded via ReadPackage statements in the init.g file. +

+ +ShowPackageVariables +In conclusion, here is some practical advice on how to check which variables +are used by the package. +

+Firstly, there is a function +. +If the package pkgname is available +but not yet loaded then ShowPackageVariables( pkgname ) +prints a list of global variables that become bound and of methods +that become installed when the package is loaded (for that, the package +will be actually loaded, so ShowPackageVariables can be called +only once for the same package in the same &GAP; session.) +The second optional argument version may specify a particular +package version to be loaded. +An error message will be printed if (the given version of) the package +is not available or already loaded. +

+Info lines for undocumented variables will be marked with an asterisk +*. Note that the &GAP; help system is case insensitive, +so it is difficult to document identifiers that differ only by case. +

+The following entries are omitted from the list: +default setter methods for attributes and properties that are declared +in the package, +and Setattr and Hasattr type variables +where attr is an attribute or property. +

+For example, for the Example package +it may produce the output looking like this: + ShowPackageVariables("example"); +---------------------------------------------------------------- +Loading Example 3.3 (Example/Template of a GAP Package) +by Werner Nickel (http://www.mathematik.tu-darmstadt.de/~nickel), + Greg Gamble (http://www.math.rwth-aachen.de/~Greg.Gamble), and + Alexander Konovalov (http://www.cs.st-andrews.ac.uk/~alexk/). +---------------------------------------------------------------- +new global functions: + EgSeparatedString( str, c )* + FindFile( dir, file ) + HelloWorld( ) + ListDirectory( arg ) + LoadedPackages( ) + WhereIsPkgProgram( prg ) + Which( prg ) + +new global variables: + FruitCake + +new operations: + Recipe( arg ) + +new methods: + Recipe( cake ) +]]> + +Another trick is to start &GAP; with -r -A options, immediately +load your package and then call +which returns a list of the global variable names created since the +library was read, to which a value is currently bound. For example, for the +Example it produces + NamesUserGVars(); +[ "EgSeparatedString", "FindFile", "FruitCake", "HelloWorld", "ListDirectory", + "LoadedPackages", "Recipe", "WhereIsPkgProgram", "Which" ] +]]> +but for packages with dependencies it will also contain variables created by +other packages. Nevertheless, it may be a useful check to search for unwanted +variables appearing after package loading. A potentially dangerous situation +which should be avoided is when the package uses some simply named temporary +variables at the loading stage. Such phantom variables may then remain +unnoticed and, as a result, there will be no warnings if the user occasionally +uses the same name as a local variable name in a function. Even more +dangerous is the case when the user variable with the same name already exists +before the package is loaded so it will be silently overwritten. + +

+ + + +
+Package Dependencies (Requesting one &GAP; Package from within Another) + +needed package +suggested package +dependencies +It is possible for one &GAP; package A, say, +to require another package B. +For that, one simply adds the name and the (least) version number of the +package B to the NeededOtherPackages component of the +Dependencies component of the PackageInfo.g file of the package +A. +In this situation, loading the package A forces that also the package +B is loaded, and that A cannot be loaded if B is not +available. +

+ +If B is not essential for A but should be loaded if it is +available +(for example because B provides some improvements of the main system +that are useful for A) +then the name and the (least) version number of B should be added to +the SuggestedOtherPackages component of the +Dependencies component of the PackageInfo.g file of A. +In this situation, loading A forces an attempt to load also B, +but A is loaded even if B is not available. +

+ +Also the component Dependencies.OtherPackagesLoadedInAdvance in +PackageInfo.g is supported, which describes needed packages that +shall be loaded before the current package is loaded. +See +for details about this and more generally about the order in which the files +of the packages in question are read. +

+ +All package dependencies must be documented explicitly in the +PackageInfo.g file. It is important to properly +identify package dependencies and make the right decision +whether the other package should be needed or suggested. +For example, declaring package as needed when suggested +might be sufficient may prevent loading of packages under Windows for +no good reason. +

+ +It is not appropriate to explicitly call + when the package is loaded, +since this may distort the order of package loading and result in warning +messages. It is recommended to turn such dependencies into needed or +suggested packages. For example, a package can be designed in such a way +that it can be loaded with restricted functionality if another package +(or standalone program) is missing, and in this case the missing package +(or binary) is suggested. Alternatively, if the package author +decides that loading the package in this situation makes no sense, +then the missing component is needed. +

+ +On the other hand, if is called +inside functions of the package then there is no such problem, provided +that these functions are called only after the package has been loaded, +so it is not necessary to specify the other package as suggested. The same +applies to test files and manual examples, which may be simply extended +by calls to . +

+ +OnlyNeeded +It may happen that a package B that is listed as a suggested +package of package A is actually needed by A. +If no explicit calls for B +occur in A at loading time, this can now be detected using +the new possibility to load a package without loading its suggested +packages using the global option OnlyNeeded which +can be used to (recursively) suppress loading the suggested packages +of the package in question. Using this option, one can check whether +errors or warnings appear when B is not available (note that this option +should be used only for such checks to simulate the situation when +package B is not available; it is not supposed to be used in an actual +&GAP; session when package B will be loaded later, since this may cause +problems). In case of any errors or warnings, their consequence can +then be either turning B into a needed package or (since apparently B +was not intended to become a needed package) changing the code accordingly. +Only if package A calls for B at +loading time (see above) then package B needs to be deinstalled +(i.e. removed) to test loading of A without B. + +

+ +Finally, if the package manual is in the &GAPDoc; format, +then &GAPDoc; should still be listed as needed for +this package (not as suggested), even though &GAPDoc; +is now a needed package for &GAP; itself. +

+ +

+ + + + +
+Declaration and Implementation Part of a Package + +When &GAP; packages require each other in a circular way, +a bootstrapping problem arises of defining functions before they are +called. +The same problem occurs in the &GAP; library, and it is resolved there +by separating declarations (which define global variables such as +filters and operations) +and implementations (which install global functions and methods) +in different files. +Any implementation file may use global variables defined in any declaration +file. +&GAP; initially reads all declaration files (in the library they have a +.gd suffix) and afterwards reads all implementation files +(which have a .gi suffix). +

+Something similar is possible for &GAP; packages: +if a file read.g exists in the home directory of the package, +this file is read only after all the init.g files of all +(implicitly) required &GAP; packages are read. +Thus one can separate declaration and implementation for a &GAP; package +in the same way as is done for the &GAP; library, +by creating a file read.g, +restricting the statements in +init.g to only read those files of the package that provide +declarations, +and to read the implementation files from read.g. +

+Examples: +

+Suppose that there are two packages A and B, +each with files init.g and read.g. +

+ + + If package A suggests or needs package B + and package B does not need or suggest any other package + then first init.g of B is read, + then read.g of B, + then init.g of A, + then read.g of A. + + + If package A suggests or needs package B + and package B (or a package that is suggested or needed by B) + suggests or needs package A + then first the files init.g of A and B are read + (in an unspecified order) + and then the files read.g of A and B + (in the same order). + + +

+ +In general, when &GAP; is asked to load a package then first the dependencies +between this packages and its needed and suggested packages are inspected +(recursively), and a list of package sets is computed such that no cyclic +dependencies occur between different package sets and such that no package +in any of the package sets needs any package in later package sets. +Then &GAP; runs through the package sets and reads for each set first all +init.g files and then all read.g files of the packages in the +set. +(There is one exception from this rule: +Whenever packages are autoloaded before the implementation part of the &GAP; +library is read, only the init.g files of the packages are read; +as soon as the &GAP; library has been read, the read.g files of these +packages are also read, and afterwards the above rule holds.) +

+ +IsPackageMarkedForLoading +It can happen that some code of a package depends on the availability of +suggested packages, i.e., different initialisations are performed +depending on whether a suggested package will eventually be loaded or not. +One can test this condition with the function +. +In particular, one should not call +(and use the value returned by this call) the function + inside +package code that is read during package loading. +Note that for debugging purposes loading suggested packages may +have been deliberately disabled via the global option OnlyNeeded. +

+ +Note that the separation of the &GAP; code of packages into declaration +part and implementation part does in general not allow one to actually +call functions from a package when the implementation part is read. +For example, +in the case of a cyclic dependency as in the second example above, +suppose that B provides a new function f or a new global record +r, say, which are declared in the declaration part of B. +Then the code in the implementation part of A may contain +calls to the functions defined in the declaration part of B. +However, the implementation part of A may be read +before the implementation part of B. +So one can in general not assume that during the loading of A, +the function f can be called, or that one can access components of +the record r. +

+ +If one wants to call the function f or to access components of the +record r in the code of the package A then the problem is +that it may be not possible to determine a cyclic dependency between A +and B from the packages A and B alone. +A safe solution is then to add the name of B to the component +Dependencies.OtherPackagesLoadedInAdvance of the PackageInfo.g +file of A. +The effect is that package B is completely loaded before the file +read.g of A is read, provided that there is no cyclic +dependency between A and B, +and that package A is regarded as not available in the case that +such a cyclic dependency between A and B exists. +

+ +A special case where Dependencies.OtherPackagesLoadedInAdvance +can be useful is that a package wants to force the complete &GAP; library +to be read before the file read.g of the package A is read. +In this situation, the package name "gap" should be added +to this component in the PackageInfo.g file of A. +

+ +autoreadable variables +In the case of cyclic dependencies, one solution for the above problem +might be to delay those computations (typically initialisations) +in package A that require package B to be loaded +until all required packages are completely loaded. +This can be done by moving the declaration and implementation of the +variables that are created in the initialisation into a separate file +and to declare these variables in the init.g file of the package, +via a call to +(see also ). +

+ +

+ + + +
+Autoreadable Variables + +Package files containing method installations must be read +when the package is loaded. +For package files not containing method installations +(this applies, for example, to many data files) +another mechanism allows one to delay reading such files +until the data are actually accessed. See + for further +details. + +
+ + + + +
+Standalone Programs in a &GAP; Package + + + +&GAP; packages that involve stand-alone programs are fundamentally +different from &GAP; packages that consist entirely of &GAP; code. +

+This difference is threefold: A user who installs the &GAP; package +must also compile (or install) the package's binaries, the +package must check whether the binaries are indeed available, +and finally the &GAP; code of the package has to start the external +binary and to communicate with it. +We will cover these three points in the following sections. +

+If the package does not solely consist of an interface to an external +binary and if the external program called is not just special-purpose +code, but a generally available program, chances are high that sooner +or later other &GAP; packages might also require this program. +We therefore strongly recommend the provision of a documented &GAP; +function that will call the external binary. We also suggest to create +actually two &GAP; packages; the first providing only the binary and the +interface and the second (requiring the first, +see ) being the actual &GAP; package. +

+ + + + +Installation of &GAP; Package Binaries + +sysinfo.gap +external binaries +The scheme for the installation of package binaries which is described +further on is intended to permit the installation on different +architectures which share a common file system (and share the +architecture independent file). +

+A &GAP; package which includes external binaries contains a bin +subdirectory. This subdirectory in turn contains subdirectories for +the different architectures on which the &GAP; package binaries are +installed. The names of these directories must be the same as the +names of the architecture dependent subdirectories of the main bin +directory. Unless you use a tool like autoconf yourself, you must +obtain the correct name of the binary directory from the main &GAP; +branch. To help with this, the main &GAP; directory contains a file +sysinfo.gap which assigns the shell variable GAParch to the +proper name as determined by &GAP;'s configure process. +For example on a Linux system, the file sysinfo.gap may look like +this: +

+ +

+We suggest that your &GAP; package contains a file configure which +is called with the path of the &GAP; root directory as +parameter. This file then will read sysinfo.gap and set up +everything for compiling under the given architecture (for example +creating a Makefile from Makefile.in). As initial templates, +you may use installation scripts of the Example package +or files generated with the help of PackageMaker. + + + + + +Test for the Existence of GAP Package Binaries + +If an external binary is essential for the workings of a &GAP; package, +the function stored in the component AvailabilityTest of the +PackageInfo.g file of the package should test whether the program +has been compiled on the architecture (and inhibit package loading +if this is not the case). +This is especially important if the package is loaded automatically. +

+The easiest way to accomplish this is to use + +for checking for the actual binaries in the path given by + +for the respective package. +For example the example &GAP; package could use the +following function to test whether the binary hello has been compiled; +it will issue a warning if not, and will only load the package if the binary +is indeed available: +

+ fail; + end, +... +]]> +

+However, if you look at the actual PackageInfo.g file of the +example package, you will see that its +AvailabilityTest function always returns true, +and just logs the warning if the binary is not available +(which may be later viewed with +). +This means that the binary is not regarded as essential for this +package. +

+You might also have to cope with the situation that external binaries will +only run under UNIX (and not, say, under Windows), or may not compile with +some compilers or default compiler options. +See  +for information on how to test for the architecture. +

+LogPackageLoadingMessage +Last but not least: do not print anything in the AvailabilityTest +function of the package via Print or Info. Instead one should +call to store +a message which may be viewed later with + +(the latter two functions have been introduced in &GAP; 4.5) + + + + + + +Calling of and Communication with External Binaries + +There are two reasons for this: the input data has to be passed on to +the stand-alone program and the stand-alone program has to be started +from within &GAP;. +

+There are two principal ways of doing this. +

+The first possibility is to write all the data for the stand-alone to +one or several files, then start the stand-alone with + or + +which then writes the output data to file, and finally read in +the standalone's output file. +

+The second way is interfacing via input-output streams, +see Section . +

+Some &GAP; packages use kernel modules +(see ) +instead of external binaries. +A kernel module is implemented in C and follows certain conventions to +comply with the &GAP; kernel interface, which we plan to document later. +In the meantime, we advise you to look at existing examples of such packages +and get in touch with &GAP; developers if you plan to develop such a package. + + + +

+ + + + +
+Having an InfoClass + + + +InfoClass +It is a good idea to declare an InfoClass for your package. This gives +the package user the opportunity to control the verbosity of output +and/or the possibility of receiving debugging information +(see ). Below, we give a quick +overview of its utility. +

+An InfoClass is defined with a DeclareInfoClass( InfoPkgname ); +statement and may be set to have an initial InfoLevel other than the +zero default (which means no Info statement is to output information) +via a SetInfoLevel( InfoPkgname, level ); statement. An initial +InfoLevel of 1 is typical. +

+Info statements have the form: +Info( InfoPkgname, level, expr1, expr2, ...); +where the expression list expr1, expr2, ... +appears just like it would in a Print statement. The only difference is +that the expression list is only printed (or even executed) if the +InfoLevel of InfoPkgname is at least level. + +

+ + + + +
+The Banner + + + +banner + +When the package is loaded, &GAP; will display a default package banner, +constructed from the package metadata provided in the PackageInfo.g file. +

+Alternatively, the package may establish its own banner by assigning a string +to the BannerString field of the record argument of SetPackageInfo +in the PackageInfo.g file. +

+If you will be designing a banner for your package, it is a good idea to suggest +there how to access package documentation. For example, the banner of the +Example package says: +

+ +

+In order for this to display the introduction of the +Example package the index-entry +&tlt;Index&tgt;Example package&tlt;/Index&tgt; +was added just before the first paragraph of the introductory section in +the file doc/example.xml of the Example package. + +

+ + + +
+Version Numbers + +version number +Version numbers are strings containing nonnegative integers separated +by non-numeric characters. They are compared by + +which first splits them at non-digit characters and then lexicographically +compares the resulting integer lists. +Thus version "2-3" is larger than version "2-2-5" +but smaller than "4r2p3" or "11.0". +

+It is possible for code to require &GAP; packages in certain +versions. In this case, all versions, whose number is equal or larger +than the requested number are acceptable. It is the task of the +package author to provide upwards compatibility. +

+Loading a specific version of a package (that is, not one with a +larger version number) can be achieved by prepending = to the desired +version number. +For example, LoadPackage( "example", "=1.0" ) will load version +"1.0" of the package "example", +even if version "1.1" is available. +As a consequence, version numbers must not start with =, +so "=1.0" is not a valid version number. +

+Package authors should choose a version numbering scheme that admits a +new version number even after tiny changes to the package, and +ensure that version numbers of successive package versions increase. +The automatic update of package archives in the &GAP; distribution will +only work if a package has a new version number. +

+It is a well-established custom to name package archives like +name-version.tar.gz, name-version.tar.bz2 etc., +where name is the lower case name, and version is +the version (another custom is that the archive then should extract +to a directory that has exactly the name name-version). +

+It is very important that there should not ever be, for a given &GAP; +package, two different archives with the same package version number. +If you make changes to your package and place a new archive of the +package onto the public server, please ensure that a new archive has +a new version number. This should be done even for very minor changes. +

+For most of the packages it will be inappropriate to re-use the date +of the release as a version number. It's much more obvious how big are +the changes between versions "4.4.12", "4.5.1" and "4.5.2" than between +versions "2008.12.17", "2011.04.15" and "2011.09.14". The concept of +using version numbers to convey the meaning of the status of the code +and the way it has been modified is known as Semantic Versioning, +see http://semver.org/ for further recommendations on its use. +

+Since version information is duplicated in several places throughout the +package documentation, for &GAPDoc;-based manuals you may define the +version and the release manual in the comments in PackageInfo.g +file close to the place where you specified its Version and +Date components, for example + +## +## +## +## <#/GAPDoc> +]]> +notify that a part of the +document is stored in PackageInfo.g (see example/makedocrel.g), +read this data into the header of the main document via +<#Include Label="PKGVERSIONDATA"> directive and then use them via +&VERSION; and &RELEASEDATE; entities almost everywhere where you +need to refer to them (most commonly, in the title page and installation +instructions). + +

+ + + +
+Testing a &GAP; package + +There are several aspects of testing a &GAP; package. +

+First, one should ensure that the package functionality works as expected. +Below we give an advice on creating test files for automated tests that may +be run by package authors, by &GAP; developers as part of the release +preparation, and by package users interested in checking that the package +works. Such tests should be included in the package distribution, and the +responsibility for ensuring that they pass stays with package authors. +

+Second, the package should cleanly integrate into the &GAP; system and other +packages, and should not break their functionality. In particular, all tests +from the standard &GAP; testing suite should pass if the package is loaded. +This is more comprehensive and time consuming test, which &GAP; developers +regularly run using special tools. They will report to you any detected issues. +Below we explain how to do several simple and less time consuming checks +which package authors are recommended to perform themselves. + + +Tests files for a GAP package + +The (optional) tst directory of your package may contain as +many tests of the package functionality as appears appropriate. These tests +should be organised into test files similarly to those in the tst +directory of the &GAP; distribution as documented in +. +

+For a deposited package, a test file with a basic test of the package +(for example, to check that it works as expected and/or that the manual +examples are correct) may be specified in the component TestFile +in the PackageInfo.g to be included in the &GAP; standard test suite. +This file can either consist of calls of or + (in this case, it is common to call it testall.g) +or be itself a test file having an extension .tst and supposed to be +read via . It is assumed that the +latter case occurs if and only if the file contains the substring

"gap> START_TEST(" +

+\noindent +(with exactly one space after the &GAP; prompt). +

+For deposited packages, these tests are run by the &GAP; Group regularly, +as a part of the standard &GAP; test suite. For the efficient testing it +is important that the test specified in the PackageInfo.g file +does not display any output (e.g. no test progress indicators) except +reporting discrepancies if such occur and the completion report as +in the example below: + Test("tst/testall.tst"); +Example package: testall.tst +GAP4stones: 3333 +true +]]> +Tests which produce extended output and/or require substantial runtime +are not supposed to be a part of the &GAP; standard test suite but may +be placed in the tst directory of the packages with further +instructions on how to run them elsewhere. +

+Because of different approaches to testing, used by different packages, +it is not always easy to identify whether an automated test passed or failed. +Presently, automated detection works fine if a package uses a single +.tst file or uses to run a collection of +tests. Otherwise, one should follow the convention to output a string of a +fixed format to indicate the result of the test in the test script along the +following lines: + + + + + +Testing &GAP; package loading + +To test that your package may be loaded into &GAP; without any problems +and conflicts with other packages, test that it may be loaded in various +configurations: + + +starting &GAP; with no packages (except needed for &GAP;) using -r -A options +and calling LoadPackage("packagename"); + + +starting &GAP; with no packages (except needed for &GAP;) using -r -A options +and calling LoadPackage("packagename" : OnlyNeeded ); + + +starting &GAP; in the default configuration (with no options) +and calling LoadPackage("packagename"); + + +starting &GAP; in the default configuration (with no options) +and calling LoadPackage("packagename" : OnlyNeeded ); + + +finally, together with all other packages using + (see below) in four possible combinations +of starting &GAP; with/without -r -A options and calling + with/without Reversed option. + + +The test of loading all packages is the most subtle one. Quite often +it reveals problems which do not occur in the default configuration +but may cause difficulties to the users of specialised packages. +

+For your convenience, make testpackagesload called in the &GAP; +root directory will run all package loading tests listed in this subsection +and write their output in its dev/log directory. +

+It will produce four files with test logs, corresponding to the +four cases above (the letter N in the filename stands for +needed, A stands for autoloaded): + + +dev/log/testpackagesload1_... + + +dev/log/testpackagesloadN1_... + + +dev/log/testpackagesloadA_... + + +dev/log/testpackagesloadNA_... + + +Each file contains small sections for loading individual packages: among those, +you need to find the section related to your package and may ignore all other +sections. For example, the section for the Example package looks like + +so it has clearly passed the test. If there are any error messages displayed +between Loading ... and Loaded ... lines, they will signal on +errors during loading of your package. +

+Additionally, this test collects information about variables created since +the library was read (obtained using ) +with either short names (no more than three characters) or names breaking a +recommended naming convention that the &GAP; core system and &GAP; packages +should not use global variables starting in the lowercase +(see Section ). +Their list will be displayed in the test log (in the example above, Example +packages does not create any such variables, so an empty list is displayed). +It may be hard to attribute a particular identifier to a package, since it +may be created by another package loaded because of dependencies, so when +a more detailed and precise report on package variables is needed, it may +be obtained using +(also, make testpackagesvars called in the &GAP; root directory +produces such reports for each package and writes them to a file +dev/log/testpackagesvars_...). +

+Finally, each log file finishes with two large sections for loading all +packages in the alphabetical and reverse alphabetical order (to check more +combinations of loading one package after another). We are aiming at +releasing only collections of package which do not break + in any of the four configurations, so if +it is broken when you plug in the development version of your package into +the released version of &GAP;, it is likely that your package triggers +this error. If you observe that is broken +and suspect that this is not the fault of your package, please contact +the &GAP; Support. + + + + + +loads all &GAP; packages from their list sorted in alphabetical order +(needed and suggested packages will be loaded when required). This is a +technical function to check packages compatibility, so it should NOT be +used to run anything except tests; it is known that &GAP; performance is +slower if all packages are loaded. To introduce some variations of the +order in which packages will be loaded for testing purposes, + accepts option Reversed to load +packages from their list sorted in the reverse alphabetical order. + + + + + +Testing a &GAP; package with the &GAP; standard test suite + +The tst directory of the &GAP; installation contains a selection of +test files and scripts such as testinstall.g and teststandard.g +which are a part of the &GAP; standard test suite. +

+ +It is important to check that your package does not break &GAP; standard +tests. To perform a clean test and avoid interfering with other packages, +first you must start a new &GAP; session and then read either testinstall.g +or teststandard.g as demonstrated below. +

+ +The quicker test, testinstall.g, requires about 1 GB of memory and +runs for several minutes. It may be started with the command + Read( Filename( DirectoriesLibrary( "tst" ), "testinstall.g" ) ); +]]> +You will get a large number of lines with output about the progress of +the tests, for example: + +

+ +(optionally, you may start &GAP; with the command line options which you +will see in the test output, to run it in a more conservative settings). +

+ +The more thorough test is teststandard.g which exercises more of &GAP;'s +capabilities, also including all test files from teststandard.g. +It requires about 1 GB of memory, runs for about one hour, and produces +an output similar to the testinstall.g test. +To run it, also start a new &GAP; session and then call + Read( Filename( DirectoriesLibrary( "tst" ), "testall.g" ) ); +]]> +You may repeat the same check loading your package with OnlyNeeded +option. Remember to perform each subsequent test in a new &GAP; session. +

+Also you may perform individual tests from the tst directory of the +&GAP; installation loading them with . +

+ + + +

+ + + +
+Access to the &GAP; Development Version + +We are aiming at providing a stable platform for package development and +testing with official &GAP; releases. We also invite everyone to contribute +by submitting patches, pull requests, and bug reports. We would like to +make the contributing process as easy as possible. +

+The main GAP development repository is hosted on GitHub at +https://github.com/gap-system/gap. Many &GAP; packages +also have public repositories and issue trackers, and we are keeping +a list of such packages at https://gap-packages.github.io/. +

+For further information about contributing to the GAP development, please see +https://github.com/gap-system/gap/blob/master/CONTRIBUTING.md. +

+ + + +
+Version control and continuous integration for &GAP; packages + +As we have mentioned above, many &GAP; packages have public repositories and +issue trackers on GitHub, and we are keeping a list of such packages at +https://gap-packages.github.io/. We welcome establishing public +repositories for new packages and migrating existing package repositories +there as well. Such repositories may be hosted under their authors' accounts +or under the gap-packages organisation (https://github.com/gap-packages/). +The latter has the benefit that while the authors will preserve their deciding +role on all aspects of the package development, the package will become more +visible for potential collaborators and &GAP; developers may help to set up +continuous integration for your package so that every commit to the +repository will trigger automated running of package tests and reporting any +failures to package maintainers. +
+ + + +
+Selecting a license for a &GAP; Package + +As it was mentioned in the description of the LICENSE file in +Section , +it is advised to make clear in the documentation of the package the basis +on which it is being distributed to users. &GAP; itself is distributed under +the GNU Public License version 2 (version 2 or later). We would encourage +you to consider the GPL license for your packages, but you might wish to be more +restrictive (for instance forbidding redistribution for profit) or less +restrictive (allowing your software to be incorporated into commercial +software). See Choosing a License for the Distribution of Your Package +from http://www.gap-system.org/Packages/Authors/authors.html and also +https://choosealicense.com/ for further details. +

+ +In the past many &GAP; packages used the text +We adopt the copyright regulations of &GAP; as detailed in the copyright +notice in the &GAP; manual or a similar statement. We now advise to be +more explicit by making the exact reference to the GPL license, for example: +

+ +packagename is free software; you can redistribute it +and/or modify it under the terms of the +http://www.fsf.org/licenses/gpl.html +as published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +and also including a copy of the full text of the license. + +

+ + +
+Releasing a GAP Package + +Currently, the &GAP; distribution provides archives in four different +formats. +

+ +.tar.gz + + a standard UNIX tar archive, compressed with gzip + +.tar.bz2 + + a standard UNIX tar archive, compressed with bzip2 + +.zip + + an archive in zip format, where text files should have + UNIX style line breaks + +-win.zip + + an archive in zip format, where text files should have + Windows style line breaks + + +

+For convenience of possible users it is sensible that you provide an +archive of your package in at least one of these formats. +

+For example, if you wish to supply a .tar.gz archive, +you may create it with the command +

tar -cvzf packagename-version.tar.gz packagename +

+\noindent +Because the release of the &GAP; package is independent of the version +of &GAP;, a &GAP; package should be wrapped up in separate file that +can be installed onto any version of &GAP;. In this way, a package can +be upgraded any time without the need to wait for new &GAP; releases. +To ensure this, the package should be archived from the &GAP; pkg +directory, that is all files are archived with the path starting at the +package's name. +

+GAPDocManualLab +The archive of a &GAP; package should contain all files necessary for the +package to work. In particular there should be a compiled documentation, +which includes the manual.six, manual.toc and manual.lab +file in the +documentation subdirectory which are created by &GAPDoc; while &TeX;ing +the documentation. +(The first two files are needed by the &GAP; help system, +and the manual.lab file is needed if the main manuals or another +package is referring to your package. +Use the command GAPDocManualLab( packagename ); to create this file +for your help books if you use &GAPDoc;.) +

+ +For packages which are redistributed via the &GAP; website, +we offer an automatic conversion of any of the formats listed +above to all the others (note that this, as well as wrapping +the &GAP; distribution as a single archive containing the +core system and all currently redistributed packages, will +change file timestamps, so one should not rely on them anywhere +in the package). +

+ +To use the conversion and repackaging service, you can provide any of +the four archive formats or even more than one, however you should +adhere to the following rule: text files in .tar.gz +and .tar.bz2 archives must have UNIX style line breaks, +while text files in -win.zip archives must have +DOS/Windows line breaks. +

+ +The package wrapping tools for the &GAP; distribution and webpages +then will use a sensible list of file extensions to decide if a file +is a text file (being conservative, it may miss a few text files). +These rules may be prepended by the application of rules from the +PackageInfo.g file: + + +if it has a .TextFiles component, then consider the given files +as text files before &GAP; defaults will be applied; + + +if it has a .BinaryFiles component, then consider given files +as binary files before &GAP; defaults will be applied; + + +if it has a .TextBinaryFilesPatterns component, then apply it +before &GAP; defaults will be applied; + + +

+ +Utility functions from the lib/lbutil.g file in &GAP;, namely +DosUnixLinebreaks, UnixDosLinebreaks, MacUnixLinebreaks +may be helpful. They are described in the comments to their source code. +

+ +For packages hosted on GitHub publishing package release and establishing its +website can be very efficiently automated using two tools: +ReleaseTools (https://github.com/gap-system/ReleaseTools) and +GitHubPagesForGAP (https://github.com/gap-system/GitHubPagesForGAP). + +

+ + + +
+The homepage of a Package + +If you want to distribute your package you should create its homepage containing +some basic information, archives for download, +the README file with installation instructions, +and a copy of the package's PackageInfo.g file. +

+The responsibility to maintain this homepage is with the package +authors/maintainers. +

+If you tell the &GAP; Group about your package +(say, by mail to support@gap-system.org) +we may consider either + + +adding a link to your package homepage from the &GAP; website +(thus, the package will be an undeposited contribution); + + +or redistributing the current version of your package as a part of +the &GAP; distribution (this, the package will be deposited), +also ; + + +In the latter case we can also provide some services for producing several +archive formats from the archive you provide (e.g., you produce a .tar.gz +version of your archive and we produce also a .tar.bz2, .zip +and a -win.zip version from it). +

+Please also consider submitting your package to the &GAP; package refereeing +process (see http://www.gap-system.org/Contacts/submit.html for +further information). +

+For packages hosted on GitHub publishing package release and establishing its +website can be very efficiently automated using two tools: +GitHubPagesForGAP (https://github.com/gap-system/GitHubPagesForGAP) +and ReleaseTools (https://github.com/gap-system/ReleaseTools). + +

+ + + +
+Some things to keep in mind + + + + +Some packages still use for their manuals the old gapmacro format, +support for which may be discontinued in the future. We encourage authors +of those packages to eventually convert their documentation &GAPDoc;. +New packages are recommended to use &GAPDoc;, which, for example, is +capable of creating HTML documentation with MathJax support, allows +easy extraction of examples from documentation for testing, etc. One could +also use the AutoDoc which simplifies writing documentation +by generating most of the &GAPDoc; code automatically. + + + +The concept of an autoloaded package, which existed before &GAP; 4.5, +has been integrated with the needed +and suggested mechanism that exists between packages. &GAP; itself +now needs certain packages (for instance &GAPDoc;) and suggests others +(typically the packages that were autoloaded). The decisions +which packages &GAP; should need or suggest are made by developers based on +technical criteria. They can be easily overridden by a user +using the new gap.ini +(see ). +The default file ensures that all formerly autoloaded packages are +still loaded if present. + + + +Optional ~/.gap directory for user's customisations which may +contain e.g. locally installed packages (see ). +If package installation instructions explain how to install the package in a +non-standard location, they should mention this. + + + +Packages loading mechanism allows to make loading packages more +informative, while avoiding confusing the user with warning and error +messages for packages they didn't know they were loading. +For example, many messages are stored but not +displayed using the function +and there is a function +to show log messages that occur during package loading. +Packages are encouraged to use these mechanisms to report +problems in loading (e.g. binaries not compiled), +rather than printing messages directly. + + + + +
+ + + +
+Package release checklists + +The following checklists should be useful to package authors and maintainers, as +well as to everyone involved in the depositing and refereeing of &GAP; packages. + + +Checklist for releasing a new package + + + + + Test that the package: + + + does not break testinstall.g and teststandard.g, + and does not slow them down noticeably + (see ); + + + may be loaded in various configurations (see ); + + + follows the guidelines of Section + + about names of functions and variables; + + + + + + PackageInfo.g file: + + + correctly specifies package version, release date, and package authors; + + + passes validation using ; + + + besides mandatory components, which are required to pass validation, + also has relevant optional components (such as, for example, URLs of + public source code repository and issue tracker; hints to distinguish + binary and text files in case of non-standard file names and extensions, + etc.); + + + + + + Package documentation: + + + is built and included in the package archive together with + its source files; + + + states the same version, release date and package authors + as specified in the PackageInfo.g file; + + + has the same version, release date and package authors + details as stated in the PackageInfo.g file; + + + is searchable using the &GAP; help system in all formats + (text, HTML and PDF); + + + is clear about the license under which the package is distributed, + and refers to the LICENSE file which should be included in + the package; + + + + + + + Package archive(s): + + + have correct permissions for all files and directories after their + unpacking (755 for directories and executables, if any; 644 for other + files); + + + contain files with correct line breaks for the given format + (see Section ); + + + contain no hidden system files and directories that are not supposed + to be included in the package, e.g. .gitignore, + .git etc.; + + + + + + Package availability: + + + not only the package archive(s), but also the + PackageInfo.g and README files + are available online; + + + + + + + + + +Checklist for upgrading the package for the next major release of &GAP; + +&GAP; ecosystem is not static: both the core &GAP; system and packages +redistributed with &GAP; are in constant development. &GAP; has a policy +that changes that may have a disruptive effect on packages redistributed +with &GAP; should only be introduced in major &GAP; releases. When the next +&GAP; major release is prepared, a beta version for package authors will be +made available in order to give them an opportunity to check and update, +if necessary, their packages for the public release of the next major version +of &GAP;. +

+ +The following checklist will help you to check how well your package is +ready to work with the next major release of &GAP; +

+ + + + +Check that the package functionality works as expected, +package tests run with no discrepancies, and manual examples +correspond to new version of &GAP;. This is a convenient opportunity +to polish existing and add new tests, and improve manual examples. + + + +Revise package dependencies: check that the PackageInfo.g file +has correct list of needed and suggested packages +(see Section ). + + + +Revise licensing information: +check that the package states clearly under which conditions it is distributed +and includes a LICENSING file with the text of a license +(see Section ). + + + +Rebuild the package documentation to update cross-references to main &GAP; +manuals and, if relevant, to the documentation of other &GAP; packages. +This will ensure that cross-references from the package manual to the main &GAP; +manuals are correct and that the &GAP; help system will be able to navigate to +the more precise location in the package manual. This will also improve the layout of +the package documentation by picking up the changes in documenting tools. + + + +Check if the package still relies on some obsolete variables +(see Chapter ) +and replace their usage by the new commands. To perform such check, start &GAP; +with `-O` command line option to disable loading obsoletes, and then load +your package. + + + +Check for any specific advice in release notes for the beta release for +package authors. + + + + + + +

+ + diff --git a/doc/ref/overview.xml b/doc/ref/overview.xml index d3bd4a3044..9fd2f9596f 100644 --- a/doc/ref/overview.xml +++ b/doc/ref/overview.xml @@ -24,8 +24,8 @@ the &GAP; language, and use them in just the same way as the programs which form part of the system (the library). Indeed, we actively support the contribution, refereeing and distribution of extensions to the system, in the form of &GAP; packages. Further details of this -can be found in chapter , and -on our website. +can be found in chapter , +and on our website.

Development of &GAP; began at Lehrstuhl D für Mathematik, RWTH-Aachen, under the leadership of Joachim Neubüser @@ -143,8 +143,8 @@ data sources such as the electronic version of the Atlas of Finite Group Representations; therefore, installation and usage of packages is recommended.

Further details about &GAP; packages can be found in chapter -, and on the &GAP; -website here: https://www.gap-system.org/Packages/packages.html. +, and on the +&GAP; website here: https://www.gap-system.org/Packages/packages.html. diff --git a/doc/ref/run.xml b/doc/ref/run.xml index 10d3529980..ba5f1bfa63 100644 --- a/doc/ref/run.xml +++ b/doc/ref/run.xml @@ -73,7 +73,7 @@ whose component names are the command line options -A By default, some needed and suggested &GAP; packages -(see ) are loaded, +(see ) are loaded, if present, into the &GAP; session when it starts. This option disables (actually toggles) the loading of suggested packages, which can be useful for debugging or testing. diff --git a/lib/package.gd b/lib/package.gd index 919efc77bd..2c4cbe4cf1 100644 --- a/lib/package.gd +++ b/lib/package.gd @@ -702,11 +702,11 @@ DeclareGlobalFunction( "LoadPackageDocumentation" ); ## true ## ]]> ##

-## The package name may be appropriately abbreviated. For example, -## LoadPackage("semi"); will load the Semigroups -## package, and LoadPackage("d"); will load the -## DESIGN package. If the abbreviation can not be uniquely -## completed, further suggestions will be offered. +## The package name may be appropriately abbreviated. For example, at the time +## of writing, LoadPackage("semi"); will load the +## Semigroups package, and LoadPackage("j"); will +## load the json package. If the abbreviation can not be +## uniquely completed, further suggestions will be offered. ##

## If the optional version string version is given, ## the package will only be loaded in a version number at least as large as