Make uses same source file for different object files

后端 未结 2 1038
庸人自扰
庸人自扰 2021-01-28 12:59

Make chooses the same source file for different object files. Both are a list of files, only with different filenames. Make switches between the object files but not the source

相关标签:
2条回答
  • 2021-01-28 13:10

    Consider the rule...

    $(OBJFILES): $(SRCFILES)
            $(CC) $(CCFLAGS) -c $< -o $@
    

    Let's say, for the sake of argument, that we have...

    SRCFILES := a.c b.c
    OBJFILES := a.o b.o
    

    If you expand the rule manually it becomes...

    a.o b.o: a.c b.c
            $(CC) $(CCFLAGS) -c $< -o $@
    

    I think (correct me if I'm wrong) you are under the impression that this will be interpreted by make as a.o depends on a.c and, separately, b.o depends on b.c. That's not the case. What it actually states is that both of a.o and b.o depend on both of a.c and b.c.

    So, when make tries to update the target a.o it sees the full prerequisite list of a.c and b.c and assigns the first of these, a.c, to the builtin variable $<. That's why you always see the first source file in $(SRCFILES) being compiled.

    The best way to solve this probably depends on how you intend to structure your source file hierarchy and object files but you might want to take a look at using one or more vpath directives.

    0 讨论(0)
  • 2021-01-28 13:26

    The pattern rule does not put all objects in root directory, consider

    CFILES := path/to/a.c b.c
    OBJFILES := $(foreach f,$(CFILES),$(f:%.c=%.o))
    
    all: $(OBJFILES)
    
    %.o: %.c
        $(CC) $(CCFLAGS) -c $< -o $@
    

    Here is what you get:

    cc -c path/to/a.c -o path/to/a.o
    cc -c b.c -o b.o
    

    The following is not a recommendation, but kind of an exercise in makefile programming.

    If you have $(SRCFILES) and want to compile them one at a time, you can use:

    define compile
    $1.o: $1.c
        $(CC) $(CCFLAGS) -c $$< -o $$@
    endef
    
    $(foreach src,$(SRCFILES),$(eval $(call compile, $(src:%.c=%))))
    

    If the correspondence of lists of sources and objects is not by name, but only by placement in list, you can destroy the CFILES list

    define compile
    src := $(CFILES)
    CFILES := $(wordlist 2, $(words $(CFILES)), $(CFILES))
    $1: $(src)
        $(CC) $(CCFLAGS) -c $$< -o $$@
    endef
    
    $(foreach obj,$(OBJFILES),$(eval $(call compile, $(obj))))
    

    Or you may use a helper list, to keep CFILES unchanged:

    helperlist := $(CFILES)
    
    define compile
    src := $(firstword $(helperlist))
    helperlist := $(wordlist 2, $(words $(helperlist)), $(helperlist))
    $1: $(src)
        $(CC) $(CCFLAGS) -c $$< -o $$@
    endef
    
    $(foreach obj,$(OBJFILES),$(eval $(call compile, $(obj))))
    
    0 讨论(0)
提交回复
热议问题