According to the
GNU make documentation, assignment with '=' causes "recursive expansion"; that is, variables referenced within variable assigned this way are expanded on demand. Say you have a variable 'foo', and you set it as follows:
foo = $(bar)
Note that make has no problem with you referencing a currently undefined variable when using recursive expansion. Then, later on you can define 'bar' as follows:
bar = Hello.
When you reference 'foo', it is finally fully expanded to the value 'Hello.'.
Assignment with the ':=' operator causes "simple expansion". Variables that are simply expanded are immediately replaced with their values.
If you know about pointers in C, then you can imagine simple expansion as working with values and recursive expansion as working with pointers. I'm not sure why, in your example, 'ARCH' and 'HOSTCC' are set differently though; for static values such as those, I don't see a difference between the two expansion schemes.
'export' adds a variable to the environment of any future child processes. So in your case, if you export 'SHELL' and then call `gcc`, then GCC will be able to "see" your custom 'SHELL' variable. Most or all shells (bash, ash, csh, etc.) also offer similar variable exporting functionality.