1. 程式人生 > >“萬能makefile”寫法詳解,一步一步寫一個實用的Makefile

“萬能makefile”寫法詳解,一步一步寫一個實用的Makefile

提示:本文在原博文的基礎上做了一點點修改與完善,諸如原博文的後面有顯示不全的地方,自己已完善!


目的:編寫一個實用的makefile,能自動編譯當前目錄下所有.c/.cpp原始檔,支援二者混合編譯。並且當某個.c/.cpp、.h或依賴的原始檔被修改後,僅重編涉及到的原始檔,未涉及的不編譯。


要達到這個目的,用到的技術有:
1-使用wildcard函式來獲得當前目錄下所有.c/.cpp檔案的列表。
2-make的多目標規則。
3-make的模式規則。
4-用gcc -MM命令得到一個.c/.cpp檔案include了哪些檔案。(具體使用細節,請點選博文連結)
5-用sed命令對gcc -MM命令的結果作修改。
6-用include命令包含依賴描述檔案.d。

三 準備知識
(一)多目標
對makefile裡下面2行,可看出多目標特徵,執行make bigoutput或make littleoutput可看到結果:

bigoutput littleoutput: defs.h pub.h  
    @echo [email protected] $(subst output,OUTPUT,[email protected]) $^  

註釋:[email protected]指該規則目標集合中能引起該規則執行的目標,$^指這個規則裡所有依賴的集合。
該行是把目標(bigoutput或littleoutput)裡的子串output替換成大寫的OUTPUT

(二)隱含規則
對makefile裡下面4行,可看出make的隱含規則,執行foo可看到結果:
第3、4行表示由.c得到.o,第1、2行表示由.o得到可執行檔案。
如果把第3、4行註釋的話,效果一樣。
即不寫.o來自.c的規則,它會自動執行gcc -c -o foo.o foo.c這條命令,由.c編譯出.o(其中-c表示只編譯不連結),然後自動執行gcc -o foo foo.o連結為可執行檔案。

foo:foo.o  
 gcc -o foo foo.o; ./foo  #連結目標檔案成可執行檔案,並執行該檔案
foo.o:foo.c     #註釋該行看效果  
 gcc -c foo.c
-o foo.o #註釋該行看效果

(三)定義模式規則
下面定義了一個模式規則,即如何由.c檔案生成.d檔案的規則。

foobar: foo.d bar.d  
    @echo complete generate foo.d and bar.d  

#make會對當前目錄下的每個.c檔案,依次該依賴規則裡面的命令,
使得每個.c檔案生成對應.d檔案。
%.d: %.c    
    @echo from $< to [email protected]  
    g++ -MM $< > [email protected]  

假定當前目錄下有2個.c檔案:foo.c和bar.c(檔案內容隨意)。
驗證方法有2種,都可:
1-執行make foo.d(或make bar.d),表示想要生成foo.d這個目標。
根據規則%.d: %.c,這時%匹配foo,這樣%.c等於foo.c,即foo.d這個目標依賴於foo.c。
此時會自動執行該規則裡的命令gcc -MM foo.c > foo.d,來生成foo.d這個目標。
2-執行make foo bar,因為foo bar依賴於foo.d和bar.d這2個檔案,即會一次性生成這2個檔案。


下面詳述如何自動生成依賴性,從而實現本例的makefile。

(一)
本例使用了makefile的模式規則,目的是對當前目錄下每個.c檔案,生成其對應的.d檔案,例如由main.c生成的.d檔案內容為:

main.o : main.c command.h  

這裡指示了main.o目標依賴於哪幾個原始檔,我們只要把這一行的內容,通過make的include指令包含到makefile檔案裡,即可在其任意一個依賴檔案被修改後,重新編譯目標main.o。
下面詳解如何生成這個.d檔案。

(二)
gcc/g++編譯器有一個-MM選項,可以對某個.c/.cpp檔案,分析其依賴的原始檔,例如假定main.c的內容為:

#include <stdio.h>//標準標頭檔案(以<>方式包含的),被-MM選項忽略,被-M選項收集  
#include "stdlib.h"//標準標頭檔案(以""方式包含的),被-MM選項忽略,被-M選項收集  
#include "command.h"  
int main()  
{  
    printf("##### Hello Makefile #####\n");  
    return 0;  
}  

則執行
gcc -MM main.c後,螢幕輸出:
    main.o: main.c command.h  
cc -M main.c後,螢幕輸出:
    main.o: main.c /usr/include/stdio.h /usr/include/features.h \  
    /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \  
    /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \  
    /usr/include/gnu/stubs-64.h \  
    /usr/lib/gcc/x86_64-linux-gnu/4.4.3/include/stddef.h \  
    /usr/include/bits/types.h /usr/include/bits/typesizes.h \  
    /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \  
    /usr/lib/gcc/x86_64-linux-gnu/4.4.3/include/stdarg.h \  
    /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \  
    /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h \  
    /usr/include/endian.h /usr/include/bits/endian.h \  
    /usr/include/bits/byteswap.h /usr/include/sys/select.h \  
    /usr/include/bits/select.h /usr/include/bits/sigset.h \  
    /usr/include/bits/time.h /usr/include/sys/sysmacros.h \  
    /usr/include/bits/pthreadtypes.h /usr/include/alloca.h command.h  

(三)
可見,只要把這些行挪到makefile裡,就能自動定義main.c的依賴是哪些檔案了,做法是把命令的輸出重定向到.d檔案裡:gcc -MM main.c > main.d,再把這個.d檔案include到makefile裡。(’>’是重定向符號,把生成的資料重定向寫入指定的檔案中)

如何include當前目錄每個.c生成的.d檔案:

#使用$(wildcard *.c)來獲取工作目錄下的所有.c檔案的列表。  
sources:=$(wildcard *.c) 
#這裡dependence是所有.d檔案的列表.即把sources串裡的.c換成.d。  
dependence=$(sources:.c=.d) 
#include後面可以跟若干個檔名,用空格分開,支援萬用字元,
include $(dependence) 


----------
#例如:
#這裡是把所有.d檔案一次性全部include進來。**注意該句要放在終極目標all的規則
之後,否則.d檔案裡的規則會被誤當作終極規則了。**
include  foo.make  *.mk   

(四)
現在main.c command.h這幾個檔案,任何一個改了都會重編main.o。但這裡還有一個問題,如果修改了command.h,即在command.h中加入#include “pub.h”,這時:
1-再make,由於command.h改了,這時會重編main.o,並且會使用新加的pub.h,看起來是正常的。
2-這時開啟main.d檢視,發現main.d中未加入pub.h,因為根據模式規則%.d: %.c中的定義,只有依賴的.c檔案變了,才會重新生成.d,而剛才改的是command.h,不會重新生成main.d、及不會在main.d中加入對pub.h的依賴關係,這樣一來會導致問題。
3-修改新加的pub.h的內容,再make,果然問題出現了,make報告up to date,沒有像期望那樣重編譯main.o。
**現在問題在於,main.d裡的某個.h檔案改了,沒有重新生成main.d。進一步說,main.d裡給出的每個依賴檔案,任何一個改了,都要重新生成這個main.d。
所以main.d也要作為一個目標來生成,它的依賴應該是main.d裡的每個依賴檔案,也就是說make裡要有這樣的定義:**

main.d: main.c command.h
這時我們發現,main.d與main.o的依賴是完全相同的,可以利用make的多目標規則,把main.d與main.o這兩個目標的定義合併為一句:

main.o main.d: main.c command.h
現在,main.o: main.c command.h這一句我們已經有了,如何進一步得到main.o main.d: main.c command.h呢?

(五)
解決方法是行內字串替換,對main.o,取出其中的子串main,加上.d字尾得到main.d,再插入到main.o後面。能實現這種替換功能的命令是sed。
實現的時候,先用gcc -MM命令生成臨時檔案main.d.temp,再用sed命令從該臨時檔案中讀出內容(用<重定向輸入)。做替換後,再用>輸出到最終檔案main.d。
命令可以這麼寫:

g++ -MM main.c > main.d.temp  
sed 's,main\.o[ :]*,\1.o main.d : ,g' < main.d.temp > main.d  

其中:
#指示sed命令從臨時檔案main.d.temp讀取輸入,作為命令的來源字串。
 sed 's,\(main\)\.o[ :]*,\1.o main.d : ,g'   #是sed命令。
 < main.d.temp    
 > main.d     #把行內替換結果輸出到最終檔案main.d。

(六)

1.這條sed命令的結構是s/match/replace/g。有時為了清晰,可以把每個/寫成逗號,
即這裡的格式s,match,replace,g。
2.該命令表示把源串內的match都替換成replace,s指示match可以是正則表示式。
g表示把每行內所有match都替換,如果去掉g,則只有每行的第1match被替換
(實際上不需要g,因為一個.d檔案中,只會在開頭有一個main.o:)。
3.這裡match是正則式\(main\)\.o[ :]*,它分成3段:
第1段是main,在sed命令裡把main用括號括起來,使接下來的replace中可以用\1
引用main。
第2段是\.o,表示匹配main.o,(這裡\不知何意,去掉也是可以的)。
第3段是正則式[ :]*,表示若干個空格或冒號,(其實一個.d裡只會有一個冒號,
如果這裡寫成[ ]*:,即匹配若干個空格後跟一個冒號,也是可以的)。

總體來說match用來匹配’main.o :’這樣的串。
這裡的replace是\1.o main.d :,其中\1會被替換為前面第1個用括號括起的內容,即main,這樣replace值為main.o main.d :
這樣該sed命令就實現了把main.o :替換為main.o main.d :的目的。

這兩行實現了把臨時檔案main.d.temp的內容main.o : main.c command.h改為main.o main.d : main.c command.h,並存入main.d檔案的功能。

(七)
進一步修改,採用自動化變數。使得當前目錄下有多個.c檔案時,make會依次對每個.c檔案執行這段規則,生成對應的.d:

gcc -MM  $< > [email protected].temp;  
sed 's,$∗\.o[ :]*,\1.o [email protected] :,g' < [email protected].temp > [email protected];  

(八)
現在來看上面2行的執行流程:

第一次make,假定這時從來沒有make過,所有.d檔案不存在,這時鍵入make:
1-include所有.d檔案的命令無效果。
2-首次編譯所有.c檔案。每個.c檔案中若#include了其它標頭檔案,會由編譯器自動讀取。由於這次是完整編譯,不存在什麼依賴檔案改了不會重編的問題。
3-對每個.c檔案,會根據依賴規則%.d: %.c,生成其對應的.d檔案,例如main.c生成的main.d檔案為:

main.o main.d: main.c command.h
第二次make,假定改了command.h、在command.h中加入#include “pub.h”,這時再make:
1-include所有.d檔案,例如include了main.d後,得到依賴規則:

main.o main.d: main.c command.h
注意所有include命令是首先執行的,make會先把所有include進來,再生成依賴規則關係。
2-此時,根據依賴規則,由於command.h的檔案戳改了,要重新生成main.o和main.d檔案。
3-先呼叫gcc -c main.c -o main.o生成main.o,
再呼叫gcc -MM main.c > main.d重新生成main.d。
此時main.d的依賴檔案裡增加了pub.h:

main.o main.d: main.c command.h pub.h
4-對其它依賴檔案沒改的.c(由其.d檔案得到),不會重新編譯.o和生成其.d。
5-最後會執行gcc $(objects) -o main生成最終可執行檔案。

第三次make,假定改了pub.h,再make。由於第二遍中,已把pub.h加入了main.d的依賴,此時會重編main.c,重新生成main.o和main.d。
這樣便實現了當前目錄下任一原始檔改了,自動編譯涉及它的.c。

(九)
進一步修改,得到目前大家普遍使用的版本:

set -e; rm -f [email protected]; \  
$(CC) -MM $(CPPFLAGS) $< > [email protected].$$$$; \  
sed 's,$∗\.o[ :]*,\1.o [email protected] : ,g' < [email protected].$$$$ > [email protected]; \  
rm -f [email protected].$$$$

第一行,set -e表示,如果某個命令的返回引數非0,那麼整個程式立刻退出。
rm -f用來刪除上一次make時生成的.d檔案,因為現在要重新生成這個.d,
老的可以刪除了(不刪也可以)。
第二行:前面臨時檔案是用固定的.d.temp作為字尾,為了防止重名覆蓋掉有用的檔案,
這裡把temp換成一個隨機數,該數可用$$得到,其值是當前程序號。
由於$是makefile特殊符號,一個$要$$來轉義,所以2$要寫成$$$$
(你可以在makefile裡用'echo $$$$'來顯示程序號的值)。
第三行:sed命令的輸入也改成該臨時檔案.


每個shell命令的程序號通常是不同的,為了每次呼叫$$$$時得到的程序號相同,
必須把這4行放在一條命令中,這裡用分號把它們連線成一條命令
(在書寫時為了易讀,用\拆成了多行),這樣每次.便是同一個檔案了。
你可以在makefile裡用下面命令來比較:

@echo $$$$; \
echo $$$$;  
@echo $$$$

輸出的結果是:(你輸出的結果很大可能不是以下值,也是正常的)
5879
5879
5880

**注意:第二行的echo前不能有@符號,否則會提示找不到該命令。原因在於@符號的作用
是執行命令之前不列印命令,而使用了接續符\,所以該行屬於上行,
若仍舊在該行行首新增@,等於在行首和行中添加了@,所以報錯了**

第四行:當make完後,每個臨時檔案.d.$$,已經不需要了,刪除之。
但每個.d檔案要在下一次make時被include進來,要保留。

(十)
綜合前面的分析,得到我們的makefile檔案:

#使用$(wildcard *.c)來獲取工作目錄下的所有.c檔案的列表  
sources:=$(wildcard *.c)  
objects:=$(sources:.c=.o)  
#這裡,dependence是所有.d檔案的列表.即把sources串裡的.c換成.d  
dependence:=$(sources:.c=.d)  

#所用的編譯工具  
CC=gcc  

#當$(objects)列表裡所有檔案都生成後,便可呼叫這裡的 $(CC) $^ -o [email protected] 命令生成最終目標all了  
#把all定義成第1個規則,使得可以把make all命令簡寫成make  
all: $(objects)  
 $(CC) $^ -o [email protected]  

#這段是make的模式規則,指示如何由.c檔案生成.o,即對每個.c檔案,呼叫gcc -c XX.c -o XX.o命令生成對應的.o檔案。  
#如果不寫這段也可以,因為make的隱含規則可以起到同樣的效果  
%.o: %.c  
 $(CC) -c $< -o [email protected]  

include $(dependence) #要放在終極目標all的規則之後,否則.d檔案裡的規則會被誤當作終極規則了  
%.d: %.c  
 set -e; rm -f [email protected]; \  
 $(CC) -MM $(CPPFLAGS) $< > [email protected].$$$$; \  
 sed 's,$∗\.o[ :]*,\1.o [email protected] :,g' < [email protected].$$$$ > [email protected]; \  
 rm -f [email protected].$$$$

.PHONY: clean #之所以把clean定義成偽目標,是因為這個目標並不對應實際的檔案  
clean:  
 rm -f all $(objects) $(dependence) #清除所有.o和.d檔案。-f表示被刪檔案不存在時不報錯 

(十一)
上面這個makefile已經能正常工作了(編譯C程式),但如果要用它編譯C++,變數CC值要改成g++,每個.c都要改成.cpp,有點繁瑣。現在我們繼續完善它,使其同時支援C和C++,並支援二者的混合編譯。

#一個實用的makefile,能自動編譯當前目錄下所有.c/.cpp原始檔,支援二者混合編譯  
#並且當某個.c/.cpp、.h或依賴的原始檔被修改後,僅重編涉及到的原始檔,未涉及的不編譯  
#詳解文件:http://blog.csdn.net/huyansoft/article/details/8924624  
#author:胡彥 2013-5-21  

#----------------------------------------------------------  
#編譯工具用g++,以同時支援C和C++程式,以及二者的混合編譯  
CC=g++  

#使用$(winldcard *.c)來獲取工作目錄下的所有.c檔案的列表  
#sources:=main.cpp command.c  

#變數sources得到當前目錄下待編譯的.c/.cpp檔案的列表,
#兩次呼叫winldcard、結果連在一起即可  
sources:=$(wildcard *.c) $(wildcard *.cpp)  

#變數objects得到待生成的.o檔案的列表,把sources中每個檔案的副檔名換成.o即可。
#這裡兩次呼叫patsubst函式,第1次把sources中所有.cpp換成.o,
#第2次把第1次結果裡所有.c換成.o  
objects:=$(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(sources)))  

#變數dependence得到待生成的.d檔案的列表,把objects中每個副檔名.o換成.d即可。
#也可寫成$(patsubst %.o,%.d,$(objects))  
dependence:=$(objects:.o=.d)  

#----------------------------------------------------------  
#當$(objects)列表裡所有檔案都生成後,便可呼叫這裡的 $(CC) $^ -o [email protected] 命令
#生成最終目標all了  
#把all定義成第1個規則,使得可以把make all命令簡寫成make  
all: $(objects)  
    $(CC) $(CPPFLAGS) $^ -o [email protected]  
    @./[email protected]   #編譯後立即執行  

#這段使用make的模式規則,指示如何由.c檔案生成.o,即對每個.c檔案,呼叫gcc -c XX.c -o XX.o命令生成對應的.o檔案  
#如果不寫這段也可以,因為make的隱含規則可以起到同樣的效果  
%.o: %.c  
    $(CC) $(CPPFLAGS) -c $< -o [email protected]  

#同上,指示如何由.cpp生成.o,可省略  
%.o: %.cpp  
    $(CC) $(CPPFLAGS) -c $< -o [email protected]  

#----------------------------------------------------------  
include $(dependence)   #要放在終極目標all的規則之後,否則.d檔案裡的規則會被誤當作終極規則了  

#因為這4行命令要多次凋用,定義成命令包以簡化書寫  
define gen_dep  
set -e; rm -f [email protected]; \  
$(CC) -MM $(CPPFLAGS) $< > [email protected].$$$$; \  
sed 's,$∗\.o[ :]*,\1.o [email protected] : ,g' < [email protected].$$$$ > [email protected]; \  
rm -f [email protected].$$$$
endef  

#指示如何由.c生成其依賴規則檔案.d  
#這段使用make的模式規則,指示對每個.c檔案,如何生成其依賴規則檔案.d,
#呼叫上面的命令包即可  
%.d: %.c  
    $(gen_dep)  

#同上,指示對每個.cpp,如何生成其依賴規則檔案.d  
%.d: %.cpp  
    $(gen_dep)  

#----------------------------------------------------------  
#清除所有臨時檔案(所有.o和.d)。之所以把clean定義成偽目標,是因為這個目標並不對應實際的檔案  
.PHONY: clean  
clean:  #.$$已在每次使用後立即刪除。-f引數表示被刪檔案不存在時不報錯  
    rm -f all $(objects) $(dependence)  

echo:   #除錯時顯示一些變數的值  
    @echo sources=$(sources)  
    @echo objects=$(objects)  
    @echo dependence=$(dependence)  
    @echo CPPFLAGS=$(CPPFLAGS)  

#提醒:當混合編譯.c/.cpp時,為了能夠在C++程式裡呼叫C函式,必須把每一個要呼叫的
#C函式,其宣告都包括在extern "C"{}塊裡面,這樣C++連結時才能成功連結它們。 


makefile學習體會:
剛學過C語言的讀者,可能會覺得makefile有點難,因為makefile不像C語言那樣,一招一式都那麼清晰明瞭。在makefile裡到處是“潛規則”,都是一些隱晦的東西,要弄明白只有搞清楚這些“潛規則”。
基本的規則無非是“一個依賴改了,去更新哪些目標”。
正因為隱晦動作較多,寫成一個makefile才不需要那麼多篇幅,畢竟專案程式碼才是主體。只要知道makefile的框架,往它的套路里填就行了。

較好的學習資料是《跟我一起寫Makefile.pdf》這篇文件(下載包裡已經附帶了),比較詳細,適合初學者。我們學習的目的是,能夠編寫一個像本文這樣的makefile,以滿足簡單專案的基本需求,這要求理解前面makefile幾個關鍵點:
1-多目標
2-隱含規則
3-定義模式規則
4-自動生成依賴性
可惜的是,這篇文件雖然比較全面,卻沒有以一個完整的例子為引導,對幾處要點沒有突出指明,尤其是“定義模式規則”在最後不顯眼的位置(第十一部分第五點),導致看了“自動生成依賴性”一節後還比較模糊。所以,看了《跟我一起寫Makefile.pdf》後,再結合本文針對性的講解,會有更實際的收穫。
另一個學習資料是《GNU make v3.80中文手冊v1.5.pdf》,這個手冊更詳細,但較枯燥,不適合完整學習,通常是遇到問題再去查閱。

[END]

相關推薦

萬能makefile寫法一個實用makefile sed 's,\($*\)\.o[ :]*,\1.o [emai

一 目的:編寫一個實用的makefile,能自動編譯當前目錄下所有.c/.cpp原始檔,支援二者混合編譯。並且當某個.c/.cpp、.h或依賴的原始檔被修改後,僅重編涉及到的原始檔,未涉及的不編譯。 二 要達到這個目的,用到的技術有: 1-使用wildcard函式來獲得當

萬能makefile寫法一個實用Makefile

提示:本文在原博文的基礎上做了一點點修改與完善,諸如原博文的後面有顯示不全的地方,自己已完善! 一 目的:編寫一個實用的makefile,能自動編譯當前目錄下所有.c/.cpp原始檔,支援二者混合編譯。並且當某個.c/.cpp、.h或依賴的原始檔

【K8S】Service服務看這篇就夠了!!

k8s用名稱空間namespace把資源進行隔離,預設情況下,相同的名稱空間裡的服務可以相互通訊,反之進行隔離。 1.1 Service Kubernetes中一個應用服務會有一個或多個例項(Pod,Pod可以通過rs進行多複本的建立),每個例項(Pod)的IP地址由網路外掛動態隨機分配(Pod重啟後IP地址

Java 8 中新的 Date 和 Time 類入門 DateUtil ,以後可以少幾個了關鍵是執行緒安全了

這篇文章主要是java8中新的Date和Time API的實戰。新的Date和Time類是java開發者社群千呼萬喚始出來的。Java8 之前存在的Date類一直都受人詬病,很多人都會選擇使用第三方的date庫joda-time。Java8中的date和time api

keepalived篇讓你入門

Keepalived介紹 轉:詳細請看http://blog.51cto.com/zephiruswt/1235852 Keepalived是一款高可用軟體,它的功能主要包括兩方面: 1)通過IP漂移,實現服務的高可用:伺服器叢集共享一個虛擬IP,同一時間只有一個伺服器佔有虛擬IP並

js實現快速排序二分查詢 (次學會)

js中幾大演算法,最近看到網上各路大神的解答,都蠻好的,自己也來玩一玩 一,快速排序 大致分三步: 在資料集之中,選擇一個元素作為"基準"(pivot)。 所有小於"基準"的元素,都移到"基準"的左邊;所有大於"基準"的元素,都移到"基準"的右邊。 對"基準"左邊和右邊的兩個子集,不斷重複

WaitForMultipleObjects用法看就懂

原文:https://blog.csdn.net/sac761/article/details/52456385 WaitForMultipleObjects是Windows中的一個功能非常強大的函式,幾乎可以等待Windows中的所有的核心物件。 函式原型為: DWORD Wait

IIC包括原理、過程最後步步教你實現IIC

IIC詳解 1、I2C匯流排具有兩根雙向訊號線,一根是資料線SDA,另一根是時鐘線SCL   2、IIC總線上可以掛很多裝置:多個主裝置,多個從裝置(外圍 裝置)。上圖中主裝置是兩個微控制器,剩下的都是從裝置。  3、多主機會產生匯流排裁決問題。當多個主機同時想佔用匯

cron表示式cron表示式寫法cron表示式例子

cron表示式格式: {秒數} {分鐘} {小時} {日期} {月份} {星期} {年份(可為空)} 例  "0 0 12 ? * WED" 在每星期三下午12:00 執行(年份通常 省略) 先了解每個位置代表的含義,在瞭解每個位置允許的範圍,以及一些特殊寫法,還有常用的案例,足夠你掌握c

BP神經網路計算過程用筆手算遍弄懂反向傳播

手算BP神經網路 現在很多人都說,做it門檻很低,腦子靈活點,願意去熬的,培訓個幾個月就可以,無非是調調函式而已。 確實,現在一些程式設計師的工作,調調函式掌握得好的話,也是能夠勝任的。但是,想要更進一步,還得不斷提升自己,努力理解各種演算法結構。 (類)

[轉載]最詳盡的 JS 原型與原型鏈終極沒有「可能是」。(

三篇文章都更新完畢,完整的剖析了 JS 原型與原型鏈,希望通過這些教程能讓你對 Javascript 這門語言理解的更透徹!一. 普通物件與函式物件JavaScript 中,萬物皆物件!但物件也是有區別的。分為普通物件和函式物件,Object 、Function 是 JS 自帶的函式物件。下面舉例說明var

漢諾塔問題原始碼種比較形象的輸出顯示結果

// Hanoi.cpp : Defines the entry point for the console application. // #include <stdafx.h> #include "stdio.h" #include "iostream.h

163vip郵箱註冊及登陸方法分鐘秒懂!

fff vpd 註冊 是什麽 oss pro shadow water tom 高效辦公,缺了郵箱可不行,163vip郵箱的註冊及登陸方法是什麽呢?一分鐘!用吃一片厚切牛舌的時間帶你秒懂!註冊 1、在百度搜索TOMvip郵箱,點擊進入2、點擊屏幕右側的“立即註冊按鈕”3、選

ActiveMQ訊息傳送機制以及ACK機制 AcitveMQ是作為種訊息儲存和分發元件涉及到client與broker端資料互動的方方面面它不僅要擔保訊息的儲存安全性還要提供額外的

    AcitveMQ是作為一種訊息儲存和分發元件,涉及到client與broker端資料互動的方方面面,它不僅要擔保訊息的儲存安全性,還要提供額外的手段來確保訊息的分發是可靠的。 一. ActiveMQ訊息傳送機制     Producer客戶端使用來發送訊息的, Consumer客戶端用來消費

扒使用boostrap-fileinput上傳外掛遇到的坑Bootstrap-fileinput上傳外掛的使用

由於公司專案的需求,需要實現動植物名錄的新增,包括姓名等資訊和圖片等,需要使用bootstrap-fileinput的上傳外掛,在提交新增介面表單資料的同時上傳一張或者多張圖片,並將上傳的圖片儲存到本地磁碟中(本文是f:盤的目錄下),在在實現的時候,不適用bootstrap-

關於AIDL使用和Binder機制你只需要看這篇即可

本篇文章從AIDL的角度來闡述Binder機制呼叫遠端服務的內部執行原理。因此本篇文章的第一部分介紹AIDL的使用,第二部分從AIDL的使用上具體介紹Binder機制。關於Binder機制的原理,可以參考簡單理解Binder機制的原理,對其有個大概的瞭解。 一、AIDL

Hibernate 初相識()Hibernate API 配置檔案對映檔案

導航{ } Hibernate 在三層框架中的位置。 一,第一個Hibernate 專案。  地址:https://github.com/gengzi/Hibernate 【1】匯入jar包 解

轉載 最詳盡的 JS 原型與原型鏈終極沒有「可能是」。(

-s 繼續 沒有 clas 程序設計 target 普通 fop 曾經 轉自:https://www.jianshu.com/p/dee9f8b14771 三篇文章都更新完畢,完整的剖析了 JS 原型與原型鏈,希望通過這些教程能讓你對 Javascript 這門語言

JVM類載入機制建議看這篇就夠了深入淺出總結的十分詳細!

## 類載入機制 虛擬機器把描述類的資料從Class檔案載入到記憶體,並對資料進行校驗、轉換解析和初始化,最終形成可以被虛擬機器直接使用的Java型別,這就是虛擬機器的類載入機制。 ## 類載入的時機 * 遇到new(比如new Student())、getstatic和putstatic(讀取或設定

POI操作Excel讀取xls和xlsx格式的文件

shee xss split 類型 後綴 .sh lan xls lin package org.ian.webutil; import java.io.File; import java.io.FileInputStream; import java.io.FileN