Makefile. How to exclude one specific file from compilation?

I am trying to exclude the main.cpp file from the list of files that should be compiled according to the rule below:

$(TMPDIRPATH)%.o: %.cpp @echo compile $< ifneq ($(notdir $<), main.cpp) @$(COMPILE.cpp) $(OUTPUT_OPTION) $< endif 

This ifneq condition is always evaluated as true, which is strange. What am I doing wrong? Is there a better way to exclude one file from an explicit rule?

+4
source share
4 answers

This is not the best way to do this, but if you do it on these lines, write it as a shell condition without using the GNU make conditions:

 $(TMPDIRPATH)%.o: %.cpp @echo compile $< @if [ $(notdir $<) != main.cpp ]; \ then $(COMPILE.cpp) $(OUTPUT_OPTION) $<; \ fi 

Continuation markers required (backslashes). Similarly, semicolons. Values ​​prefixed with $ will be extended to make before the shell is invoked to interpret them. You probably don't want the echo where it is. You probably need:

 $(TMPDIRPATH)%.o: %.cpp @if [ $(notdir $<) != main.cpp ]; \ then echo compile $<; \ $(COMPILE.cpp) $(OUTPUT_OPTION) $<; \ fi 

As I expected, this will be with a list of files that need to be compiled. Using any wild card mechanism leads to problems when adding additional files - other tests or roaming files that are not actually part of the system.


The comment says: "But the GNU Make Manual says that ifneq should work."

ifneq will work if it is placed correctly, which means "do not back down as part of the rule-related commands." So you could write something like (a terribly bad example, but my brain is on Fritz):

 ifneq (${CFLAGS}, -Wall) CFLAGS += -Wall endif file1.o: file1.c ${CC} ${CFLAGS} -c $< 

But when ifneq is indented, as in the question, it's just a command that is not actually found on the system when make launches a shell to process the command.

+5
source

Why aren't you trying to use the filter-out text function if you are using GNU Make.

Returns all words, separated by spaces, in the text that do not match any of the words in the template, deleting words that match one or more. This is the exact opposite of the filter function.

For example, given:

 objects=main1.o foo.o main2.o bar.o mains=main1.o main2.o 

The following generates a list containing all the object files that are not in the 'mains:

 $(filter-out $(mains),$(objects)) 
+8
source

The ifneq line is evaluated only once when make is launched and parses the makefile. In this context, $< empty.

To get a different behavior for each of the goals matching your pattern, you can do something like

 $(TMPDIRPATH)%.o: %.cpp @echo compile $< @$(if $(filter main.cpp,$<),$(COMPILE.cpp) $(OUTPUT_OPTION) $<) 

This can help you understand the difference between ifneq and $(if) in the make file as the difference between #if and if() in the C code.

However, let's take a step back: if you do not want main.cpp be compiled by this rule, you probably want to provide an explicit rule with $(TMPDIRPATH)main.o as your target, which will always be preferable to the rule template. Or, if you do not want $(TMPDIRPATH)main.o be obtained at all, you should look for the rules that have it in the right image : and delete it from there.

+4
source

Make really doesn't have a good way to handle conditional expressions inside a rule. You can put a conditional expression in a command, but in this case there is a cleaner way:

 $(TMPDIRPATH)main.o: @echo compile $< (but not really) $(TMPDIRPATH)%.o: %.cpp @echo compile $< @$(COMPILE.cpp) $(OUTPUT_OPTION) $< 

EDIT:
I did not understand that you do not have main.cpp . The solution is simple: remove main.cpp as a prerequisite for the rule main.o (I deleted it above). Now the make file is not needed, and will not try to create it.

But you are still using the rule, which means that something is still trying to create main.o , either as an explicit goal or as a prerequisite for something else. This is a symptom of confusion that this change in the makefile will not be fixed. If you tell us more about the situation, perhaps we can offer a better solution. What causes main.o ? Do you have main.o ? What purpose do you indicate when calling Make?

+2
source

Source: https://habr.com/ru/post/1342222/


All Articles