Eine "extern"-Deklaration teilt dem Compiler nur mit, dass irgendwo
(i.d.R. in einer anderen Quelldatei) eine Variable mit dem angegebenen
Namen Datentyp existiert. Wie kosmonaut pirx schon andeutete, wird durch
eine extern-Deklaration keine Variable angelegt, also kein Speicherplatz
belegt. Damit diese Variable allerdings überhaupt genutzt werden kann,
muss sie an genau einer Stelle OHNE das "extern" deklariert oder
definiert sein. Ist das nicht der Fall, dann meckert der Linker (und das
völlig zu Recht).
BTW:
Deine zweite Version ist ja im Unterschied zur ersten auch zumindest
funktionell korrekt (bis auf den Schreibfehler bei der Definition in
main.h). Die Variable wird in main.h definiert und in allen anderen
Sourcen wird nur die defines.h eingebunden, die die "extern"-Deklaration
enthält.