日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

google gn构建系统的介绍

發(fā)布時(shí)間:2023/11/27 生活经验 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 google gn构建系统的介绍 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

GN語言和操作

  • GN語言和操作
    • 內(nèi)容
    • 介紹
      • 使用內(nèi)置的幫助
      • 設(shè)計(jì)理念
    • 語言
      • 字符串
      • 清單
      • 條件語句
      • 循環(huán)
      • 函數(shù)調(diào)用
      • 作用域和執(zhí)行Scoping and execution
    • 命名事物
      • 文件和目錄名稱
    • 構(gòu)建配置
    • 目標(biāo)
    • CONFIGS
      • 公共配置
    • 模板
    • 其他特性
      • Imports
      • 路徑處理
      • 模式
      • 執(zhí)行腳本
  • 與Blaze的區(qū)別和相似之處

介紹

本頁面描述了許多語言的細(xì)節(jié)和行為。

使用內(nèi)置的幫助!

GN有一個(gè)廣泛的內(nèi)置幫助系統(tǒng),為每個(gè)功能和內(nèi)置變量提供參考。這個(gè)頁面更高級(jí)。

gn help

你也可以看到2016年3月份的GNE幻燈片。演講者筆記包含完整的內(nèi)容。

設(shè)計(jì)理念

  • 編寫構(gòu)建文件不應(yīng)該是一個(gè)創(chuàng)造性的努力。理想情況下,兩個(gè)人應(yīng)該產(chǎn)生相同的構(gòu)建文件來實(shí)現(xiàn)相同的需求。除非絕對(duì)需要,否則不應(yīng)有任何靈活性。做越多的事情越可能產(chǎn)生致命的錯(cuò)誤。

  • 定義應(yīng)該比代碼更像代碼。我不想編寫或調(diào)試Prolog。但是我們團(tuán)隊(duì)的每個(gè)人都可以編寫和調(diào)試C ++和Python。

  • 構(gòu)建語言應(yīng)該被視為構(gòu)建應(yīng)該如何工作。表達(dá)任意事物不一定容易甚至不可能。我們應(yīng)該改變?cè)创a和工具,使構(gòu)建變得更簡(jiǎn)單,而不是把所有事情都變得更復(fù)雜以符合外部要求(在合理的范圍內(nèi))。

  • 在有意義的時(shí)候就像Blaze一樣(見下面的“與Blaze的區(qū)別和相似之處”)。

語言

GN使用非常簡(jiǎn)單的動(dòng)態(tài)類型語言。類型是:

  • 布爾(truefalse)。
  • 64位有符號(hào)整數(shù)。
  • 字符串。
  • 列表(任何其他類型)。
  • 范圍(Scopes)(有點(diǎn)像字典,僅是內(nèi)置的東西(built-in stuff))。

有一些內(nèi)置變量的值取決于當(dāng)前的環(huán)境。了解gn help更多信息。

語言中故意有許多遺漏。例如沒有用戶定義的函數(shù)調(diào)用,(模板是最接近的)。按照上述設(shè)計(jì)理念,如果你需要這樣的東西,你可能做錯(cuò)了。

變量sources有一個(gè)特殊的規(guī)則:賦值給它時(shí),將應(yīng)用一個(gè)排除模式列表。這被設(shè)計(jì)成自動(dòng)過濾掉某些類型的文件。見gn help set_sources_assignment_filtergn help label_pattern了解更多。

語言書呆子的完整語法可以在gn help grammar獲取到。

字符串

字符串用雙引號(hào)括起來,并使用反斜杠作為轉(zhuǎn)義字符。唯一支持的轉(zhuǎn)義序列是:

  • \" (用于直接引用)
  • \$ (字面上的美元符號(hào))
  • \\ (用于文字反斜杠)

任何其他反斜杠的使用都被視為文字反斜杠。所以,例如,\b在模式中使用不需要轉(zhuǎn)義,大多數(shù)Windows路徑"C:\foo\bar.h"也不需要。

使用$支持簡(jiǎn)單的變量替換,其中美元符號(hào)后的單詞被替換為變量的值。如果沒有非變量名字符來終止變量名稱,可以選擇{}包圍名稱。更復(fù)雜的表達(dá)式不被支持,僅支持變量名稱替換。

a = "mypath"
b = "$a/foo.cc"  # b -> "mypath/foo.cc"
c = "foo${a}bar.cc"  # c -> "foomypathbar.cc"

b = "$a/foo.cc"  # b -> "mypath/foo.cc"
c = "foo${a}bar.cc"  # c -> "foomypathbar.cc"

您可以使用 “$0xFF” 語法對(duì)8位字符進(jìn)行編碼,因此帶有換行符(十六進(jìn)制0A)的字符串會(huì)如下所示,"look$0x0Alike$0x0Athis"

清單

沒有辦法得到一個(gè)列表的長(zhǎng)度。如果你發(fā)現(xiàn)自己想要做這種事情,那么你就是想在構(gòu)建中做太多的工作。

列表支持追加:

a = [ "first" ]
a += [ "second" ]  # [ "first", "second" ]
a += [ "third", "fourth" ]  # [ "first", "second", "third", "fourth" ]
b = a + [ "fifth" ]  # [ "first", "second", "third", "fourth", "fifth" ]

a += [ "second" ]  # [ "first", "second" ]
a += [ "third", "fourth" ]  # [ "first", "second", "third", "fourth" ]
b = a + [ "fifth" ]  # [ "first", "second", "third", "fourth", "fifth" ]

將列表追加到另一個(gè)列表,是追加第二個(gè)列表中的項(xiàng)目,而不是將列表追加為嵌套成員。

您可以從列表中刪除項(xiàng)目:

a = [ "first", "second", "third", "first" ]
b = a - [ "first" ]  # [ "second", "third" ]
a -= [ "second" ]  # [ "first", "third", "fourth" ]

b = a - [ "first" ]  # [ "second", "third" ]
a -= [ "second" ]  # [ "first", "third", "fourth" ]

列表中的 - 運(yùn)算符搜索匹配項(xiàng)并刪除所有匹配的項(xiàng)目。從另一個(gè)列表中減去一個(gè)列表將刪除第二個(gè)列表中的每個(gè)項(xiàng)目。

如果找不到匹配的項(xiàng)目,將會(huì)拋出錯(cuò)誤,因此您需要事先知道該項(xiàng)目在移除之前確實(shí)已經(jīng)存在。鑒于沒有辦法測(cè)試包含,主要的用例是建立一個(gè)文件或標(biāo)志的主列表,并基于各種條件刪除那些不適用于當(dāng)前版本的構(gòu)建。

從風(fēng)格上來說,最好只添加到列表,并讓每個(gè)源文件或依賴項(xiàng)只出現(xiàn)一次。這與Chrome團(tuán)隊(duì)用于GYP的建議相反(GYP傾向于列出所有文件,然后刪除條件中不需要的文件)。

列表支持從零開始的下標(biāo)以提取值:

a = [ "first", "second", "third" ]
b = a[1]  # -> "second"

b = a[1]  # -> "second"

[]運(yùn)算符是只讀的,不能用來改變列表。這個(gè)主要的用例是當(dāng)一個(gè)外部腳本返回幾個(gè)已知的值,并且你想提取它們。

在某些情況下,如果您要添加到列表中,則很容易覆蓋列表。為了幫助理解這種情況,將非空列表分配給包含現(xiàn)有非空列表的變量是錯(cuò)誤的。如果您想避開此限制,請(qǐng)首先將目標(biāo)變量分配給空列表。

a = [“one”]
a = [“two”]#錯(cuò)誤:用非空列表覆蓋非空列表。
a = []#OK
a = [“two”]#OK

a = [“two”]#錯(cuò)誤:用非空列表覆蓋非空列表。
a = []#OK
a = [“two”]#OK

請(qǐng)注意,構(gòu)建腳本的執(zhí)行沒有內(nèi)在知識(shí)的底層數(shù)據(jù)的意義。例如,這意味著它不知道sources是一個(gè)文件名列表。所以,如果你刪除一個(gè)項(xiàng)目,它必須匹配文字字符串,而不是指定一個(gè)不同的名稱,那將解析為相同的文件名稱。

條件語句

條件看起來像C:

  if(is_linux ||(is_win && target_cpu ==“x86”)){sources -= [ "something.cc" ]} else if(...){...} else {...}
sources -= [ "something.cc" ]} else if(...){...} else {...}

如果只能在某些情況下聲明目標(biāo),則可以在大多數(shù)地方使用它們,甚至在整個(gè)目標(biāo)周圍使用它們。

循環(huán)

你可以使用foreach迭代一個(gè)列表。這是不鼓勵(lì)的。構(gòu)建應(yīng)該做的大部分事情通常都可以在不做這件事情的情況下表達(dá)出來,如果你覺得有必要的話,這可能表明你在元構(gòu)建中做了太多工作。

foreach(i,mylist){print(i)  # Note: i is a copy of each element, not a reference to it.
}
print(i)  # Note: i is a copy of each element, not a reference to it.
}

函數(shù)調(diào)用

簡(jiǎn)單的函數(shù)調(diào)用看起來像大多數(shù)其他語言

print("hello, world")
assert(is_win, "This should only be executed on Windows")

assert(is_win, "This should only be executed on Windows")

這些功能是內(nèi)置的,用戶不能定義新的功能。

一些函數(shù)在它們下面接受一個(gè)由{ }組成的代碼塊:

static_library(“mylibrary”){sources = [“a.cc”]
}
sources = [“a.cc”]
}

其中大多數(shù)用來定義目標(biāo)。用戶可以使用下面討論的模板機(jī)制來定義新的函數(shù)。

確切地說,這個(gè)表達(dá)式意味著該塊成為函數(shù)執(zhí)行的參數(shù)。大多數(shù)塊式函數(shù)都會(huì)執(zhí)行塊,并將結(jié)果范圍視為要讀取的變量字典。

作用域和執(zhí)行(Scoping and execution)

文件和函數(shù)調(diào)用后面跟著{ }塊引入新的作用域。作用域是嵌套的。當(dāng)您讀取一個(gè)變量時(shí),將會(huì)以相反的順序搜索包含的作用域,直到找到匹配的名稱。變量寫入總是進(jìn)入最內(nèi)層的作用域。

除了最內(nèi)層的作用域以外,沒有辦法修改任何封閉作用域。這意味著當(dāng)你定義一個(gè)目標(biāo)時(shí),例如,你在塊內(nèi)部做的任何事情都不會(huì)泄露到文件的其余部分。

if/ else/ foreach語句,即使他們使用{ },不會(huì)引入新的范圍,所以更改將持續(xù)在語句之外。

命名事物

文件和目錄名稱

文件和目錄名稱是字符串,并被解釋為相對(duì)于當(dāng)前構(gòu)建文件的目錄。有三種可能的形式:

相對(duì)名稱:

"foo.cc"
"src/foo.cc"
"../src/foo.cc"

"src/foo.cc"
"../src/foo.cc"

源代碼樹絕對(duì)名稱:

“//net/foo.cc”
“//base/test/foo.cc”

“//base/test/foo.cc”

系統(tǒng)絕對(duì)名稱(罕見,通常用于包含目錄):

"/usr/local/include/"
"/C:/Program Files/Windows Kits/Include"

"/C:/Program Files/Windows Kits/Include"

構(gòu)建配置

目標(biāo)

目標(biāo)是構(gòu)建圖中的一個(gè)節(jié)點(diǎn)。它通常代表將要生成的某種類型的可執(zhí)行文件或庫文件。目標(biāo)取決于其他目標(biāo)。內(nèi)置的目標(biāo)類型(請(qǐng)參閱gn help <targettype>以獲取更多幫助)是:

  • action:運(yùn)行一個(gè)腳本來生成一個(gè)文件。
  • action_foreach:為每個(gè)源文件運(yùn)行一次腳本。
  • bundle_data:聲明數(shù)據(jù)加入到Mac / iOS包。
  • create_bundle:創(chuàng)建一個(gè)Mac / iOS包。
  • executable:生成一個(gè)可執(zhí)行文件。
  • group:引用一個(gè)或多個(gè)其他目標(biāo)的虛擬依賴關(guān)系節(jié)點(diǎn)。
  • shared_library:.dll或.so。
  • loadable_module:.dll或.so只能在運(yùn)行時(shí)加載。
  • source_set:一個(gè)輕量級(jí)的虛擬靜態(tài)庫(通常比真正的靜態(tài)庫更可取,因?yàn)樗臉?gòu)建速度會(huì)更快)。
  • static_library:.lib或.a文件(通常你會(huì)想要一個(gè)source_set)。

您可以使用模板來擴(kuò)展它制作自定義目標(biāo)類型(請(qǐng)參見下文)。在Chrome中,一些更常用的模板是:

  • component:源集或共享庫,取決于構(gòu)建類型。
  • test:測(cè)試可執(zhí)行文件 在移動(dòng)設(shè)備上,這將為測(cè)試創(chuàng)建適當(dāng)?shù)谋緳C(jī)應(yīng)用程序類型。
  • app:可執(zhí)行文件或Mac / iOS應(yīng)用程序。
  • android_apk:制作一個(gè)APK。有很多其他的Android模版,看//build/config/android/rules.gni

CONFIGS

配置文件是命名對(duì)象,用于指定標(biāo)志集,包含目錄和定義。他們可以被應(yīng)用到一個(gè)目標(biāo),并推到相關(guān)的目標(biāo)。

要定義一個(gè)配置:

config("myconfig") {includes = [ "src/include" ]defines = [ "ENABLE_DOOM_MELON" ]
}
includes = [ "src/include" ]defines = [ "ENABLE_DOOM_MELON" ]
}

要將配置應(yīng)用于目標(biāo):

executable("doom_melon") {configs = [ ":myconfig" ]
}
configs = [ ":myconfig" ]
}

構(gòu)建配置文件通常指定設(shè)置默認(rèn)配置列表的目標(biāo)默認(rèn)值。目標(biāo)可以根據(jù)需要添加或刪除。所以在實(shí)踐中你通常會(huì)使用configs += ":myconfig"追加到默認(rèn)列表。

請(qǐng)參閱gn help config有關(guān)如何聲明和應(yīng)用配置的更多信息。

公共配置

目標(biāo)可以將設(shè)置應(yīng)用于依賴它的其他目標(biāo)。最常見的例子是一個(gè)第三方目標(biāo),它需要一些定義或包含目錄頭才能正確編譯。您希望這些設(shè)置既適用于第三方庫本身的編譯,也適用于使用該庫的所有目標(biāo)。

要做到這一點(diǎn),你寫一個(gè)你想要應(yīng)用的設(shè)置的配置:

config("my_external_library_config") {includes = "."defines = [ "DISABLE_JANK" ]
}
includes = "."defines = [ "DISABLE_JANK" ]
}

然后這個(gè)配置作為“公共”配置被添加到目標(biāo)。它既適用于目標(biāo),也適用于直接依賴目標(biāo)的目標(biāo)。

shared_library("my_external_library") {...# Targets that depend on this get this config applied.public_configs = [ ":my_external_library_config" ]
}
...# Targets that depend on this get this config applied.public_configs = [ ":my_external_library_config" ]
}

依賴目標(biāo)又可以通過將目標(biāo)作為“公共”依賴項(xiàng)添加到另一個(gè)級(jí)別,從而將依賴關(guān)系樹轉(zhuǎn)發(fā)到另一個(gè)級(jí)別。

static_library("intermediate_library") {...# Targets that depend on this one also get the configs from "my external library".public_deps = [ ":my_external_library" ]
}
...# Targets that depend on this one also get the configs from "my external library".public_deps = [ ":my_external_library" ]
}

通過把它設(shè)置成all_dependent_config一個(gè)目標(biāo)可以轉(zhuǎn)發(fā)一個(gè)配置給所有的依賴者,直到達(dá)到一個(gè)鏈接邊界為止。這是強(qiáng)烈不鼓勵(lì)的,因?yàn)樗鼘⒈缺匾臉?gòu)建配置超出更多的標(biāo)志和定義。使用public_deps來控制哪些標(biāo)志適用于哪里來代替它。

在Chrome中,更喜歡build/buildflag_header.gni用于定義的構(gòu)建標(biāo)題頭文件系統(tǒng),以防止大多數(shù)編譯器定義的錯(cuò)誤。

模板

模板是GN重用代碼的主要方式。通常情況下,模板會(huì)擴(kuò)展到一個(gè)或多個(gè)其他目標(biāo)類型。

# Declares a script that compiles IDL files to source, and then compiles those
#source files.
template("idl") {#Always base helper targets on target_name so they're unique。Target name#will be the string passed as the name when the template is invoked.idl_target_name =“$ {target_name} _generate”action_foreach(idl_target_name){...}#Your template should always define a target with the name target_name.#When other targets depend on your template invocation, this will be the#destination of that dependency.source_set(target_name){...deps = [ ":$idl_target_name" ]  # Require the sources to be compiled.}
}

#source files.
template("idl") {#Always base helper targets on target_name so they're unique。Target name#will be the string passed as the name when the template is invoked.idl_target_name =“$ {target_name} _generate”action_foreach(idl_target_name){...}#Your template should always define a target with the name target_name.#When other targets depend on your template invocation, this will be the#destination of that dependency.source_set(target_name){...deps = [ ":$idl_target_name" ]  # Require the sources to be compiled.}
}

通常,您的模板定義將放入.gni文件中,用戶將導(dǎo)入該文件以查看模板定義:

import("//tools/idl_compiler.gni")idl("my_interfaces") {sources = [ "a.idl", "b.idl" ]
}
idl("my_interfaces") {sources = [ "a.idl", "b.idl" ]
}

當(dāng)時(shí)聲明一個(gè)模板會(huì)在范圍內(nèi)的變量周圍創(chuàng)建一個(gè)閉包。當(dāng)模板被調(diào)用時(shí),魔術(shù)變量invoker被用來從調(diào)用范圍中讀取變量。模板通常會(huì)將感興趣的值復(fù)制到自己的范圍中:

template("idl") {source_set(target_name){sources = invoker.sources}
}
source_set(target_name){sources = invoker.sources}
}

模板執(zhí)行時(shí)的當(dāng)前目錄將是調(diào)用的構(gòu)建文件的目錄,而不是模板源文件。這是因?yàn)閺哪0逭{(diào)用者傳入的文件是正確的(這通常是模板中大多數(shù)文件處理的原因)。但是,如果模板本身有文件(可能會(huì)生成一個(gè)運(yùn)行腳本的動(dòng)作),則需要使用絕對(duì)路徑(“//foo/…”)來引用這些文件,以說明當(dāng)前目錄在調(diào)用時(shí)將不可預(yù)知。查看gn help template更多信息和更完整的例子。

其他特性

Imports

您可以使用import函數(shù)將.gni文件導(dǎo)入到當(dāng)前作用域。這不是 C++意義上的包含。導(dǎo)入的文件是獨(dú)立執(zhí)行的,生成的作用域被復(fù)制到當(dāng)前文件中(C ++在include指令出現(xiàn)的當(dāng)前上下文中執(zhí)行包含的文件)。這樣可以緩存導(dǎo)入的結(jié)果,還可以防止包含多個(gè)包含文件在內(nèi)的一些更“創(chuàng)造性”的用途。

通常情況下,一個(gè).gni會(huì)定義構(gòu)建參數(shù)和模板。了解gn help import更多信息。

您的.gni文件可以定義不導(dǎo)出到文件臨時(shí)變量,通過使用名稱中的前面的下劃線來包含它,就像_this

路徑處理

通常情況下,您需要?jiǎng)?chuàng)建一個(gè)文件名或相對(duì)于不同目錄的文件名列表。運(yùn)行腳本時(shí),這種情況尤為常見,這些腳本是以構(gòu)建輸出目錄作為當(dāng)前目錄執(zhí)行的,而構(gòu)建文件通常是指與其包含的目錄相關(guān)的文件。

您可以使用rebase_path轉(zhuǎn)換目錄。查看gn help rebase_path更多的幫助和例子。將相對(duì)于當(dāng)前目錄的文件名轉(zhuǎn)換為相對(duì)于根目錄的典型用法是:new_paths = rebase_path("myfile.c", root_build_dir)

模式

模式用于為自定義目標(biāo)類型的給定輸入集生成輸出文件名,并自動(dòng)從sources變量中移除文件(請(qǐng)參閱參考資料gn help set_sources_assignment_filter)。

他們就像簡(jiǎn)單的正則表達(dá)式。了解gn help label_pattern更多信息。

執(zhí)行腳本

有兩種方法來執(zhí)行腳本。GN中的所有外部腳本都是Python。第一種方法是作為構(gòu)建步驟。這樣的腳本將需要一些輸入,并生成一些輸出作為構(gòu)建的一部分。調(diào)用腳本的目標(biāo)是使用“action”目標(biāo)類型聲明的(請(qǐng)參閱參考資料gn help action)。

執(zhí)行腳本的第二種方法是在構(gòu)建文件執(zhí)行期間同步。這在某些情況下是必要的,以確定要編譯的文件集合,或獲取構(gòu)建文件可能依賴的某些系統(tǒng)配置。構(gòu)建文件可以讀取腳本的標(biāo)準(zhǔn)輸出(stdout)并以不同的方式對(duì)其執(zhí)行操作。

同步腳本的執(zhí)行由exec_script函數(shù)完成(詳見gn help exec_script參考資料)。因?yàn)橥綀?zhí)行一個(gè)腳本需要暫停當(dāng)前的構(gòu)建文件執(zhí)行,直到Python進(jìn)程完成執(zhí)行,依靠外部腳本是慢的,應(yīng)該盡量減少。

為了防止濫用,允許調(diào)用的文件exec_script可以在頂層.gn文件中列入白名單。Chrome做到這一點(diǎn)需要額外的代碼審查這樣的補(bǔ)充。看gn help dotfile

您可以同步讀取和寫入在同步運(yùn)行腳本時(shí)不鼓勵(lì)但偶爾需要的文件。典型的用例是傳遞一個(gè)比當(dāng)前平臺(tái)的命令行限制長(zhǎng)的文件名列表。請(qǐng)參閱gn help read_file以及gn help write_file如何讀取和寫入文件。如果可能,應(yīng)該避免這些功能。

超過命令行長(zhǎng)度限制的操作可以使用響應(yīng)文件繞過此限制,而不同步寫入文件。看gn help response_file_contents

與Blaze的區(qū)別和相似之處

Blaze是Google的內(nèi)部構(gòu)建系統(tǒng),現(xiàn)在已經(jīng)作為Bazel公開發(fā)布。它啟發(fā)了一些其他系統(tǒng),如Pants和Buck。

在Google的同類環(huán)境中,對(duì)條件的需求非常低,并且可以通過少量的手段(abi_deps)來獲得。Chrome使用各地的條件,需要添加這些是文件看起來不同的主要原因。

GN還增加了“配置”的概念來管理一些棘手的依賴和配置問題,同樣不會(huì)出現(xiàn)在服務(wù)器上。Blaze有一個(gè)“配置”的概念,就像一個(gè)GN工具鏈,但內(nèi)置在工具本身。GN工具鏈的工作方式是試圖以一種簡(jiǎn)潔的方式將這個(gè)概念分離到構(gòu)建文件中的結(jié)果。

GN保留了一些GYP概念,比如“全部依賴”設(shè)置,這些設(shè)置在Blaze中有些不同。這部分是為了使現(xiàn)有的GYP代碼更容易轉(zhuǎn)換,GYP結(jié)構(gòu)通常會(huì)提供更細(xì)粒度的控制(根據(jù)具體情況而定,好或壞)。

GN也使用GYP名稱,比如“sources”而不是“srcs”,因?yàn)榭s寫似乎是不必要的,盡管它使用了Blaze的“deps”,因?yàn)椤癲ependencies”很難打字。Chromium還在一個(gè)目標(biāo)中編譯多種語言,因此指定目標(biāo)名稱前綴的語言類型被刪除(例如,從cc_library)。

總結(jié)

以上是生活随笔為你收集整理的google gn构建系统的介绍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。