HowTo Use OpenFOAM with Eclipse/Fool the indexer

From OpenFOAMWiki

Enabling symbol recognition and autocompletion in Eclipse by fooling the indexer

This tutorial focuses on "repairing" Eclipse's indexer, in order for it to function appropriately. It is an extension to this Eclipse tutorial for OpenFOAM.

How OpenFOAM includes pEqn.H in a solver

OpenFOAM #include-s many lines of code in a copy-paste manner, e.g. “createTime.H” and “UEqn.H” in many solvers. These included files are not actual C-headers in the “normal” sense. Their sole purpose is to distribute executable lines of code over multiple files for readability and reusability. This method allows OpenFOAM to define reusable local variables. They are typically included in the middle of the code, rather than at the top of a file (like a “normal” C-header). Take for example “pEqn.H” in the “interFoam” solver (in the figure on the right hand side).

Eclipse's indexer does not understand this way of using headers, because it is considered bad-style. (Despite this, it is a really convenient thing to do in OpenFOAM.) The compiler does, however, understand it: It is allowed in C++. Therefore, your code will compile, whereas Eclipse tells you there are numerous errors:

Eclipse example of errors.png

Luckily, up to a certain degree, we can fool the indexer by feeding it with more information. This will solve many problems, although not all of them.

1 Advantages / Disadvantages

The present method for fooling the indexer has both advantages and disadvantages. Judge for yourself whether you think the advantages outweigh the disadvantages. Please do note that nothing we do to the indexer will change the functioning of your code, as the compiler is responsible for that – not the indexer.

The advantages are:

  • Eclipse will no longer give you errors for correct things inside your C file, e.g. “interFoam.C”.
  • Symbols will be recognized, allowing you to use the (Navigate -> Open Declaration (F3)) function to jump to its declaration.
  • Methods/Functions will be recognized, allowing you to use F3 once again.
  • You will be able to use the autocompletion function while programming.

The disadvantages are:

  • Eclipse will still give you “Syntax errors” inside the included header files (like UEqn.H). Autocompletion does not work, although F3 does behave decently. (Note that everything works if the included file is copied into the C file – which is particularly useful if you are developing a new code.)
  • It is relatively labor-intensive to set it up. (But luckily you only have to do it once for a given project, and the "pro tips" section below gives tips on how to do it a lot faster.)
  • Fooling the indexer to understand the code may cause the indexer to understand code which cannot be compiled. This may happen when included variables are used outside their scope: The deceived indexer will no longer be able to tell you when the variables are out of scope, as they will be treated as global variables.
  • Similar to the above problem, there may be other unexpected consequences of fooling the indexer, which are unknown at the time of writing.



2 Before we start

First follow these steps to import your code into Eclipse. In the following subsections, the most important steps are shown.

For the exemplifying figures below, “Eclipse Mars.1 (4.5.1)” with “CDT 8.8.1” is used. Then, (a copy of) “interFoam v2.3.x” will be imported into Eclipse. The used indexer settings (Window->Preferences->C/C++->Indexer) are as follows:

Eclipse Preferences Indexer.png

2.1 Copying interFoam

Copying “interFoam” can be done quickly as follows (Linux, OF Version 23x.png). This assumes that the OpenFOAM environment has been sourced in the terminal:

$ cd $FOAM_USER_SOLVERS 
$ cp -r $FOAM_SOLVERS/multiphase/interFoam ./interFoam_EclipseTut
$ cd interFoam_EclipseTut
$ 'rm' -r interDyMFoam interMixingFoam LTSInterFoam porousInterFoam Allwmake Allwclean
$ wclean

Now replace references to APPBIN to USER_APPBIN, but first see if the behaviour is as expected:

$ grep -lre "FOAM_APPBIN" . | xargs -l sed -e 's/FOAM_APPBIN/FOAM_USER_APPBIN/g'

If the behaviour is as expected, then actually search-and-replace:

$ grep -lre "FOAM_APPBIN" . | xargs -l sed -i -e 's/FOAM_APPBIN/FOAM_USER_APPBIN/g'

Similarly for the name of “our” solver:

$ grep -lre "interFoam" . | xargs -l sed -e 's/interFoam/interFoam_EclipseTut/g'
$ grep -lre "interFoam" . | xargs -l sed -i -e 's/interFoam/interFoam_EclipseTut/g'
$ mv interFoam.C interFoam_EclipseTut.C

And finally test if it still compiles (and clean right after):

$ wmake && ls $FOAM_USER_APPBIN && wclean

2.2 Including directories

After importing the project into Eclipse, (in the case of “interFoam”) add the following include directories (Project->Properties->C/C++ General->Paths and Symbols), as described here:

Eclipse interFoam includeDirs.png

This will enable Eclipse's indexer to find all included headers (see the following figure). It will, however, not recognize all symbols yet. We must first feed the indexer with more information.

Eclipse interFoam EclipseTut justLoaded.png


2.3 Adding symbols

As a final preparation, it is important to add the Symbol “WM_DP” and/or “WM_SP” to (Project->Properties->C/C++ General->Paths and Symbols->Symbols). This is required for Eclipse to understand OpenFOAM's “scalar”. You can do so as follows (“1” is an arbitrary number, it can be anything):

Eclipse WM DP.png

3 Fooling the indexer

It is impossible to have Eclipse's indexer understand what is going on. We can, however, trick it to make it think it understands. The downside is of course that just like any human being who thinks he/she understands whereas he/she does not: it is bound to make some mistakes (see the disadvantages).

The trick is to manually include the files holding the declarations of the variables (e.g. “createTime.H”) in the preprocessor. This will trick the indexer to think that the declared variables are global variables in the project. So the indexer effectively loses the concept of “variable scope”. In the case of a solver, this is perfectly fine: all variables are in effect global variables anyway!

First, go to (Window->Preferences->C/C++->Property Pages Settings) and tick the box 'Display “Include Files” tab on Paths and Symbols page':

Eclipse WindowPreferences IncludeFiles.png

Now go to (Project->Properties->C/C++ General->Paths and Symbols->Include Files) and add all header files which Eclipse is complaining about. Do not forget to rebuild the index, if your Eclipse does not do so automatically (Project -> C/C++ Index -> Rebuild). For example, add “createTime.H” for the variable “runTime” to be recognized:

Eclipse add createTime.png
Eclipse createTime added.png


Note that the method “run” from the variable “runTime” is not yet recognized. (Actually, no method will be recognized.) For it to be recognized, “Time.H” must also be added. Or rather: “fvCFD.H” must be added, because this is the file which includes “Time.H” in our project. “fvCFD.H” must be included before “createTime.H”. I am not sure why the order matters, but it is probably because “fvCFD.H” includes “Time.H”, which must be known before “createTime.H” is interpreted.

Continuing this process for all errors, we eventually end up with the following list of includes (for interFoam v.2.3.x). (Note that the order does again matter for some files.)

Eclipse all included files.png

Including “pEqn.H”, “UEqn.H” and all includes below them is optional. For example, the first two are required to make the variable “UEqn” and “pEqn” known in the C-file, but it is not required to remove the errors in the case of “interFoam”, because “interFoam” does not use those variables in the C-file. The final result is then:

Eclipse final no error result.png

Now, in your “UEqn.H”, “pEqn.H” and “createFields.H” you will still see “Syntax error”. At the time of writing, it is not yet know how to solve this issue. If you do know, please share it with the rest of us. Also, as was mentioned in the disadvantages, you will not have autocompletion within these files, and F3 works only partially (it shows a list of possible functions, rather than choosing the correct function). In your C-file, however, everything works perfectly (as can be seen in the figure above). Now, if you'd copy the content of e.g. “UEqn.H” into your C file, it is fully functional: both autocompletion and F3 work flawlessly. Although it is not completely convenient to do so, this does permit us to use Eclipse's powerful features!

4 Pro tips

4.1 Using XML

It is as well possible to use XML to do all the above, instead of using Eclipse's GUI to add each included file one-at-a-time. Within your project directory, Eclipse has created a hidden file called “.cproject”. Within this file, the link to all included files and directories are saved. You may as well edit this file yourself, and then refresh your project inside Eclipse (select project, press F5).

For the above “interFoam” example, the following lines were added by Eclipse:

<option id="gnu.cpp.compiler.option.include.paths.812006697" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/OpenFOAM/lnInclude&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/finiteVolume/lnInclude&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/OSspecific/POSIX/lnInclude&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/turbulenceModels/incompressible/turbulenceModel/lnInclude&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/transportModels/&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/transportModels/interfaceProperties/lnInclude&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/transportModels/incompressible/lnInclude&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/transportModels/twoPhaseMixture/lnInclude&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/transportModels/immiscibleIncompressibleTwoPhaseMixture/lnInclude&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/fvOptions/lnInclude&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/meshTools/lnInclude&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/sampling/lnInclude&quot;"/>
</option>
<option id="gnu.cpp.compiler.option.include.files.607748979" name="Include files (-include)" superClass="gnu.cpp.compiler.option.include.files" valueType="includeFiles">
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/finiteVolume/lnInclude/fvCFD.H&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/OpenFOAM/lnInclude/createTime.H&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/OpenFOAM/lnInclude/createMesh.H&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/fvOptions/lnInclude/fvIOoptionList.H&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/transportModels/immiscibleIncompressibleTwoPhaseMixture/lnInclude/immiscibleIncompressibleTwoPhaseMixture.H&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/turbulenceModels/incompressible/turbulenceModel/lnInclude/turbulenceModel.H&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/finiteVolume/lnInclude/alphaControls.H&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${workspace_loc:/interFoam_EclipseTut/createFields.H}&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${workspace_loc:/interFoam_EclipseTut/UEqn.H}&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${workspace_loc:/interFoam_EclipseTut/pEqn.H}&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/finiteVolume/lnInclude/upwind.H&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/finiteVolume/lnInclude/createPrghCorrTypes.H&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/finiteVolume/lnInclude/readTimeControls.H&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${FOAM_SRC}/finiteVolume/lnInclude/CourantNo.H&quot;"/>
	<listOptionValue builtIn="false" value="&quot;${workspace_loc:/interFoam_EclipseTut/alphaCourantNo.H}&quot;"/>
</option>
<option id="gnu.cpp.compiler.option.preprocessor.def.1367553323" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" valueType="definedSymbols">
	<listOptionValue builtIn="false" value="WM_DP=1"/>
</option>

You could as well add these lines manually to “.cproject”. This trick allows you to easily and quickly include all directories/files in a new project. So the 'labour-intensive' disadvantage is no longer a problem. The lines should be within the XML-tag “tool”, which looks something like:

<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.784993940" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug">
	RIGHT_HERE
</tool>

If you cannot find such a line, just add one include directory using Eclipse's GUI. Then find this directory name inside ".cproject". You will then know where to put the other include directories, since they should be the siblings of the directory you just added.

And while we're at it: you could do the same for the build targets (wmake and wclean). Do note though, this will only work if Eclipse is not running. Otherwise Eclipse will not read your build targets.

<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets">
        <buildTargets>
                <target name="wclean" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
                        <buildCommand>wclean</buildCommand>
                        <buildArguments/>
                        <buildTarget/>
                        <stopOnError>true</stopOnError>
                        <useDefaultCommand>false</useDefaultCommand>
                        <runAllBuilders>true</runAllBuilders>
                 </target>
                 <target name="wmake" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
                        <buildCommand>wmake</buildCommand>
                        <buildArguments/>
                        <buildTarget/>
                        <stopOnError>true</stopOnError>
                        <useDefaultCommand>false</useDefaultCommand>
                        <runAllBuilders>true</runAllBuilders>
                </target>
        </buildTargets>
</storageModule>

The buildtarget-XML-lines should be contained just above the following line (so at level 2: they are children of the main node: <cproject>):

</cproject>

4.2 Making variables “less global”

Instead of including files into our project, it is as well possible to include files into individual C-files. To do so, right-click the C-file in the "Project Explorer" (on the left side of Eclipse) and go to (Properties->C/C++ General->Paths and Symbols->Include Files). Using this method will make the indexer think of the variables as file-global, instead of project-global.

A note of caution though: changing anything for an individual file will put it out-of-sync with the project's “Paths and Symbols” settings. Any changes to the project's “Paths and Symbols”, will not affect this file. Therefore, you should be really careful with this kind of “micromanagement”, and preferably avoid this altogether.

4.3 An alternative location to include files

It is as well possible to include files at “CDT User Entries” (Properties->C/C++ General->Preprocessor Include Paths, Macros etc.->Entries). This seems to (and should) give the same effect. The only difference I know is that the content does not get saved to “.cproject”. In fact, by default it does not get saved to the project's directory at all.

However, if you tick the box “Store entries in project settings folder (easier for project migration)” (Properties->C/C++ General->Preprocessor Include Paths, Macros etc.->Providers->CDT User Setting Entries), the content will be saved to “.settings/language.settings.xml”.

One major note: Do not mix this alternative location with the (Properties->C/C++ General->Paths and Symbols->Include Files)-location. This may have unexpected consequences, because the order in which the files are included matters for the indexer (see the FAQ).

5 FAQ

5.1 Error: Symbol '...' could not be resolved.

You need to include the file in which the variable is declared. For example, if the symbol "runTime" is not recognized, you must include:

${FOAM_SRC}/OpenFOAM/lnInclude/createTime.H


5.2 Error: Invalid arguments ... Candidates are ...

This happens when the variable names are recognized, but the variable types are not. The source of this error is that you included the file in which this variable is defined, before including the file in which its type is defined.

In solvers, this will most-commonly occur in lines in which the variable "phi" is used. It is important that "createFields.H" is included after "fvCFD.H".

This is easily solved by switching the order of inclusion.


5.3 Error: <variable name> is ambiguous

The problem occurs because we are fooling the indexer: We trick it to think that things are global. Therefore, it cannot distinguish between two 'global' variables/functions. Still, your code will compile (unless the error is a real error of course, and thus not an incorrect indexer error), because in reality one variable/function is local, whereas the other one is global. The compiler will then always choose the local one, above the global one. However, the indexer is confused.

This most-commonly occurs in temperature solvers. The variable is conveniently called 'T'. Sadly, some global functions in the namespace Foam are called 'T' as well, which compute the transpose of a matrix. The indexer cannot distinguish between these two T's.

It is currently unknown how to solve this problem. A work-around would be to rename your variable... Although that is probably not desirable.


5.4 I did all the above, but Eclipse is still showing errors!!

This can be many things. Check the following possibilities in sequence:

If they are “Syntax errors”, then please read the disadvantages. This is currently an unsolved problem.

If you open “${FOAM_SRC}/finiteVolume/lnInclude/volFieldsFwd.H” in Eclipse and hover over “scalar” (or select it and hit F3), does it recognize this symbol? If not, return to this step.

5.4.1 The include order matters!

Try switching the order of several include files to see if the indexer's result changes. For example, "fvCFD.H" should be the very first included file.

In general, the header containing a class definition should be included before the file which defines a variable. For example, for a dynamic mesh, the correct order would be:

${FOAM_SRC}/dynamicFvMesh/lnInclude/dynamicFvMesh.H
${FOAM_SRC}/dynamicFvMesh/lnInclude/createDynamicFvMesh.H

The other way around would not work!

5.4.2 Are you missing an include file?

If all the above are not your issues, are you able to reproduce the tutorial as presented here, i.e. “interFoam 2.3.x”? If you can reproduce the tutorial, but you cannot get your own solver to work in Eclipse, then you are probably missing at least one include file. This is very likely one of the header files included at the top of your C-file (above the main function). For the case of “interFoam v2.3.x” these are:

Eclipse headers included at top.png

Worst-case scenario, you can search the OpenFOAM tree (or use Doxygen) for the method to see which header file you must include. For example, the following was used to find the include for “upwind” in the present tutorial:

$ grep -rne "upwind" ${FOAM_SRC}
# Some result is shown here, conclusion: upwind.H is the file. Let us see if we can find its 'boss' easily:
$ grep -rne "#include \"upwind.H\"" ${FOAM_SRC}
# It turns out that tracing it back is not that easy, so how about we simply include "upwind.H"?
# This easy-way-out has been taken in the present tutorial. 
 


5.5 What are the big integer numbers in the XML files?

The big integer numbers, e.g. “784993940” in the following example, are part of the “id” of a node in the XML tree. You can put anything there, but each node should have a unique id. Eclipse uses this uniqueness in its option parsing.

<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.784993940" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug">


5.6 What do you mean by 'F3'?

In Eclipse, F3 is the default key binding for (Navigate -> Open Declaration). If your cursor is within a variable/method/... name, using this Eclipse feature will open the file in which the variable/method/... was declared. Eclipse will automatically show you where exactly in this file it was declared.


5.7 Are there any other neat features of Eclipse I should know about?

You may want to try these features:

  • Navigate -> Open Declaration (F3)
  • Navigate -> Toggle Source/Header (Ctrl+Tab)
  • Navigate -> Open Include Browser (Ctrl+Alt+I)
  • Navigate -> Last Edit Location (Ctrl+Q)
  • Press Ctrl+Space while typing (e.g. "U.bounda" as in an image in the tutorial above) and Eclipse will show you autocompletion options
  • Source -> Toggle Comment (Ctrl+/)
  • If you start a comment with "TODO", the message will be added to the "Tasks" list.


5.8 My question wasn't there

Please leave a message on the forum.