mirror of https://github.com/abinit/abinit.git
282 lines
12 KiB
Markdown
282 lines
12 KiB
Markdown
---
|
|
authors: MG, XG
|
|
---
|
|
|
|
# HowTo guide for developers
|
|
|
|
This page is intended as a quick reference to solve some of the problems
|
|
that are commonly encountered when developing within the Abinit project.
|
|
|
|
## How to generate the configure script via *makemake*
|
|
|
|
Abinit uses the standard **configure && make** [approach](https://thoughtbot.com/blog/the-magic-behind-configure-make-make-install)
|
|
to build from source.
|
|
Note, however, that the developmental version does not contain the *configure* script.
|
|
To generate the *configure* script and the other files required by the build system,
|
|
you need to execute **makemake**:
|
|
|
|
cd ~abinit
|
|
./config/scripts/makemake
|
|
|
|
*makemake* requires a recent version of the python interpreter as well as
|
|
[m4](https://www.gnu.org/software/m4/), [autoconf](https://www.gnu.org/software/autoconf/),
|
|
and [automake](https://www.gnu.org/software/automake/).
|
|
If these tools are not installed on your machine, you need to compile them from source or use
|
|
your preferred package manager to install them.
|
|
I usually use the [conda](https://docs.conda.io/en/latest/) package manager and:
|
|
|
|
conda install m4 autoconf automake -c conda-forge
|
|
|
|
!!! important
|
|
|
|
Remember to run *makemake* every time you add/remove a Fortran file or a new directory or you
|
|
change parts the buildsystem *i.e.* the files in *~abinit/config*.
|
|
|
|
## How to build Abinit
|
|
|
|
Developers are invited to build the executables inside a **build** directory *i.e.* a directory that is **separated**
|
|
from the source tree in order to keep the source directory as clean as possible and allow for multiple builds.
|
|
I usually use the naming scheme: `_build_[compiler_name]` for the build directory and an external file
|
|
(e.g. *gcc.ac*) storing the configuration options that can be passed to *configure* via the **--with-config-file** option:
|
|
|
|
```sh
|
|
mkdir _build_gcc
|
|
cd _build_gcc
|
|
|
|
../configure --with-config-file=gcc.ac
|
|
|
|
make -j8 # use 8 processes to compile
|
|
```
|
|
|
|
Note that the name of the options in the *config-file* is in normalized form that is:
|
|
|
|
* Remove the initial `--` from the name of the option
|
|
* Replace `-` with underscore `_` everywhere
|
|
|
|
For instance, `--with-mpi-prefix` in normalized form becomes `with_mpi_prefix`.
|
|
Examples of configuration files for clusters can be found in the [abiconfig package](https://github.com/abinit/abiconfig).
|
|
A detailed description of the configuration options supported by the build system is given in this guide by Marc:
|
|
|
|
<embed src="https://school2019.abinit.org/images/lectures/abischool2019_installing_abinit_lecture.pdf"
|
|
type="application/pdf" width="100%" height="480px">
|
|
|
|
Once the build is completed, it is a good idea to check whether the executable works as expected
|
|
by running the tests in the *v1* directory with:
|
|
|
|
```sh
|
|
cd tests
|
|
../../tests/runtests.py v1 -j4
|
|
```
|
|
|
|
As usual, use:
|
|
|
|
../../tests/runtests.py --help
|
|
|
|
to list the available options.
|
|
A more detailed discussion is given in [this page](/developers/testsuite_howto).
|
|
|
|
[](https://asciinema.org/a/40324)
|
|
|
|
!!! tip
|
|
|
|
Remember to run the tests as **frequently** as possible while developing new features
|
|
in order to spot possible regressions or incompatibilities.
|
|
Trust me, you can save a lot of time if you run *runtests.py* systematically!
|
|
|
|
## How to browse the source files
|
|
|
|
The HTML documentation generated by Robodoc is available at
|
|
[this page](https://www.abinit.org/sites/default/files/robodoc-html/masterindex.html).
|
|
|
|
If you need a tool to navigate the Abinit code inside the editor,
|
|
I would sugest [exuberant-ctags](http://ctags.sourceforge.net/).
|
|
|
|
To generate a **tags** file containing the list of procedures, modules, datatypes for all files inside *~abinit/src*, use:
|
|
|
|
cd ~abinit/src
|
|
ctags -R
|
|
|
|
Now it is possible to open the file containing the declaration of the *dataset_type* Fortran datatype
|
|
directly from the terminal with:
|
|
|
|
vi -t dataset_type
|
|
|
|
Inside the editor, you can go directly to a tag definition by entering the following in vim command mode:
|
|
|
|
:tag dataset_type
|
|
|
|
More tips for vim users are available [here](https://andrew.stwrt.ca/posts/vim-ctags/).
|
|
For `emacs` see [this page](https://www.emacswiki.org/emacs/EmacsTags).
|
|
|
|
Finally, one can use the *abisrc.py* script in the `~abinit` directory.
|
|
|
|
TODO
|
|
|
|
|
|
## How to debug with gdb
|
|
|
|
Load the executable in the GNU debugger using the syntax:
|
|
|
|
gdb path_to_abinit_executable
|
|
|
|
Run the code with the gdb *run* command and redirect the standard input with:
|
|
|
|
(gdb) run < run.files
|
|
|
|
Wait for the error e.g. SIGSEGV, then print the **backtrace** with:
|
|
|
|
(gdb) bt
|
|
|
|
|
|
!!! tip
|
|
|
|
Remember to compile the code with the `-g` option. Avoid debugging code compiled with -O3.
|
|
In some tricky cases, you may need to resort to -O0 or use Fortran `print` statements to avoid miscompilation.
|
|
|
|
|
|
For a more complete introduction to *gdb*, we suggest this youtube tutorial:
|
|
|
|
<iframe width="1384" height="629" src="https://www.youtube.com/embed/bWH-nL7v5F4" frameborder="0"
|
|
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
|
|
|
<!--
|
|
How to use LLDB
|
|
|
|
$ lldb ../../../src/98_main/abinit
|
|
(lldb) target create "../../../src/98_main/abinit"
|
|
Current executable set to '../../../src/98_main/abinit' (x86_64).
|
|
(lldb) settings set target.input-path t85.in
|
|
(lldb) run
|
|
-->
|
|
|
|
<!--
|
|
## Basic conventions
|
|
|
|
* All Fortran procedures should be declared in modules and imported by client code with the `use` statements
|
|
* Module names usually start with `m_`
|
|
* CPP macros and standard imports
|
|
* Low-level code is located in low-level directories
|
|
* Avoid cyclic dependencies inside a directory
|
|
|
|
We use lot of CPP macros defined in `abi_common.h` to wrap basic Fortran statements.
|
|
Please, familiarize yourself with the definitions in `abi_common.h`.
|
|
In particular:
|
|
|
|
* **Never ever** use Fortran `stop` to abort but handle the error with `MSG_ERROR(msg)` or `MSG_BUG(msg)`
|
|
* Return an exit status if low-level procedure and let the caller handler the error.
|
|
* Use `call wrtout(unit, ...)` instead of `print` or `write(*,*)`
|
|
* Use `ABI_MALLOC(array, (3, 3))` instead of `allocated(array(3, 3))`
|
|
* Use `ABI_FREE(array)` to deallocate memory or the `ABI_SFREE` variant if you need to check the allocation status.
|
|
|
|
!!! important
|
|
|
|
Abinit uses specialized logic to track Fortran **allocations** and **deallocations** in order to spot possible memory leaks
|
|
-->
|
|
|
|
## How to add a new Fortran file
|
|
|
|
* Create the F90 module and `git add` it
|
|
* Register the F90 file in the `abinit.src` file (avoid duplicated names in the public API, **abisrc.py** will complain about that)
|
|
* Register the F90 file in the `CMakeLists.txt` file as well
|
|
* Rerun `makemake` in the source directory
|
|
* Rerun `configure` and `make` in the build directory (possibly `make clean && make`)
|
|
|
|
## How to add a new Abinit input variable
|
|
|
|
This section documents the procedure required to add a new Abinit input variable.
|
|
To make things as simple as possible, we ignore the (more complicated) case of dimensions
|
|
such as [[nkpt]] or [[nsym]] whose value may depend on the dataset.
|
|
To add a new variables follow the below steps:
|
|
|
|
- Add the new variable to **dataset_type**.
|
|
Remember that the name cannot end with a digit as this enters into conflict with the multidataset syntax.
|
|
|
|
- The default value of the new input variable can be specified in two different ways:
|
|
|
|
* in the **declaration** of the Fortran type if the size is known at compile time
|
|
and the initial value does not depend on other variables.
|
|
* in the **indefo** routine if the value must be computed at runtime.
|
|
|
|
- Add the name of the new variable to **chkvars**.
|
|
|
|
- Add a new section to **dtset_copy** to copy the new variable (use **alloc_copy** if allocatable).
|
|
|
|
- If you need an **allocatable entity**, remember to **deallocate** memory in **dtset_free**.
|
|
|
|
- Read the variable in the **invars2** (if it is not a basic dimension).
|
|
|
|
- Change one of the outvars routines (**outvar_a_h**, **outvar_i_n**, **outvar_o_z**) to print the variable
|
|
according to the first letter of the new variable
|
|
|
|
- The logic for checking the consistency of input variables goes to **chkinp**.
|
|
Use the routines *chkint_eq*, *chkint_ne*, *chkint_ge*, *chkint_le*, *chkdpr*.
|
|
|
|
- Add the documentation of the new variable to `~abinit/abimkdocs/variables_CODE.py`
|
|
following the instructions given in [this section](/developers/abimkdocs#how-to-addmodify-an-input-variable).
|
|
|
|
Finally,
|
|
|
|
make clean && make -j8
|
|
|
|
since you *broke* the [ABI](https://en.wikipedia.org/wiki/Application_binary_interface)
|
|
of a public datastructure and all the object files depending on this datastructure must be recompiled
|
|
(if you are developing a library, you should release a new major version!)
|
|
|
|
No, it's not a typo, **ABIs** and **APIs** are two different concepts!
|
|
From this answer on [stackoverflow](https://stackoverflow.com/questions/2171177/what-is-an-application-binary-interface-abi)
|
|
|
|
> If you expand, say, a 16-bit data structure field into a 32-bit field, then already-compiled code
|
|
that uses that data structure will not be accessing that field (or any following it) correctly.
|
|
Accessing data structure members gets converted into memory addresses and offsets during compilation
|
|
and if the data structure changes, then these offsets will not point to what the code is expecting
|
|
them to point to and the results are unpredictable at best.
|
|
|
|
For the treatment of dimensions see **invars0**, **invars1m**
|
|
|
|
## How to add a new test in the test suite
|
|
|
|
Please see the [testsuite documentation](/developers/testsuite_howto/#how-to-add-a-new-test-in-the-test-suite).
|
|
|
|
## Code Coverage
|
|
|
|
In computer science, [code coverage](http://en.wikipedia.org/wiki/Code_coverage)
|
|
is a measure used to describe the degree to which the source code
|
|
of a program is tested by a particular test suite.
|
|
A program with high code coverage has been more thoroughly tested and has a lower chance of containing
|
|
software bugs than a program with low code coverage.
|
|
Many different metrics can be used to calculate code coverage; some of the most basic
|
|
are the percent of program subroutines and the percent of program statements called
|
|
during execution of the test suite.
|
|
We aim that the test suite covers all the functionalities of ABINIT.
|
|
|
|
How to trigger a coverage report?
|
|
|
|
There is one slave dedicated to *on-demand* execution of branches by the developers
|
|
that produces a code coverage report, at present, **higgs_gnu_7.5_cov**.
|
|
It can be launched by the general [on-demand interface](https://bbportal.abinit.org)
|
|
(contact Jean-Michel or Xavier if you do not yet have access to it).
|
|
Code coverage reports from recent runs of the tests are available [here](http://coverage.abinit.org).
|
|
If you see parts of the code which are not well tested, please contribute to improving coverage by writing new tests!
|
|
|
|
|
|
!!! info
|
|
|
|
How does it work?
|
|
|
|
ABINIT is built with special options such that every function that is executed in the program
|
|
is mapped back to the function points in the source code.
|
|
A `.gcno` file is generated when the source file is compiled with the GCC *-ftest-coverage* option.
|
|
It contains information to reconstruct the basic block graphs and assign source line numbers to blocks.
|
|
More info are available in the [Gvoc page](https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/index.html#toc-gcov---a-Test-Coverage-Program).
|
|
A *.gcda* file is generated when a program containing object files built with the GCC *-fprofile-arcs* option is executed.
|
|
A separate *.gcda* file is created for each object file compiled with this option.
|
|
It contains arc transition counts, and some summary information.
|
|
Finally, we use [lcov](http://ltp.sourceforge.net/coverage/lcov.php) to analyze the *.gcda* files for generating a html report
|
|
|
|
|
|
{% include doc/developers/robodoc.doc.txt %}
|
|
|
|
{% include doc/developers/debug_make_parents %}
|
|
|
|
{% include doc/developers/debug_make_abiauty %}
|