搜尋此網誌

2009年2月5日 星期四

GCC 的使用

目前的工作是在Linux的環境中寫程式,自然也就免不了要使用gcc
怕自己忘記該如何使用gcc, 所以就在網路上搜尋一下使用方式的文章,並貼出來跟大家分享.


GCC 的使用
簡介:
GCC 是由 GNU 出的 C 語言編譯器,可將由 ANSI C 或 traditional C 語言寫成的程式碼編譯成可執行檔。由於 GCC 能分別編譯出可執行於許多不同硬體、作業系統下的程式,在 UNIX 系統上是相當多人常用的 C 語言編譯程式。
使用方法簡介

基本的使用方法及常用指令
前言
編譯器在編譯過程中,先將程式碼編譯成 object 檔,然後再和程式庫聯結,成為可執行檔。故一個編譯器須提供的參數主要有幾類:
指定編譯器編出的 object 檔或是可執行檔檔名。
在編譯過程做最佳化,可提升程式的執行速度。
設定搜尋程式庫的標頭檔 (header file) 及程式庫檔的目錄及指定程式庫檔檔名。
提供進一步的資訊以便使用者找尋程式中的錯誤。
以下便以這四個大類分別介紹。
注意:下面在不同類別中所介紹的參數,幾乎都可以混合著使用。

設定編譯出的 object 檔檔名或是可執行檔檔名:
參數: -o out_put_filename
說明: 指定編譯出的檔名為 out_put_filename。

範例: 本例將程式碼 'test.c' 編譯成可執行檔,並設定檔名為 'test'。

gcc test.c -o test

在編譯過程做最佳化
參數: -O
說明: 在編譯過程做最佳化,以提升增快程式執行速度。

範例:本例將程式碼 'test.c' 編譯成可執行檔 'test',並在編譯過程做最佳化'。

gcc -O test.c -o test

設定搜尋標頭檔目錄、程式庫檔的目錄及指定程式庫檔。

設定搜尋標頭檔目錄
參數: -Idir_name
說明: 將目錄 'dir_name' 設定為搜尋標頭檔目錄之一。


設定搜尋程式庫目錄。
參數: -Ldir_name
說明: 將目錄 'dir_name' 設定為搜尋程式庫目錄之一。


設定程式庫檔案。

參數: -lname
說明: 聯結程式庫 libname.a 。

範例一:本例中假設你的程式檔名為test.c,數學函數如 sin等,所要聯結的程式庫為 libm.a。

gcc -I/usr/X11R6/include -L/usr/X11R6/lib -lX11 test.c -o test

範例二:本例中假設你的程式檔名為 test.c,使用到 X window 函數,所需的 include 檔放在 /usr/X11R6/include 中,所須聯結的程式庫放在 /usr/X11R6/lib,所要聯結的程式庫為 libX11.a。
gcc -I/usr/X11R6/include -L/usr/X11R6/lib -lX11 test.c -o test

提供進一步的資訊以便使用者找尋程式中的錯誤。
參數: -Wall

說明: 輸出較多的警告訊息,以便找出程式的錯誤。

範例: 編譯 test.c 時輸出較多的警告訊息。

gcc -Wall test.c

參數: -g

說明: 在編譯出可執行檔時,附加執行時除錯資訊,以供 gdb 讀取 (若要使用 ABSoft 的除錯程式,則須將參數改為 -gdwarf )。

範例: 將 'test.c' 編譯成可執行檔 'test',並附加除錯資訊。

gcc -g test.c -o test



進階參數
1. 僅編譯成 object 檔。
參數: -c

說明: 僅編譯成 object 檔而不進行程式庫聯結。

範例: 將 test.c 編譯成 object 檔 test.o。

gcc -c test.c -o test.o

2. 聯結數個 object 成可執行檔。

範例: 將 'test1.o'、'test2.o' 和程式庫聯結後成為可執行檔 test。

gcc test1.o test2.o -o test

3. 觀察巨集展開情形:

參數: -E

說明:展開程式中的巨集以便了解巨集是否依照預期方式展開。

範例:將 test1.c 中的巨集展開後儲存到 test1.c.ext 。

gcc -E test1.c > test1.c.ext

4. 產生組合語言程式碼:

參數: -S

範例:編譯 test.c 產生對應的組合語言程式碼檔 test.s。

gcc -S test.c -o test.s

編譯參數列表 -o out_put_filename 將編譯後產生的檔名設為 out_put_filename
-O 編譯時做最佳化,以增加程式執行效率。
-c 將原始語言編譯成 .o 檔(object檔) 不做程式庫連結的工作。
-g 編譯出 .o 檔時,保留除錯的資訊,在連結後產生的可執行檔中包含 gdb 需要的資訊。(若要給 ABSoft 的除錯程式使用,須將此參數改為 -gdwarg )
-E 將原始語言編譯將 test.c 中的巨集展開,之後輸出到 stdout。
-L/usr/X11R6/lib 連結程式時,搜尋程式庫檔時,將 /usr/X11R6/lib 列入搜尋目錄。
-lm 在連結程式時,將 libm.a 列入搜尋檔案中。
-I/usr/X11R6/include 到 /usr/X11R6/include 找尋被 include 的檔案。
-S 產生 test.c 對應的組合語言程式檔 test.s 。
-Wall 產生比較多的警告訊息 (平常不須使用,但當找不到程式中的錯誤時,可以加以使用。)



快速入門


範例:將 test.c 編譯成可執行檔 test 並在編譯過程中做最佳化。

gcc -O test.c -o test

範例: 將 test1.c 和 test2.c 編譯聯結成可執行檔 test 並在編譯過程中做最佳化。

gcc -O test1.c test2.c -o test


範例:若程式中有使用數學函數如 sin 等,編譯時須加入 -lm 。

gcc -O test.c -o test -lm

範例:發現程式有執行時錯誤,編譯後需用 GDB 除錯。

gcc -O -g test.c -o test

範例:發現程式有執行時錯誤,編譯後要跟 ABSoft F77 聯結後以 ABSoft 的除錯程式除錯。
gcc -O -gdwarf test.c -o test


更多的說明
man gcc
info gcc

-------------------------------------
看下面的例子:test.c

#include

main()

{ char *str="I like Linux! I advices you jion in the Linux World";

printf("%s\n",str);

exit(0);

}

使 用gcc編譯。輸入gcc -c test.c得到目標文件test.o.-c命令表示對文件進行編譯和彙編。但並不連接。如果再健入gcc -o ../bin/test test.o,那麼將得到名為test的可執行文件。其實這兩不可以一氣呵成,gcc ../bin/test test.c.如果程序沒有錯誤救生成了可執行文件。也許你會覺得基於命令行的編譯器比不上如VC之類的集成開發環境,的確gcc的界面要改進,但是你一 旦熟練了就會感到。gcc的效率如此之高。可以告訴大家的是Linux底下強大的C/C++集成開發環境Kdevelope和Vc一樣強大,使用了Gcc 編譯器。

2009年2月4日 星期三

在Unix命令列下寄送mail

工作的需要,需要寫一小段寄信的程式,雖然在我還是小朋友的時候就在Linux上寫過一個功能不算陽春的寄收件軟體,幾乎可以解80% mime type的信件,不過事隔多年,也忘了差不多了.好在這次要寫的東西功能非常陽春,我也在網路上找到一個應該勉強可以用的文章,就貼出來和大家分享.


在Unix命令列下寄送mail m110092006 發表於 December 18, 2006 04:37 PM

在命令列下寄送mail很多人都會,但是更多人不會。本篇告訴你怎麼寄純文字、加附檔及HTML格式的mail 。


在Unix的系統管理上我們常會把各式各樣指令的輸出導到檔案去,但是檔案在系統上,想看一下內容難免還得要登入上去。於是懶惰的人就會把這些輸出寄出來給相關的人,這樣就不需要還得連進去系統了。
在Unix下寄mail是一件很平常的事,有人可能會覺得這個有點老生常談,但事實是還是有人會來問我命令列下要怎麼寄 mail,而這個問題在網路上應該還是FAQ中的FAQ。

在Unix下最常被用來寄信的指令應該非mail莫屬,因為它普遍的存在各種不同版本不同平台的Unix系統上。或許你習慣用它的加強版 mailx。不過這二個用起來差不多我也不清楚到底有什麼差別,知道的人跟我講一下吧。另外有一個指令叫mutt 它是一個功能相當強大的MUA軟體,如果你有安裝的話,也可以使用它來寄mail。
假設你想把/etc/hosts的內容傳到你的電腦上,你不需要使用ftp來把它抓到你的電腦,只要使用指令來將它寄給你自己。

# cat /etc/hosts |mailx -s 'hosts table' jerry@abc.com

許多人應該都知道要怎麼用,而且也很多人應該是這樣子用的。上面的指令並沒有錯,只是可以直接把檔案導入給 mailx,為什麼要cat給mailx呢?公司薪水給的又不多,實在沒必要多花時間在處理公事上,所以字能少打就少打吧。

# mailx -s 'hosts table' jerry@abc.com < /etc/hosts

-s(Subject)是主旨,如果主旨有空白字元的話,記得要用單引號(')或是雙引號(")括起來。最後一個參數是收件人,如果收件人有多個的時候要用逗號(,)分隔,如jerry@abc.com,jerry@abc.com.tw。
或者你在Linux下,而且又裝了mutt。你也可以使用mutt來寄信,mutt的參數和mail差不多。

# mutt -s 'hosts table' jerry@abc.com < /etc/hosts

可是這樣子寄,/etc/hosts的內容是在信裡面呀,我想把它變成附件可以嗎?當然可以,只要跟其他的程式配合就可以了。

# uuencode /etc/hosts hosts.txt | mailx -s 'hosts table' jerry@abc.com

利用uuencode把/etc/hosts編碼過後丟給mailx就可以了,uuencode第一個參數是要編碼的檔案,第二個參數是編碼後的檔名,在這裡就是附件的檔名。下面的例子示範了把tar檔變成附件直接寄出。

# tar cf - /etc/* | uuencode etc.tar | mailx -s 'hosts table' jerry@abc.com

如果你用的是mutt那就更簡單了。只要加個-a(attach file)

# echo '/etc/hosts'|mutt -a /etc/hosts -s 'hosts table' jerry@abc.com

有人會問說,Jerry,我不要只是寄純文字的mail,可以寄html格式的mail嗎?在我回答之前,可以容許我先打你一拳嗎?如果你有 mutt(1.5.x 以上才行)的話要寄html格式的mail就很容易了(什麼,到這個時候還沒發現mutt有多好用嗎?還不快去裝起來。)。一行指令就可以搞定。

# mutt -e 'set content_type="text/html"' jerry@abc.com -s 'html format' <>

mutt允許我們對要寄出的mail修改它的檔頭(header),所以可以使用-e來設定檔頭的變數content_type 為"text/html",這個變數名稱content_type和真正檔頭Content-type的字不一樣哦!不要搞錯了。最後再導入一個html 格式的檔案給它就可以了。記住,-e後面那一串字不能錯哦!(1.5.x 以上才有這個變數。)
如果沒有mutt呢!裝一個,不然就繼續看下去。絕大多數的Unix系統應該都有內建sendmail,而sendmail有個參數-t可以達成我們的要求。看看下面的範例。

# echo 'Mime-Version: 1.0
> Content-type: text/html; charset="iso-8859-1"
> From: jerry@abc.com
> To: jerry@abc.com.tw
> Subject: test.......
>
>
html file
> ' | sendmail -t

使用echo把檔頭和所要html的內容全部輸出給sendmail這樣子就可以了。不過我想沒人會真的在命令列這樣使用,多半會用在script裡面。下面提供一個script範例給你參考,主要的部份在被#包住的那個區塊,把你要的輸出做成html格式就可以了。

#!/bin/sh
fromuser=jerry@abc.com
touser=jerry@abc.com,abc,boss@abc.com
subject="`uname -n` df output"
sendmail="/usr/sbin/sendmail -t"

header="Mime-Version: 1.0
Content-type: text/html; charset="iso-8859-1"
From: $fromuser
To: $touser
Subject: $subject

"

footer="

"
{
echo "$header"
### replace your code here. ###
df -k |awk '/^//{$5=sprintf("
%2d%",$5) ; print $0}'
###############################
echo "$footer"
} | $sendmail

下面二個script,第一個是shell script;第二個是perl script,你可以把要輸出的內容存成html檔,再用sendhtml直接寄出html格式的mail。寫的不怎麼樣,但最少可以使用啦!也給你一個 想法做參考,你可以以此延伸然後寫一個符合你的script。
使用的方法如下,
sendhtml.pl "my subject" jerry@abc.com my_file.html

#!/bin/sh
## usage : sendhtml.sh subject To_User html_file
subject="$1"
touser="$2"
htmlfile="$3"
fromuser="jerry@abc.com"
sendmail="/usr/sbin/sendmail -t"

header="Mime-Version: 1.0
Content-type: text/html; charset="iso-8859-1"
From: $fromuser
To: $touser
Subject: $subject"
{
echo "$header"
cat "$htmlfile"
} | $sendmail

#!/usr/bin/perl -w
# usage : sendhtml.pl subject To_User html_file
my $sendmail = "/usr/sbin/sendmail";
my $fromuser = "jerry@abc.com";
$subject = $ARGV[0];
$touser = $ARGV[1];
$htmlfile = $ARGV[2];

$header="Mime-Version: 1.0
Content-type: text/html; charset="iso-8859-1"
From: $fromuser
To: $touser
Subject: $subjectn";

open(fd2, "| $sendmail -t");
print fd2 $header;
open(fd1, $htmlfile);
while(my $line=) {
print fd2 "$linen";
}
close(fd2);
close(fd1);

在寄附件的部份,能不用uuencode就不要用,因為uuencode+mailx所寄出來的mail並不會在檔頭的部份加入MIME編碼的訊 息,而現在有越來越多的郵件程式不會正確讀取此種格式的mail。如yahoo, MSN....等webmail,在開啟這些mail時都會顯示亂碼,而不是正確的附檔,所以建議儘量使用別的程式來取代。
在命令列下寄mail的方法不只這些,如使用nail(已經改名叫mailx)或是使用perl、php....等也是可以,但以一般需求來講,我覺得這些應該已經夠了。如果你有什麼好的方法,歡迎你和大家分享。