Resolving Elaboration Circularities (GNAT User’s Guide for Native Platforms)

### 9.10 Resolving Elaboration Circularities ¶

The most desirable option from the point of view of long-term maintenance is to rearrange the program so that the elaboration problems are avoided. One useful technique is to place the elaboration code into separate child packages. Another is to move some of the initialization code to explicitly invoked subprograms, where the program controls the order of initialization explicitly. Although this is the most desirable option, it may be impractical and involve too much modification, especially in the case of complex legacy code.

When faced with an elaboration circularity, you should also consider the tactics given in the suggestions section of the circularity diagnostic. Depending on the units involved in the circularity, their ‘with’ clauses, purity, preelaborability, presence of elaboration-control pragmas and invocations at elaboration time, the binder may suggest one or more of the following tactics to eliminate the circularity:

- Pragma Elaborate elimination

      remove pragma Elaborate for unit "..." in unit "..."

  The binder suggests this tactic when it has determined that:

  - pragma `Elaborate` prevents a set of units from being elaborated.
  - The removal of the pragma will not eliminate the semantic effects of the pragma. In other words, the argument of the pragma will still be elaborated prior to the unit containing the pragma.
  - The removal of the pragma will enable the successful ordering of the units.

  You should remove the pragma as advised and rebuild the program.

- Pragma Elaborate_All elimination

      remove pragma Elaborate_All for unit "..." in unit "..."

  The binder suggests this tactic when it has determined that:

  - pragma `Elaborate_All` prevents a set of units from being elaborated.
  - The removal of the pragma will not eliminate the semantic effects of the pragma. In other words, the argument of the pragma along with its ‘with’ closure will still be elaborated prior to the unit containing the pragma.
  - The removal of the pragma will enable the successful ordering of the units.

  You should remove the pragma as advised and rebuild the program.

- Pragma Elaborate_All downgrade

      change pragma Elaborate_All for unit "..." to Elaborate in unit "..."

  The binder always suggests this tactic when it suggests the pragma `Elaborate_All` elimination tactic. It offers a different alternative of guaranteeing that the argument of the pragma will still be elaborated prior to the unit containing the pragma.

  You should update the pragma as advised and rebuild the program.

- Pragma Elaborate_Body elimination

      remove pragma Elaborate_Body in unit "..."

  The binder suggests this tactic when it has determined that:

  - pragma `Elaborate_Body` prevents a set of units from being elaborated.
  - The removal of the pragma will enable the successful ordering of the units.

  Note that the binder cannot determine whether the pragma is required for other purposes, such as guaranteeing the initialization of a variable declared in the spec by elaboration code in the body.

  If the pragma is not required for another purpose, you should remove the pragma as advised and rebuild the program.

- Use of pragma Restrictions

      use pragma Restrictions (No_Entry_Calls_In_Elaboration_Code)

  The binder suggests this tactic when it has determined that a task activation at elaboration time:

  - Prevents a set of units from being elaborated.

  Note that the binder cannot determine with certainty whether the task will block at elaboration time.

  The programmer should create a configuration file, place the pragma within, update the general compilation arguments, and rebuild the program.

- Use of dynamic elaboration model

      use the dynamic elaboration model (compiler switch -gnatE)

  This tactic is suggested when the binder has determined that an invocation at elaboration time:

  - Prevents a set of units from being elaborated.
  - The use of the dynamic model will enable the successful ordering of the units.

  You have two options:

  - Determine the units involved in the invocation using the detailed invocation information and add compiler switch `-gnatE` to the compilation arguments of those units only. This approach will yield safer elaboration orders compared to the other option because it will minimize the opportunities presented to the dynamic model for ignoring invocations.
  - Add compiler switch `-gnatE` to the global compilation arguments.
- Use of detailed invocation information

      use detailed invocation information (compiler switch -gnatd_F)

  The binder always suggests this tactic when it suggests use of the dynamic model tactic. It causes the circularity section of the circularity diagnostic to describe the flow of elaboration code from a unit to a unit, enumerating all such paths in the process.

  You should analyze this information to determine which units should be compiled with the dynamic model.

- Forced-dependency elimination

      remove the dependency of unit "..." on unit "..." from the argument of switch -f

  The binder suggests this tactic when it has determined that a dependency present in the forced-elaboration-order file indicated by binder switch `-f`:

  - Prevents a set of units from being elaborated.
  - The removal of the dependency will enable the successful ordering of the units.

  You should edit the forced-elaboration-order file, remove the dependency, and rebind the program.

- All forced-dependency elimination

      remove switch -f

  The binder suggests this tactic when editing the forced-elaboration-order file is not an option.

  You should remove binder switch `-f` from the binder arguments and rebind.

- Multiple-circularities diagnostic

      diagnose all circularities (binder switch -d_C)

  By default, the binder only diagnoses the highest-precedence circularity. If the program contains multiple circularities, the binder will suggest the use of binder switch `-d_C` in order to obtain the diagnostics for each circularity.

  You should add binder switch `-d_C` to the binder arguments and rebind.

If none of the tactics suggested by the binder eliminate the elaboration circularity, you should consider using one of the legacy elaboration models, in the following order:

- Use the pre-20.x legacy elaboration-order model, with binder switch `-H`.
- Use both pre-18.x and pre-20.x legacy elaboration models, with compiler switch `-gnatH` and binder switch `-H`.
- Use the relaxed static-elaboration model, with compiler switches `-gnatH` `-gnatJ` and binder switch `-H`.
- Use the relaxed dynamic-elaboration model, with compiler switches `-gnatH` `-gnatJ` `-gnatE` and binder switch `-H`.