Eclipse CDT Manual Setup

mach Setup

Most people should be reading the Eclipse CDT page instead of this one, now that mach ide eclipse is a thing.

This page contains the content that used to live on the Eclipse CDT page that most people will likely just consider noise. There is valuable information here that should be integrated back into that page, but a large amount of it is now taken care of by the mach project generation code. For now it's stored here until that integration happens in order that the Eclipse CDT page isn't hugely cluttered with mostly redundant information, make setting up Eclipse look much more complicated than it is nowadays.

Setup time

Some points in the rest of this document below are old and taken care of by the mach commands described above (although some of the project configuration is not done automatically yet). Some of it like the section on building the index and usage tips are still relevant, and other parts still may provide useful background information to understand it in more detail on how Eclipse works.

You can expect it to take an hour or so to work through these instructions if you're doing so for the first time.

(This assumes that you already have a copy of the Mozilla source, and that you have also built the source so that you have a pre-existing object directory. If that is not the case, then get your build going now so that it can be running while you continue with the instructions below. FAQ: Wait, why does Eclipse need an object directory?)

Code assistance

Out of the box, Eclipse can provide some code assistance for the Mozilla source, but it will be incomplete and often just plain broken. If you set up Eclipse as detailed below, you will experience much better results.

Important background

To help you make sense of the instructions that follow (and so that you can modify them to meet your own needs if necessary), this section provides some background on what IDEs need in order to provide advanced code assistance, and what Eclipse CDT needs in particular.

To be able to provide really good code assistance for a project's source code, IDEs like Eclipse need to carry out a thorough static analysis of the project's source files, to build up a picture of the code (what Eclipse is trying to do when it "indexes" the source.) Static analysis involves parsing the source files, so naturally it can only produce good results if it has a sensible set of preprocessor defines, include paths and pre-include files for each source file. Since Eclipse doesn't initially have any of this information, the code assistance that it's able to provide out of the box is pretty broken.

For projects the size and complexity of Mozilla, it's impractical to manually configure Eclipse when there is a valid set of defines and includes paths for each of the different parts of the source code. Happily, Eclipse makes manual configuration unnecessary. Like some other IDEs, that are used with projects like Mozilla that have their own build system. Eclipse provides a tool that can collect the options that are passed to the compiler for each file that's compiled during an actual build. This process is sometimes called "build option discovery" or "compiler option discovery".

The way that Eclipse CDT does build option discovery is to scan the console output from a real build looking for lines where a compiler was invoked. For each line that invoked a compiler, it tries to figure out which source file was being built and what its include paths were. If relative paths are used to specify the source file or any of its include paths (common in Mozilla), and if you fail to take steps to make sure the build output specifies which directory the compiler is invoked from, this will not be possible. If Eclipse can successfully identify which source file was being compiled, then it can associate with that file the resolvable include paths, preprocessor defines, and pre-include files that were passed to the compiler.

Note the requirements that this method of build option discovery imposes on us. First, Eclipse needs build console output for a complete build, so that it can find compiler options for as many source files as possible. The build must be explicitly instructed to output information that allows the directory, where the compiler is being invoked from to be identified (i.e., 'make' must be instructed to output "Entering directory..."/"Leaving directory..." lines). Finally, the build must not be parallelized, since that would result in the interleaving of build output from different directories (breaking resolution of relative paths by interleaving the "Entering directory..."/"Leaving directory..." lines), and the build must not be silenced/quietened.

Conversely, note this very carefully: if you configure Eclipse to invoke a build process that is parallelized, silenced, or that fails to identify the directory that the compiler is being run from, then it will mess up the compiler options that Eclipse associates with your files, and that in turn will significantly degrade the quality of the code assistance that Eclipse will provide after it next re-indexes the code.

These requirements aren't a very good fit with the typical Mozilla developer's wish to minimize build times, implying parallelized, silenced builds.

The consequences of the above observations are this:

  • It is strongly recommended that you invoke your normal (re)builds from the command line, externally of Eclipse.
  • Below we will configure Eclipse's build step so that you use it only occasionally to manually trigger a special "build" (actually a fast script that fakes a build) purely for the purposes of setting/updating the compiler options that Eclipse associates with each source file.

(Not using Eclipse to invoke your real builds does lose you some minor benefits that Eclipse has to offer, but these are worth sacrificing for much improved code assistance. See the Building from Eclipse section below if you're interested in what you lose. If you're interested in future improvements to Eclipse that would allow parallel builds to be run from inside Eclipse while still allowing it to obtain the compiler options, see the FAQ Isn't there a better method of build option discovery? below.)

Initial workspace preferences

When you open Eclipse, it will ask you to "Select a workspace" (a directory where Eclipse will store files that it generates during indexing, and so on.) It's recommended that you have a separate workspace containing only a single project for each Mozilla source tree [rational], and that you choose a directory outside the Mozilla source. Something like $HOME/eclipse-workspaces/mozilla-tree-1, for example. After selecting an appropriate directory, click OK, then close the "Welcome" tab when the main Eclipse window opens.

Before you proceed any further, check that your changes to Eclipse's memory limits have taken effect and are present in Eclipse/Help > About Eclipse > Installation Details > Configuration.

To avoid confusion in this and the following sections, note that "workspace preferences" and "project properties" are different things (we'll get to the details below).

Whenever you create a new workspace for a Mozilla source tree, you should be sure to turn off the following two settings in the workspace preferences (Window > Preferences, or Eclipse > Preferences) before creating a project in that workspace:

  • in "General > Workspace", disable "Build automatically"
  • in "C/C++ > Indexer", disable "Automatically update the index"

Turning off automatic indexing prevents the CPU intensive indexer from running at various stages during the steps below before we're ready.

Select "General > Content Types", expand "Text > C Source File > C++ Source File", click "Add" and add "*.mm". Eclipse CDT doesn't currently understand Objective-C files (although there is a project that promises to add Objective-C support), so for now, this is the best we can do to give Eclipse a chance of expanding its understanding of the source into the Objective-C files.

Select "General > Editors > Text Editors". If you want line numbers, tick "Show line numbers". If you want a column marker to mark the 80th column to help with formatting code to Mozilla's 80 character line limit, tick "Show print margin" and set the value to 80.

Select "General > Workspace" and select "Refresh using native hooks or polling" and "Refresh on access" to prevent Eclipse giving you annoying "Resource is out of sync" messages when files change from under it due to Mercurial or other external activity.

Select "C/C++ > Build > Console" and set "Limit console output (number of lines)" to something large, like "1000000".

Eclipse CDT will try to format C/C++ code that you add as you type. However, its default formats are not a good match to Mozilla's style rules. Download this first pass at an Eclipse formatter configuration for Mozilla C/C++ coding style, and install it by opening the workspace preferences, selecting "C/C++ > Code Style > Formatter", and then using the "Import" button to import that file. The "Active profile" field should then automatically change to "Mozilla". Depending on the area of the code that you work on, you may need to tweak this configuration using the "Edit" button. (Note that the format settings under "General > Editors > Text Editors" have no effect in C/C++ views, since the C/C++ settings are more specific and override those settings. However, you may still want to tweak those settings if you'll be editing other file types in Eclipse.)

Select "C/C++ > Editor" and set "Workspace default" to "Doxygen".

Select "C/C++ > Editor > Content Assist" and set the Auto-Activation delay to 0 so that autocomplete suggestions don't seem to be laggy. (Sadly, there is no auto-activation option to activate autocomplete suggestion., so as soon as you type any alphabetical character that may begin with a symbol name like there is in other IDEs.)

Select "C/C++ > Editor > Save Actions" and deselect "Ensure newline at the end of file".

Select "C/C++ > Editor > Scalability" and set "Enable scalability mode when the number of lines in the file is more than:" to something larger, like 100000.

Select "Run/Debug > Console" and deselect "Limit console output".

If you want to increase the text size in the editor, select "General > Appearance > Colors and Fonts", select "Basic > Text Font", and edit the font size.

Creating an Eclipse project

To create an Eclipse project for your Mozilla source tree, select "File > New > Makefile Project with Existing Code". In the "Import Existing Code" window that opens, enter a meaningful Project Name that identifies your Mozilla source tree, set the code location to the root of your source tree, select an appropriate Toolchain (e.g., "MacOSX GCC"), and click Finish.

The status bar at the bottom right of the window should now show that Eclipse is "Refreshing the workspace" (gathering a list of all the files in the source tree). Click on the little green button beside this message to open the "Progress" tab, and keep an eye on the "Refreshing workspace" item as you continue with the steps below. (If an "indexing" item starts after the "Refreshing the workspace" item has finished, click the little red box beside that item to cancel it, since we want to configure the project before the indexer runs.)

Initial project properties

So that the indexer will run faster and give better results, and so that Eclipse doesn't give results for irrelevant files, you should add some resource filters to have Eclipse ignore certain non-source files and directories. Note, you must not make Eclipse ignore your (main) object directory. That object directory is needed to resolve include paths to the various headers that the build process generates/copies there.

To create resource filters, open the project properties (different to the workspace preferences!) by selecting Properties from the context menu for the project (root item) in the Project Explorer tab on the left, or by selecting Project > Properties from the menubar. Select "Resource > Resource Filters" on the left of the window that opens, then use the Add button to add the following filters:

  • Add an "Exclude all" filter for folders with a Project Relative Path matching ".hg". (This directory doesn't show in the Project Explorer tab, but Eclipse still indexes it without this filter!)
  • If you have secondary object directories (object directories that are not your only/the primary object directory) for the source tree and those directories are inside the source tree (or if you might have such object directories in future), then add an "Exclude all", regular expression filter for folders with a Project Relative Path matching "obj(?!-debug(?:$|/)).+". This particular regular expression will exclude all directories beginning with the string "obj" except "obj-debug", so if "obj-debug" is not the name of your main object directory, then adjust the regular expression as necessary.
  • Add a recursive, regular expression "Exclude all" filter for files with Name matching "\.(?:rej|orig|o|pp|swp)$" to exclude .rej, .orig, .pp, .o, and .swp files.
  • Add "Exclude all" filters for any other non-source directories that you've added to your source tree (e.g., Xcode or MSVC project directories).

Click OK to close the filters window, wait for Eclipse to finish processing your resource filters, then make sure the filtered directories and files have disappeared from the Project Explorer tab on the left. Also, if your main object directory is in your source tree, and not somewhere outside it, make sure that it has not disappeared from the Project Explorer tab.

Reopen the project properties window and select "C/C++ Build" from the left of the project properties window. Select the "Builder Settings" tab, untick "Use default build command", set the build command to "just-print-mozilla-build.py" or, if you're on Mac, to "bash -l -c 'just-print-mozilla-build.py'" (on Mac Eclipse doesn't seem to pick up the environment properly, so it's necessary to invoke just-print-mozilla-build.py indirectly through bash). (just-print-mozilla-build.py is a fast script that we'll download in the next section.) (append '--objdir /path/to/objdir' if your objdir lives outside your tree) Set the build directory to "${ProjDirPath}/path/of/your/objdir/relative/to/the/root/of/your/source". Select the "Behavior" tab, delete the word "all" from the "Build (incremental build)" field, and disable the Clean checkbox.

If you can't untick "Use default build command", you must change the current builder by clicking on "Tool Chain Editor" (in C/C++ Build) and choosing another builder (e.g., "Gnu Make Builder").

If you will not be using Eclipse for debugging, select "C/C++ Build > Settings" on the left, select the "Binary Parsers" tab, and make sure that all the parsers are deselected. This prevents the (useless if not debugging) "Searching for binaries" action from constantly interrupting everything.

If you will be using Eclipse for debugging, select "C/C++ General > Paths and Symbols" and select the "Output Location" tab. You should now add the folder containing your Firefox binary (note on Mac this is inside the .app - so "{your-obj-dir}/dist/NightlyDebug.app/Contents/MacOS/" - and since the UI will only allow you to select to the 'dist' folder, you'll need to type the end of the path in manually). How you add this depends on whether your object directory is inside or outside your source tree. If inside, use the "Add Folder" button; if outside, use the "Link Folder" button and tick the "Link to folder in the file system" checkbox. Once you've added this folder, delete the existing output folder that was set to the root of the project. Doing this prevents the "Searching for binaries" which Eclipse constantly starts from taking too long.

Select "C/C++ General > Preprocessor include Paths, Macros, and so on." Select the Providers tab. Make sure that "CDT GCC Build Output Parser" is selected, and that "CDT Managed Build Settings Entries" is not selected. Highlight (select) "CDT GCC Build Output Parser", then in the "Language Settings Provider Options" that appear below, make sure that "Share setting entries between projects (global provider)" is not ticked.

If the main object directory for your source tree is a Fennec build: In the "CDT GCC Build Output Parser", change the compiler command pattern to

(.*gcc)|(.*[gc]\+\+)|(clang)

(before this change it should have been "(gcc)|([gc]\+\+)|(clang)"). This pattern is what CDT uses to identify compiler commands when parsing the build output. By default, it recognizes commands of the form "gcc", "g++", "c++", and "clang". This is fine for a desktop build, where the commands are in fact "gcc" and "g++". For Fennec builds, however, most of the commands are something like "arm-linux-androideabi-g++", which will not be recognized by the default regex. The modified regex accepts any command that ends with "gcc" or "g++". This may also affect other non-desktop builds besides Fennec.

Especially important if the main object directory for your source tree is located somewhere outside your tree's top source directory: If this applies to you, then select the Entries tab, select "GNU C++", select "CDT User Settings Entries", and click "Add". Change "Project Path" to "Filesystem", then select the 'dist/include' directory that's in your main object directory and click OK. Repeat these steps, but this time for "GNU C" instead of "GNU C++". (See the Headers are only parsed once section below to understand why this step is important for people who have their object directory outside their source tree.)

Getting code assistance working

You're now ready to get code assistance working. :-)

Build option discovery

This section requires that you have already built your mozilla source tree (so that you have an object directory for it), and it is strongly recommended that the object directory is up to date so that the just-print-mozilla-build.py script runs quickly.

As explained in the Code assistance section above, to provide good code assistance Eclipse CDT needs to collect build information for the source files by processing a build log from a full, clean build made using -j1 -w. Since such a non-parallel, full build would take a very long time, we're going to cheat and set Eclipse's "Build" action to run jwatt's just-print-mozilla-build.py script instead. This script will complete in about 30 seconds on a warm tree (files cached in RAM) if your object directory is up to date, although Eclipse will take several minutes to process the "build output" that it produces.

Download just-print-mozilla-build.py and change its permissions to make it executable ('chmod a+x just-print-mozilla-build.py').

If you don't put just-print-mozilla-build.py somewhere in your PATH, then go back to the Initial project properties section where you set just-print-mozilla-build.py and specify its absolute path instead of just its name.

Now invoke the script by clicking the Build button (the button with the hammer symbol) or by selecting "Project > Build Project" from the main menu. That done, select the "Console" tab at the bottom of the main Eclipse window and you should see the build console output flying by as Eclipse processes it. It should take about 5-10 minutes for Eclipse to finish processing the output.

Additional discovery for C++11 mode

As of Mozilla 25, Mozilla is built in C++11 mode. When GCC is invoked in C++11 mode, it defines pre-processor symbols that enable conditional compilation of C++11 code in its standard library. To correctly parse this code, Eclipse CDT needs to know about these symbols. Unfortunately, the build option discovery process outlined above does not pick up this information, so CDT needs to be told separately about C++11 mode. To do this, go to "Preferences -> C/C++ -> Build -> Settings -> [Discovery] tab -> CDT GCC Built-in Compiler Settings" and add the flag "-std=c++11" at the end of the field labeled "Command to get compiler specs".

In CDT 8.3 (unreleased as of August 2013), there will be a more user-friendly way to specify this (see http://wiki.eclipse.org/CDT/User/NewIn83#Toolchains).

Building the index

Once you see the end of the build output in the Console tab and the Build item has disappeared from the Progress tab, you can start indexing the source. If indexing started automatically (see the Progress tab), cancel it, since there seems to be a bug that makes it give bad results when it starts automatically at this stage. Right-click the project root in the Project Explorer tab and select "Index > Rebuild". You will now see "Indexing..." in the status bar at the bottom right and an Indexing item in the Progress tab. It will take 10 minutes or so on a decent developer machine for a full rebuild of the index.

Once the indexer has finished (keep an eye on the Progress tab), sanity check that everything went as it should have by right-clicking the project in the Project Explorer tab and selecting "Index > Search For Unresolved Includes". If you get many more than 2000 unresolved includes (as of May 2012), then things have gone pretty wrong. You should be able to use the list of unresolved includes to help figure out what the problem is (see also the Parser errors section for more troubleshooting tips).

Assuming everything went as expected, you should now find that Eclipse's code assistance works a whole lot better. :-) To test out the code assistance, see the Code assistance subsection of the Usage tips section below.

To improve code assistance even more, see the Headers are only parsed once subsection of the Known Issues section.