kj501 回復于:2004-10-02 10:55:53 |
configure.in寫一個就夠了,Makefile.am要在不同的目錄下分別寫。
這些東東都是要實際操作才能理解的。能不能把你的情況說詳細一些。 |
wubulen 回復于:2004-10-02 23:27:19 |
感謝你的回答。我再講我的例子說的詳細些(舉例)?,F在我有兩個子目錄,dir1 和 dir2, 在子目錄dir1 下有源文件 code1.c, code1.h, code2.c, code2.h, code3.c, code3.h, 在子目錄dir2下同樣有幾個源文件,code4.c, code4.h, code5.c, code5.h, code6.c, code6.h。最后我希望在bin目錄下生成幾個可執行文件,比如 code1.c, code2.c 生成 prog1, 而 code3.c 生成prog2, code4.c 和 code5.c 生成 prog3。 更復雜一點的是在不同子目錄下的程序互相關聯,比如 code2.c 中需要用到 code6.c 中的函數。還有在不同目錄下的兩個文件生成一個可執行文件,如 code2.c 和 code6.c 生成 prog4。
還有一個問題,是否可以指定編譯器。通常在linux下就用 gcc, 但是有些程序需要特殊的編譯器,比如mpicc (編譯mpi 函數)。這如何在configure.in 文件中指定? 謝謝指教。 |
mep 回復于:2004-10-03 10:57:49 |
我們在SourceForge上發布的項目CORBA Component Model實現StarCCM有幾十萬行代碼。支持Win+VC nmake和linux、solaris。原代碼中有configure.in和Makefile.in(沒有Makefile.am,我們自己寫的Makfile.in),可以看到,StarCCM中如何使用.m4;如何在一個大項目中包含幾個項目。
網址:http://sf.net/projects/starccm/ |
kj501 回復于:2004-10-03 11:40:35 |
[quote:656c0e17e3="wubulen"]感謝你的回答。我再講我的例子說的詳細些(舉例)?,F在我有兩個子目錄,dir1 和 dir2, 在子目錄dir1 下有源文件 code1.c, code1.h, code2.c, code2.h, code3.c, code3.h, 在子目錄dir2下同樣有幾個源文件,code4.c,..........[/quote:656c0e17e3]
bin目錄是那個目錄,是你的程序安裝的目錄嗎?如果我估計得不錯的話,應該是/usr/bin,或者是/usr/local/bin吧。 prog1應該是一個可以單獨執行的程序吧。不需要調用自己編寫的動態庫文件嗎? |
kj501 回復于:2004-10-03 17:39:25 |
先來舉一個簡單的例子吧。如何寫用code1.c, code2.c生成 prog1的configure.in和Makefile.am。
首先建立一個項目文件夾tt。在tt下建立dir1目錄。 [code:1:78df12705f] [kj501@s2023 dir1]$ mkdir tt [kj501@s2023 dir1]$ mkdir tt/dir1 [/code:1:78df12705f] 然后在dir1目錄中分別建立code1.c, code1.h, code2.c, code2.h,由于樓主沒有給出源代碼,我自己寫了幾個簡單的語句,以便說明問題。 下面是code1.h: [code:1:78df12705f] #include <stdlib.h> void foo_a(); [/code:1:78df12705f] 下面是code1.c: [code:1:78df12705f] #include "code1.h" void foo_a() { printf("This is code1.\n"); } [/code:1:78df12705f] 下面是code2.h: [code:1:78df12705f] #include <stdlib.h> void foo_b(); [/code:1:78df12705f] 下面是code2.c,這里讓code.c作為prog1的入口點: [code:1:78df12705f] #include "code1.h" #include "code2.h" void foo_b() { printf("This is code2.\n"); } int main() { foo_a(); foo_b(); } [/code:1:78df12705f] 建立好這幾個文件之后,下面就可以正式建立configure.in和Makefile.am了。 首先在tt目錄下建立configure.in文件: [code:1:78df12705f] #指定項目的一個源文件 AC_INIT(dir1/code2.c) #指定項目名稱和版本號 AM_INIT_AUTOMAKE(prog1, 0.0.1) #檢查編譯器 AC_PROG_CC #輸出Makefile文件 AC_OUTPUT(Makefile dir1/Makefile ) [/code:1:78df12705f] 同時建立tt目錄下的Makefile.am文件,這個文件很簡單,就一句話: [code:1:78df12705f] SUBDIRS=dir1 [/code:1:78df12705f] 然后建立dir1目錄下的Makefile.am文件,這才是真正起作用的Makefile.am文件: [code:1:78df12705f] bin_PROGRAMS=prog1 prog1_SOURCES=code1.c code2.c [/code:1:78df12705f] 完成之后,為了方便操作,再寫一個autogen.sh文件,保存在tt目錄下。 [code:1:78df12705f] #!/bin/sh aclocal automake --add-missing autoconf [/code:1:78df12705f] 存盤之后,用chmod +x改成可執行文件。然后執行autogen.sh。 [code:1:78df12705f] ./autogen.sh [/code:1:78df12705f] 即可在tt目錄下生成configure和makefile文件,同時在dir1目錄下也會生成一個makefile文件?,F在在tt目錄下執行make,屏幕將顯示如下信息: [code:1:78df12705f] [kj501@s2023 tt]$ make Making all in dir1 make[1]: Entering directory `/home/kj501/program/c/tt/dir1' gcc -DPACKAGE=\"prog1\" -DVERSION=\"0.0.1\" -I. -I. -g -O2 -c code1.c code1.c:6:2: warning: no newline at end of file gcc -DPACKAGE=\"prog1\" -DVERSION=\"0.0.1\" -I. -I. -g -O2 -c code2.c code2.c:13:2: warning: no newline at end of file gcc -g -O2 -o prog1 code1.o code2.o make[1]: Leaving directory `/home/kj501/program/c/tt/dir1' make[1]: Entering directory `/home/kj501/program/c/tt' make[1]: Nothing to be done for `all-am'. make[1]: Leaving directory `/home/kj501/program/c/tt' [/code:1:78df12705f] 進入dir1目錄,就可以看到生成的prog1程序。如果再執行make install,prog1將被安裝到缺省的/usr/local/bin目錄下去。 這就是一個最簡單的configure.in和Makefile.am的編寫情況。你如果不熟悉,最好自己動手做一遍,復雜的configure.in和Makefile.am都是在這個基礎上擴充的。 |
kj501 回復于:2004-10-03 17:57:56 |
在此基礎上,如果要同時實現code1.c, code2.c生成 prog1, 而 code3.c生成prog2。由于code1.c,code2.c,code3.c都在同一個目錄,只要改寫dir1目錄下的Makefile.am就可以了。
為了便于說明問題,首先要在dir1目錄下增加一個code3.h 和code3.c文件。 下面是code3.h: [code:1:4ecf204e74] #include <stdlib.h> void foo_c(); [/code:1:4ecf204e74] 下面是code3.c: [code:1:4ecf204e74] #include "code3.h" void foo_c() { printf("This is code3.\n"); } int main() { foo_c(); } [/code:1:4ecf204e74] 然后修改dir1目錄下的Makefile.am文件: [code:1:4ecf204e74] bin_PROGRAMS=prog1 prog2 prog1_SOURCES=code1.c code2.c prog2_SOURCES=code3.c [/code:1:4ecf204e74] 再重新執行一次autogen.sh。make之后,在dir1目錄下就會同時存在prog1和prog2兩個程序。 你先體會一下吧。然后自己做做用code4.c和 code5.c生成 prog3。應該很容易的。 |
wubulen 回復于:2004-10-03 19:46:03 |
十分感謝精靈王詳盡的解釋,現在已經清楚多了。還有三個問題需要確認。
1。兩個處在不同子目錄下的文件共同生成一可執行文件,那需要在兩個子目錄下都寫Makefile.am嗎,還是只要在帶main的那個文件的目錄下寫? 2。在同一個目錄下的文件生成幾個可執行文件,configure.in寫法問題。code1.c,?。悖铮洌澹玻悖◣В恚幔椋睿∩桑穑颍铮纾?,code3.c生成prog2. AC_INIT(dir1/code2.c?。洌椋颍保悖铮洌澹常悖? AM_INIT_AUTOMAKE(prog,0.0.1) #prog 這個名字可以隨便??? 3。關于編譯器的問題,如何指定特定的編譯器,?。粒茫撸校遥希牵撸茫弥粫z查C編譯器? 再次感謝! |
kj501 回復于:2004-10-04 12:08:45 |
先回答第1個問題。一般互相引用的源程序都是放在同一個目錄下的,如果要放在不同的目錄,可以把要引用的源文件編譯成靜態庫文件。
為便于說明問題,準備了如下文件: 在tt目錄下新建dir2目錄,保存code4.h和code4.c文件。 下面是code4.h: [code:1:1d78027594] #include <stdlib.h> void foo_d(); [/code:1:1d78027594] 下面是code4.c: [code:1:1d78027594] #include "code1.h" #include "code4.h" void foo_d() { printf("This is code4.\n"); } int main() { foo_a(); foo_d(); } [/code:1:1d78027594] dir1目錄下的code1.h和code1.c和上面的一樣,我就不寫了。 修改tt目錄下的configure.in文件。 [code:1:1d78027594] #指定項目的一個源文件 AC_INIT(dir2/code4.c) #指定項目名稱和版本號 AM_INIT_AUTOMAKE(myproject, 0.0.1) #檢查編譯器 AC_PROG_CC #檢查ranlib AC_PROG_RANLIB #輸出Makefile文件 AC_OUTPUT(Makefile dir1/Makefile dir2/Makefile ) [/code:1:1d78027594] 同時修改tt目錄下的Makefile.am文件。 [code:1:1d78027594] SUBDIRS = dir1 dir2 [/code:1:1d78027594] 在dir1目錄下修改Makefile.am文件。這時是將code1.c編譯成一個不安裝(noinst)的靜態庫文件。 [code:1:1d78027594] noinst_LIBRARIES=libcode1.a libcode1_a_SOURCES=code1.c [/code:1:1d78027594] 在dir2目錄下添加一個Makefile.am文件。 [code:1:1d78027594] INCLUDES= -I../dir1 bin_PROGRAMS=prog4 prog4_SOURCES=code4.c prog4_LDADD=../dir1/libcode1.a [/code:1:1d78027594] 然后執行autogen.sh就可以了。 |
kj501 回復于:2004-10-04 17:10:26 |
關于第2個問題,我舉的第2個例子正是說明這個問題,不過看來有些地方你沒有理解。
AC_INIT(dir1/code2.c)寫一個要檢查的源文件就夠了。多寫是沒有用的。不信你可以作一下試驗。 只要把AC_INIT改為AC_INIT(dir1/code2.c,dir1/vvv.c),這個vvv.c文件是不存在的,但執行configure時,一樣不會報錯。但這個要檢查的文件應該是程序的主文件,少了它,程序將無法運行。 AM_INIT_AUTOMAKE(package, version)是項目文件打包時的名字。比如說,AM_INIT_AUTOMAKE(mypro, 0.0.1),如果項目要發布源代碼,這時打包就可以執行一個make dist,會自動生成一個mypro-0.0.1.tar.gz的文件。只要你從網上下載并編譯過軟件的源代碼,對于這個應該不會陌生。當然從技術的角度來說,項目名稱和項目版本號可以隨便取,但為了管理上的方便,一般都有規范可循。 |
kj501 回復于:2004-10-04 17:32:28 |
第3個問題我也沒有碰到過,我得想一下才能答復你。 |
wubulen 回復于:2004-10-04 20:53:47 |
謝謝精靈網,你的回答使我清楚多了,我會自己實踐一下的。:-) |
kj501 回復于:2004-10-05 17:43:44 |
第3個問題我看可以你可以用這個辦法解決。
首先在configure.in中加上對特殊編譯器的檢查,如果檢查不到,則configure時會停止并給出“Couldn't find mpicc.”的出錯信息: [code:1:f1442f64d8] #檢查mpicc編譯器 AC_CHECK_PROG(MPICC,mpicc,yes,no) if test "$MPICC" = no; then AC_MSG_ERROR([Couldn't find mpicc.]) fi [/code:1:f1442f64d8] 然后把需要用mpicc編譯的源程序放在一個目錄下面。在這個目錄中先用上面的方法寫Makefile.am文件。然后再加上下面這部分: [code:1:f1442f64d8] CC=mipcc CFLAGS= [/code:1:f1442f64d8] 這樣用自己定義的編譯器和編譯標志取代系統定義的編譯器和編譯標志。 由于我沒有mpicc編譯器,沒有辦法親自做試驗??赡苁褂胢picc還有其它的要求,直接照做不一定行得通。但解決問題的思想應該就是這樣了,希望你能舉一反三。 |
win_hate 回復于:2004-10-05 17:55:05 |
[img:e414ca7818]http://bbs.chinaunix.net/forum/templates/subSilver/images/good_re.gif[/img:e414ca7818] [img:e414ca7818]http://bbs.chinaunix.net/forum/templates/subSilver/images/good_re.gif[/img:e414ca7818] [img:e414ca7818]http://bbs.chinaunix.net/forum/templates/subSilver/images/good_re.gif[/img:e414ca7818] [img:e414ca7818]http://bbs.chinaunix.net/forum/templates/subSilver/images/good_re.gif[/img:e414ca7818] [img:e414ca7818]http://bbs.chinaunix.net/forum/templates/subSilver/images/good_re.gif[/img:e414ca7818] |
kj501 回復于:2004-10-06 10:51:09 |
:) |
CNL 回復于:2004-10-06 20:28:24 |
非常感謝kj501,我也正在摸索autoconf的用法,幫了大忙了 :em02: |
chrisyan 回復于:2004-10-09 09:45:22 |
http://www.gnu.org/software/autoconf/manual/autoconf-2.57/html_chapter/autoconf_toc.html |
wubulen 回復于:2004-10-21 04:27:00 |
關于這個主題我經過實踐嘗試,終于得到了正確的結果。但是還有一個問題,是在我發布程序時產生的(make dist)。
因為有部分程序不能公開發布,所以我想將它們生成庫,(*.la, 通過libtool 生成),但我解開生成的壓縮文件,發現庫文件沒在壓縮文件里面,所以make的時候會有些函數找不到,產生錯誤。 請問如何能讓帶庫文件的文件夾也一起包括的壓縮文件里去呢? |
kj501 回復于:2004-10-21 11:55:53 |
如果代碼中用了庫文件,要先編譯安裝庫文件,再編譯代碼。你可以把編譯成庫文件的代碼獨立出來單獨打包,這樣也便于管理。我前面給的例子中庫文件是只編譯不安裝的。我明天給一個動態庫安裝的例子出來。 |
superdoctor 回復于:2004-10-21 12:07:13 |
值得收藏,思路非常清晰的教材啊 |
stsaofirst 回復于:2004-10-21 12:55:47 |
太棒了,goodgoodstudy to kj501, daydayup! |
daniel-hou 回復于:2004-10-21 19:16:42 |
我做的Makefile安裝時默認安裝在/usr/local/bin底下, 而我想安裝在/usr/sbin下,不知道該怎么改? 先謝謝了!! |
kj501 回復于:2004-10-21 21:49:37 |
這個問題不需要修改configure.in或者Makefile.am文件。用./configure --help可以看到有一個bindir參數可以指定可執行文件的安裝目錄。你只需要執行./configure --bindir=/usr/sbin就可以了。 |
daniel-hou 回復于:2004-10-21 21:59:15 |
老兄,你可來了,幫幫忙,這個問題搞了一天了,還是沒結果!! http://bbs.chinaunix.net/forum/23/20041021/429469.html |
daniel-hou 回復于:2004-10-21 22:00:13 |
謝謝,我試試看! |
daniel-hou 回復于:2004-10-21 22:09:27 |
本人才學疏淺,慚愧慚愧!! 以后多多學習才是!! :em02: :em02: |
daniel-hou 回復于:2004-10-22 19:23:51 |
上面的問題已經解決,但又有個新的問題: 我的程序是這樣的: mailrelay目錄下有兩個文件夾,poprelay和sendmailrelay. 在poprelay下的process.c中使用了crypt()函數,它要求gcc編譯時加-lcrypt參數,但默認情況下編譯時沒有加-lcrypt,所以編譯就通不過. 請問我該怎樣做才能編譯自動加上-lcrpty參數?? 我自己瞎捉摸了一下,在configure.in文件加了這么一行: [quote:580b093323]CFLAGS=-lcrypt[/quote:580b093323] 不知對不對??? |
kj501 回復于:2004-10-23 11:01:40 |
當然不對啦。要是對了,你也不沒有必要問這個問題了。
應該是在Makefile.am中寫 [code:1:4c199d24c7] LIBS = -lcrypt [/code:1:4c199d24c7] 我覺得你對configure.in和Makefile.am的作用不清楚。configure.in是用來生成configure的,主要用于檢查系統的編譯環境。至于編譯的各項參數,是由Makefile.am生成的Makefile決定的。建議你在網上找點資料仔細看看。 |
daniel-hou 回復于:2004-10-24 11:04:15 |
謝謝你,那我就在網上找一些資料學習一下,我也看過一些關于automake,autoconf的文檔,就是大部分看不太懂,呵呵!
以后還要不斷學習才是啊,現在對這方面的動西,我是太死板了,其實主要原因還是沒理解.還望以后多多指教??! :D :D :D |
wubulen 回復于:2004-12-02 03:04:45 |
隔了很長時間,現在又回到這個主題上。我安裝了動態庫,在lib目錄下,可是通過make dist 還是不能將庫文件(*.la) 打進包里。是否可以將庫文件打到包里呢?因為有些源程序不能發布,所以必須有庫文件。 |
kj501 回復于:2004-12-02 11:44:56 |
如果要發布編譯好的二進制可執行程序,可以采用rpm包的形式。 |
yunin 回復于:2004-12-03 16:28:29 |
值得收藏,多謝kj501,辛苦了。 |
simtiger 回復于:2004-12-11 20:51:48 |
kj501的回答很耐心哈,很喜歡這種step by step的例子。
喜歡這種細致討論的氣氛。 收藏! |