Adding new programs to Madagascar: Difference between revisions
typos |
|||
Line 1: | Line 1: | ||
[[Image:Fotolia_800161_XS.jpg|right|]] | [[Image:Fotolia_800161_XS.jpg|right|]] | ||
Madagascar is fully extensible, so you can share your work with the world or keep it for yourself. The following instructions explain the simplest way to add your own programs to the package. | |||
==How to add your program== | ==How to add your program== | ||
Line 7: | Line 7: | ||
#The following conventions are adopted: | #The following conventions are adopted: | ||
#*Files containing main programs start with <tt>M</tt>, i.e. <tt>Mmyprog.c</tt> or <tt>Mmyprog.py</tt>. Each main program file should start with a short one-line comment describing its purpose. | #*Files containing main programs start with <tt>M</tt>, i.e. <tt>Mmyprog.c</tt> or <tt>Mmyprog.py</tt>. Each main program file should start with a short one-line comment describing its purpose. | ||
#*Files containing subroutines start with small letters. A header/interface file <tt>myprog.h</tt> is automatically generated from <tt>myprog.c</tt>. By using header files, dependencies between different functions will be figured out automatically. Include a comment of the form <font color="#cd4b19">/*^*/</font> after any block of text that you want to be included in the header file. ''Such blocks must not contain any all-whitespace lines.'' Include a comment of the form <font color="#cd4b19">/*< My function description >*/</font> after a function definition if you want its interface included in the header file. | #*Files containing subroutines start with small letters. A header/interface file <tt>myprog.h</tt> is automatically generated from <tt>myprog.c</tt>. By using header files, dependencies between different functions will be figured out automatically. Include a comment of the form <font color="#cd4b19">/*^*/</font> after any block of text that you want to be included in the header file. ''Such blocks must not contain any all-whitespace lines.'' Include a comment of the form <font color="#cd4b19">/*< My function description >*/</font> after a function definition if you want its interface included in the header file. It is a good habit to comment interfaces to all your functions. | ||
#Create a <tt>SConstruct</tt> file in your directory by following examples from other <tt>user</tt> directories. Inside the triple quotation marks after <tt>progs=</tt>, replace the names of their programs with the names of your programs with spaces between | #Create a <tt>SConstruct</tt> file in your directory by following examples from other <tt>user</tt> directories. Inside the triple quotation marks after <tt>progs=</tt>, replace the names of their programs with the names of your programs with spaces between them. | ||
#Note that running <tt>scons</tt> inside your <tt>user</tt> directory compiles programs with debugging flags to make them suitable for debugging with | #Note that running <tt>scons</tt> inside your <tt>user</tt> directory compiles programs with debugging flags to make them suitable for debugging with standard debuggers such as [http://www.gnu.org/software/gdb/ gdb], dbx, or [http://www.etnus.com/ TotalView]. Running <tt>scons install</tt> inside <tt>$RSFSRC</tt> will compile your programs with optimization flags and install them in <tt>$RSFROOT</tt>. | ||
==How to share your program with others== | ==How to share your program with others== | ||
Line 16: | Line 16: | ||
==How to document your program== | ==How to document your program== | ||
There are three levels of documentation | There are three levels of documentation, from the most simple to the most complex: in-code documentation, the Wiki, and reproducible papers. | ||
===In-code documentation=== | ===In-code documentation=== | ||
Of course, | Of course, comment your code, focusing on "why" (the code itself describes the "how"). Keep comments sparse so the human reader can simultaneously absorb as much code as possible. Use the other levels for more information. | ||
If you follow a certain syntax for some of your comments, then the scripts in the Madagascar framework will be able to | If you follow a certain syntax for some of your comments, then the scripts in the Madagascar framework will be able to produce a self-doc page for your program automatically. This page will be displayed in the terminal (using basic text-mode formatting) when the program is invoked without any arguments, and an HTML version will be automatically generated in $RSFDOC (default: $RSFROOT/doc). The self-doc page has the following sections: <tt>Name</tt>, <tt>Description</tt>, <tt>Synopsis</tt>, <tt>Comments</tt>, <tt>Parameters</tt>, <tt>Used in</tt>, <tt>Source</tt> and <tt>Version</tt>. | ||
====Self-doc for C programs==== | ====Self-doc for C programs==== | ||
To automatically populate the <tt>Description</tt> and <tt>Comments</tt> sections, use the following syntax. Start the file with: | To automatically populate the <tt>Description</tt> and <tt>Comments</tt> sections, use the following syntax. Start the file with: | ||
Line 31: | Line 31: | ||
/* Copyright notice */ | /* Copyright notice */ | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Notice that | Notice that (1) the description line is the first line in the file; (2) Comments are closed and then open again on a new line for Copyright (so that Copyright does not show up in the documentation). | ||
To make input parameters and their default values (if they exist) automatically appear in the <tt>Synopsis</tt> and <tt>Parameters</tt> sections, make sure to read the parameters in the code like in the following example: | To make input parameters and their default values (if they exist) automatically appear in the <tt>Synopsis</tt> and <tt>Parameters</tt> sections, make sure to read the parameters in the code like in the following example: | ||
Line 45: | Line 45: | ||
====Self-doc for Python programs==== | ====Self-doc for Python programs==== | ||
To automatically populate the <tt>Description</tt> page | To automatically populate the <tt>Description</tt> page and <tt>Comments</tt> sections, use the following syntax. Start the file with: | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
#! /usr/bin/env python | #! /usr/bin/env python | ||
Line 59: | Line 59: | ||
import rsfprog | import rsfprog | ||
</syntaxhighlight> | </syntaxhighlight> | ||
To make input parameters and their default values (if they exist) automatically appear in the <tt>Synopsis</tt> and <tt>Parameters</tt> sections, make sure to follow each argument read with a comment | To make input parameters and their default values (if they exist) automatically appear in the <tt>Synopsis</tt> and <tt>Parameters</tt> sections, make sure to follow each argument read with a comment and call <tt>selfdoc</tt> if no argument was given. Here is an example from <tt>user/ivlad/Mpclip.py</tt>: | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
par = rsf.Par(argv) | par = rsf.Par(argv) | ||
Line 82: | Line 82: | ||
To make input parameters and their default values (if they exist) automatically appear in the <tt>Synopsis</tt> and <tt>Parameters</tt> sections, make sure to read the parameters in the code like in the following example: | To make input parameters and their default values (if they exist) automatically appear in the <tt>Synopsis</tt> and <tt>Parameters</tt> sections, make sure to read the parameters in the code like in the following example: | ||
<pre> | <pre> | ||
call from_par( "n1", nt, 512 ) ! Param description on same line or first line after | call from_par( "n1", nt, 512 ) ! Param description on the same line or first line after | ||
</pre> | </pre> | ||
===Wiki documentation=== | ===Wiki documentation=== | ||
The self-doc is good as a reminder of what the parameters mean and | The self-doc is good as a reminder of what the parameters mean and their default values, but more is usually needed for someone who has never used the tool. This is what the [[Guide to Madagascar programs|Guide to programs]] is for. Whenever you change or create a program, add a section for it, too, if possible, with an implementation section. Documenting programs that already exist is also a great idea. | ||
You may have noticed that each program section on that page starts with a table | You may have noticed that each program section on that page starts with a table with the same content as the self-doc. That is created automatically the following way. Say you want to create this table for <tt>sfattr</tt>. At a command line, type: | ||
<pre> | <pre> | ||
sfdoc -m $HOME attr | sfdoc -m $HOME attr | ||
</pre> | </pre> | ||
This will create the file <tt>$HOME/sfattr.wiki</tt>. Its content can be copied and pasted into the Madagascar wiki | This will create the file <tt>$HOME/sfattr.wiki</tt>. Its content can be copied and pasted into the Madagascar wiki because it is already in MediaWiki format. Another directory can be used instead of $HOME. | ||
If your program/script reads an environment variable, | If your program/script reads an environment variable, check [[Advanced Installation#Environment variables|the list of environment variables used by Madagascar]] and add your new variable or your peculiar usage of an existing variable. | ||
After creating the appropriate section in the [[Guide to madagascar programs|Guide to programs]], add your program name without the <tt>sf</tt> prefix to the <tt>docprogs</tt> list at the beginning of <tt>RSFSRC/framework/rsf/doc.py</tt> . This will ensure | After creating the appropriate section in the [[Guide to madagascar programs|Guide to programs]], add your program name without the <tt>sf</tt> prefix to the <tt>docprogs</tt> list at the beginning of <tt>RSFSRC/framework/rsf/doc.py</tt> . This will ensure a link to the wiki section is created in the auto-generated HTML program page in <tt>$RSFDOC</tt>. | ||
Add your program to the [[Task-centric program list]] so that | Add your program to the [[Task-centric program list]] so that users who do not already know they need it can find it. | ||
===Reproducible documents=== | ===Reproducible documents=== | ||
<tt>Madagascar</tt> programs are tested and illustrated by means of [[Reproducible_Documents|reproducible documents]]. See the [[Reproducible computational experiments using SCons|Guide to SCons interface for reproducible computations]] for a brief explanation of | <tt>Madagascar</tt> programs are tested and illustrated by means of [[Reproducible_Documents|reproducible documents]]. See the [[Reproducible computational experiments using SCons|Guide to SCons interface for reproducible computations]] for a brief explanation of a reproducible paper and how to produce one. | ||
==Style guide== | ==Style guide== | ||
* Use components (macros, types, functions) from the Madagascar library to maximize component reuse and | * Use components (macros, types, functions) from the Madagascar library to maximize component reuse and ensure you do not reinvent the wheel. Be familiar with the [[Library Reference]]. | ||
* User interface convention: if your program provides a verbosity option, use <tt>verb=n [y/n]</tt> | * User interface convention: if your program provides a verbosity option, use <tt>verb=n [y/n]</tt> | ||
* Do not keep commented code in your program. This does not refer to writing comments | * Do not keep commented code in your program. This does not refer to writing code comments but to commenting out actual code. You can always use the version control system to retrieve the older version | ||
* Use standard C: declare all variables | * Use standard C: declare all variables at the beginning of the program, use C-style comments <tt>/* */</tt>. Some compilers do not allow C++-style variable declarations and comments in C programs. | ||
==How to test your program== | ==How to test your program== | ||
The testing mechanism is semi-automatic. Testing can be done for any program | The testing mechanism is semi-automatic. Testing can be done for any program in a reproducible document in the <tt>RSF/book</tt> directory. To test whether the change you made in a program called, say, <tt>sfmyprog</tt> introduced any new bugs, make sure you have the latest set of stored figures from the [[Installation#RSF_reproducible_figures|figures repository]] and do the following: | ||
#<tt>cd RSF/book</tt> | #<tt>cd RSF/book</tt> | ||
#Run <pre>scons sfmyprog.test</pre> If the error messages are not helpful you can omit them from the console, but keep them in a file like this (sh): <pre>scons sfmyprog.test 2> sfmyprog.test.err</pre> or like this (csh): <pre>(scons sfmyprog.test > /dev/stdin) >& sfmyprog.test.err</pre> | #Run <pre>scons sfmyprog.test</pre> If the error messages are not helpful you can omit them from the console, but keep them in a file like this (sh): <pre>scons sfmyprog.test 2> sfmyprog.test.err</pre> or like this (csh): <pre>(scons sfmyprog.test > /dev/stdin) >& sfmyprog.test.err</pre> | ||
#If testing fails, find the directory and figure where failure happened from the "<tt>Comparing ... and ...</tt>" statement just before the beginning of the error messages. The directory name will appear before that in | #If testing fails, find the directory and figure out where the failure happened from the "<tt>Comparing ... and ...</tt>" statement just before the beginning of the error messages. The directory name will appear before that in the line "<tt> Testing in ...</tt>". <tt>cd</tt> to that directory. Let's say the figure that failed is called <tt>myfig.vpl</tt>. Run <pre>scons myfig.flip</pre> That will open a graphical display window that quickly alternates between the stored figure and your figure. | ||
#* If the figures look identical, then | #* If the figures look identical, then the differences are due to rounding errors and other insignificant differences between platforms (work is done on improving the comparison mechanism). Load your figure into your copy of the figures repository with <pre>scons myfig.lock</pre> | ||
#* If you see differences between the two figures, | #* If you see differences between the two figures, it is time to debug your program. | ||
==Tips and tricks== | ==Tips and tricks== | ||
===Backups=== | ===Backups=== | ||
You may want to back up only your developer directory, not the entire Madagascar source tree. If you do not want to or do not have the permissions to change the backup scripts, you | You may want to back up only your developer directory, not the entire Madagascar source tree. If you do not want to or do not have the permissions to change the backup scripts, you must make your RSF user directory a link to somewhere else. To get that to work, you need to modify your <tt>username/SConstruct</tt>. First thing in the file, define | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
RSF_src_root = '/path/to/madagascar/source/root/' | RSF_src_root = '/path/to/madagascar/source/root/' | ||
Line 131: | Line 131: | ||
===External libraries=== | ===External libraries=== | ||
To link your programs to an external library, add to the <tt>env.Prepend</tt> statement in <tt>username/Sconstruct</tt> | To link your programs to an external library, add to the <tt>env.Prepend</tt> statement in <tt>username/Sconstruct</tt> | ||
the paths to its <tt>include</tt> dir, <tt>lib</tt> dir and the name of the library you are linking to. | the paths to its <tt>include</tt> dir, <tt>lib</tt> dir, and the name of the library you are linking to. | ||
Line 159: | Line 159: | ||
(setq c-basic-offset 4))) | (setq c-basic-offset 4))) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
:to | :to ensure that the indentation in C files follows the previously adopted convention. | ||
=== Vim customization === | === Vim customization === |
Latest revision as of 02:28, 25 November 2024
Madagascar is fully extensible, so you can share your work with the world or keep it for yourself. The following instructions explain the simplest way to add your own programs to the package.
How to add your program[edit]
- Create a directory for yourself or your group under $RSFSRC/user, where $RSFSRC is the top source directory. Put your programs there.
- The following conventions are adopted:
- Files containing main programs start with M, i.e. Mmyprog.c or Mmyprog.py. Each main program file should start with a short one-line comment describing its purpose.
- Files containing subroutines start with small letters. A header/interface file myprog.h is automatically generated from myprog.c. By using header files, dependencies between different functions will be figured out automatically. Include a comment of the form /*^*/ after any block of text that you want to be included in the header file. Such blocks must not contain any all-whitespace lines. Include a comment of the form /*< My function description >*/ after a function definition if you want its interface included in the header file. It is a good habit to comment interfaces to all your functions.
- Create a SConstruct file in your directory by following examples from other user directories. Inside the triple quotation marks after progs=, replace the names of their programs with the names of your programs with spaces between them.
- Note that running scons inside your user directory compiles programs with debugging flags to make them suitable for debugging with standard debuggers such as gdb, dbx, or TotalView. Running scons install inside $RSFSRC will compile your programs with optimization flags and install them in $RSFROOT.
[edit]
Follow the guide on Contributing new programs to Madagascar.
How to document your program[edit]
There are three levels of documentation, from the most simple to the most complex: in-code documentation, the Wiki, and reproducible papers.
In-code documentation[edit]
Of course, comment your code, focusing on "why" (the code itself describes the "how"). Keep comments sparse so the human reader can simultaneously absorb as much code as possible. Use the other levels for more information.
If you follow a certain syntax for some of your comments, then the scripts in the Madagascar framework will be able to produce a self-doc page for your program automatically. This page will be displayed in the terminal (using basic text-mode formatting) when the program is invoked without any arguments, and an HTML version will be automatically generated in $RSFDOC (default: $RSFROOT/doc). The self-doc page has the following sections: Name, Description, Synopsis, Comments, Parameters, Used in, Source and Version.
Self-doc for C programs[edit]
To automatically populate the Description and Comments sections, use the following syntax. Start the file with:
/* Short description line
Comments here blablabla lorem ipsum dolores sit amet...
You can use several paragraphs for comments, no problem.*/
/* Copyright notice */
Notice that (1) the description line is the first line in the file; (2) Comments are closed and then open again on a new line for Copyright (so that Copyright does not show up in the documentation).
To make input parameters and their default values (if they exist) automatically appear in the Synopsis and Parameters sections, make sure to read the parameters in the code like in the following example:
if (!sf_getbool("su",&su)) su=false;
/* y if input is SU, n if input is SEGY */
Notice that there are no complex logical operations inside the if, that there is no space between the equal sign and the right and left hand, and that a short comment follows immediately. If by necessity the parameter is read in a complex fashion, use angular brackets inside the short line following the read block, i.e.:
... sf_getfloat ... complex stuff ... /*< parameter_name parameter meaning >*/
Self-doc for Python programs[edit]
To automatically populate the Description page and Comments sections, use the following syntax. Start the file with:
#! /usr/bin/env python
'''My one-line description of this program
If I have comments, put them in the lines below.
I can use several paragraphs for that'''
# Copyright notice...
Then, make sure to
import rsfprog
To make input parameters and their default values (if they exist) automatically appear in the Synopsis and Parameters sections, make sure to follow each argument read with a comment and call selfdoc if no argument was given. Here is an example from user/ivlad/Mpclip.py:
par = rsf.Par(argv)
inp = par.string('inp') # input file
out = par.string('out') # output file
if None in (inp, out):
rsfprog.selfdoc() # self-doc
return error
verb = par.bool('verb', False) # if y, print system commands, outputs
Self-doc for Fortran 90 programs[edit]
To automatically populate the Description section (Comments is not available), use the following syntax. Start the file with:
! One-line short description, leave a blank line after it ! Copyright notice...
To make input parameters and their default values (if they exist) automatically appear in the Synopsis and Parameters sections, make sure to read the parameters in the code like in the following example:
call from_par( "n1", nt, 512 ) ! Param description on the same line or first line after
Wiki documentation[edit]
The self-doc is good as a reminder of what the parameters mean and their default values, but more is usually needed for someone who has never used the tool. This is what the Guide to programs is for. Whenever you change or create a program, add a section for it, too, if possible, with an implementation section. Documenting programs that already exist is also a great idea.
You may have noticed that each program section on that page starts with a table with the same content as the self-doc. That is created automatically the following way. Say you want to create this table for sfattr. At a command line, type:
sfdoc -m $HOME attr
This will create the file $HOME/sfattr.wiki. Its content can be copied and pasted into the Madagascar wiki because it is already in MediaWiki format. Another directory can be used instead of $HOME.
If your program/script reads an environment variable, check the list of environment variables used by Madagascar and add your new variable or your peculiar usage of an existing variable.
After creating the appropriate section in the Guide to programs, add your program name without the sf prefix to the docprogs list at the beginning of RSFSRC/framework/rsf/doc.py . This will ensure a link to the wiki section is created in the auto-generated HTML program page in $RSFDOC.
Add your program to the Task-centric program list so that users who do not already know they need it can find it.
Reproducible documents[edit]
Madagascar programs are tested and illustrated by means of reproducible documents. See the Guide to SCons interface for reproducible computations for a brief explanation of a reproducible paper and how to produce one.
Style guide[edit]
- Use components (macros, types, functions) from the Madagascar library to maximize component reuse and ensure you do not reinvent the wheel. Be familiar with the Library Reference.
- User interface convention: if your program provides a verbosity option, use verb=n [y/n]
- Do not keep commented code in your program. This does not refer to writing code comments but to commenting out actual code. You can always use the version control system to retrieve the older version
- Use standard C: declare all variables at the beginning of the program, use C-style comments /* */. Some compilers do not allow C++-style variable declarations and comments in C programs.
How to test your program[edit]
The testing mechanism is semi-automatic. Testing can be done for any program in a reproducible document in the RSF/book directory. To test whether the change you made in a program called, say, sfmyprog introduced any new bugs, make sure you have the latest set of stored figures from the figures repository and do the following:
- cd RSF/book
- Run
scons sfmyprog.test
If the error messages are not helpful you can omit them from the console, but keep them in a file like this (sh):scons sfmyprog.test 2> sfmyprog.test.err
or like this (csh):(scons sfmyprog.test > /dev/stdin) >& sfmyprog.test.err
- If testing fails, find the directory and figure out where the failure happened from the "Comparing ... and ..." statement just before the beginning of the error messages. The directory name will appear before that in the line " Testing in ...". cd to that directory. Let's say the figure that failed is called myfig.vpl. Run
scons myfig.flip
That will open a graphical display window that quickly alternates between the stored figure and your figure.- If the figures look identical, then the differences are due to rounding errors and other insignificant differences between platforms (work is done on improving the comparison mechanism). Load your figure into your copy of the figures repository with
scons myfig.lock
- If you see differences between the two figures, it is time to debug your program.
- If the figures look identical, then the differences are due to rounding errors and other insignificant differences between platforms (work is done on improving the comparison mechanism). Load your figure into your copy of the figures repository with
Tips and tricks[edit]
Backups[edit]
You may want to back up only your developer directory, not the entire Madagascar source tree. If you do not want to or do not have the permissions to change the backup scripts, you must make your RSF user directory a link to somewhere else. To get that to work, you need to modify your username/SConstruct. First thing in the file, define
RSF_src_root = '/path/to/madagascar/source/root/'
Then, replace ../.. throughout the SConstruct with
os.path.join(RSF_src_root,'whatever_followed_after_dotdots')
External libraries[edit]
To link your programs to an external library, add to the env.Prepend statement in username/Sconstruct the paths to its include dir, lib dir, and the name of the library you are linking to.
Emacs customization[edit]
If you use Emacs, the following might be helpful.
- Install the python mode (if you don't have it installed already) and put
(setq auto-mode-alist
(cons '("SConstruct" . python-mode) auto-mode-alist))
- in your .emacs file to enable it on SConstruct files.
- Put
(set-default 'compile-command "scons")
- in your .emacs file to have scons as the default compile command.
- Use
(add-hook 'c-mode-common-hook
'(lambda () (c-set-style "linux")
(c-set-offset 'case-label 4)
(setq c-basic-offset 4)))
- to ensure that the indentation in C files follows the previously adopted convention.
Vim customization[edit]
To enable syntax highlighting on SConstruct files in vim, add the following to your ~/.vimrc file:
au BufRead,BufNewFile SConstruct set filetype=python
syntax enable