user_guide:extend:extensions

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
reference:extensions [2013/06/03 23:32] – [How to manage changes in extensions] gawrilowuser_guide:extend:extensions [2021/01/12 15:38] (current) – external edit 127.0.0.1
Line 7: Line 7:
   * C++ clients and class libraries   * C++ clients and class libraries
  
-//**Note**//\\ Extension management has been completely reworked prior to polymake snapshot version 2.12.4.  All commands and procedures depicted below are only applicable to this snapshot or later releases.  Please refer to the older version of this page for description pertaining to polymake 2.12 or earlier. + 
-===== How to start an own extension ===== +===== Starting an own extension ===== 
-  - Choose a location on your computer (or a network share) where you have write permissions; let's name it ''my_ext'' in the examples below.\\ If you are working with an SVN working copy of polymake, please make sure that your new directory is **outside** the source tree.+ 
 +  - Choose a location on your computer (or a network share) where you have write permissions; let's name it ''my_ext'' in the examples below.\\ If you are working with a git working copy of polymake, please make sure that your new directory is **outside** the source tree.
   - In an interactive polymake session, execute the commands:\\ ''%%found_extension "~/my_ext";%%''\\ ''%%extend_application "~/my_ext", "APP_NAME";%%''\\ where //APP_NAME// is the name of an existing application you are going to enhance.   - In an interactive polymake session, execute the commands:\\ ''%%found_extension "~/my_ext";%%''\\ ''%%extend_application "~/my_ext", "APP_NAME";%%''\\ where //APP_NAME// is the name of an existing application you are going to enhance.
  
Line 20: Line 21:
 If you have written some C++ clients, they will be automatically compiled at the beginning of the next interactive session; however, later changes must be compiled manually by invoking\\ ''make -C ~/my_ext''. If you have written some C++ clients, they will be automatically compiled at the beginning of the next interactive session; however, later changes must be compiled manually by invoking\\ ''make -C ~/my_ext''.
  
-===== How to enhance other applications in the same extension =====+===== Adding more applications to the same extension =====
  
 You repeat the same command ''extend_application'' as described above, specifying the same extension directory. You repeat the same command ''extend_application'' as described above, specifying the same extension directory.
  
 To create a really new application from scratch, execute the command\\ ''%%found_application "~/my_ext", "APP_NAME";%%'' \\ To create a really new application from scratch, execute the command\\ ''%%found_application "~/my_ext", "APP_NAME";%%'' \\
-Again, it will create a folder hierarchy rooting at ''my_ext/apps/APP_NAME'' After having composed the rules and/or clients, you may include the ''APP_NAME'' in the custom variable ''@start_applications'' stored in ''prefer.pl'' in your polymake settings directory (usually ''~/.polymake''so that you'll have your new application at hand in every interactive session.+Again, it will create a folder hierarchy rooting at ''my_ext/apps/APP_NAME'' After having composed the rules and/or clients, you may add the ''APP_NAME'' to the [[:user_guide:howto:shell_custom#custom_variables|custom variable]] ''@start_applications''so that you'll have your new application at hand in every interactive session.
  
-===== How to configure an extension =====+===== Configuring an extension =====
  
 If your extension depends on third-party software packages which need to be installed separately, you'll have to provide some auto-configuration routines in the rules.  To resolve dependencies on autonomous programs, you can use all the fancy tools available in the "standard" rules: custom variables, ''CONFIGURE'' clauses, utilities like ''find_location'', ''find_program'', etc. If your extension depends on third-party software packages which need to be installed separately, you'll have to provide some auto-configuration routines in the rules.  To resolve dependencies on autonomous programs, you can use all the fancy tools available in the "standard" rules: custom variables, ''CONFIGURE'' clauses, utilities like ''find_location'', ''find_program'', etc.
  
-In the case your extension needs the third-party software already in the initial build phase, because you are using it in your clients as a callable library, you should provide a pre-build configuration procedure performing some preparations and sanity checks like adding compiler and linker flags necessary to find the library, asserting that the version of the library is not too old for you, etc.+In the case your extension needs third-party library to build the C++ clients, you should provide a pre-build configuration procedure performing some preparations and sanity checks like adding compiler and linker flags necessary to find this library, asserting that its version is not too old for you, etc.
  
-All this is done in a script ''configure.pl'' located in the top directory of your extension.  For this purpose, every extension gets at its birth a personal copy of a script template ''configure.pl.template'' You should edit it, filling the stubs of the functions with appropriate actions, introduce configuration options, if needed, and finally rename the script into ''configure.pl'' Then this script will be executed immediately during the extension import (see below) as well as each time one runs the interactive command ''reconfigure_extension'' All clients in the extension are recompiled after each reconfiguration, at the latest at the beginning of the next polymake session.+All this is done in a script ''configure.pl'' located in the ''support'' directory of your extension.  For this purpose, every extension gets at its birth a personal copy of a script template ''configure.pl.template'' You should edit it, filling the stubs of the functions with appropriate actions, introduce configuration options, if needed, and finally rename the script into ''configure.pl'' Then this script will be executed immediately during the [[#using_other_people_s_extensions|extension import]] as well as each time one runs the interactive command ''reconfigure_extension'' All clients in the extension are recompiled after each reconfiguration, at the latest at the beginning of the next polymake session.
  
 The script template contains comments describing the purpose and signature of each mandatory function; you may also want to look for the examples into the configuration scripts of extensions bundled with polymake.  At your disposal are all utilities from the module ''perllib/Polymake/Configure.pm'' and all core configuration variables, both defined in the package ''Polymake::Configure'' The extension configuration script is interpreted in a separate package; please, don't change into other package within the script.  Also be aware that the extended perl syntax (like namespace mode) is not allowed for the configure script. The script template contains comments describing the purpose and signature of each mandatory function; you may also want to look for the examples into the configuration scripts of extensions bundled with polymake.  At your disposal are all utilities from the module ''perllib/Polymake/Configure.pm'' and all core configuration variables, both defined in the package ''Polymake::Configure'' The extension configuration script is interpreted in a separate package; please, don't change into other package within the script.  Also be aware that the extended perl syntax (like namespace mode) is not allowed for the configure script.
  
 +The outcome of a successful run of the configuration script is a list of variable assignments, which are stored in the file ''build.ARCH/conf.make'' in your extension which is included at each subsequent build.  These variables can be referred to in custom ''make'' rules placed in ''Makefile.inc'' next to your clients; besides this, the script may directly add values to standard variables like ''CXXflags'' or ''Libs'' If your extension has [[#relations_between_extensions|prerequisites]] with their own configuration scripts, all their ''make'' variables are available in your extension build as well.
  
-===== How to share an extension with other people =====+In a complex scenario when the build process //and// the rules share some configurable paths or options,  
 +a rulefile can access the configured ''make'' variables of the own extension and all prerequisites by calling a special function ''load_extension_config_vars'' in its CONFIGURE clause.  It is advisable to copy all necessary values into custom variables, as to avoid expensive parsing of makefiles in each polymake session. 
 + 
 +==== Example ==== 
 + 
 +  custom $path_to_something; 
 +   
 +  CONFIGURE { 
 +    my $vars=load_extension_config_vars(); 
 +    $path_to_something=$vars->{SOME_DIR}; 
 +    1   # signal success 
 +  } 
 +where the script ''configure.pl'' is supposed to contain (among others) the following fragments: 
 +  @make_vars=qw( SOME_DIR ); 
 +   
 +  sub proceed { 
 +    $SOME_DIR=find_something() or die "can't find an important thing!\n"; 
 +  } 
 +===== Sharing an extension with other people =====
  
 There are three possible ways to make your extension available to other people, which may also be arbitrarily combined: There are three possible ways to make your extension available to other people, which may also be arbitrarily combined:
Line 49: Line 69:
 The URI of your choice must be stored in the description file ''%%~/my_ext/polymake.ext%%'' This file is created by ''found_extension'' command and already contains a tentative URI starting with ''%%file:///%%'' Please replace it with an URI of your choice.  Don't forget to submit the description file into the repository if you are using any.  From now on each XML data file containing any of the extension-specific features will bear an additional ''ext'' attribute showing your URI. The URI of your choice must be stored in the description file ''%%~/my_ext/polymake.ext%%'' This file is created by ''found_extension'' command and already contains a tentative URI starting with ''%%file:///%%'' Please replace it with an URI of your choice.  Don't forget to submit the description file into the repository if you are using any.  From now on each XML data file containing any of the extension-specific features will bear an additional ''ext'' attribute showing your URI.
  
-===== How to create documentation for an extension =====+===== Documentation =====
  
 As your extension keeps growing, you'll want to create the documentation HTML pages to have a better overview of all the new features at hand.  This can be done very easily with the script ''generate_docs'' shipped with polymake.  Just call it from the interactive session like this: ''%%script("generate_docs", "%%//OUT_DIR//%%");%%''  Then you'll obtain the complete set of documentation pages describing the standard system //and// all loaded extensions, rooted at the given directory //OUT_DIR//, which you can load directly into your web browser or deploy to your local webserver. As your extension keeps growing, you'll want to create the documentation HTML pages to have a better overview of all the new features at hand.  This can be done very easily with the script ''generate_docs'' shipped with polymake.  Just call it from the interactive session like this: ''%%script("generate_docs", "%%//OUT_DIR//%%");%%''  Then you'll obtain the complete set of documentation pages describing the standard system //and// all loaded extensions, rooted at the given directory //OUT_DIR//, which you can load directly into your web browser or deploy to your local webserver.
Line 60: Line 80:
  
 In the case of a large team working together on an extension individual contributions may still be distinguished by usual  In the case of a large team working together on an extension individual contributions may still be distinguished by usual 
-[[reference:rulefiles#credits_and_help|credit notes]] embedded in the rulefiles; then the credit note of the entire extension will be assigned by default to all rules and functions lacking individual credit notes.+[[user_guide:extend:rulefiles#credits_and_help|credit notes]] embedded in the rulefiles; then the credit note of the entire extension will be assigned by default to all rules and functions lacking individual credit notes.
  
-===== How to manage changes in extensions =====+===== Managing changes in data model =====
  
 In the course of time you may change the data representation or rename properties introduced in your extension.  These changes may render your old data files useless, as polymake won't be able to load them any more.  To be able to recover the old files automatically, you should make use of //versioning// To this end, you adopt some numbering scheme and append the current version number to the URI of your extension, like this: ''<nowiki>http://www.your.domain/polymake/extension/EXTNAME#1.0</nowiki>'' (recall that this is stored in the description file ''polymake.ext'' in the top folder of your extension).  Then, each time you are introducing an incompatible change in your extension, you bump the version number (for example up to 1.1) and create a transformation stylesheet (XSLT) ''xml/upgrade-1.1'' . There are some lines that need to be present in any transformation sheet. Here is an example In the course of time you may change the data representation or rename properties introduced in your extension.  These changes may render your old data files useless, as polymake won't be able to load them any more.  To be able to recover the old files automatically, you should make use of //versioning// To this end, you adopt some numbering scheme and append the current version number to the URI of your extension, like this: ''<nowiki>http://www.your.domain/polymake/extension/EXTNAME#1.0</nowiki>'' (recall that this is stored in the description file ''polymake.ext'' in the top folder of your extension).  Then, each time you are introducing an incompatible change in your extension, you bump the version number (for example up to 1.1) and create a transformation stylesheet (XSLT) ''xml/upgrade-1.1'' . There are some lines that need to be present in any transformation sheet. Here is an example
Line 92: Line 112:
 When polymake loads a very old data file lying behind several version bumps, all transformations between its version and the current version are applied in the proper (ascending) order; thus each transformation stylesheet should only contain converting operations specific for a single version bump. When polymake loads a very old data file lying behind several version bumps, all transformations between its version and the current version are applied in the proper (ascending) order; thus each transformation stylesheet should only contain converting operations specific for a single version bump.
  
-===== How to use other people's extensions =====+===== Writing testcases ==== 
 + 
 +It is always a good idea - especially if your extension is large - to write unit tests for your code. Those are essentially small examples which test individual rules and functions. One advantage of this is that you will quickly notice if a change in your code (or in a new polymake release) breaks something in your extension. Polymake offers a convenient set of tools for this, you can find a full description [[user_guide:extend:unit_tests|here]]. 
 +===== Using other people's extensions =====
  
 Depending on the way of distribution (as described above), you may have to check out the extension from a repository or download a tarball and unpack it.  In any case the concluding step will be \\ ''%%import_extension "~/my_ext";%%''\\ called in a interactive session. Depending on the way of distribution (as described above), you may have to check out the extension from a repository or download a tarball and unpack it.  In any case the concluding step will be \\ ''%%import_extension "~/my_ext";%%''\\ called in a interactive session.
  
-Some extensions may ask for prerequisite libraries provided by third parties, necessary to compile the client functions.  Such an extension will try to locate the required libraries automatically and prepare the compilation process to use them.  If the automatic recognition fails, the extension won'be imported.  Instead, you will see a (hopefully intelligible) error message explaining what exactly has been missing and how you can remedy the problem.  In the case you have installed the required third-party libraries at some non-standard location, or want to disable some optional part of the extension functionality, you can tell it to the extension by passing appropriate options as string arguments to the ''import_extension'' command.  The exact wording of these options should be conceivable from the error message; otherwise, you are invited to complain by the author of the extension.  The TAB completion and context-sensitive help to ''import_extension'' will try to assist you as well.+Some extensions may ask for prerequisite libraries provided by third parties, necessary to compile the client functions.  Such an extension will provide a configuration script which tries to automatically locate the required libraries and prepare the compilation process to use them.  If the automatic recognition fails, the extension will be put in a disabled (unconfigured) state.  You will see a (hopefully intelligible) error message explaining what exactly has been missing and how you can remedy the problem.  When you have installed the required third-party libraries, or decided to turn down some optional part of the extension functionality, you can try to reactivate it using the command ''reconfigure_extension'' Depending on the style in which the extension configuration script is written, you might have to supply some options as string arguments to this command, or it will try to ask you some questions interactively.  You can investigate the behavior calling \\ ''%%reconfigure_extension "~/my_ext", "--help";%%''\\ as well as trying the TAB completion or context-sensitive help (F1) when typing in this command.  If nothing helps, you are invited to complain by the authors of the extension and asking them for assistance.  Note that all configuration options can also be passed immediately to ''import_extension'' in the first place, as far as you can guess them up front.  An active extension can also be reconfigured any time later, if needed.
  
 An extension can also be imported on demand, in the course of loading a data file containing an unknown extension URI.  As soon as polymake encounters such a URI in the data file, it stops the loading procedure and asks you for the location where the extension resides.  If you have no idea where to obtain the extension right now or simply don't want to bother installing it, you should type in ''stop'' (thus interrupting the loading process) or ''skip'' (loading only standard properties).  In the latter case a backup copy of the data file is created.  Your decision to despise this particular extension is remembered until the end of the interactive session; should you change your mind later, you'll have to restart polymake. An extension can also be imported on demand, in the course of loading a data file containing an unknown extension URI.  As soon as polymake encounters such a URI in the data file, it stops the loading procedure and asks you for the location where the extension resides.  If you have no idea where to obtain the extension right now or simply don't want to bother installing it, you should type in ''stop'' (thus interrupting the loading process) or ''skip'' (loading only standard properties).  In the latter case a backup copy of the data file is created.  Your decision to despise this particular extension is remembered until the end of the interactive session; should you change your mind later, you'll have to restart polymake.
  
-===== How to combine several extensions =====+You can stocktake your imported and configured extensions at any time using the interactive shell command\\ ''show_extensions;'' 
 + 
 +===== Relations between extensions ===== 
 + 
 +Extensions may build upon each other, establishing dependence relations similar to software packages installed on your computer.  The relations between extensions are described in dedicated sections of description files ''polymake.ext'' Every section contains one or more URIs of related extensions, separated with white spaces or distributed over several lines.  An empty line marks the end of a section, similar to [[user_guide:extend:rulefiles]]. 
 + 
 +  ? ''REQUIRE'' URI URI#version ... 
 +  :: List of prerequisite extensions.  In order to be able to import this extension, you must have imported all prerequisites up front.  An optional version number expresses an additional requirement to have the specified extension in the given version or newer. 
 +  .. A prerequisite bundled extension is specified using its short URI ''bundled://NAME//''
 +  ? ''REPLACE'' URI ... 
 +  :: List of obsolete URIs assigned earlier to this extension as well as to other old extensions merged with this one.  You may also invent an abstract URI designating a feature provided by this extension and some alternatives.  Then other extensions depending on this feature can list this abstract URI among their prerequisites.  Any extension providing this URI as REPLACEment will successfully fulfill the role of that prerequisite. 
 +  .. Bundled extensions may also have a REPLACE section if they were initially born as independent extensions and only later became part of polymake distribution. 
 +  ? ''CONFLICT'' URI ... 
 +  :: List of extensions which can't be imported together with this one. 
 + 
 +Additional remarks about prerequisite extensions:
  
-You can mix pieces from several extensionswritten by yourselves as well as imported from elsewhere.  In the ideal case, the extensions should not depend on each other.  But if they dopolymake can cope with it very wellprovided you have listed them in the right order in your custom variable ''@lookup_applications''.  Data files containing features from several extensions are allowed; they will contain the ''ext'' attributes with all relevant URIsbut not necessarily grouped at one spot.+  * As long as any prerequisite is disabled due to configuration script failurethe dependent extension will stay in disabled state as well.  A successful reconfiguration of all prerequisites might automatically re-activate the dependent extension as well, unless it is equipped with its own configuration script. 
 +  * Rulefiles of the dependent extension may refer to all property typesobject types, user functions, and other features defined in the rulesfiles of prerequisite extensions without any constraints.  C++ clients may include header files from prerequisite extensions as if they were directly located in the dependent extension.  It is forbiddenhoweverto have client source files and header files of identical names in the prerequisite extensions and dependent extension. 
 +  * polymake may automatically establish dependence relations to bundled extensions when the rulefiles of your extension instantiate C++ class or function templates involving types defined in that bundled extensions.  As these relations are manifested in the description file ''polymake.ext'' distributed with your extensionall future users of your extension will need to enable that bundled extensions as well.  You might want to revise the REQUIRE section of your extension prior to exposing it to the public.
  
-Instances of parameterized C++ types and functions (templates) with argument types stemming from different extensions will be generated as if belonging to the rightmost extensions from all involved ones (that is, the one loaded last.)+===== Getting rid of an extension =====
  
-===== How to get rid of an extension =====+One nice day you might suddenly want to get rid of an extension.  The reason may be that you aren't interested in it any more, or that its functionality has silently moved into the standard distribution or another extension.  The most comfortable way is to use the command ''obliterate_extension'' .  It deletes all traces of the extension in your polymake settings.  Be aware, however, that in the current interactive session you still have the pieces from the discarded extension loaded and ready-to-use.  Thus, to avoid confusion, you should quit the session as soon as possible after using this command.  Note also that you can't obliterate an extension as long as other registered extensions depend on it as a prerequisite.
  
-One nice day you might suddenly want to get rid of an extension.  The reason may be that you aren't interested in it any more, or that its functionality has been merged into the standard distribution or another extension.  The most comfortable way is to use the command ''forget_extension'' .  It deletes all traces of the extension in the long-term memory of polymake.  Be aware, however, that in the current interactive session you still have the pieces from the discarded extension loaded and ready-to-use.  Thus, to avoid confusion, you should quit the session as soon as possible after using this command.+If you later try to load a data file referring to the URI of the obliterated extensionpolymake will ask you, as usual, to enter its installation directory.  If you are sure that in the meanwhile all the stuff has migrated into the standard distribution and/or other (already loaded) extensions, you should respond with the magic word ''ignore'' .
  
-If you later try to load a data file containing some properties or objects defined in the discarded extension, polymake will ask you, as usual, to enter its installation directory.  If you are sure that in the meanwhile all the stuff has migrated into the standard distribution and/or other (already loaded) extensions, you should response with the magic word ''ignore'' . 
  • user_guide/extend/extensions.1370302324.txt.gz
  • Last modified: 2014/01/03 15:45
  • (external edit)