導航:首頁 > 源碼編譯 > s文件怎麼編譯

s文件怎麼編譯

發布時間:2025-02-22 14:23:42

① 怎麼用gcc編譯文件

在終端中輸入 gcc 文件名 -o 目標文件名x0dx0a然後 ./目標文件名 就行了,沒有目標文件名,自動存為 ax0dx0a執行 ./a 就行了。x0dx0ax0dx0a在使用Gcc編譯器的時候,我們必須給出一系列必要的調用參數和文件名稱。GCC編譯器的調用參數大約有100多個,其中多數參數我們可能根本就用不到,這里只介紹其中最基本、最常用的參數。x0dx0aGCC最基本的用法是∶gcc [options] [filenames]x0dx0a其中options就是編譯器所需要的參數,filenames給出相關的文件名稱。x0dx0a-c,只編譯,不連接成為可執行文件,編譯器只是由輸入的.c等源代碼文件生成.o為後綴的目標文件,通常用於編譯不包含主程序的子程序文件。x0dx0a-o output_filename,確定輸出文件的名稱為output_filename,同時這個名稱不能和源文件同名。如果不給出這個選項,gcc就給出預設的可執行文件a.out。x0dx0a-g,產生符號調試工具(GNU的gdb)所必要的符號資訊,要想對源代碼進行調試,我們就必須加入這個選項。x0dx0a-O,對程序進行優化編譯、連接,採用這個選項,整個源代碼會在編譯、連接過程中進行優化處理,這樣產生的可執行文件的執行效率可以提高,但是,編譯、連接的速度就相應地要慢一些。x0dx0a-O2,比-O更好的優化編譯、連接,當然整個編譯、連接過程會更慢。x0dx0a-Idirname,將dirname所指出的目錄加入到程序頭文件目錄列表中,是在預編譯過程中使用的參數。C程序中的頭文件包含兩種情況∶x0dx0aA)#include x0dx0aB)#include 「myinc.h」x0dx0a其中,A類使用尖括弧(< >),B類使用雙引號(「 」)。對於A類,預處理程序cpp在系統預設包含文件目錄(如/usr/include)中搜尋相應的文件,而B類,預處理程序在目標文件的文件夾內搜索相應文件。 x0dx0ax0dx0aGCC執行過程示例x0dx0ax0dx0a示例代碼 a.c:x0dx0a#include x0dx0aint main()x0dx0a{x0dx0aprintf("hello\n");x0dx0a}x0dx0a預編譯過程:x0dx0a這個過程處理宏定義和include,並做語法檢查。x0dx0a可以看到預編譯後,代碼從5行擴展到了910行。x0dx0agcc -E a.c -o a.ix0dx0acat a.c | wc -lx0dx0a5x0dx0acat a.i | wc -lx0dx0a910x0dx0a編譯過程:x0dx0a這個階段,生成匯編代碼。x0dx0agcc -S a.i -o a.sx0dx0acat a.s | wc -lx0dx0a59x0dx0a匯編過程:x0dx0a這個階段,生成目標代碼。x0dx0a此過程生成ELF格式的目標代碼。x0dx0agcc -c a.s -o a.ox0dx0afile a.ox0dx0aa.o: ELF 64-bit LSB relocatable, AMD x86-64, version 1 (SYSV), not strippedx0dx0a鏈接過程:x0dx0a鏈接過程。生成可執行代碼。鏈接分為兩種,一種是靜態鏈接,另外一種是動態鏈接。使用靜態鏈接的好處是,依賴的動態鏈接庫較少,對動態鏈接庫的版本不會很敏感,具有較好的兼容性;缺點是生成的程序比較大。使用動態鏈接的好處是,生成的程序比較小,佔用較少的內存。x0dx0agcc a.o -o ax0dx0a程序運行:x0dx0a./ax0dx0ahellox0dx0a編輯本段x0dx0aGCC編譯簡單例子x0dx0ax0dx0a編寫如下代碼:x0dx0a#include x0dx0aint main()x0dx0a{x0dx0aprintf("hello,world!\n");x0dx0a}x0dx0a執行情況如下:x0dx0agcc -E hello.c -o hello.ix0dx0agcc -S hello.i -o hello.sx0dx0agcc -c hello.s -o hello.ox0dx0agcc hello.c -o hellox0dx0a./hellox0dx0ahello,world!

② 如何編譯一個 dll文件

創建DLL工程
這里,我們為了簡要說明DLL的原理,我們決定使用最簡單的編譯環境VC6.0,如下圖,我們先建立一個新的Win32 Dynamic-Link Library工程,名稱為「MyDLL」,在Visual Studio中,你也可以通過建立Win32控制台程序,然後在「應用程序類型」中選擇「DLL」選項,

點擊確定,選擇「一個空的DLL工程」,確定,完成即可。

一個簡單的dll
在第一步我們建立的工程中建立一個源碼文件」dllmain.cpp「,在「dllmain.cpp」中,鍵入如下代碼

[cpp] view plain
#include <Windows.h>
#include <stdio.h>

BOOL APIENTRY DllMain(HMODULE hMole, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
printf("DLL_PROCESS_ATTACH\n");
break;
case DLL_THREAD_ATTACH:
printf("DLL_THREAD_ATTACH\n");
break;
case DLL_THREAD_DETACH:
printf("DLL_THREAD_DETACH\n");
break;
case DLL_PROCESS_DETACH:
printf("DLL_PROCESS_DETACH\n");
break;
}
return TRUE;
}
之後,我們直接編譯,即可以在Debug文件夾下,找到我們生成的dll文件,「MyDLL.dll」,注意,代碼裡面的printf語句,並不是必須的,只是我們用於測試程序時使用。而DllMain函數,是dll的進入/退出函數。

實際上,讓線程調用DLL的方式有兩種,分別是隱式鏈接和顯式鏈接,其目的均是將DLL的文件映像映射進線程的進程的地址空間。我們這里只大概提一下,不做深入研究,如果感興趣,可以去看《Window高級編程指南》的第12章內容。
隱式鏈接調用
隱士地鏈接是將DLL的文件影響映射到進程的地址空間中最常用的方法。當鏈接一個應用程序時,必須制定要鏈接的一組LIB文件。每個LIB文件中包含了DLL文件允許應用程序(或另一個DLL)調用的函數的列表。當鏈接器看到應用程序調用了某個DLL的LIB文件中給出的函數時,它就在生成的EXE文件映像中加入了信息,指出了包含函數的DLL文件的名稱。當操作系統載入EXE文件時,系統查看EXE文件映像的內容來看要裝入哪些DLL,而後試圖將需要的DLL文件映像映射到進程的地址空間中。當尋找DLL時,系統在系列位置查找文件映像。

1.包含EXE映像文件的目錄
2.進程的當前目錄
3.Windows系統的目錄
4.Windows目錄
5.列在PATH環境變數中的目錄

這種方法,一般都是在程序鏈接時控制,反映在鏈接器的配置上,網上大多數講的各種庫的配置,比如OPENGL或者OPENCV等,都是用的這種方法

顯式鏈接調用
這里我們只提到兩種函數,一種是載入函數
[cpp] view plain
HINSTANCE LoadLibrary(LPCTSTR lpszLibFile);

HINSTANCE LoadLibraryEx(LPCSTR lpszLibFile,HANDLE hFile,DWORD dwFlags);
返回值HINSTANCE值指出了文件映像映射的虛擬內存地址。如果DLL不能被映進程的地址空間,函數就返回NULL。你可以使用類似於

[cpp] view plain
LoadLibrary("MyDLL")
或者

[cpp] view plain
LoadLibrary("MyDLL.dll")
的方式進行調用,不帶後綴和帶後綴在搜索策略上有區別,這里不再詳解。

顯式釋放DLL

在顯式載入DLL後,在任意時刻可以調用FreeLibrary函數來顯式地從進程的地址空間中解除該文件的映像。
[cpp] view plain
BOOL FreeLibrary(HINSTANCE hinstDll);
這里,在同一個進程中調用同一個DLL時,實際上還牽涉到一個計數的問題。這里也不在詳解。
線程可以調用GetMoleHandle函數:

[cpp] view plain
GetMoleHandle(LPCTSTR lpszMoleName);
來判斷一個DLL是否被映射進進程的地址空間。例如,下面的代碼判斷MyDLL.dll是否已被映射到進程的地址空間,如果沒有,則裝入它:

[cpp] view plain
HINSTANCE hinstDll;
hinstDll = GetMoleHandle("MyDLL");
if (hinstDll == NULL){
hinstDll = LoadLibrary("MyDLL");
}
實際上,還有一些函數,比如 GetMoleFileName用來獲取DLL的全路徑名稱,FreeLibraryAndExitThread來減少DLL的使用計數並退出線程。具體內容還是參見《Window高級編程指南》的第12章內容,此文中不適合講太多的內容以至於讀者不能一下子接受。

DLL的進入與退出函數

說到這里,實際上只是講了幾個常用的函數,這一個小節才是重點。
在上面,我們看到的MyDLL的例子中,有一個DllMain函數,這就是所謂的進入/退出函數。系統在不同的時候調用此函數。這些調用主要提供信息,常常被DLL用來執行進程級或線程級的初始化和清理工作。如果你的DLL不需要這些通知,就不必再你的DLL源代碼中實現此函數,例如,如果你創建的DLL只含有資源,就不必實現該函數。但如果有,則必須像我們上面的格式。
DllMain函數中的ul_reason_for_call參數指出了為什麼調用該函數。該參數有4個可能值: DLL_PROCESS_ATTACH、DLL_THREAD_ATTACH、DLL_THREAD_DETACH、DLL_PROCESS_DETACH。
其中,DLL_PROCESS_ATTACH是在一個DLL首次被映射到進程的地址空間時,系統調用它的DllMain函數,傳遞的ul_reason_for_call參數為DLL_PROCESS_ATTACH。這只有在首次映射時發生。如果一個線程後來為已經映射進來的DLL調用LoadLibrary或LoadLibraryEx,操作系統只會增加DLL的計數,它不會再用DLL_PROCESS_ATTACH調用DLL的DllMain函數。
而DLL_PROCESS_DETACH是在DLL被從進程的地址空間解除映射時,系統調用它的DllMain函數,傳遞的ul_reason_for_call值為DLL_PROCESS_DETACH。我們需要注意的是,當用DLL_PROCESS_ATTACH調用DLL的DllMain函數時,如果返回FALSE,說明初始化不成功,系統仍會用DLL_PROCESS_DETACH調用DLL的DllMain。因此,必須確保沒有清理那些沒有成功初始化的東西。
DLL_THREAD_ATTACH:當進程中創建一個線程時,系統察看當前映射到進程的地址空間中的所有DLL文件映像,並用值DLL_THREAD_ATTACH調用所有的這些DLL的DllMain函數。該通知告訴所有的DLL去執行線程級的初始化。注意,當映射一個新的DLL時,進程中已有的幾個線程在運行,系統不會為已經運行的線程用值DLL_THREAD_ATTACH調用DLL的DllMain函數。
而DLL_THREAD_DETACH,如果線程調用ExitThread來終結(如果讓線程函數返回而不是調用ExitThread,系統會自動調用ExitThread),系統察看當前映射到進程空間的所有DLL文件映像,並用值DLL_THREAD_DETACH來調用所有的DLL的DllMain函數。該通知告訴所有的DLL去執行線程級的清理工作。
這里,我們需要注意的是,如果線程的終結是因為系統中的一個線程調用了TerminateThread,系統就不會再使用DLL_THREAD_DETACH來調用DLL和DllMain函數。這與TerminateProcess一樣,不再萬不得已時,不要使用。
下面,我們貼出《Window高級編程指南》中的兩個圖來說明上述四種參數的調用情況。

好的,介紹了以上的情況,下面,我們來繼續實踐,這次,建立一個新的空的win32控制台工程TestDLL,不再多說,代碼如下:

[cpp] view plain
#include <iostream>
#include <Windows.h>
using namespace std;

DWORD WINAPI someFunction(LPVOID lpParam)
{
cout << "enter someFunction!" << endl;
Sleep(1000);
cout << "This is someFunction!" << endl;
Sleep(1000);
cout << "exit someFunction!" << endl;
return 0;
}

int main()
{
HINSTANCE hinstance = LoadLibrary("MyDLL");
if(hinstance!=NULL)
{
cout << "Load successfully!" << endl;
}else {
cout << "Load failed" << endl;
}
HANDLE hThread;
DWORD dwThreadId;

cout << "createThread before " << endl;
hThread = CreateThread(NULL,0,someFunction,NULL,0,&dwThreadId);
cout << "createThread after " << endl;
cout << endl;

Sleep(3000);

cout << "waitForSingleObject before " << endl;
WaitForSingleObject(hThread,INFINITE);
cout << "WaitForSingleObject after " << endl;
cout << endl;

FreeLibrary(hinstance);
return 0;
}

代碼很好理解,但是前提是,你必須對線程有一定的概念。另外,注意,我們上面編譯的獲得的「MyDLL.dll"必須拷貝到能夠讓我們這個工程找到的地方,也就是上面我們提到的搜索路徑中的一個地方。
這里,我們先貼結果,當然,這只是在我機器上其中某次運行結果。

有了上面我們介紹的知識,這個就不是很難理解,主進程在調用LoadLibrary時,用DLL_PROCESS_ATTACH調用了DllMain函數,而線程創建時,用DLL_THREAD_ATTACH調用了DllMain函數,而由於主線程和子線程並行的原因,可能輸出的時候會有打斷。但是,這樣反而能讓我們更清楚的理解程序。

③ GCC編譯過程詳解

在使用GCC編譯器編譯名為 hello.c 的C程序時,GCC編譯過程會經歷多個步驟,包括預處理、編譯、匯編和鏈接。下面詳細解釋GCC編譯的過程:

假設有一個名為 hello.c 的C源代碼文件。使用GCC編譯器編譯此文件通常涉及以下步驟:

預處理(Preprocessing)步驟中,GCC會掃描源代碼文件。它處理以 # 符號開頭的預處理指令,如 #include、#define 等。所有包含的頭文件,例如標准庫頭文件 stdio.h,將被插入源代碼中。宏定義也被展開。此過程生成一個中間文件,通常以 .i 或 .ii 為擴展名。

在單獨執行預處理命令時,使用cpp命令。命令為:cpp hello.c -o hello.i。這會將預處理後的代碼保存為 hello.i 文件。

編譯(Compiling)階段,GCC接受預處理後的代碼,並進行詞法分析、語法分析以及類型檢查。C源代碼被翻譯成匯編語言,生成一個匯編代碼文件,具有 .s 擴展名。

使用gcc命令單獨執行編譯步驟。命令為:gcc -S hello.i -o hello.s。這會將編譯後的匯編代碼保存為 hello.s 文件。

匯編(Assembling)階段,匯編器將匯編代碼文件轉化為機器碼指令,生成目標文件,通常具有 .o、.obj 或 .elf 擴展名。

使用as命令單獨執行匯編步驟。命令為:as hello.s -o hello.o。這將匯編代碼轉換為二進制目標文件,並保存為 hello.o。

鏈接(Linking)階段,鏈接器將目標文件與其他目標文件和庫文件鏈接在一起,創建最終的可執行文件。鏈接器解析程序中使用的函數和符號,確保它們正確連接。最終生成的可執行文件通常沒有擴展名(或在Windows上為 .exe)。

單獨執行鏈接命令時,使用gcc。命令為:gcc hello.o -o hello。這將目標文件與所需庫文件鏈接,生成可執行文件 hello。

整個編譯過程演示了如何單獨執行GCC編譯過程的各個階段,並通過使用不同命令控制每個階段的輸出。通過單獨執行這些步驟,可以更詳細地了解每個階段的處理過程和生成的文件。然而,在實際開發中,通常使用一個簡單的命令來完成整個編譯過程。命令為:gcc hello.c -o hello。這會自動執行所有步驟,生成最終可執行文件 hello。

GCC編譯器將源代碼轉換為可執行文件的過程涉及多個詳細步驟,每個步驟都有其特定的任務。這個過程確保代碼正確性並使其可執行。每個階段通過查看中間文件和目標文件深入了解編譯器處理過程,進行調試或優化。步驟自動執行,只需運行合適的編譯器命令就能完成整個過程。

④ codeblocks怎麼編譯當前文件

1、打開CodeBlocks軟體,點擊左上角的文件菜單,然後選擇新建下面的項目選項鎮裂。
2、彈出的新建界面中選擇ConsoleApplication選項。
3、進入項目語言選擇的界面,選擇C++即可。
4、給控制台項目起名字,並且設置項目的存儲位置。
5、選擇C++項目的編譯器為GNUGCCCompiler。拿旅知
6、回到CodeBlocks界面中,就可以看到左側創建好了控制台項目了,打開maincpp文件,裡面已經默認編寫了消消C++基本代碼。

閱讀全文

與s文件怎麼編譯相關的資料

熱點內容
國際服吃雞戰斗伺服器怎麼沒反應 瀏覽:55
小綠人官網哪裡下載app 瀏覽:486
用文件夾可以做手機架嗎 瀏覽:684
c語言編程軟體在哪裡下載 瀏覽:278
apk廣告文件夾 瀏覽:657
python如何使用循環比較字元串 瀏覽:106
sim碼加密 瀏覽:55
pdfviewerandroid 瀏覽:22
安卓微信密碼忘了怎麼找 瀏覽:988
如何將三個文件夾壓縮成一個文件 瀏覽:933
硬碟文件夾改密碼 瀏覽:27
曲黎敏pdf 瀏覽:250
go開源代碼如何編譯 瀏覽:245
如何訪問本地的tomcat伺服器埠設置 瀏覽:114
聽話的音樂app哪個好用 瀏覽:527
cmd怎麼命令 瀏覽:327
金軌智行app哪裡下載 瀏覽:82
西瓜視頻ip演算法 瀏覽:452
linux中的exec 瀏覽:919
3相壓縮機是幾匹的 瀏覽:369