File: developers_howto.md

package info (click to toggle)
abinit 9.10.4-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 518,712 kB
  • sloc: xml: 877,568; f90: 577,240; python: 80,760; perl: 7,019; ansic: 4,585; sh: 1,925; javascript: 601; fortran: 557; cpp: 454; objc: 323; makefile: 77; csh: 42; pascal: 31
file content (280 lines) | stat: -rw-r--r-- 11,921 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
---
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).

[![asciicast](https://asciinema.org/a/40324.png)](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)
* 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 %}