MPC使用介紹(二)(zt)


下面的內容緊接着MPC使用介紹(一)
3. 編寫MPC和MWC文件
這節將爲大家分別介紹各種輸入文件類型和語法的詳細信息:
3.1 輸入文件
MPC處理四種不同類型的文件,但是針對大多數的用戶,通常情況下只需要關心mpc文件和mwc文件。
3.1.1 項目文件(mpc)
項目文件(使用mpc後綴),包含了這些信息:包含路徑、庫目錄、源文件以及項目間的依賴關係。一個mpc文件可以有一個或多個的項目,這些項目需要使用唯一的名稱來避免項目生成是出現錯誤,這些項目同時還包括生成的目標類型(庫和可執行文件)。
3.1.2 工作區文件(mwc)
工作區在一個mwc文件中定義了一系列的mpc文件、目錄以及其他的一些mwc文件。針對每一個mpc文件,工作區創建器調用項目創建器來生成相應的項目。在所有的項目都成功生成之後,將會創建對應的工作區來包含生成的項目,並生成項目之間的依賴關係(只有生成工具支持纔會生成)。一個mwc文件可以包含一個或多個使用唯一的名稱來進行區別的工作區。如果沒有爲工作區創建器指定任何和工作區文件,工作區創建器將會在當前目錄中搜索所有的mpc文件,並組合成一個單獨的工作區來進行處理。
3.1.3 基礎項目文件(mpb)
MPC中一個重要的特性就是項目之間的繼承,項目繼承允許用戶設置一個基礎項目(mpb文件),該基礎項目包含所有繼承項目都需要的公有信息,包含路徑、庫目錄以及項目間的依賴關係等公有信息都可以包含在該基礎項目中,任何從該項目繼承的項目都將缺省擁有這些信息。
3.1.4 基礎工作區文件(mwb)
同項目一樣,工作區同樣可以從其他工作區進行繼承,一個基礎工作區可以提供對於其他一些工作區都需要的相同信息並使用繼承關係來是這些工作區都擁有這些信息。
3.2 一般性的輸入文件語法
在這一小節中,我們將對不同文件的語法進行一個介紹,並同時介紹該文件類型的中所使用的部分缺省值。
3.2.1 mwc和mwb
在工作區中,可以包含不同的mpc文件和路徑,在同一個mwc文件中可以同時定義一個或者多個工作區。例如:
workspace(optional name) : optional_base_workspace {
file.mpc
directory
other.mwc
exclude(vc6, vc7, vc71, vc8, nmake) {
this_directory
}
}
可以通過在workspace關鍵字後用括號括起來的字符串來爲工作區指定名稱,如果沒有爲工作區指定名稱,則使用mwc文件不帶文件後綴的文件名來作爲該工作區的名稱。
工作區同時支持從其他工作區進行繼承。在上面的例子中,optional_base_workspace是一個帶有工作區信息的mwb文件不帶文件後綴的文件名,這些信息將會被從該基礎工作區中繼承的工作區所使用。
在花括號之間,可以是賦值語句、mpc文件、路徑、其他工作區以及排除項。其中列出的mpc文件將會包含在該工作區中;如果一個路徑在工作區中出項,則工作區創建器會遞歸的遍歷該目錄以及其子目錄,並搜索所有的mpc文件;如果一個mwc文件被包含在該工作區中,則該文件將會被聚合到該工作區中來。
賦值語句可以散佈在項目和路徑之間,並影響項目生成的方式:
cmdline設置可以用來實現同從命令行中爲mpc.pl腳本提供選項一樣的功能(參見命令行選項)。不過,-type、-recurse、-noreldefs、-make_coexistence、-genins、-into、-language以及輸入文件將會被忽略。環境變量可以通過$NAME方式來訪問(其中NAME是環境變量名)。cmdline設置對於需要正確處理的特殊工作區來說極其有用。
除了上面列出的一些設置之外,mwc.pl腳本還支持的設置是implicit。如果implicit被指定爲1,則在沒有mpc文件的路徑下,將會生成一個缺省的項目,implicit同樣可以設置爲基礎項目的名稱,在這種情況下,隱式生成的項目將從繼承該基礎項目。不論何種方式,如果一個路徑下並沒有可以用來放置到項目中的文件,則不會生成項目。當你需要定義一個特殊的工作區,而MPC的缺省行爲即能生成有效的項目的時候,指定implicit設置將是非常方便的一種方式。
在一個範圍中指定的賦值將隻影響在該範圍中包含的mpc文件和路徑。如,在下面的例子中,cmdline設置僅僅影響到在相同範圍內的項目,在該例子中,MPC將會針對directory/foo.mpc添加-static選項,而其他在該工作區中列出的mpc文件和路徑則不受此影響。
workspace {

static {
cmdline += -static
directory/foo.mpc
}
exclude(gnuace, make) {
some.mpc
}
}
排除項用來阻止mpc文件和路徑被處理。這些被排除的mpc文件和路徑將不會生成項目文件和工作區。可以在exclude關鍵字之後用括號對需要排除的項目類型進行指定(如上面的例子),該方式將指示工作區創建器只針對列出的項目類型排除生成。如果不指定任何的排除項目類型,則表示排除所有的項目類型。
同C++語言一樣,在一行中,所有在//之後的內容都會被視爲註釋而被忽略掉。
3.2.2 mpc和mpb
3.2.2.1 項目聲明
項目聲明同工作區聲明類似,但是相比要複雜一些。一個mpc文件可以包含一個或者多個項目,並且每個項目都可以從基礎項目中進行繼承。
project(optional name) : base_project, another_base_project {
exename = client
includes += directory_name other_directory
libpaths += /usr/X11R6/lib
Header_Files {
file1.h
file2.h
fileN.h
}
Source_Files {
file1.cpp
file2.cpp
fileN.cpp
}
}
如果沒有爲項目指定名稱,則使用mpc文件不帶文件後綴的文件名來作爲該項目的名稱。但是,如果你的mpc文件需要包含多個項目,爲這些項目指定不同名稱是非常重要的,否則,後面生成的項目將會覆蓋前面生成的項目。如果發現相同的項目名稱,MPC會輸出錯誤並停止處理。
3.2.2.2 基礎項目
基礎項目的文件名可以使用mpb或者mpc後綴名。如果,MPC處理器在包含的搜索路徑中無法找到使用以mpb或者mpc作爲後綴名,並且文件名爲基礎項目名稱的文件,則MPC會輸出一個嚴重錯誤並停止處理。
3.2.2.3 賦值關鍵字
表3中列出了可以在mpc文件中的賦值語句(如:=、+=和-=)中使用一系列關鍵字,其中最常用的關鍵字用黑體進行表示:
表3. 賦值關鍵字
關鍵字 描述
after 指定該項目需要在列出的項目之後才進行生成。
avoids 指定在生成項目文件是,哪些特性需要被禁止。在GNUACE類型中,可以同時指定在生成目標時,哪些make宏不應該被設置。
custom_only 該設置告訴MPC生成僅包含可定製生成步驟的項目,在該項目中的所有文件將通過使用Defined_Custom中提供的可定製組件列表來進行處理。
dynamicflags 指定當生成動態庫的時候,傳遞給編譯器的選項。
dllout 如果被定義,指定動態庫的放置路徑,該設置在生成動態庫類型時會覆蓋libout的值。
exename 指定項目是可執行的項目,並同時指定生成的可執行文件名。
includes 指定提供給編譯器的附加搜索路徑。
install 指定可是否對執行程序進行安裝。
libout 指定動態庫和靜態庫的放置路徑。
libpaths 指定提供給連接器的附件庫搜索路徑。
libs 指定一個或者多個需要連接到目標中的庫,當在模板文件中進行處理時,庫修飾符有可能會被添加進來。例如,在使用vc6項目類型時,庫修飾符就會被添加進來。
lit_libs 該設置作用同libs,區別是不會添加庫修飾符。
macros 在這裏提供的所有值將會作爲編譯器命令行中的宏定義來進行添加。
pch_header 預編譯頭的頭文件名。更多信息見表後說明。
pch_source 與編譯頭的源文件名。更多信息見表後說明。
pure_libs 該設置同lit_libs,區別是不會添加任何的前綴和文件後綴名。
postbuild 如果被指定,則該設置的值將會在項目被成功生成後,被作爲命令來執行。<% %>結構可以在該設置中使用來訪問模板變量和模板函數。(關於模板的更多信息,參考模板文件(mpd)一節)
recurse 如果被設置成1,MPC會遞歸遍歷在組件列表中(如:Source_Files、Header_Files等)列出的目錄以及其子目錄,並添加所有組件相關的文件到列表中。該關鍵字可以作爲全局的項目設置或者組件範圍的設置來進行添加。
requires 指定在生成項目文件時,必須的特性。在GNUACE類型中,可以同時指定在生成目標時,哪些make宏應該被設置。
sharedname 指定項目是共享庫的項目,並同時指定生成的共享庫文件名。更多信息見表後說明。
staticflags 指定當生成靜態庫的時候,傳遞給編譯器的選項。
staticname 指定項目是靜態庫的項目,並同時指定生成的靜態庫文件名。更多信息見表後說明。
tagchecks 僅對GNUACE項目類型有效,指定由一個或者多個由tagname指定的名稱,在宏中進行搜索。
tagname 指定在生成目標之前,需要進行檢查的GNUACE make宏。
version 指定庫或者可執行文件的版本號。

賦值語句可以通過+=或者-=操作符來在關鍵字值中添加或者刪除指定的值。
如果在mpc文件中指定了sharedname而沒有指定staticname,則會使用sharedname的值來作爲staticname的值;反之亦然。
如果沒有指定exename、sharedname和staticname,MPC會在所有的源文件中搜索main函數。如果找到了main函數,則exename會被指定爲包含了main函數的源文件去除後綴之後的文件名;如果沒有找到,則以項目名稱來作爲sharedname或者staticname。
如果項目名稱、exename、sharedname和staticname中包含了星號,則MPC會根據特定的規則來替換名稱中的星號:如果是項目名稱中包含了星號,則使用缺省項目名稱來替換星號;如果是exename、sharedname和staticname中包含了星號,則會使用相應的項目名稱來替換星號。
如果有形如*_pch.h的文件存在於mpc文件所在的目錄中,並且pch_header關鍵字沒有被指定,則該文件會被作爲預編譯頭的頭文件,如果在該目錄下有多個符合條件pch文件,則最接近項目名稱頭文件將會被指定爲該項目的與編譯頭的頭文件。該規則同樣適用於pch_source關鍵字。
3.2.2.4 組件
mpc文件可以同時指定需要包含在生成的項目中的文件,這些文件使用表4中列出的名稱來進行指定。不過,大多數情況下,用戶可能只需要MPC爲項目文件提供的缺省值就足夠了。

表4. 組件名稱和缺省值


名稱 缺省值
Source_Files 缺省爲目錄下擁有以下後綴的文件:cpp、cxx、cc、c和C。
Header_Files 缺省爲目錄下擁有以下後綴的文件:h、hpp、hxx和hh。
Inline_Files 缺省爲目錄下擁有以下後綴的文件:i和inl。
Template_Files 缺省爲目錄下以如下結尾的文件:_T.cpp、_T.cxx、_T.cc、_T.c和_T.C。
Documentation_Files 缺省爲目錄下滿足如下條件的文件:README、readme、.doc、.html和.txt。
Resource_Files 缺省爲目錄下匹配項目名稱並以rc作爲後綴的文件。

如果某個組件未在mpc文件中列出,則使用其缺省值。爲了防止可能在目錄中出現的一組文件被作爲缺省值使用,用戶應該爲相應的組件定義一個空的集合。
每個組件名稱均有兩種格式,第一種格式只是簡單的在結構中使用一系列文件來表示:
Source_Files {
file1.cpp
file2.cpp
}
第二種格式是一系列命名塊的組合:
Source_Files(MACRO_NAME) {
BlockA {
file1.cpp
file2.cpp
}
BlockB {
file3.cpp
file4.cpp
}
}
第二種格式允許用戶在邏輯上將文件進行分組,以便將來能夠更容易的進行維護。使用這種格式同樣會對em3、gnuace、vc6、vc7、vc71和vc8的項目類型產生影響。如果某個在Source_Files中列出的源文件有相應的頭文件或者內聯文件同時存在於目錄中,並且該文件並沒有在相應的組件列表中列出,則該會自動添加到相應的組件列表中去。
3.2.2.5 verbatim語句
verbatim結構可以用來指定需要原樣放置到生成的項目文件中去的內容。語法如下:
vertabim(<project type>, <location>) {
..
}
當MPC在生成由<project type>指定的項目類型,並且在模板文件中遇到匹配<location>名稱指定的佔位符(原文marker)時,將會直接使用塊中的內容對去進行替換。如果在塊中的空白需要被保留,在塊中的每一行都應該使用雙引號來把內容括起來。如,下面的例子描述了在生成的gnuace項目類型的GNUmakefile文件末尾,所有的all:目標都應該依賴foo。
verbatim(gnuace, bottom) {
all: foo
}
3.2.2.6 specific語句
specific關鍵字可以用來爲特定的項目類型定義特殊的賦值語句。該關鍵字允許爲項目指定平臺相關或者OS相關的值。例如,當你想在其中一些平臺中鏈接qt-mt庫,而在其他平臺連接qt-mt230nc庫時,可以使用如下的例子:
specific(bmake, nmake, vc6, vc7, vc71, vc8) {
lit_libs += qt-mt230nc
} else {
lit_libs += qt-mt
}
其中else語句必須與後花括號在同一行中出現(如果有的話)。對某一種項目類型使用非操作(使用“!”)將會導致塊中的內容被應用到除該項目類型之外的其他項目類型。如果出現在specific語句中的某個關鍵字並不是MPC關鍵字,則該關鍵字將被作爲模板值修飾符來解釋。在這種情況下,該塊的作用同-value_template命令行選項一樣。
3.2.2.7 conditional語句
conditional塊允許爲特定的項目類型添加額外的源文件。語法如下:
conditional(<project type> [, <project type> …]) {
source1.cpp

}
conditional(<project type> [, <project type> …]) {
source1.cpp

} else {
source2.cpp

}
其中else語句必須與後花括號在同一行中出現(如果有的話)。對某一種項目類型使用非操作(使用“!”)將會導致塊中的內容被應用到除該項目類型之外的其他項目類型。
3.2.2.8 自定義類型和生成規則
MPC允許用戶根據需要自定義文件類型來支持自定義的生成規則。例如:
project {
Define_Custom(MOC) {
automatic = 0
command = $(QTDIR)/bin/moc
output_option = -o
inputext = .h
pre_extension = _moc
source_outputext = .cpp
keyword mocflags = commandflags
}
// Custom Component
MOC_Files {
QtReactor.h
}
Source_Files {
QtReactor_moc.cpp
}
}
上面的例子定義了一個名爲“MOC”的自定義文件類型,其中描述瞭如何處理輸入文件以及如何生成相應的輸出文件,一旦該自定義文件類型被定義,用戶可以使用MOC_Files來爲該新文件類型指定輸入文件。表5中列出了可以在Define_Custom塊中使用的關鍵字。

表5. Define_Custom關鍵字

關鍵字 描述
automatic 如果設置爲1,則會嘗試爲自定義類型搜索滿足條件的文件並進行添加;如果設置爲0,則不進行自動添加。
command 用來處理自定義類型的輸入文件的命令。
commandflags 任何需要傳遞給命令的選項。
dependent 如果有值,則在所有生成的文件中都會根據值來添加依賴項,缺省值是沒有任何值。
inputext 這是能夠由該命令處理的用逗號分隔的輸入文件擴展名列表。
keyword <name> 該關鍵字允許用戶映射<name>到項目級別的命名空間,設置到該結構的值必須是可以在Define_Custom語句中使用的關鍵字之一,使用該關鍵字的作用是修改通常只能在自定義組件中使用的關鍵字的值(如:command、commandflags等)。
libpath 如果該命令需要一個不在通常的庫搜索路徑中出現的路徑,該關鍵字可以用來保證命令能夠找到在運行時需要的庫。
output_option 如果命令能夠指定單一的輸出文件名,則應該進行指定;否則,應該對其進行忽略。
pch_postrule 如果設置爲1,則會在自定義規則中添加一條規則,該規則將會修改源輸出文件來包含相應的預編譯頭文件。
postcommand 該命令允許用戶在主命令處理完成自定義的輸入文件之後,運行指定的命令。
pre_extension 如果該命令生成多個擁有相同擴展名的文件,該命令可以用來在逗號分隔的列表中對其進行指定。例如,tao_idl分別爲不同的擴展名生成兩種類型的文件(C.h、S.h、C.cpp和S.cpp)。該關鍵字影響所有的擴展類型。
source_pre_extension 該關鍵字功能同pre_extension,但是隻影響source_outputext。
inline_pre_extension 該關鍵字功能同pre_extension,但是隻影響inline_outputext。
header_pre_extension 該關鍵字功能同pre_extension,但是隻影響header_outputext。
template_pre_extension 該關鍵字功能同pre_extension,但是隻影響template_outputext。
resource_pre_extension
該關鍵字功能同pre_extension,但是隻影響resource_outputext。
documentation_pre_extension 該關鍵字功能同pre_extension,但是隻影響documentation_outputext。
pre_filename 該關鍵字語法同pre_extension,不同之處在於是添加到文件名前面,而不是後面。該關鍵字影響所有的擴展類型。
source_pre_filename 該關鍵字功能同pre_filename,但是隻影響source_outputext。
inline_pre_filename 該關鍵字功能同pre_filename,但是隻影響inline_outputext。
header_pre_filename 該關鍵字功能同pre_filename,但是隻影響header_outputext。
template_pre_filename 該關鍵字功能同pre_filename,但是隻影響template_outputext。
resource_pre_filename 該關鍵字功能同pre_filename,但是隻影響resource_outputext。
documentation_pre_filename 該關鍵字功能同pre_filename,但是隻影響documentation_outputext。
source_outputext 該關鍵字包含由逗號分隔的一系列可能的輸出源文件擴展名,如果該命令不生成源文件,則不需要使用該關鍵字。
inline_outputext 該關鍵字包含由逗號分隔的一系列可能的輸出內聯文件擴展名,如果該命令不生成內聯文件,則不需要使用該關鍵字。
header_outputext 該關鍵字包含由逗號分隔的一系列可能的輸出頭文件擴展名,如果該命令不生成頭文件,則不需要使用該關鍵字。
template_outputext 該關鍵字包含由逗號分隔的一系列可能的輸出模板文件擴展名,如果該命令不生成模板文件,則不需要使用該關鍵字。
resource_outputext 該關鍵字包含由逗號分隔的一系列可能的輸出資源文件擴展名,如果該命令不生成資源文件,則不需要使用該關鍵字。
documentation_outputext 該關鍵字包含由逗號分隔的一系列可能的輸出文檔文件擴展名,如果該命令不生成文檔文件,則不需要使用該關鍵字。
generic_outputext 如果該命令不生成前面列出的文件類型,那麼在這裏指定這些擴展名。

在自定義組件和源文件組件、頭文件組件和內聯文件組件之間有特殊的交互作用:如果一個custom定義被設置爲“automatic”,並且自定義組件文件存在卻沒有直接指明,除非這些名字已經在這些組件中列出(或者部分列出),否則缺省行爲將自動將這些生成的文件名自動添加到相應的源文件組件、頭文件組件和內聯文件組件列表中去。
針對自定義生成類型的個別輸出擴展名並不是必須的。但是,至少需要指定一個輸出擴展類型來告訴MPC如果生成目標。另一方面,使用的命令並不一定要生成輸出,但是如果你想要你的輸入文件能夠在項目編譯時被處理,則必須要指定一種擴展類型。
如果自定義輸出類型不能在上面列出的擴展類型關鍵字(*_outputext)中列出,但是你能夠預先知道輸出文件名稱,則可以用“>>”構造塊來列出。下面是一個展示如何使用“>>”構造塊的例子,在該例子中,該命令使用一個輸入文件foo.prp,並生成兩個沒有任何關聯的輸出文件:hello.h和hello.cpp。
project {
Define_Custom {
automatic = 0
command = perl quogen.pl
commandflags = --debuglevel=1 --language=c++ \
        --kernel_language=c++
inputext = .cpp
keyword quogenflags = commandflags
}
Quogen_Files {
foo.prp >> hello.h hello.cpp
}
Source_Files {
hello.cpp
}
}
你可以使用“<<”結構在表示特定的自定義輸入文件的依賴關係。例如,在上面的例子中,假定輸入文件foo.prp依賴於foo.in,則我們可以通過“<<”來像下面例子一樣的來對foo.in進行指定。
Quogen_Files {
foo.prp >> hello.h hello.cpp << foo.in
}
在Custom_Build塊中,還可以使用optional結構,該結構用來在當特定的輸出文件依賴於特定的可選命令行參數時,對其進行指定。
project {
Define_Custom(TEST) {
optional(keyword) {
flag_keyword(option) += value [, value]
}
}
}
在上面的片段中,keyword可以是任何形式的pre_extension、pre_filename或者是以_outputext結尾的關鍵字。flag_keyword可以是任何的自定義組件關鍵字(儘管只有commandflags有功能性的值),MPC會在在flag_keyword的值中搜索括號中的option值,如果有,則在+=後的value或者values將會被添加到keyword指定的列表中去,可以使用非操作(使用“!”)來達到相反的效果。
下面的例子optional結構是如何使用來影響tao_idl命令的自定義定義的(參見:ACE_wrappers/bin/MakeProjectCreator/config/taoidldefaults.mpb)。其中的-GA命令行選項將導致tao_idl基於idl文件的文件名生成額外的使用A.cpp擴展的源文件,-Sc命令行選項將導致tao_idl不生成與S_T有關的文件。
Define_Custom(IDL) {

inputext = .idl
source_pre_extension = C, S
header_pre_extension = C, S
inline_pre_extension = C, S
source_outputext = .cpp, .cxx, .c, .C
header_outputext = .h, .hpp, .hxx, .hh
inline_outputext = .inl, .i
keyword idlflags = commandflags
optional(source_pre_extension) {
commandflags(-GA) += A
}
optional(template_outputext) {
commandflags(!-Sc) += S_T.cpp, S_T.cxx, S_T.cc, S_T.C
}
optional(header_pre_extension) {
commandflags(!-Sc) += S_T
}
optional(inline_pre_extension) {
commandflags(!-Sc) += S_T
}
}
對於自定義文件類型,只有如下的的關鍵字可以在自定義文件類型組件列表中使用:command、commandflags、dependent、gendir、postcommand和recurse。其中:recurse關鍵字作用同賦值關鍵字中的相同;command、commandflags、dependent和postcommand可以用來增加或覆蓋在Define_Custom節中的設置;gendir關鍵字用來指定存放輸出文件的目錄(只有在Define_Custom中設置了output_option時才起作用),例如:
MOC_Files {
commandflags += -nw
gendir = moc_generated
QtReactor.h
}
Source_Files {
moc_generated/QtReactor_moc.cpp
}
在上面的例子中,-nw命令行選項被添加到commandflags值中,並且輸出文件(QtReactor_moc.cpp)被存放到moc_generated目錄。如果MOC自定義組件並沒有設置output_option,則命令行選項沒必要添加到commandflags值中去,同時需要使用postcommand來保證輸出文件被存放到moc_generated目錄。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章