1# Contributor's Guidelines to ADIOS 2
2
3This guide will walk you through how to submit changes to ADIOS 2 and interact
4with the project as a developer. Information found on ADIOS 2 wiki: https://github.com/ornladios/ADIOS2/wiki under the Contributing to ADIOS section.
5
6Table of Contents
7=================
8
9   * [Contributor's Guide](#contributors-guide)
10   * [Table of Contents](#table-of-contents)
11      * [Workflow](#workflow)
12      * [Setup](#setup)
13      * [Making a change and submitting a pull request](#making-a-change-and-submitting-a-pull-request)
14         * [Create the topic branch](#create-the-topic-branch)
15            * [Do I need to merge master into my branch first?](#do-i-need-to-merge-master-into-my-branch-first)
16         * [Submit a pull request](#submit-a-pull-request)
17      * [Template implementation separation](#template-implementation-separation)
18         * [Example](#example)
19            * [Before separation of public and private template implementation](#before-separation-of-public-and-private-template-implementation)
20               * [Foo.h](#fooh-containing-all-implementation)
21            * [After separation of public and private template implementation](#after-separation-of-public-and-private-template-implementation)
22               * [Foo.h](#fooh-containing-only-prototypes-and-explicit-instantiation-declarations)
23               * [Foo.inl](#fooinl-containing-template-implementations-that-always-need-to-be-included)
24               * [Foo.tcc](#footcc-containing-template-implementations-that-should-be-restricted-to-only-known-types)
25               * [Foo.cpp](#foocpp-containing-non-template-implementations-and-explicit-instantiations-definitions-for-known-types)
26      * [Code formatting and style](#code-formatting-and-style)
27
28## Workflow
29ADIOS uses the GitHub fork-and-branch model. In this, the project "lives" in it's main repository located at https://github.com/ornladios/adios2.git, while each individual developer has their own copy of the repo to work in.  Changes are then submitted to the main repository via pull-requests made with branches from your fork.
30
31## Setup
32To setup your local repository for development:
33
34  1. Fork the main repository on GitHub:
35     1. Navigate to https://github.com/ornladios/adios2 in your browser.
36     1. Click the `[Fork]` button in the upper right-hand side of the page.
37  2. Clone the upstream repository to your local machine:
38```
39$ mkdir adios
40$ cd adios
41$ git clone https://github.com/ornladios/adios2.git source
42Cloning into 'source'...
43remote: Counting objects: 4632, done.
44remote: Compressing objects: 100% (80/80), done.
45remote: Total 4632 (delta 33), reused 0 (delta 0), pack-reused 4549
46Receiving objects: 100% (4632/4632), 1.23 MiB | 224.00 KiB/s, done.
47Resolving deltas: 100% (2738/2738), done.
48Checking connectivity... done.
49$
50```
51  3. Run the `scripts/development/setup.sh` script.  The script will configure an `upstream` remote and link your local master branch to the upstream.
52```
53$ cd source/
54$ ./scripts/developer/setup.sh
55Enter your GitHub username: chuckatkins
56Setup SSH push access? [(y)/n] y
57Re-configuring local master branch to use upstream
58Fetching origin
59remote: Counting objects: 6, done.
60remote: Compressing objects: 100% (6/6), done.
61remote: Total 6 (delta 0), reused 0 (delta 0), pack-reused 0
62Unpacking objects: 100% (6/6), done.
63From https://github.com/chuckatkins/adios2
64Fetching upstream
65From https://github.com/ornladios/adios2
66 * [new branch]      master     -> upstream/master
67 * [new branch]      dashboard  -> upstream/dashboard
68 * [new branch]      hooks      -> upstream/hooks
69Setting up git aliases...
70Setting up git hooks...
71$
72```
73
74## Making a change and submitting a pull request
75At this point you are ready to get to work.  The first thing to do is to create a branch.  ADIOS uses a "branchy" workflow where all changes are committed through self-contained "topic branches".  This helps ensure a clean traceable git history and reduce conflicts.
76
77### Create the topic branch
78
791. Make sure you are starting from a current master:
80```
81$ git checkout master
82$ git pull
83```
842. Create a branch for your change:
85```
86$ git checkout -b <your-topic-branch-name>
87```
883. Make your changes and commits to the branch.
894. Push the branch to your fork:
90```
91$ git push -u origin HEAD
92Counting objects: 189, done.
93Delta compression using up to 8 threads.
94Compressing objects: 100% (134/134), done.
95Writing objects: 100% (189/189), 70.30 KiB | 0 bytes/s, done.
96Total 189 (delta 128), reused 102 (delta 44)
97remote: Resolving deltas: 100% (128/128), completed with 82 local objects.
98To git@github.com:<your-GitHub-username-here>/adios2.git
99 * [new branch]      HEAD -> <your-topic-branch-name>
100Branch <your-topic-branch-name> set up to track remote branch <your-topic-branch-name> from origin.
101$
102```
103
104#### Do I need to merge master into my branch first?
105Not usually.  The only time to do that is to resolve conflicts.  You're pull request will be automatically rejected if merge-conflicts exist, in which case you can then resolve them by either re-basing your branch the current master (preferable):
106```
107$ git fetch --all -p
108...
109$ git rebase upstream/master
110$ git push -f
111```
112or if necessary or re-basing is not a viable option then you can always fall back to merging in master but it should be generally discouraged as it tends to make the git history difficult to follow:
113```
114$ git fetch --all -p
115...
116$ git merge upstream/master
117$ git push -f
118```
119
120### Submit a pull request
1211. Log in to your GitHub fork.
1222. You should see a message at the top that informs you of your recently pushed branch, something like: `<your-topic-branch-name> (2 minutes ago)`.  On the right side, select the `[Compare & pull request]` button.
1233. Fill in the appropriate information for the name of the branch and a brief summary of the changes it contains.
124   * The default configuration will be for the topic branch to be merged into the upstream's master branch.  You can change this if you want to submit to a different branch.
1254. Click `[Create pull request]`.
126
127You have now created a pull request (PR) that is pending several status checks before it can be merged.  Currently, the only check being performed is for source code formatting and style.  In the future, however, the will be a more in depth continuous integration system tied to the pull requests that tests for build and test failures every time a PR is submitted or updated.  Once the status checks pass, the PR will be eligible for merging by one of the project maintainers.
128
129## Template implementation separation
130The ADIOS C++ classes try to explicitly separate class declarations from their implementation.  Typically this is done by having a separate .h and .cpp file,  however it get's more complicated when templates are involved.  To maintain the distinct separation between definition and implementation, we use explicit instantiation with 4 different source file types:
131* ClassName.h
132  * The main header file containing *only* the class and member declarations with no implementation.  This also contains the declarations for explicitly instantiated members.
133* ClassName.inl
134  * A file containing inline function implementations that need to be made public.  This is to be included at the bottom of ClassName.h and should *only* contain implementations that need to be made public.
135* ClassName.tcc
136  * A file containing most of the template implementations that can be hidden through explicit instantiation.
137* ClassName.cpp
138  * A file containing the non-template implementations and the explicit instation of any template members.
139
140### Example
141Here is an example of a simple class `Foo` with template member functions `Bar1` and `Bar2`
142
143#### Before separation of public and private template implementation
144##### Foo.h containing all implementation
145```cpp
146#ifndef FOO_H_
147#define FOO_H_
148
149namespace adios
150{
151
152class Foo
153{
154public:
155    Foo()
156    : m_Bar1Calls(0), m_Bar2Calls(0), m_Bar3Calls(0);
157    {
158    }
159
160    virtual ~Foo() = default;
161
162    template<typename T>
163    void Bar1()
164    {
165        Bar1Helper<T>();
166    }
167
168    template<typename T>
169    void Bar2()
170    {
171        Bar2Helper<T>();
172    }
173
174    void Bar3()
175    {
176        Bar3Helper();
177    }
178
179private:
180    template<typename T>
181    void Bar1Helper()
182    {
183        ++m_Bar1Calls;
184    }
185
186    template<typename T>
187    void Bar2Helper()
188    {
189        ++m_Bar2Calls;
190    }
191
192    void Bar3Helper()
193    {
194        ++m_Bar3Calls;
195    }
196
197    size_t m_Bar1Calls;
198    size_t m_Bar2Calls;
199    size_t m_Bar3Calls;
200};
201
202} // end namespace adios
203#endif // FOO_H_
204```
205
206#### After separation of public and private template implementation
207
208In this example, we want to hide the template implementation from the header.  We will implement this such that `Bar1` is only callable from the core numeric types, i.e. ints, floats, and complex, while `Bar2` is callable from all types.  This will necessitate that `Bar1` and it's helper function is implemented in a .tcc file with explicit instantiation for the allowed types while `Bar2` and it's helper function will need to be inlined in the .inl file to be accessible for all types.  We will also use a helper macro ADIOS provides to iterate over the core numeric types for the explicit instantiation of `Bar1`.
209
210##### Foo.h containing only prototypes and explicit instantiation declarations
211```cpp
212#ifndef FOO_H_
213#define FOO_H_
214
215#include "ADIOSMacros.h"
216
217namespace adios
218{
219class Foo
220{
221public:
222    Foo();
223    virtual ~Foo() = default;
224
225    template<typename T>
226    void Bar1();
227
228    template<typename T>
229    void Bar2();
230
231    void Bar3();
232private:
233    template<typename T>
234    void Bar1Helper();
235
236    template<typename T>
237    void Bar2Helper();
238
239    void Bar3Helper;
240
241    size_t m_Bar1Calls;
242    size_t m_Bar2Calls;
243    size_t m_Bar3Calls;
244};
245
246// Create declarations for explicit instantiations
247#define declare_explicit_instantiation(T)       \
248    extern template void Foo::Bar1<T>();
249
250ADIOS_FOREACH_STDTYPE_1ARG(declare_explicit_instantiation)
251#undef(declare_explicit_instantiation)
252} // end namespace adios
253
254#include "Foo.inl"
255#endif // FOO_H_
256```
257Note here that Bar1Helper does not need an explicit instantiation because it's not a visible funtion in the callable interface.  It's implementaion will be available to Bar1 inside the tcc file where it's called from.
258
259##### Foo.inl containing template implementations that always need to be included
260```cpp
261#ifndef FOO_INL_
262#define FOO_INL_
263#ifndef FOO_H_
264#error "Inline file should only be included from it's header, never on it's own"
265#endif
266
267// No need to include Foo.h since it's where this is include from
268
269namespace adios
270{
271
272template<typename T>
273void Foo::Bar2()
274{
275    Bar2Helper<T>();
276}
277
278template<typename T>
279void Foo::Bar2Helper()
280{
281    ++m_Bar2Calls;
282}
283
284} // end namespace adios
285
286#endif // FOO_INL_
287```
288
289##### Foo.tcc containing template implementations that should be restricted to only known types
290```cpp
291#ifndef FOO_TCC_
292#define FOO_TCC_
293
294#include "Foo.h"
295namespace adios
296{
297
298template<typename T>
299void Foo::Bar1()
300{
301    Bar1Helper<T>();
302}
303
304template<typename T>
305void Foo::Bar1Helper()
306{
307    ++m_Bar1Calls;
308}
309
310} // end namespace adios
311
312#endif // FOO_TCC_
313```
314
315##### Foo.cpp containing non-template implementations and explicit instantiations definitions for known types.
316```cpp
317#include "Foo.h"
318#include "Foo.tcc"
319
320namespace adios
321{
322
323Foo::Foo()
324: m_Bar1Calls(0), m_Bar2Calls(0), m_Bar3Calls(0)
325{
326}
327
328void Foo::Bar3()
329{
330    Bar3Helper();
331}
332
333void Foo::Bar3Helper()
334{
335    ++m_Bar3Calls;
336}
337
338// Create explicit instantiations of existing definitions
339#define define_explicit_instantiation(T)  \
340    template void Foo::Bar1<T>();
341
342ADIOS_FOREACH_STDTYPE_1ARG(define_explicit_instantiation)
343#undef(define_explicit_instantiation)
344
345} // end namespace adios
346```
347
348## Code formatting and style using clang-format 7
349ADIOS uses the [clang-format version 7](https://releases.llvm.org/7.0.0/tools/clang/docs/ClangFormat.html) tool to automatically enforce source code style and formatting rules.  There are various ways to integrate the clang-format tool into your IDE / Code Editor depending on if you use Emacs, Vim, Eclipse, KDevelop, Microsoft Visual Studio, etc. that are a bit outside the scope of this document. A quick google search for "integrate <insert-editor-here> clang-format" should point you in the right direction.  However, you can always reformat the code manually by running:
350
351```
352clang-format -i SourceFile.cpp SourceFile.h
353```
354
355That will apply the formatting rules used by the ADIOS project.
356
357While some of the formatting rules are fairly detailed, the main points are:
358
3591. Lines no longer than 80 characters.
3601. Always use braces { and }, even for 1 line if blocks.
3611. Use 4 spaces for indentation.
362
363There are more formatting rules but these three should at least get you close and prevent any drastic re-writes from the re-formatting tools.  More details can be found by looking at the `.clang-format` config file in the root of the repository and by looking at the [clang-format documentation](https://releases.llvm.org/7.0.0/tools/clang/docs/ClangFormat.html).
364