right! I forgot the "pre"
It happens before any tools in the compile/link tool chain get invoked.
On a Unix system, for example, one creates make files for a project of any complexity. The make file defines the rules for mapping one kind of object to another (source to object, object to library, library to executable, etc.) with multiple rules for various kinds of objects (source - .c, .cpp, .f, .s, etc., object - .o, etc.). The make file also contains a list of files to consider - all the source files that make up a library, for instance.
It is this make file (information) that the Arduino IDE is constructing (and that there are some issues with). Once the make file is constructed, make does whatever is required to map the (modified) input files to the specific output files. If it determines that the process of building a .o file requires a specific .c file, and that .c file is newer that the .o file, then it knows it needs to apply the .c to .o file rule to the .c file.
There determination of what files are relevant to the process is one of the week points of the whole build process.