Default answer: if the contents of your translation unit (= pre-processed source file) changes, you need to recompile it in order to save its object file in accordance with its original form.
Changing the header file with #include d changes the pre-processed source of the translation unit, so it must be recompiled to be fully synchronized. Therefore, from this point of view, changing the header requires recompilation.
However, this is the most conservative approach. (And if something goes wrong with any more complex approach, you should return to it). In practice, you may not need to recompile if all you have done is add an enumeration to an enumeration.
If you enter a new e42 header in the header but don't actually use it anywhere in the x.cpp file, it is very likely that the object file created from x.cpp with x.cpp will be 100% of the object created from x.cpp without x.cpp . Therefore, from this point of view, recompilation is meaningless. Ideally, you only need to recompile the source file if the generated object file differs from the previously modified one.
Assuming that you are not using a new enumerator in a file, to a large extent the only thing that can lead to a change in the object file is this: the size of the enumeration type can change. If your largest enumerator value is 2147483647, and you add a new one, it is possible that the size of the enumeration itself will go from 32 bits to 64 bits.
You can get around this limitation by using the C ++ 11 feature to explicitly specify the underlying type of an enumeration. Be sure to include it for the listing you are distributing like this.
enum EnumerationBeingExtended : int // ^^^^^ this part { // ... list of enumerators as before };
If you have an enumeration size (virtually the entire base type) fixed in this way, it is very likely that object files containing only the old enumeration definition (without e42 ) will work fine with object files containing the new one (one with e42 ).
Of course, you will technically find yourself in a poorly formed territory of the program, because the program will violate the rule of uniform clarity (different units of translation have a different definition for this enumeration). However, if everything you do uses enumeration values, you are likely to be completely safe in practice.
I would be wary of this trick if you make funky, for example, using typeid in an enumeration type. But if you use only enumerations and the enumeration type itself is “normal”, you should be good.
Of course, you should ideally isolate this enumeration with a header file containing just that, and document its intended use to a large extent. You may also have to make allowances on your build system so as not to rebuild the file due to a header change.
In short: formally, you will have a poorly formed program. But in practice, you should be safe.