編譯makefile
1. c語言!!編譯的時候出現這個提彈窗,makefile.win已經改變,是否重新從硬碟讀取。這是什麼
主要原因可能是:1.在編譯器外打開、載入或修改了所用文件。2.可能是引用或打開的路徑不正確。3.某些語法錯誤時引起編譯器對後面程序的錯誤解讀,報出錯誤的警報信息。
可以嘗試:1 關閉文件後重新,關閉編譯器後重新打開項目。2.關閉其他打開該文件的軟體或者編輯器 3.注釋掉新修改部分的代碼,排查錯誤。
2. 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強制變成可執行文件。
3. 如何編寫makefile
你先用gcc把它給編譯出來。然後再想用makefile
gcc最一般的用法就是:
gcc -o 要生成的可執行文件名 源代碼文件名
如:gcc -o hello.x hello.c
如果一些頭文件要指明的話,可以這樣:
gcc -o hello.x -I頭文件所在的文件夾 -l一些庫名 hello.c
最通常,我們用到一些數學庫。gcc -o hello.x -lm hello.c
makefile的話,你可以基於上述的語句進行修改:建議你看點資料,或一些典型的例子。但是注意的是規則那一行,得用Tab鍵打頭。
hello.x : hello.o
gcc -o hello.x hello.o (這一行,得用Tab打頭)
hello.o : hello.c 頭文件
gcc -c hello.o hello.c -I頭文件所在目錄 -lm (這一行,得用Tab打頭)
4. iar使用makefile編譯
要編譯出在 iar開發板上運行的可執行文件,需要使用到交叉編譯器 iar-linux-gnueabihf-gcc 來編譯,在終端中輸入如下命令:
iar-linux-gnueabihf-gcc -g -c led.s -o led.o
上述命令就是將 led.s 編譯為 led.o,其中「-g」選項是產生調試信息,GDB 能夠使用這些
調試信息進行代碼調試。「-c」選項是編譯源文件,但是不鏈接。「-o」選項是指定編譯產生的文
件名字,這里我們指定 led.s 編譯完成以後的文件名字為 led.o。執行上述命令以後就會編譯生
成一個 led.o 文件
2 、arm-linux-gnueabihf-ld 鏈接文件
arm-linux-gnueabihf-ld 用來將眾多的.o 文件鏈接到一個指定的鏈接位置。我們在學習SMT32 的時候基本就沒有聽過「鏈接」這個詞,我們一般用 MDK 編寫好代碼,然後點擊「編
譯」,MDK 或者 IAR 就會自動幫我們編譯好整個工程,最後再點擊「下載」就可以將代碼下載
到開發板中。這是因為鏈接這個操作 MDK 或者 IAR 已經幫你做好了,因此我們現在需要做的就是確定一下本試驗最終的可執行文件其運行起始地址,也就是鏈接地址。這里我們要區分「存儲地址」和「運行地址」這兩個概念,「存儲地址」就是可執行文件存儲在哪裡,可執行文件的存儲地址可以隨意選擇。「運行地址」就是代碼運行的時候所處的地址,這個我們在鏈接的時候就已經確定好了,代碼要運行,那就必須處於運行地址處,否則代碼肯定運行出錯。比如設備支持 SD 卡、EMMC、NAND 啟動,因此代碼可以存儲到 SD 卡、EMMC 或者 NAND 中,但是要運行的話就必須將代碼從 SD 卡、EMMC 或者NAND 中拷貝到其運行地址(鏈接地址)處,「存儲地址」和「運行地址」可以一樣,比如STM32 的存儲起始地址和運行起始地址都是 0X08000000,輸入如下命令
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
上述命令中-Ttext 就是指定鏈接地址,「-o」選項指定鏈接生成的 elf 文件名,這里我們命名
為 led.elf
5. c語言編譯運行出現Makefile.win已經改變,怎麼改
這個提示是說你當前項目里有多個文件里都有叫main的函數,這樣會導致系統不清楚從哪個main執行,建議你可以把其它文件里的main隨便改下下名字比如叫main1什麼的,只把你當前要運行的文件里的主函數改為main就行了。
或者建議如果只有一般的測試代碼只有一個文件的那種,新建的時候就不要建項目,直接建文件就可以了。