It sounds like you don’t quite understand how compiling works, so I’ll briefly explain it for you and everyone else who may be new to all of this
On the left side of the image, is the “standard” build process used by the C++ compiler. All of these steps are automated in visual studio, but if you are using a different compiler (such as GCC in linux), you may have to perform each of these steps manually using a command line. Anyways, here’s what happens when you “build” a standard C++ project:
All of your preprocessor directives are processed. Any line of code which comes with a # in front of it is a preprocessor directive. When you write “#include <somefile.h>”, the preprocessor will go look for this file and copy/paste it at that line. All of your #defines are processed here as well, so “#define PI 3.1415” will cause the preprocessor to go through all of your code and swap all versions of PI for 3.1415. This is also where your #if and $ifdef, etc are handled. By using preprocessors, you can alter the .CPP and .H code which gets compiled in the next step. UE4 uses these with the Build Configuration selector to change what code gets run. Fancy stuff.
The compiler will then go through all of your .CPP and .H files and parse them. There’s a lot of compiler theory that we could get into here to explain how it does that, but it’s not really that important. The bottom line is that if you have syntax errors in your code, this is where the compiler will fail on you (ie, forgot a semicolon or something).
If all of your code can be successfully compiled, the output is an intermediate OBJ file. Usually you get one OBJ file per class in your code. If you have hundreds of classes, you have hundreds of OBJ files. The next step in the build process is to merge all of these OBJ files together to build a single binary file. This is done by the “Linker”. The linker does a few things. I’m a bit fuzzy on the exact internals/process here, but I think that when it is processing your OBJ files, it is taking your function and class declarations and mapping them to the memory address of its implementation (at the assembly/binary code level). So, IF you have a header file which contains a function declaration, such as OnEquip(), but you don’t have an implementation for it, then the linker will fail to bind that method to a fixed memory address and you’ll get a linker error. Once the linker has finished matching all function declarations to fixed memory addresses, it creates a binary executable file. This is what you run.
The binary executable file is always native code, commonly in the form of an EXE or DLL. It’s important to note that the binary file will differ depending on whether your compiler built a debuggable version or a release version. If you build a debug version of a binary file, the compiler will not optimize the binary and it will allow you to set break points on “symbols” and step through the code using a debugger. These types of binary files come with a lot of bloat and are much larger, but are very friendly to debug. If your binary is set for “release”, then the compiler will try to perform every optimization trick in the book to build a fast and lean binary file. The file size and speed are as fine tuned as possible (though, maybe not nearly as optimized as really good assembly code written manually).
Anyways, that’s the common build process for native C++ applications.
With UE4, it’s a bit different.
UE4 uses a pair of applications called the “Unreal Build Tool” (UBT) and “Unreal Header Tool” (UHT) to build your game code. (Correct me if I’m wrong) The UBT handles the overall building of your game code, and the UHT handles the processing of all UE4 specific macros. Anytime you have something like UCLASS(), UPROPERT(), UFUNCTION(), etc, that gets processed by UHT. The UHT step happens right after all preprocessor directives are handled, and acts almost as another type of preprocessor. But instead of being a preprocessor, it is a program which writes code. This is the “generated” code you may see in your project files. The generated code is additional code which gets added to your compiler. Epic calls this “Reflection”. So, if you mess something up in the UE4 reflection code, the UHT will fail, which causes the UBT to fail, and if you’re lucky, you’ll get errors which tell you which part of your reflection code caused an error (you have to look at your output log, not your error log).
It’s really important to realize that the UHT generates additional code for you. Sometimes it’ll create additional methods (such as with replication or blueprint native events) which are not explicitly declared in your .H file but need to be added to your .CPP file. If you mess this up, you may run into linker errors as well and the UBT will fail. Thankfully though, the linker is usually pretty good at telling you what the error is (though, a bit verbose with the gobbledegook it spits out)
It’s also really important to note that the UBT will take ALL of the source code in your source directory and try to build off of it. It does NOT care about what files you have added within your visual studio project. So, if you intend to exclude a class from your game, removing it from your project isn’t going to remove it from your game. You have to remove the file from your source code directory tree.
It’s also really important to note that the generated code and OBJ files don’t all get cleaned out from your intermediate folders. If you remove a class from the project, the intermediate file and OBJ files will still exist and they may be linked against and included in your project. In these rare cases, you have to manually go into your intermediate folders and delete all OBJ files and generated files to get a “clean build”. If you don’t, you may get funky linker errors. Or, if you get funky linker errors, do a manual clean. (I wrote a batch file which does this for me).
Note #2: If you built the engine from source code and you do a “clean” on your project, the clean will also clean out the engine intermediate files, requiring a complete recompile. This costs a lot of time, so I do it manually
Anyways, this is a lot of info to absorb. I hope this helps.