Adding new programs to Madagascar: Difference between revisions
m added motivational illustration |
|||
(31 intermediate revisions by 4 users not shown) | |||
Line 4: | Line 4: | ||
==How to add your program== | ==How to add your program== | ||
#Create a directory for yourself or your group under <tt> | #Create a directory for yourself or your group under <tt>$RSFSRC/user</tt>, where <tt>$RSFSRC</tt> is the top source directory. Put your programs there. | ||
#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. 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. | #*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 the names. | #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 the names. | ||
#Note that running <tt>scons</tt> inside your <tt>user</tt> directory compiles programs with debugging flags to make them suitable for debugging with common debuggers such as [http://www.gnu.org/software/gdb/ gdb], dbx, or [http://www.etnus.com/ TotalView]. Running <tt>scons install</tt> inside | #Note that running <tt>scons</tt> inside your <tt>user</tt> directory compiles programs with debugging flags to make them suitable for debugging with common 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== | |||
Follow the guide on [[Contributing new programs to Madagascar]]. | |||
==How to document your program== | ==How to document your program== | ||
Line 25: | Line 23: | ||
====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: | ||
< | <syntaxhighlight lang="c"> | ||
/* Short description line | /* Short description line | ||
Comments here blablabla lorem ipsum dolores sit amet... | Comments here blablabla lorem ipsum dolores sit amet... | ||
Line 32: | Line 30: | ||
/* Copyright notice */ | /* Copyright notice */ | ||
</ | </syntaxhighlight> | ||
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). | 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: | ||
< | <syntaxhighlight lang="c"> | ||
if (!sf_getbool("su",&su)) su=false; | if (!sf_getbool("su",&su)) su=false; | ||
/* y if input is SU, n if input is SEGY */ | /* y if input is SU, n if input is SEGY */ | ||
</ | </syntaxhighlight> | ||
Notice that there are no complex logical operations inside the <tt>if</tt>, 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.: | Notice that there are no complex logical operations inside the <tt>if</tt>, 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.: | ||
<pre> | <pre> | ||
Line 45: | Line 43: | ||
/*< parameter_name parameter meaning >*/ | /*< parameter_name parameter meaning >*/ | ||
</pre> | </pre> | ||
====Self-doc for Python programs==== | ====Self-doc for Python programs==== | ||
To automatically populate the <tt>Description</tt> page, and <tt>Comments</tt> sections, use the following syntax. Start the file with: | To automatically populate the <tt>Description</tt> page, and <tt>Comments</tt> sections, use the following syntax. Start the file with: | ||
< | <syntaxhighlight lang="python"> | ||
#! /usr/bin/env python | #! /usr/bin/env python | ||
'''My one-line description of this program | '''My one-line description of this program | ||
Line 55: | Line 54: | ||
# Copyright notice... | # Copyright notice... | ||
</ | </syntaxhighlight> | ||
Then, make sure to | Then, make sure to | ||
< | <syntaxhighlight lang="python"> | ||
import rsfprog | import rsfprog | ||
</ | </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, and call <tt>selfdoc</tt> if no argument was given. Here is an example from <tt>user/ivlad/Mpclip.py</tt>: | 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"> | ||
par = rsf.Par(argv) | par = rsf.Par(argv) | ||
Line 71: | Line 70: | ||
verb = par.bool('verb', False) # if y, print system commands, outputs | verb = par.bool('verb', False) # if y, print system commands, outputs | ||
</ | </syntaxhighlight> | ||
====Self-doc for Fortran 90 programs==== | ====Self-doc for Fortran 90 programs==== | ||
To automatically populate the <tt>Description</tt> section (<tt>Comments</tt> is not available), use the following syntax. Start the file with: | To automatically populate the <tt>Description</tt> section (<tt>Comments</tt> is not available), use the following syntax. Start the file with: | ||
Line 85: | Line 85: | ||
</pre> | </pre> | ||
=== | ===Wiki documentation=== | ||
The self-doc is good as a reminder of what the parameters mean and what their default values are, but more is usually needed for someone who never used the tool. This is what the [[Guide to madagascar programs|Guide to programs]] is for. Whenever you change or create a program, make sure to add a section for it in there too, if possible with an implementation section. Documenting programs that already exist is also a great idea. | The self-doc is good as a reminder of what the parameters mean and what their default values are, but more is usually needed for someone who never used the tool. This is what the [[Guide to madagascar programs|Guide to programs]] is for. Whenever you change or create a program, make sure to add a section for it in there too, if possible with an implementation section. Documenting programs that already exist is also a great idea. | ||
Line 96: | Line 96: | ||
If your program/script reads an environment variable, make sure you 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. | If your program/script reads an environment variable, make sure you 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/ | 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 that 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 it can be found by those users who do not already know they need it. | Add your program to the [[Task-centric program list]] so that it can be found by those users who do not already know they need it. | ||
Line 106: | Line 106: | ||
* Use components (macros, types, functions) from the Madagascar library to maximize component reuse and to make sure you do not reinvent the wheel. Be familiar with the [[Library Reference]]. | * Use components (macros, types, functions) from the Madagascar library to maximize component reuse and to make sure 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. | * Do not keep commented code in your program. This does not refer to writing comments about code, 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 in 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 that is used 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> | #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. <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 will quickly alternate between the stored figure and your figure. | #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 a 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 will quickly alternate between the stored figure and your figure. | ||
#* If the figures look identical, then it means 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 the figures look identical, then it means 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, then it is time to debug your program. | #* If you see differences between the two figures, then it is time to debug your program. | ||
Line 120: | Line 121: | ||
===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 will need to 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 | 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 will need to 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"> | ||
RSF_src_root = '/path/to/madagascar/source/root/' | RSF_src_root = '/path/to/madagascar/source/root/' | ||
</ | </syntaxhighlight> | ||
Then, replace <tt>../..</tt> throughout the SConstruct with | Then, replace <tt>../..</tt> throughout the SConstruct with | ||
< | <syntaxhighlight lang="python"> | ||
os.path.join(RSF_src_root,'whatever_followed_after_dotdots') | os.path.join(RSF_src_root,'whatever_followed_after_dotdots') | ||
</ | </syntaxhighlight> | ||
===External libraries=== | ===External libraries=== | ||
Line 132: | Line 133: | ||
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. | ||
===Emacs customization=== | ===Emacs customization=== | ||
Line 140: | Line 140: | ||
* Install the [http://www.emacswiki.org/cgi-bin/wiki/PythonMode python mode] (if you don't have it installed already) and put | * Install the [http://www.emacswiki.org/cgi-bin/wiki/PythonMode python mode] (if you don't have it installed already) and put | ||
<lisp> | <syntaxhighlight lang="lisp"> | ||
(setq auto-mode-alist | (setq auto-mode-alist | ||
(cons '("SConstruct" . python-mode) auto-mode-alist)) | (cons '("SConstruct" . python-mode) auto-mode-alist)) | ||
</ | </syntaxhighlight> | ||
:in your <tt>.emacs</tt> file to enable it on <tt>SConstruct</tt> files. | :in your <tt>.emacs</tt> file to enable it on <tt>SConstruct</tt> files. | ||
* Put | * Put | ||
<lisp> | <syntaxhighlight lang="lisp"> | ||
(set-default 'compile-command "scons") | (set-default 'compile-command "scons") | ||
</ | </syntaxhighlight> | ||
:in your <tt>.emacs</tt> file to have <tt>scons</tt> as the default compile command. | :in your <tt>.emacs</tt> file to have <tt>scons</tt> as the default compile command. | ||
* Use | * Use | ||
<lisp> | <syntaxhighlight lang="lisp"> | ||
(add-hook 'c-mode-common-hook | (add-hook 'c-mode-common-hook | ||
'(lambda () (c-set-style "linux") | '(lambda () (c-set-style "linux") | ||
(c-set-offset 'case-label 4) | (c-set-offset 'case-label 4) | ||
(setq c-basic-offset 4))) | (setq c-basic-offset 4))) | ||
</ | </syntaxhighlight> | ||
:to make sure that the identation in C files follows the previously adopted convention. | :to make sure that the identation in C files follows the previously adopted convention. | ||
=== Vim customization === | |||
To enable syntax highlighting on SConstruct files in vim, add the following to your <tt>~/.vimrc</tt> file: | |||
<syntaxhighlight lang="bash"> | |||
au BufRead,BufNewFile SConstruct set filetype=python | |||
syntax enable | |||
</syntaxhighlight> |
Latest revision as of 23:16, 16 June 2015
Whether you want to share your work with the world or keep it for yourself, madagascar is fully extensible. 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 the names.
- Note that running scons inside your user directory compiles programs with debugging flags to make them suitable for debugging with common 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, they are: in-code documentation, the Wiki, and reproducible papers.
In-code documentation[edit]
Of course, do comment your code -- focusing on "why" (the code itself describes the "how"). Keep comments sparse so that as much code as possible can be kept in mind at the same time by the human reader. 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 automatically produce a self-doc page for your program. This page will be displayed in the terminal (using basic text-mode formatting) when the program is invoked without any arguments, and a 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 same line or first line after
Wiki documentation[edit]
The self-doc is good as a reminder of what the parameters mean and what their default values are, but more is usually needed for someone who never used the tool. This is what the Guide to programs is for. Whenever you change or create a program, make sure to add a section for it in there 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 that has 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, as they already are in the MediaWiki format. Another directory can be used instead of $HOME.
If your program/script reads an environment variable, make sure you 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 that 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 it can be found by those users who do not already know they need 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 what a reproducible paper is and how to produce one.
Style guide[edit]
- Use components (macros, types, functions) from the Madagascar library to maximize component reuse and to make sure 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 comments about code, 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 in 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 that is used 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 where failure happened from the "Comparing ... and ..." statement just before the beginning of the error messages. The directory name will appear before that in a 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 will quickly alternate between the stored figure and your figure.- If the figures look identical, then it means 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, then it is time to debug your program.
- If the figures look identical, then it means 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 will need to 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 make sure that the identation 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