Outpost Universe Forums

Projects & Development => Outpost 2 Programming & Development => Topic started by: Hooman on August 20, 2019, 07:09:13 AM

Title: Makefile - Target Specific Variable Values
Post by: Hooman on August 20, 2019, 07:09:13 AM
I was taking a look through Makefile documentation when I found:  Target-specific Variable Values (https://www.gnu.org/software/make/manual/html_node/Target_002dspecific.html#Target_002dspecific)


Target specific variables allow you to use a general build rule, yet still have target specific variables (CFLAGS, CXXFLAGS, etc.) when applying those rules. They give the general pattern as:
Code: [Select]
target … : variable-assignment

Example:
Code: [Select]
prog : CFLAGS = -g
prog : prog.o foo.o bar.o

Here the output prog is built from three object files. Those three object files are then built using the built-in implicit rules to build .o files from .c files. Target specific variables are inherited when building dependencies, so this value is passed down to the built-in implicit rule. The built-in implicit rule references the CFLAGS variable, which is set to -g (generate debug info).



This is perhaps a surprisingly obvious feature in hindsight. Many of the OPU repositories have Makefiles with duplication of rules using different variable names to address the very problem this feature solves. For example, the difference between building the main project versus building the unit test project:
Code: [Select]

COMPILE.cpp = $(CXX) $(OUTPUT_OPTION) $(DEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(TARGET_ARCH) -c $<

$(OBJS): $(INTDIR)/%.o : $(SRCDIR)/%.cpp $(INTDIR)/%.d | build-folder
$(COMPILE.cpp)
$(POSTCOMPILE)

# ...

TESTCOMPILE.cpp = $(CXX) $(OUTPUT_OPTION) $(TESTCPPFLAGS) $(DEPFLAGS) $(CXXFLAGS) $(TARGET_ARCH) -c $<

$(TESTOBJS): $(TESTINTDIR)/%.o : $(TESTDIR)/%.cpp $(TESTINTDIR)/%.d | test-build-folder
$(TESTCOMPILE.cpp)
$(POSTCOMPILE)


The two rules are basically doing the same thing, but were written twice to account for the different variables. The main project rule expands to use the CPPFLAGS variable, while the test project rule expands to use the TESTCPPFLAGS variable. The main difference being, the test project adds an include folder for the main project so it can find the header files.

By using the target-specific variable feature of Makefiles, these rules can potentially be shortened into one, allowing for simpler and shorter Makefiles.