12.7. Source code — OpenPMIx 5.0.5 documentation

# 12.7. Source code

## 12.7.1. Code style

We intentionally do not have too many code conventions in the PMIx code base.

### 12.7.1.1. All languages

- 4 space tabs. No more, no less.

- NEVER use actual tab characters; always use spaces. Both emacs and vim have secret mojo that can automatically use spaces when you hit the `<TAB>` key. This makes the code look the same in every browser, regardless of individual tab display settings.

### 12.7.1.2. C / C++

- When comparing constants for equality or inequality, always put the constant on the left. This is defensive programming: if you have a typo in the test and miss a `!` or `=`, you’ll get a compiler error. For example:

      /* Do this */
      if (NULL == foo) { ... }

      /* Because if you have a typo (i.e., = instead of ==), this will
         be a compile error rather than a subtle bug */
      if (NULL = foo) { ... }

- More defensive programming: always include blocks in curly braces `{ }`, even if they are only one line long. For example:

      /* Do this */
      if (whatever) {
          return OMPI_SUCCESS;
      }

      /* Not this */
      if (whatever)
         return OMPI_SUCCESS;

- PMIx requires a C99-compliant compiler.

  - C++-style comments are now allowed (and preferred).

  - C99-style mixing declarations are allow allowable (and preferred).

- ALWAYS include `pmix_config.h` as your first #include file. There are very, very few cases where this is not true (E.g., some bizarre Windows scenarios). But in 99.9999% of cases, this file should be included first so that it can affect system-level #include files if necessary.

- Filenames and symbols must follow the prefix rule (see [e-mail thread](http://www.open-mpi.org/community/lists/devel/2009/07/6389.php)):

  - Filenames must be prefixed with `<framework>_<component>`.

  - Public symbols must be prefixed in components with `pmix_<framework>_<component>`. When in doubt about whether a symbol is public, be safe and add the prefix.

  - Non-public symbols must be declared `static` or otherwise made to not appear in the global scope.

- ALWAYS #define macros, even for logical values.

  - The GNU Way is to `#define` a macro when it is “true” and to `#undef` it when it is “false”.

  - In PMIx, we always `#define` a logical macro to be either 0 or 1 – we never `#undef` it.

  - The reason for this is defensive programming: if you are only checking if a preprocessor macro is defined (via `#ifdef FOO` or `#if defined(FOO)`), you will get no warning when compiling if you accidentally misspell the macro name. However, if you use the logic test `#if FOO` with an undefined macro (e.g., because you misspelled it), you’ll get a compiler warning or error.

    Rationale

    Misspelled macro names can be tremendously difficult to find when they are buried in thousands of lines of code; we will take all the help from the preprocessor/compiler that we can get!

      /* GNU Way - you will get no warning from the compiler if you
         misspell "FOO"; the test will simply be false */
      #ifdef FOO
      ...
      #else
      ...
      #endif

      /* PMIx Way - you will get a warning from the compiler if you
         misspell "FOO"; the result of the test is a different value
         than whether you spelled the macro name right or not */
      #if FOO
      ...
      #else
      ...
      #endif

### 12.7.1.3. Shell scripting

Please read some of the existing shell code in the source code tree and try to use a similar style.

- Always enclose evaluated shell variables in quotes to ensure that multi-token values are handled properly.

      # This is bad
      if test $foo = bar; then

      # This is good
      if test "$foo" = "bar"; then

  - The one exception to this is that when doing an assignment to a shell variable from another shell variable, it is not necessary to use quotes on the right hand side:

        # This is harmless, but unnecessary
        foo="$bar"

        # This is actually sufficient, even for multi-token values of $bar
        foo=$bar

- Do not use the `==` operator for `test` — this is a GNU extension and can cause portability problems on BSD systems. Instead, use the single `=` operator.

      # This is bad
      if test "$foo" == "bar"; then

      # This is good
      if test "$foo" = "bar"; then

### 12.7.1.4. m4

We do not have specific coding style guidelines for m4 (the language used to create the `configure` script). Please read some of the existing m4 code in the source code tree and try to use a similar style.

## 12.7.2. Tree layout

There are a few notable top-level directories in the source tree:

- The main PMIx source is under the `src` directory

- `config`: M4 scripts supporting the top-level `configure` script

- `etc`: Some miscellaneous text files

- `docs`: Source code for PMIx documentation

- `examples`: Trivial example programs

- `include`: The public PMIx headers

The `src` directory generates a top-level library named `libpmix`. It can be built as either a static or shared library. The directory structure under it includes:

- `class`: C++-like “classes” (using the OPAL class system) specific to this project

- `include`: Top-level internal include files

- `mca`: MCA frameworks and components specific to PMIx

- `runtime`: Startup and shutdown of PMIx at runtime

- `tools`: Executables specific to PMIx

- `util`: Random utility code

The layout of the `mca` tree is strictly defined to be of the form:

    mca/FRAMEWORK/COMPONENT

To be explicit: it is forbidden to have a directory under the `mca` tree that does not meet this template (with the exception of `base` directories, explained below). Hence, only framework and component code can be in the `mca` tree.

That is, framework and component names must be valid directory names (and C variables; more on that later). For example, the CLIENT PTL component is located in `mca/ptl/client/`.

The name `base` is reserved; there cannot be a framework or component named `base`. Directories named `base` are reserved for the implementation of the MCA and frameworks. Here are a few examples (as of the v5.0.x source tree):

    # Main implementation of the MCA
    mca/base

    # Implementation of the ptl framework
    mca/ptl/base

    # Implementation of the client component of the ptl framework
    mca/ptl/client

Under these mandated directories, frameworks and/or components may have arbitrary directory structures, however.

## 12.7.3. Symbol Visibility

The `PMIX_EXPORT` macro provides a method to annotate symbols to indicate their intended visibility when compiling dynamically shared object files (e.g., `libpmix.so`).

The macro expands to the appropriate compiler and platform flags for marking whether a symbol should be explicitly made public in the PMIx library namespace. The `PMIX_EXPORT` attribute is used to declare that a symbol is to be visible outside of the PMIx DSO’s scope.

Note

This is entirely related to dynamic library compilation and does not apply to static compilation.