makefile編譯cpp
㈠ 如何通過makefile生成cmake
CMake是一個跨平台的安裝(編譯)工具,可以用簡單的語句來描述所有平台的安裝(編譯過程)。他能夠輸出各種各樣的makefile或者project文件,能測試編譯器所支持的C++特性。只是 CMake 的組態檔取名為 CmakeLists.txt。Cmake 並不直接建構出最終的軟體,而是產生標準的建構檔(如 linux 的 Makefile 或 Windows Visual C++ 的 projects/workspaces),然後再依一般的建構方式使用。
在 linux 平台下使用 CMake 生成 Makefile 並編譯的流程如下:
編寫 CmakeLists.txt。
執行命令 「cmake PATH」 或者 「ccmake PATH」 生成 Makefile ( PATH 是 CMakeLists.txt 所在的目錄 )。
使用 make 命令進行編譯
工程實例:
一. 編寫各層CMakeLists.txt
主目錄的主程序main.cpp
#include "hello.h"
extern Hello hello;
int main()
{
hello.Print();
㈡ Ubuntu下面Makefile的使用方法
運行可執行文件hello
./hello
移除文件 rm hello
編譯文件得到可執行文件的同時,保留產生的中間文件
g++ -save-temps hello_world.cpp -o hello
單個文件編譯過程:
實際的編譯過程:預處理,對應臨時文件hello_world.ii
g++ -E hello_world.cpp -o preprocessed.ii
cat preprocessed.ii
預處理的工作主要包含去掉注釋,然後將我們include的庫tack上,以上過程使我們自己主動調用預處理器的過程
cat hello_world.ii
則展示了我們在第5)中編譯時保留的中間文件,兩者是一樣的
實際的編譯過程:這是真正的編譯過程compilation step,對應臨時文件hello_world.s(assembly code)
我們自己把.ii文件進行assembly code得到.s的方法。
g++ -S preprocessed.ii -o complied.s
.s文件是高級語言和機器語言之間的中間環節
實際的編譯過程:Assembly,將.s對應的assembly code轉換成.o對應的機器語言的過程,也叫machine-readable code或者object code
讓編譯器將.s文件assembly起來
g++ -c complied.s -o assembled.o
實際的編譯過程:最後一步Linking,產生最終的可執行文件。
"Undefined reference" errors are pretty much always linking errors, and you will probably have them. Remember this.
我們通過連接一堆.o文件,得到.exe文件的過程,命令:
g++ assembled.o -o hello_manual
多個文件編譯過程:
舉例,如果我們有定義一個class,然後我們的文件中包含dog.hpp,dog.cpp和main.cpp三個文件,然後我們只使用以下兩個命令:
g++ -c main.cpp -o main.o
g++ main.o dog_program
的話就會出錯,告訴我們undefined reference of dog::bark()
因為對於不同的.cpp文件,都要生成一個object file,也就是.o文件。所以如果我們用以下命令:
g++ -c main.cpp -o main.o
g++ -c dog.cpp
g++ dog.o main.o -o dog_program
的話,就不會出錯。
我們如果修改main.cpp中的內容的話,我們只需要重新用最後一個連接命令。但是,如果我們修改了dog class本身的內容的話,例如添加一個函數,我們就需要重新產生object file of dog.cpp,然後重新連接。
關於Make的介紹
用自己常用的記事本創建一個Makefile,並注意大小寫。在program對應的目錄下面。
gedit Makefile
Makefile裡面語句的書寫規則是
Target: tgt_dependency1 tgt_dependency2 ……
Command
所以dog.o和main.o對應的語句分別是:
dog.o: dog.hpp dog.cpp
g++ -c dog.cpp
main.o: main.cpp
g++ -c main.cpp
在Makefile中Tab是很重要的,所以不要忘記在command對應的第二行加Tab
Makefile的編譯順序
如果Makefile中有如下語句
animal_assembly : moose goose cat
command
moose : antlers hooves fur
command
goose : beak wings webbed_feet interest_in_bread
command
cat : whiskers evil_personality
command
我們可以看到animal_assembly的dependency是 moose goose cat。如果文件夾中存在moose goose cat的話,make命令只需要執行第一句就可以了。如果文件夾中缺少moose goose cat中的一個或者幾個,make命令執行的時候,需要先找到moose goose cat的生成方法,然後執行對應的命令,最後執行animal_assembly生成的命令。
moose : antlers hooves fur
command
animal_assembly : moose goose cat
command
goose : beak wings webbed_feet interest_in_bread
command
cat : whiskers evil_personality
command
如果Makefille是以上形式的話,我們只運行make的話,Makefile會只執行第一句,因為第一句的dependency都存在了,所以只把moose生成的命令執行完就好了。如果我們要生成animal_assembly,就要運行命令make animal_assembly。所以,我們需要把最重要的命令,我們最重要生成的object file對應的命令放在第一行。
所以我們的dog_program的完整的Makefile文件應該是:
dog_program: dog.o main.o
g++ dog.o main.o -o dog_program
dog.o: dog.hpp dog.cpp
g++ -c dog.cpp
main.o: main.cpp
g++ -c main.cpp
在Makefile的最後寫clean語句。
clean:
rm dog_program *.o
然後我們在命令窗口運行make clean的話,就會刪除文件夾中生成的可執行文件,和所有過程中產生的副產品。
對於Makefile中的dependency list,我們需要將每個object file的dependency list都寫好。因為make不負責檢查文件中的具體的語句,只負責執行Makefile中的語句。
dog_program:
g++ dog.o main.o -o dog_program
dog.o: dog.hpp dog.cpp
g++ -c dog.cpp
main.o: main.cpp
g++ -c main.cpp
如果像上面所示去掉dog_program的dependency list的話,運行make就會出錯,因為main是依賴於dog.cpp的。
如果文件中本身就存在dog.o和main.o的話,運行make不會出錯,因為make就是先check dog.o main.o是否存在,存在的話就直接運行。
所以,我們如果修改了main.cpp或者dog.cpp的話,我們需要重新生成dog.o和main.o。因為make是不管這個問題的。
make這個命令的功能就是執行Makefile中我們要求執行的語句,對結果沒有任何的預期,也不會檢查命令有沒有問題。所以,我們必須遵守Makefile書寫中的一些規則。
all : fill_file_with_nonsense
echo "I have mostly created a lot of junk today!"
fill_file_with_nonsense : create_file
echo "Hello, there is nothing important here" > silly_file
create_file :
touch silly_file touch是Unix中的典型命令,用於生成空的文件
move_file :
mv silly_file silly_file_new_name
delete_file :
rm _file
open_file :
gedit another_silly_file
clean :
touch junk1 junk2 junk3 junk4 junk5
really_clean :
rm junk*
如果想體驗的更加清楚,就可以運行這個文件中的內容,然後就知道make完全不會管結果是什麼,只是沒有腦子的執行命令。
解釋上面的內容:
Makefile的書寫規則。all: 放在第一句,把所以我們要生成executable依賴的Targets列出來,這樣我們需要的所有的文件都可以生成。我們看到all對應的dependency是file_file_with_nonsense,就去找file_file_with_nonsense的生成語句,發現它的dependency是create_file,然後去找create_file的生成語句,就到touch silly_file,touch是Unix中的典型命令,用於生成空的文件。create_file的語句執行完之後,回到file_file_with_nonsense,執行echo "Hello, there is nothing important here" > silly_file,就把"Hello, there is nothing important here" 寫入silly_file中,file_file_with_nonsense的語句也執行完之後,我們就返回到all,然後在命令行輸出"I have mostly created a lot of junk today!"。
因為其他的target,不在all的dependency list中,也不在all的dependency的dependency當中,所以只能通過make target的形式來調用對應的命令。
Marvelous macros(宏)
一個宏的示例,宏就是Makefile中的variables,用來定義我們需要的操作,一些變數之類的
CXX = clang++
FLAGS = -O
hello : hello_world.cpp
$(CXX) $(FLAGS) $? -o $@
clean :
rm hello
CXX,這是一個預定義的宏,default value是g++。這里把CXX定義成clang++了。
FLAGS,這里定義的是-O。FLAGS也不一定非得定義成-o,也可以是some moose have large antlers,但是這樣定義的話,就會導致調用的時候出錯。
對於上面的文件,我們在命令行輸入make的時候,實際運行的是clang++ -O hello_world.cpp -o hello。
如果我們把CXX=clang++這一行刪掉的話,在命令行輸入make,實際運行的就是g++ -O hello_world.cpp -o hello。
定義好macro宏,我們使用的時候,就要用$(MACRO)這樣的形式,這是makefile語言的一種語法。我們注意到MACRO全部用的大寫,雖然不是明確規定的,但是通常情況下用大寫。
$?和$@是makefile language裡面特別的預定義的宏。$?是指的"names of the dependencies(newer than the target)",$@是指的"name of the target"。
Complier and liner flags in CS 225
CXX = clang++ LD = clang++
CXXFLAGS = -std=c++1y -stdlib=libc++ -c -g -O0 -Wall -Wextra -Werror -pedantic
LDFLAGS = -std=c++1y -stdlib=libc++ -lpng -lc++abi
㈢ linux Makefile問題.S.s: $(CPP) $(CFLAGS) $< -o $*.s什麼意思
請慢慢看,真要詳細講起來,文字實在太多了,但是由於時間原因,我只能以粗略的文字講,語言有一些邏輯漏洞,請見諒。
首先我會以粗略的文字回答你的其中一個問題,然後後面會給出第二個問題的答案。
問:什麼時候會執行這些規則及其相對應的命令?
答:當你給make命令指定了它要生成的終極目標時,它會從要生成的終極目標定址依賴的依賴條件,然後依賴條件一級一級的查找並執行相對應的命令。即如果當有目標需要.s、.o這些依賴條件的時候,會取找要生成.s、.o目標的依賴條件,這個時候就會執行這些規則:
.S.s:
$(CPP) $(CFLAGS) $< -o $*.s
.S.o:
$(CC) $(CFLAGS) -c $< -o $*.o
.c.o:
$(CC) $(CFLAGS) -c $< -o $*.o
一、
源代碼文件必須經過:預處理(cpp)、編譯(ccl)、匯編(as)、鏈接(ld)。這四個階段最終才得到可執行的程序:
makefile里定義了變數CPP=cpp;其中$(CPP)的意思是去定義變數CPP里的值:cpp,用cpp來預處理源文件。
$(CFLAGS)的意思是取定義變數CDLAGS裡面的值,一般是一些自我定義的預處理命令和編譯命令的參數。
$<的意思是:在規則的命令中,表示第一個依賴條件
-o是一個預處理、編譯等執行命令需要的參數
/*
其實這條命令:$(CPP) $(CFLAGS) $< -o $*.s,就是一條預處理命令,將一個源文件預處理為.s文件後綴的文件,*為通配符。那源文件在哪裡呢。其實這條命令.S.s: 已經說了以.S結尾的文件就是源文件。那這條命令.S.s這么說了呢?請看下面的後綴規則講解。
*/
二、
老式風格的"後綴規則"
後綴規則是一個比較老式的定義隱含規則的方法。後綴規則會被模式規則逐步地取代。因為模式規則更強更清晰。為了和老版本的Makefile兼容,GNU make同樣兼容於這些東西。後綴規則有兩種方式:"雙後綴"和"單後綴"。
雙後綴規則定義了一對後綴:目標文件的後綴和依賴目標(源文件)的後綴。如".c.o"相當於"%o : %c"。單後綴規則只定義一個後綴,也就是源文件的後綴。
後綴規則中所定義的後綴應該是make所認識的,如果一個後綴是make所認識的,那麼這個規則就是單後綴規則,而如果兩個連在一起的後綴都被make所認識,那就是雙後綴規則。例如:".c"和".o"都是make所知道。
因而,如果你定義了一個規則是".c.o"那麼其就是雙後綴規則,意義就是".c" 是源文件的後綴,".o"是目標文件的後綴。如下示例:
.c.o:
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
其中.c.o:這個命令表示源文件的後綴為.c,目標文件的後綴為.o;即也可理解為:生成.o的目標文件依賴條件是源文件.c
下面命令是將是所有的.c源文件都編譯成.o的目標文件。
註:後綴規則不允許任何的依賴文件,如果有依賴文件的話,那就不是後綴規則,那些後綴統統被認為是文件名,
如:
.c.o: foo.h
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
這個例子,就是說,文件".c.o"依賴於文件"foo.h",而不是我們想要的這樣:
%.o: %.c foo.h
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
因此後綴規則不允許任何的依賴文件。
㈣ Linux平台Makefile文件的編寫基礎篇
目的:
基本掌握了 make 的用法,能在Linux系統上編程。
環境:
Linux系統,或者有一台Linux伺服器,通過終端連接。一句話:有Linux編譯環境。
准備:
准備三個文件:file1.c, file2.c, file2.h
file1.c:
#include
#include "file2.h"
int main()
{
printf("print file1$$$$$$$$$$$$ ");
File2Print();
return 0;
}
file2.h:
#ifndef FILE2_H_
#define FILE2_H_
#ifdef __cplusplus
extern "C" {
#endif
void File2Print();
#ifdef __cplusplus
}
#endif
#endif
file2.c:
#include "file2.h"
void File2Print()
{
printf("Print file2********************** ");
}
基礎:
先來個例子:
有這么個Makefile文件。(文件和Makefile在同一目錄)
=== makefile 開始 ===
helloworld:file1.o file2.o
gcc file1.o file2.o -o helloworld
file1.o:file1.c file2.h
gcc -c file1.c -o file1.o
file2.o:file2.c file2.h
gcc -c file2.c -o file2.o
clean:
rm -rf *.o helloworld
=== makefile 結束 ===
一個 makefile 主要含有一系列的規則,如下:
A: B
(tab)
(tab)
每個命令行前都必須有tab符號。
上面的makefile文件目的就是要編譯一個helloworld的可執行文件。讓我們一句一句來解釋:
helloworld : file1.o file2.o: helloworld依賴file1.o file2.o兩個目標文件。
gcc File1.o File2.o -o helloworld: 編譯出helloworld可執行文件。-o表示你指定 的目標文件名。
file1.o : file1.c: file1.o依賴file1.c文件。
gcc -c file1.c -o file1.o: 編譯出file1.o文件。-c表示gcc 只把給它的文件編譯成目標文件, 用源碼文件的文件名命名但把其後綴由「.c」或「.cc」變成「.o」。在這句中,可以省略-o file1.o,編譯器默認生成file1.o文件,這就是-c的作用。
file2.o : file2.c file2.h
gcc -c file2.c -o file2.o
這兩句和上兩句相同。
clean:
rm -rf *.o helloworld
當用戶鍵入make clean命令時,會刪除*.o 和helloworld文件。
如果要編譯cpp文件,只要把gcc改成g++就行了。
寫好Makefile文件,在命令行中直接鍵入make命令,就會執行Makefile中的內容了。
到這步我想你能編一個Helloworld程序了。
上一層樓:使用變數
上面提到一句,如果要編譯cpp文件,只要把gcc改成g++就行了。但如果Makefile中有很多gcc,那不就很麻煩了。
第二個例子:
=== makefile 開始 ===
OBJS = file1.o file2.o
CC = gcc
CFLAGS = -Wall -O -g
helloworld : $(OBJS)
$(CC) $(OBJS) -o helloworld
file1.o : file1.c file2.h
$(CC) $(CFLAGS) -c file1.c -o file1.o
file2.o : file2.c file2.h
$(CC) $(CFLAGS) -c file2.c -o file2.o
clean:
rm -rf *.o helloworld
=== makefile 結束 ===
這里我們應用到了變數。要設定一個變數,你只要在一行的開始寫下這個變數的名字,後 面跟一個 = 號,後面跟你要設定的這個變數的值。以後你要引用 這個變數,寫一個 $ 符號,後面是圍在括弧里的變數名。
CFLAGS = -Wall -O –g,解釋一下。這是配置編譯器設置,並把它賦值給CFFLAGS變數。
-Wall: 輸出所有的警告信息。
-O: 在編譯時進行優化。
-g: 表示編譯debug版本。
這樣寫的Makefile文件比較簡單,但很容易就會發現缺點,那就是要列出所有的c文件。如果你添加一個c文件,那就需要修改Makefile文件,這在項目開發中還是比較麻煩的。
再上一層樓:使用函數
學到這里,你也許會說,這就好像編程序嗎?有變數,也有函數。其實這就是編程序,只不過用的語言不同而已。
第三個例子:
=== makefile 開始 ===
CC = gcc
XX = g++
CFLAGS = -Wall -O –g
TARGET = ./helloworld
%.o: %.c
$(CC) $(CFLAGS) -c lt; -o [email protected]
%.o:%.cpp
$(XX) $(CFLAGS) -c lt; -o [email protected]
SOURCES = $(wildcard *.c *.cpp)
OBJS = $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES)))
$(TARGET) : $(OBJS)
$(XX) $(OBJS) -o $(TARGET)
chmod a+x $(TARGET)
clean:
rm -rf *.o helloworld
=== makefile 結束 ===
函數1:wildcard
產生一個所有以 '.c' 結尾的文件的列表。
SOURCES = $(wildcard *.c *.cpp)表示產生一個所有以 .c,.cpp結尾的文件的列表,然後存入變數 SOURCES 里。
函數2:patsubst
匹配替換,有三個參數。第一個是一個需要匹配的式樣,第二個表示用什麼來替換它,第三個是一個需要被處理的由空格分隔的列表。
OBJS = $(patsubst %.c,%.o,$(patsubst %.cc,%.o,$(SOURCES)))表示把文件列表中所有的.c,.cpp字元變成.o,形成一個新的文件列表,然後存入OBJS變數中。
%.o: %.c
$(CC) $(CFLAGS) -c lt; -o [email protected]
%.o:%.cpp
$(XX) $(CFLAGS) -c lt; -o [email protected]
這幾句命令表示把所有的.c,.cpp編譯成.o文件。
這里有三個比較有用的內部變數。 [email protected] 擴展成當前規則的目的文件名, lt; 擴展成依靠 列表中的第一個依靠文件,而 $^ 擴展成整個依靠的列表(除掉了裡面所有重 復的文件名)。
chmod a+x $(TARGET)表示把helloworld強制變成可執行文件。
㈤ [Linux]編寫一個簡單的C語言程序,編寫Makefile文件。
八 環境變數
8.1 查看環境變數
$ env 顯示所有的環境變數設置
$ echo $ENV_VARIABLE 顯示指定環境變數的設置
例:
$ echo $PATH
/bin:/etc:/usr/bin:/tcb/bin
8.2 設定環境變數
$ ENV_VARIABLE=XXX;export ENV_VARIABLE
例:
$ PATH=$PATH:$INFORMIXDIR/bin;export PATH 將環境變數PATH設定為原PATH值+$INFORMIXDIR/bin
8.3 取消環境變數設置
$ unset $ENV_VARIABLE
例:
$ set GZJ=gzj;export GZJ 設置環境變數GZJ
$ echo $GZJ
gzj 顯示環境變數值
$ unset $GZJ 取消環境變數GZJ的設置
$ echo $GZJ
已取消
一 makefile規則
makefile是一個make的規則描述腳本文件,包括四種類型行:目標行、命令行、宏定義行和make偽指令行(如「include」)。makefile文件中注釋以「#」開頭。當一行寫不下時,可以用續行符「\」轉入下一行。
1.1 目標行
目標行告訴make建立什麼。它由一個目標名表後面跟冒號「:」,再跟一個依賴性表組成。
例:
example: depfile deptarget
該目標行指出目標example與depfile和deptarget有依賴關系,如果depfile或deptarget有修改,則重新生成目標。
example1 example2 example3: deptarget1 deptarget2 depfile
該目標行指出目標名表中的example1、example2、example3這三個各自獨立的目標是用相同的依賴列表和規則生成的。
clean:
空的依賴列表說明目標clean沒有其他依賴關系。
目標行後續的以Tab 開始的行是指出目標的生成規則,該Tab字元不能以空格代替。例如:
example.o:example.c example.h
cc –c example.c
該例子指出目標example.o依賴於example.c和example.h。如果example.c或example.h其中之一改變了,就需要執行命令cc –c example.c重新生成目標example.o。
可以用文件名模式匹配來自動為目標生成依賴表,如:
prog: *.c
以下是一個簡單的makefile的例子:
圖 1 最簡單的makefile例
make使用makefile文件時,從第一個目標開始掃描。上例中的第一個目標為all,所以目標clean不會自動被執行,可以通過命令make clean來生成目標。
1.2 命令行
命令行用來定義生成目標的動作。
在目標行中分號「;」後面的文件都認為是一個命令,或者一行以Tab製表符開始的也是命令。
如在上面的makefile例中,第三行以Tab字元開始的cc命令即是一個命令行,說明要生成hello應執行的命令。也可以寫成:hello:hello.o;cc –c hello –L…
一般情況下,命令行的命令會在標准輸出中回顯出來,如對上面的makefile執行make時,標准輸出如下:
cc -c hello.c
cc -o hello -L/usr/X11R6/lib -L/usr/lib -lXm -lXt -lX11 hello.o
cc -c hello1.c
cc -o hello1 -L/usr/X11R6/lib -L/usr/lib -lXm -lXt -lX11 hello1.o
如果不希望命令本身回顯,可在命令前加@字元,如在上例中不希望回顯cc –c hello.c和cc –c hello1.c,可修改makefile文件如下:
圖 2 抑制回顯的makefile例
對該makefile文件執行make時,標准輸出如下:
cc -o hello -L/usr/X11R6/lib -L/usr/lib -lXm -lXt -lX11 hello.o
cc -o hello1 -L/usr/X11R6/lib -L/usr/lib -lXm -lXt -lX11 hello1.o
可以看出,命令行前有@字元的不回顯。
1.3 宏定義行
在makefile中,可以使用宏定義減少用戶的輸入,例如上例中對hello和hello1的編譯選項均為「-L/usr/X11R6/lib -L/usr/lib -lXm -lXt -lX11」,此時可以用宏來代替,如:
圖 3 使用宏定義的makefile例
宏定義的基本語法是:
name=value
在定義宏時,次序不重要。宏不需要在使用前定義。如果一個宏定義多次,則使用最後一次的定義值。
可以使用「$」字元和「()」或「{}」來引用宏,例如:
cc –o hello.o $(CCFLAGS) hello.o
也可以將一個宏賦值給另一個宏,但這樣的定義不能循環嵌套,如:
A=value1
B=value2
C=$(A) $(B)等價於C=value1 value2
1.4 偽指令
makefile大部分由宏定義行、命令行和目標行組成。第四種類型是make偽指令行。make偽指令沒有標准化,不同的make可能支持不同的偽指令集,使得makefile有一定的不兼容性。如果要考慮移植性問題,則要避免使用make偽指令。但有一些偽指令,如include,由於使用比較多,很多不同make都提供該偽指令。
1.4.1 偽指令include
該偽指令類似C語言中的#include,它允許一次編寫常用的定義並包括它。include偽指令必須在一行中,第一個元素必須是include,並且跟一個要包含的文件名,如:
include default.mk
1.4.2 偽指令「#」
「#」字元也是make的偽指令,它指出「#」後面的文件是注釋,如:
PROGNAME=test # define macro
#don't modify this
二 後綴規則
2.1 雙後綴規則
在前面的makefile例中有許多重復內容,例如,生成hello和hello1的命令類似,生成hello.o和hello1.o的命令也類似,除了編譯或鏈接的文件不一樣外,其它均相同,這時,我們就可以使用後綴規則。首先看一個雙後綴的例子:
圖 4 使用雙後綴規則的makefile例
後綴規則使用特殊的目標名「.SUFFIXES」。
第一行中.SUFFIXES的依賴表為空,用來清除原有的後綴規則,因為.SUFFIXES可以在makefile中多次使用,每一次都將新的後綴規則加入以前的後綴規則中。
第二行中指定後綴規則為「.c .o」,即表示將所有的.c文件轉換為.o文件。
第三行指定將.c文件轉換成.o文件的方法。$(CC)為make的預定義宏,其默認值為cc,$<為特殊的宏,代替當前的源文件,即所有要編譯的.c文件。
第六行指定目標hello和hello1的生成方法。$@為特殊的宏,代替當前的目標名,即hello和hello1,[email protected]即為hello.o和hello1.o。
上例介紹的是雙後綴規則,即它包含兩個後綴,如.c.o,用來把一個C源文件編譯為目標文件。雙後綴規則描述如何由第一個後綴類型的文件生成第二個後綴類型的文件,例如:.c.o規則描述如何由.c文件生成.o文件。
2.2 單後綴規則
單後綴規則描述了怎樣由指定後綴的文件生成由它基名為名字的文件。例如使用單後綴規則.c,可以由hello.c和hello1.c生成hello和hello1文件。例如將前面的makefile改為:
圖 5 使用單後綴規則的makefile例
由於.c後綴規則為make標准後綴規則,make為其指定了相應的命令行,所以在makefile中可以不用再指定其目標生成的具體命令行。
下表是make提供的標准後綴規則。
表 1 make標准後綴規則
後綴規則 命令行
.c $(LINK.c) –o $@ $< $(LDLIBS)
.c.ln $(LINK.c) $(POUTPUT OPTPUT OPTION) –i $<
.c.o $(COMPILE.c) $(OUTPUT OPTION) $<
.c.a $(COMPILE.c) –o $% $<
$(AR) $(ARFLAGS) $@ $%
$(RM) $%
三 特殊目標
在後綴規則中使用了特殊目標.SUFFIXES,用來指定新增的後綴規則。make還提供了幾個特殊目標來設置make的行為,下面為一些特殊的目標:
.IGNORE
make在執行命令行時,如果返回的是錯誤碼,make的預設動作是停止並退出。增加該目標後,make將忽略命令行返回的錯誤碼,並繼續執行後續的操作。
.SILENT
前面已經介紹過,make在執行命令行時會回顯命令行內容,在命令行前增加「@」字元將抑制該命令行的回顯。
如果增加該目標,所有的命令行不再回顯,相當於在每個命令行前均增加了「@」字元。
.PRECIOUS
當收到一個信號或從shell命令返回非零的錯誤碼時,make刪除它所有已建立的文件。但有些文件即使出了錯誤,用戶也不想讓make刪除,這些文件可以作為.PRECIOUS目標的參數。它可以在一個makefile中出現多次,每一次都累積文件列表。
.SUFFIXES
它為makefile指定新的後綴規則,新的後綴規則作為.SUFFIXES的依賴表給出。.SUFFIXES可以在一個makefile中多次使用,每一次都將新的後綴規則加入以前的後綴規則中,如果.SUFFIXES的依賴表為空,則設置後綴規則表為空。
四 特殊的宏
為簡單使用規則,make提供了幾個特殊的宏:
$@
整個當前目標名的值可以由宏「$@」來代替。
$<
當前的源文件由「$<」來代替。例如,在前面的例子中用到了$(CC) –c $<,其中的「$<」是所有要編譯的.c文件。宏「$<」僅在後綴規則或.DEFAULT中有效。
$*
當前目標的基名由宏「$*」來代替。例如目標的名字是hello.o,則基名就是除去了後綴.o的hello。
以上介紹的特殊宏使用了make自身的規則,用戶不可以改變。下表介紹了C中預定義的宏。
用途 宏 默認值
庫文檔匯編命令 AR ar
ARFLAGS rv
AS as
ASFLAGS
COMPILE.s $(AS) $(ASFLAGS) $(TARGET ARCH)
C編譯器命令 CC cc
CFLAGS
CPPFLAGS
COMPILE.c $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET ARCH) –c
LINK.c $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET ARCH)
鏈接編輯器命令 LD ld
LDFLAGS
rm命令 RM rm
後綴列表 SUFFIXES .o .c .c~ .s .s~ .S .S~ .ln .f .f~ .F .F~ .l .mod .mod~ .sym
.def .def~ .p .p~ .r .r~ .y .y~ .h .h~ .sh .sh~ .cps .cps~
五 makefile的應用
當調用make時,它在當前目錄下搜索文件名是「makefile」或「Makefile」的文件,並執行。
如果不想使用上述預設文件,可以使用命令行中的「-f」來指定文件,如將編寫的makefile命名為mklib,則指定為「make –f mklib」。
㈥ 鍦↙INUX緋葷粺涓緙栫▼搴忥紝makefile鏄鎬庝箞鐢熸垚鐨勶紝鏄閫氳繃GCC鎴朑DB緙栬瘧鑱旀帴鐢熸垚鐨勫悧錛燂紵錛燂紵
榪欎綅鏈嬪弸鎴戠湅鏄鏈夌偣璇瑙d簡makefile鐨勫仛鐢ㄣ俶akefile 鏄涓涓鑴氭湰錛岀敱浠栨潵鎺у埗緙栬瘧鍑虹殑紼嬪簭鐨勭増鏈銆傚綋浣犳敼鍐欎簡鍘熸枃浠跺悗錛岄氳繃makefile 鏉ユ鏌ヤ緷璧栧叧緋伙紝鏉ョ敓鎴愭渶緇堢殑鏂囦歡銆傛瘮濡備竴涓紼嬪簭鍙玜 浠栫殑婧愮爜鍙玜.c
a.c 鍙堢敤鍒板ご鏂囦歡a.h 錛宎.h鏄1.h鍜2.h鐢熸垚鐨
濡傛灉浣犳敼鍐欎簡1.h錛岄氳繃緙栧啓makefile鏂囦歡銆俶ake鏃朵細璋冪敤makefile鏉ヤ緷姝ゆ寜渚濊禆鍏崇郴鐢熸垚鏈鍚庣殑a
鎵浠ヨ寸紪璇戞椂紼嬪簭騫朵笉鐭ラ亾鐢熸垚a閮界敤鍒頒粈涔堛傛庝箞鍙鑳借嚜宸辯敓鎴愬憿銆
makefile鏄瑕佷綘鑷宸辯紪鍐欑殑錛屾潵鍛婅瘔make鏉ュ備綍緙栬瘧銆俶ake宸ュ叿灝辯浉褰撲簬涓涓鑴氭湰銆
㈦ vs2010如何編譯單個CPP文件。
可以明確的告訴你,無此種編譯器存在,編譯文件不光光是看源文件,各個工程中還有很多的配置文件存在,如果不建立工程,任何編譯器都是無法知道你到底是要編譯控制台程序,windows程序,或者是DLL。所以還不存在。
㈧ c++代碼在什麼情況下,修改了代碼,可以不需要編譯
無論是使用集成開發環境,還是使用makefile,都會根據文件的變動時間來判斷是否需要進行編譯。
例如使用main.cpp編譯出來main.exe文件。再次進行編譯時,會判斷main.cpp是否比main.exe更新。如果更新,就會觸發重新編譯。
正常情況下,修改代碼就應當進行代碼的重新編譯。但是在某些情況下,由於冗餘的頭文件引用導致不必要的擴大了編譯文件范圍。建議在包含頭文件時,盡量採用最小原則。不需要使用的頭文件就不要包含。