簡體   English   中英

如何將 $@ 更新為 Makefile 變量相關目標規則?

[英]How to update $@ into a Makefile variable dependent target rule?

我有一個 Makefile 定義了一個變量依賴目標,如下所示:

SRCFILES=./src/main.c ./src/file.c
# Get the filenames of all the sources
SRCNAMES=$(notdir $(SRCFILES))

OBJDIR=./obj/
# Replace .c to .o in all source names
OBJNAMES=$(SRCNAMES:.c=.o)
# Add the obj/ repository as prefix
OBJFILES=$(addprefix $(OBJDIR), $(OBJNAMES))

NAME=myprog

all: $(NAME)

$(NAME): $(OBJFILES)
    gcc $(OBJFILES) -o $(NAME)

$(OBJDIR)%.o: ./src/%.c
    mkdir -p $(OBJDIR)
    gcc -c $< -o $@

# If the make debug rule is called, I want my objects to be build into ./obj/debug/
debug: OBJDIR = ./obj/debug/
debug: all

使用這個 Makefile,當我運行make debug我有以下輸出:

❯ make debug
mkdir -p ./obj/debug/
gcc -c src/main.c -o obj/main.o
mkdir -p ./obj/debug/
gcc -c src/file.c -o obj/file.o
gcc ./obj/debug/main.o ./obj/debug/file.o -o myprog
gcc: error: ./obj/debug/main.o: No such file or directory
gcc: error: ./obj/debug/file.o: No such file or directory
gcc: fatal error: no input files
compilation terminated.
make: *** [Makefile:16: myprog] Error 1

我的問題是這個輸出的前兩行:

mkdir -p ./obj/debug/  # <----------- Here we see that the $(OBJDIR) variable has been updated

gcc -c src/main.c -o obj/main.o # <-- However, the $@ variable which is generated from $(OBJDIR)%.o hasn't been updated accordingly

如何在 $(OBJDIR) 更改時使$@自動變量更新?

make解析 Makefile 時,它​​將在為非隱式目標的目標構建依賴樹時擴展所有變量。 因此,當您調用make debug它會嘗試構建myprog ,而后者又會嘗試構建obj/main.o ,而不是obj/debug/main.o ,因為在解析myprog的規則時$(OBJFILES)已經擴展. 這就是為什么$@擴展為obj/main.o即使變量是正確的。 你自己看:

$ make -dr debug
...
Considering target file 'debug'.
 File 'debug' does not exist.
 Looking for an implicit rule for 'debug'.
 No implicit rule found for 'debug'.
  Considering target file 'all'.
   File 'all' does not exist.
   Looking for an implicit rule for 'all'.
   No implicit rule found for 'all'.
    Considering target file 'myprog'.
     File 'myprog' does not exist.
      Considering target file 'obj/main.o'.
       File 'obj/main.o' does not exist.
       Looking for an implicit rule for 'obj/main.o'.
       Trying pattern rule with stem 'main'.
       Trying implicit prerequisite 'src/main.c'.
       Found an implicit rule for 'obj/main.o'.
        Considering target file 'src/main.c'.
         Looking for an implicit rule for 'src/main.c'.
         No implicit rule found for 'src/main.c'.
         Finished prerequisites of target file 'src/main.c'.
        No need to remake target 'src/main.c'.
       Finished prerequisites of target file 'obj/main.o'.
      Must remake target 'obj/main.o'.
mkdir -p ./obj/debug/
...

不過有可能讓它工作。 首先,您需要在執行時使用第二個擴展來解決依賴關系。 其次,您需要以某種方式使您的$(NAME)目標成為隱式規則, make重新評估表達式。 最后,由於您的對象位置會有所不同(包括debug與否),它也會傳播到通常應該相同的源位置。 我能夠讓它像這樣工作:

$ cat Makefile
SRCFILES=./src/main.c ./src/file.c
# Get the filenames of all the sources
SRCNAMES=$(notdir $(SRCFILES))

OBJDIR=./obj/
# Replace .c to .o in all source names
OBJNAMES=$(SRCNAMES:.c=.o)
# Add the obj/ repository as prefix
OBJFILES=$(addprefix $(OBJDIR), $(OBJNAMES))

NAME=myprog

.SECONDEXPANSION:

all: $(CURDIR)/$(NAME)

# Implicit rule due to %
%/$(NAME): $$(OBJFILES)
        gcc $(OBJFILES) -o $(NAME)

%.o: ./src/$$(notdir $$*).c
        mkdir -p $(OBJDIR)
        gcc -c $< -o $@

# If the make debug rule is called, I want my objects to be build into ./obj/debug/
debug: OBJDIR = ./obj/debug/
debug: all

輸出:

$ make
mkdir -p ./obj/
gcc -c src/main.c -o obj/main.o
mkdir -p ./obj/
gcc -c src/file.c -o obj/file.o
gcc ./obj/main.o ./obj/file.o -o myprog
rm obj/main.o obj/file.o

$ rm -rf obj myprog
$ make debug
mkdir -p ./obj/debug/
gcc -c src/main.c -o obj/debug/main.o
mkdir -p ./obj/debug/
gcc -c src/file.c -o obj/debug/file.o
gcc ./obj/debug/main.o ./obj/debug/file.o -o myprog
rm obj/debug/main.o obj/debug/file.o

就個人而言,我也會考慮構建具有不同名稱或位置的最終二進制文件,否則您將永遠無法確定已構建的內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM