next up previous contents
Next: Makefile 其他法則 Up: 開發工具 - make 與 Previous: makefile 的變數   Contents

多重目標項目(target)

  • 可在 makefile 中建立多個目標項目,並於 make 時指定目標項目。
  • 例題:沿上例,加入 clean 目標項目,以移除不想要的目的檔(object)。
    1. 建立編譯的規則
      [guest@test guest]# vi makefile 
      main: main.o haha.o sin_value.o cos_value.o 
              gcc -o main main.o haha.o sin_value.o cos_value.o -lm 
      clean: 
              rm -f main main.o haha.o sin_value.o cos_value.o 
      #%* clean 冒號之後是空白。目標項目永遠會被認為過期,所以它的法則永遠會被執行。*)
      
    2. 測試標的 clean:
      [guest@test guest]# make clean 
      rm -f main main.o haha.o sin_value.o cos_value.o
      
    3. 先清除目標檔再編譯程式 main : 
      [guest@test guest]# make clean main 
      rm -f main main.o haha.o sin_value.o cos_value.o 
      cc    -c -o main.o main.c 
      cc    -c -o haha.o haha.c 
      cc    -c -o sin_value.o sin_value.c 
      cc    -c -o cos_value.o cos_value.c 
      gcc -o main main.o haha.o sin_value.o cos_value.o -lm
      

  • 沿上例,再加入 install 目標項目,將完成的應用程式安裝到不同的目錄。
    1. makefile 新的版本 Makefile3:
      all: myapp
      # Which compiler
      CC = gcc
      # Where to install
      INSTDIR = /usr/local/bin
      # Where are include files kept
      INCLUDE = .
      # Options for development
      CFLAGS = -g -Wall -ansi
      # Options for release
      # CFLAGS = -O -Wall -ansi
      myapp: main.o 2.o 3.o
         $(CC) -o myapp main.o 2.o 3.o
      main.o: main.c a.h
         $(CC) -I$(INCLUDE) $(CFLAGS) -c main.c
      2.o: 2.c a.h b.h
         $(CC) -I$(INCLUDE) $(CFLAGS) -c 2.c
      3.o: 3.c b.h c.h
         $(CC) -I$(INCLUDE) $(CFLAGS) -c 3.c
      clean:
         -rm main.o 2.o 3.o
      install: myapp
      # 每個命令都會啟動一個新的 shell,所以必須加上反斜線(\),讓所有 script 命令在同一行,且在同一個 shell 中執行。
         @if [ -d $(INSTDIR) ]; \
          then \
            cp myapp $(INSTDIR);\
            chmod a+x $(INSTDIR)/myapp;\
            chmod og-w $(INSTDIR)/myapp;\
            echo "Installed in $(INSTDIR)";\
         else \
            echo "Sorry, $(INSTDIR) does not exist";\
         fi
      
    2. &&:前個命令成功,才執行下個命令
      @if [ -d $(INSTDIR) ]; \
       then \
         cp myapp $(INSTDIR) &&\
         chmod a+x $(INSTDIR)/myapp && \
         chmod og-w $(INSTDIR/myapp && \
         echo "Installed in $(INSTDIR)" ;\
      else \
         echo "Sorry, $(INSTDIR) does not exist" ; false ; \
      fi
      
    3. 執行
      $ rm *.o myapp
      $ make -f Makefile3
      gcc -I. -g -Wall -ansi -c main.c
      gcc -I. -g -Wall -ansi -c 2.c
      gcc -I. -g -Wall -ansi -c 3.c
      gcc -o myapp main.o 2.o 3.o
      $ make -f Makefile3
      make: Nothing to be done for 'all'.
      $ rm myapp
      $ make -f Makefile3 install
      gcc -o myapp main.o 2.o 3.o
      Installed in /usr/local/bin
      $ make -f Makefile3 clean
      rm main.o 2.o 3.o
      $
      
練習題
  1. makefile 中,是否可以有多個目標項目?
    Sol. 可以。
  2. 若 makefile 中有一目標項目 clean,則如何於執行 make 時指定此目標項目?
    Sol. make clean
  3. 若有一 makefile 中,目標項目 clean 冒號之後是空白,代表意義為何?
    Sol. 目標項目永遠會被認為過期,所以它的法則永遠會被執行。
  4. 若 makefile 中,多個目標項目 main, clean 與 install,要如何指定目標項目 install 執行 make?
    Sol. make install
  5. 若 makefile 中,多個目標項目 main, clean 與 install, make 如何"一次"執行 claen 後接著 install?
    Sol. make clean install
  6. 請解釋如下 makefile 片段,假設變數 INSTDIR=mydir。
    install: myapp
       @if [ -d $(INSTDIR) ]; \
        then \
          cp myapp $(INSTDIR);\
          chmod a+x $(INSTDIR)/myapp;\
          chmod og-w $(INSTDIR)/myapp;\
          echo "Installed in $(INSTDIR)";\
       else \
          echo "Sorry, $(INSTDIR) does not exist";\
       fi
    

    Sol. 1.目標項目 install 的相依性項目有 myapp; 2. @ 表示不會在標準輸出上,顯示要執行的命令; 3.如果 mydir 是一個目錄,則執行複製 myapp 到目錄 mydir、改變 mydir/myapp 的屬性,所有使用者加上可執行屬性、其他使用者及同群組使用者刪除可寫屬性;螢幕輸出 Installed in mydir; 4.其他(即 mydir 不是一個目錄,則螢幕輸出 Sorry, mydir does not exist; 5.因為每個命令都會啟動一個新的 shell,所以必須加上反斜線(\),讓所有 script 命令在同一行,且在同一個 shell 中執行。
  7. 如下 makefile ,&& \ 代表意義為何?
    chmod a+x $(INSTDIR)/myapp && \
    chmod og-w $(INSTDIR/myapp && \
    

    Sol. && 表示前個命令成功,才執行下個命令,\ 讓 script 命令在同一行,且在同一個 shell 中執行。



2017-06-14