xmake v2.1.5版本新特性介紹

2.1.5版本現(xiàn)已進(jìn)入收尾階段饰迹,此版本加入了一大波新特性,目前正在進(jìn)行穩(wěn)定性測試和修復(fù)余舶,在這里啊鸭,先來介紹下新版本中引入了哪些新特性和改進(jìn)。

1. 提供類似cmake的find_*系列接口匿值,實現(xiàn)各種查找赠制,例如:find_package, find_library, find_file, ...
2. 提供模塊接口,實現(xiàn)編譯器的各種檢測,例如:has_features, has_flags, has_cincludes, has_cfuncs, ...
3. 實現(xiàn)大量擴(kuò)展模塊钟些,提供文件下載烟号、解壓縮、git操作等接口
4. 支持預(yù)編譯頭文件支持政恍,改進(jìn)c++編譯效率
5. 支持在工程中自定義模塊進(jìn)行擴(kuò)展
6. 提供代碼片段檢測接口汪拥,實現(xiàn)更加靈活定制化的檢測需求
7. 改進(jìn)option和target,提供更加動態(tài)化的配置
8. 通過find_package實現(xiàn)包依賴管理2.0版本
9. 改進(jìn)root權(quán)限問題篙耗,實現(xiàn)更加安全的root下運行
10. 提供compile_commands.json導(dǎo)出插件
11. 改進(jìn)vs201x工程生成插件迫筑,支持多模式、多架構(gòu)同時構(gòu)建和自由切換不干擾

利用find_package查找依賴包

此接口參考了cmake對于find_*系列接口的設(shè)計宗弯,實現(xiàn)在項目中動態(tài)的查找和添加包依賴脯燃。

target("test")
    set_kind("binary")
    add_files("*.c")
    on_load(function (target)
        import("lib.detect.find_package")
        target:add(find_package("zlib"))
    end)

上述描述代碼,通過lib.detect.find_package來查找包蒙保,如果找到zlib包辕棚,則將links, includedirslinkdirs等信息添加到target中去。

實現(xiàn)包管理2.0

2.1.4版本之前追他,xmake對于包管理坟募,是通過在項目內(nèi)置pkg/zlib.pkg方式,來檢測鏈接的邑狸,雖然也支持自動檢測懈糯,但是查找功能有限,并且內(nèi)置的各個架構(gòu)的二進(jìn)制庫到項目单雾,對git并不是很友好赚哗。

現(xiàn)在通過find_packageoption,我們可以實現(xiàn)更好的包管理:

option("zlib")
    set_showmenu(true)
    before_check(function (option)
        import("lib.detect.find_package")
        option:add(find_package("zlib"))
    end)

target("test")
    add_options("zlib")

通過定義一個名為zlib的選項作為包硅堆,關(guān)聯(lián)到target屿储,在選項被檢測之前,先從系統(tǒng)中查找zlib包渐逃,如果存在够掠,則添加對應(yīng)的links, linkdirs等配置信息,然后進(jìn)行選項檢測茄菊,如果選項檢測通過疯潭,這個target在編譯的時候就會啟用zlib。

如果要手動禁用這個zlib包面殖,使其不參與自動檢測和鏈接竖哩,只需要:

$ xmake f --zlib=n 
$ xmake

注:2.2.1版本將會實現(xiàn)包管理3.0,更加自動化的依賴包管理和使用脊僚,具體詳情見:Remote package management相叁。

例如:

add_requires("mbedtls master optional")
add_requires("pcre2 >=1.2.0", "zlib >= 1.2.11")
add_requires("git@github.com:glennrp/libpng.git@libpng >=1.6.28")
target("test")
    add_packages("pcre2", "zlib", "libpng", "mbedtls")

目前正在努力開發(fā)中,盡情期待。增淹。

模塊的自定義擴(kuò)展

我們可以通過在工程的xmake.lua文件的開頭指定下擴(kuò)展modules的目錄:

add_moduledirs("$(projectdir)/xmake/modules")

這樣xmake就能找到自定義的擴(kuò)展模塊了椿访,例如:

projectdir
 - xmake
   - modules
     - detect/package/find_openssl.lua

通過在自定義的工程模塊目錄,添加一個find_openssl.lua的腳本虑润,就可以擴(kuò)展find_package赎离,使得包查找更加精準(zhǔn)。

這里順便總結(jié)下端辱,find_package的查找順序:

  1. 如果指定{packagedirs = ""}參數(shù)梁剔,優(yōu)先從這個參數(shù)指定的路徑中查找本地包*.pkg
  2. 如果在xmake/modules下面存在detect.packages.find_xxx腳本,那么嘗試調(diào)用此腳本來改進(jìn)查找結(jié)果
  3. 如果系統(tǒng)存在pkg-config舞蔽,并且查找的是系統(tǒng)環(huán)境的庫荣病,則嘗試使用pkg-config提供的路徑和鏈接信息進(jìn)行查找
  4. 如果系統(tǒng)存在homebrew,并且查找的是系統(tǒng)環(huán)境的庫渗柿,則嘗試使用brew --prefix xxx提供的信息進(jìn)行查找
  5. 從參數(shù)中指定的pathes路徑和一些已知的系統(tǒng)路徑/usr/lib, /usr/include中進(jìn)行查找

快速判斷編譯器特性檢測支持

通過core.tool.compiler模塊的compiler.has_features接口个盆,在xmake.lua中預(yù)先判斷當(dāng)前編譯期支持的語言特性,實現(xiàn)條件編譯朵栖。

此處也是參考了cmake的設(shè)計颊亮,具體詳情見:issues#83

target("test")
    on_load(function (target)
        import("core.tool.compiler")
        if compiler.has_features("cxx_constexpr") then
            target:add("defines", "HAS_CXX_CONSTEXPR=1")
        end
    end)

上述代碼陨溅,在加載target的時候终惑,判斷當(dāng)前編譯器是否支持c++的常量表達(dá)式語法特性,如果支持則添加宏定義:HAS_CXX_CONSTEXPR=1门扇。

我們也可以在判斷時候雹有,追加一些參數(shù)控制編譯選項,例如上述特性需要c++11支持臼寄,我們可以啟用它:

if compiler.has_features({"c_static_assert", "cxx_constexpr"}, {languages = "cxx11"}) then
    -- ok
end

如果之前對這個target已經(jīng)設(shè)置了c++11霸奕,那么我們也可以傳入target對象,繼承target的所有設(shè)置:

if compiler.has_features("cxx_constexpr", {target = target, defines = "..", includedirs = ".."}) then
    -- ok
end

所有的c/c++編譯器特性列表吉拳,見:compiler.features

判斷指定c/c++頭文件是否存在

通過lib.detect.has_cincludes來檢測c頭文件是否存在质帅。

import("lib.detect.has_cincludes")

local ok = has_cincludes("stdio.h")
local ok = has_cincludes({"stdio.h", "stdlib.h"}, {target = target})
local ok = has_cincludes({"stdio.h", "stdlib.h"}, {defines = "_GNU_SOURCE=1", languages = "cxx11"})

c++頭文件的檢測,見:lib.detect.has_cxxincludes

判斷指定c/c++函數(shù)是否存在

通過lib.detect.has_cfuncs來檢測c函數(shù)是否存在留攒。

import("lib.detect.has_cfuncs")

local ok = has_cfuncs("setjmp")
local ok = has_cfuncs({"sigsetjmp((void*)0, 0)", "setjmp"}, {includes = "setjmp.h"})

c++函數(shù)的檢測煤惩,見:lib.detect.has_cxxfuncs

判斷指定c/c++類型是否存在

通過lib.detect.has_ctypes來檢測c函數(shù)是否存在稼跳。

import("lib.detect.has_ctypes")

local ok = has_ctypes("wchar_t")
local ok = has_ctypes({"char", "wchar_t"}, {includes = "stdio.h"})
local ok = has_ctypes("wchar_t", {includes = {"stdio.h", "stdlib.h"}, "defines = "_GNU_SOURCE=1", languages = "cxx11"})

c++類型的檢測盟庞,見:lib.detect.has_cxxtypes吃沪。

檢測c/c++代碼片段是否能夠編譯通過

通用的c/c++代碼片段檢測接口汤善,通過傳入多個代碼片段列表,它會自動生成一個編譯文件,然后常識對它進(jìn)行編譯红淡,如果編譯通過返回true不狮。

對于一些復(fù)雜的編譯器特性,連compiler.has_features都無法檢測到的時候在旱,可以通過此接口通過嘗試編譯來檢測它摇零。

import("lib.detect.check_cxsnippets")

local ok = check_cxsnippets("void test() {}")
local ok = check_cxsnippets({"void test(){}", "#define TEST 1"}, {types = "wchar_t", includes = "stdio.h"})

此接口是detect.has_cfuncs, detect.has_cincludesdetect.has_ctypes等接口的通用版本,也更加底層桶蝎。

因此我們可以用它來檢測:types, functions, includes 還有 links驻仅,或者是組合起來一起檢測。

第一個參數(shù)為代碼片段列表登渣,一般用于一些自定義特性的檢測噪服,如果為空,則可以僅僅檢測可選參數(shù)中條件胜茧,例如:

local ok = check_cxsnippets({}, {types = {"wchar_t", "char*"}, includes = "stdio.h", funcs = {"sigsetjmp", "sigsetjmp((void*)0, 0)"}})

上面那個調(diào)用粘优,會去同時檢測types, includes和funcs是否都滿足,如果通過返回true呻顽。

更加強(qiáng)大的xmake lua插件

2.1.4版本的時候雹顺,此插件就已經(jīng)支持REPL(read-eval-print),實現(xiàn)交互式運行來方便測試模塊:

$ xmake lua
> 1 + 2
3

> a = 1
> a
1

> for _, v in pairs({1, 2, 3}) do
>> print(v)
>> end
1
2
3

現(xiàn)在可以通過一行命令廊遍,更加快速地測試模塊接口:

$ xmake lua lib.detect.find_package openssl

返回結(jié)果如下:{links = {"ssl", "crypto", "z"}, linkdirs = {"/usr/local/lib"}, includedirs = {"/usr/local/include"}}

預(yù)編譯頭文件支持

xmake新增通過預(yù)編譯頭文件去加速c/c++程序編譯嬉愧,目前支持的編譯器有:gcc, clang和msvc。

使用方式如下:

target("test")
    set_precompiled_header("header.h")

通常情況下喉前,設(shè)置c頭文件的預(yù)編譯英染,這需要加上這個配置即可,如果是對c++頭文件的預(yù)編譯被饿,改成:

target("test")
    set_precompiled_header("header.hpp")

其中的參數(shù)指定的是需要預(yù)編譯的頭文件路徑四康,相對于當(dāng)前xmake.lua所在的目錄。

如果只是調(diào)用xmake命令行進(jìn)行直接編譯狭握,那么上面的設(shè)置足夠了闪金,并且已經(jīng)對各個編譯器進(jìn)行支持,但是有些情況下论颅,上面的設(shè)置還不能滿足需求:

  1. 如果要使用xmake project工程插件生成vs工程文件哎垦,那么還缺少一個類似stdafx.cpp的文件(上面的設(shè)置在msvc編譯的時候會自動生成一個臨時的,但是對IDE工程不友好)恃疯。
  2. 如果gcc/clang下漏设,header.h想作為c++的預(yù)編譯頭文件就不支持了,除非改成header.hpp(默認(rèn)會當(dāng)做c頭文件進(jìn)行預(yù)編譯)今妄。

因此為了更加地通用跨平臺鸳碧,可以在工程里面創(chuàng)建一個類似vc中stdafx.cpp的源文件:header.cpp

target("test")
    set_precompiled_header("header.h", "header.cpp")

header.cpp的內(nèi)容如下:

#include "header.h"

上面的設(shè)置犬性,就可以很好地處理各種情況下的預(yù)編譯處理乒裆,追加的header.cpp也告訴了xmake:header.h是作為c++來預(yù)編譯的鹤耍。

相對于經(jīng)典的vc工程中的stdafx.cppstdafx.h昂拂,也能完美支持:

target("test")
    set_precompiled_header("stdafx.h", "stdafx.cpp")

生成compiler_commands插件

擴(kuò)展xmake project工程生成插件伟姐,支持compiler_commands.json文件輸出收苏,用于導(dǎo)出每個源文件的編譯信息,生成基于clang的編譯數(shù)據(jù)庫文件愤兵,json格式鹿霸,可用于跟ide,編輯器秆乳,靜態(tài)分析工具進(jìn)行交互懦鼠。

$ xmake project -k compile_commands

輸出的內(nèi)容格式如下:

[
  { "directory": "/home/user/llvm/build",
    "command": "/usr/bin/clang++ -Irelative -DSOMEDEF=\"With spaces, quotes and \\-es.\" -c -o file.o file.cc",
    "file": "file.cc" },
  ...
]

一般用于跟IDE、編輯器插件屹堰、靜態(tài)分析工具進(jìn)行集成肛冶,對于compile_commands的詳細(xì)說明見:JSONCompilationDatabase

自定義選項檢測腳本

在選項檢測之前,動態(tài)增加一些配置條件:

option("zlib")
    before_check(function (option)
        import("lib.detect.find_package")
        option:add(find_package("zlib"))
    end)

通過覆寫檢測腳本扯键,控制選項的檢測結(jié)果:

option("test")
    add_deps("small")
    set_default(true)
    on_check(function (option)
        if option:dep("small"):enabled() then
            option:enable(false)
        end
    end)

如果test依賴的選項通過睦袖,則禁用test選項。

在選項檢測完成后荣刑,執(zhí)行此腳本做一些后期處理馅笙,也可以在此時重新禁用選項:

option("test")
    add_deps("small")
    add_links("pthread")
    after_check(function (option)
        option:enable(false)
    end)

自定義目標(biāo)加載腳本

在target初始化加載的時候伦乔,將會執(zhí)行on_load,在里面可以做一些動態(tài)的目標(biāo)配置延蟹,實現(xiàn)更靈活的目標(biāo)描述定義,例如:

target("test")
    on_load(function (target)
        target:add("defines", "DEBUG", "TEST=\"hello\"")
        target:add("linkdirs", "/usr/lib", "/usr/local/lib")
        target:add({includedirs = "/usr/include", "links" = "pthread"})
    end)

可以在on_load里面叶堆,通過target:set, target:add 來動態(tài)添加各種target屬性阱飘。

目標(biāo)自定義構(gòu)建腳本支持分平臺架構(gòu)

通過設(shè)置平臺|架構(gòu)參數(shù),控制自定義腳本的執(zhí)行條件虱颗,實現(xiàn)在不同平臺沥匈、架構(gòu)下,調(diào)用不同的腳本進(jìn)行構(gòu)建:

target("test")
    on_build("iphoneos|arm*", function (target) 
        -- TODO
    end)

或者對所有macosx平臺忘渔,執(zhí)行腳本:

target("test")
    after_build("macosx", function (target) 
        -- TODO
    end)

其他腳本高帖,例如:on_clean, before_package等也都是支持的哦,而在2.1.4之前畦粮,只支持:

target("test")
    on_package(function (target) 
        -- TODO
    end)

并不能對不同架構(gòu)散址、平臺分別處理。

獲取內(nèi)置變量的值

內(nèi)置變量可以通過此接口直接獲取宣赔,而不需要再加$()的包裹预麸,使用更加簡單,例如:

print(val("host"))
print(val("env PATH"))
local s = val("shell echo hello")

而用vformat就比較繁瑣了:

local s = vformat("$(shell echo hello)")

不過vformat支持字符串參數(shù)格式化儒将,更加強(qiáng)大吏祸,所以應(yīng)用場景不同。

目標(biāo)依賴實現(xiàn)屬性繼承

2.1.4之前的版本钩蚊,target.add_deps僅用于添加依賴贡翘,修改編譯順序:

target("test1")
    set_kind("static")
    set_files("*.c")

target("test2")
    set_kind("static")
    set_files("*.c")

target("demo")
    add_deps("test1", "test2")
    add_links("test1", "test2")
    add_linkdirs("test1dir", "test2dir")

2.1.5版本后,target還會自動繼承依賴目標(biāo)中的配置和屬性砰逻,不再需要額外調(diào)用add_links, add_includedirsadd_linkdirs等接口去關(guān)聯(lián)依賴目標(biāo)了鸣驱,上述代碼可簡化為:

target("test1")
    set_kind("static")
    set_files("*.c")

target("test2")
    set_kind("static")
    set_files("*.c")

target("demo")
    add_deps("test1", "test2") -- 會自動鏈接依賴目標(biāo)

并且繼承關(guān)系是支持級聯(lián)的,例如:

target("library1")
    set_kind("static")
    add_files("*.c")
    add_headers("inc1/*.h")

target("library2")
    set_kind("static")
    add_deps("library1")
    add_files("*.c")
    add_headers("inc2/*.h")

target("test")
    set_kind("binary")
    add_deps("library2")

新增查找工具接口

lib.detect.find_tool接口用于查找可執(zhí)行程序蝠咆,比lib.detect.find_program更加的高級丐巫,功能也更加強(qiáng)大,它對可執(zhí)行程序進(jìn)行了封裝勺美,提供了工具這個概念:

  • toolname: 工具名递胧,可執(zhí)行程序的簡稱,用于標(biāo)示某個工具赡茸,例如:gcc, clang
  • program: 可執(zhí)行程序命令缎脾,例如:xcrun -sdk macosx clang

lib.detect.find_program只能通過傳入的原始program命令或路徑,去判斷該程序是否存在占卧。
find_tool則可以通過更加一致的toolname去查找工具遗菠,并且返回對應(yīng)的program完整命令路徑联喘,例如:

import("lib.detect.find_tool")

local tool = find_tool("clang")

我們也可以指定{version = true}參數(shù)去獲取工具的版本,并且指定一個自定義的搜索路徑辙纬,也支持內(nèi)建變量和自定義腳本哦:

local tool = find_tool("clang", {check = "--help"}) 
local tool = find_tool("clang", {check = function (tool) os.run("%s -h", tool) end})
local tool = find_tool("clang", {version = true, {pathes = {"/usr/bin", "/usr/local/bin", "$(env PATH)", function () return "/usr/xxx/bin" end}})

最后總結(jié)下豁遭,find_tool的查找流程:

  1. 優(yōu)先通過{program = "xxx"}的參數(shù)來嘗試運行和檢測。
  2. 如果在xmake/modules/detect/tools下存在detect.tools.find_xxx腳本贺拣,則調(diào)用此腳本進(jìn)行更加精準(zhǔn)的檢測蓖谢。
  3. 嘗試從/usr/bin/usr/local/bin等系統(tǒng)目錄進(jìn)行檢測譬涡。

我們也可以在工程xmake.luaadd_moduledirs指定的模塊目錄中闪幽,添加自定義查找腳本,來改進(jìn)檢測機(jī)制:

projectdir
  - xmake/modules
    - detect/tools/find_xxx.lua

更加安全的root權(quán)限編譯

由于xmake提供強(qiáng)大的自定義模塊和腳本支持涡匀,并且內(nèi)置安裝盯腌、卸載等action,如果xmake.lua里面的腳本描述不當(dāng)陨瘩,容易導(dǎo)致覆寫系統(tǒng)文件腕够,因此新版本對此作了改進(jìn):

  1. 在root下編譯工程,先判斷工程目錄的用戶權(quán)限屬性舌劳,嘗試降權(quán)到非root用戶進(jìn)行編譯燕少。
  2. 如果需要寫一些系統(tǒng)文件,會提示用戶當(dāng)前權(quán)限不安全蒿囤,禁止繼續(xù)運行客们,除非加--root參數(shù)強(qiáng)制root運行。
  3. 如果當(dāng)期工程目錄是root用戶權(quán)限材诽,則同2底挫。

具體詳情見:pull#113

API接口改進(jìn)

使用includes替代老的add_subdirsadd_subfiles接口。
使用set_config_header替代老的set_config_hset_config_h_prefix接口脸侥。

新增大量擴(kuò)展模塊

  • 文件下載
  • 解壓縮
  • git操作等接口

具體詳情見文檔:擴(kuò)展模塊

原文出處:http://tboox.org/cn/2017/07/29/new-features-v2.1.5/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末建邓,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子睁枕,更是在濱河造成了極大的恐慌官边,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件外遇,死亡現(xiàn)場離奇詭異注簿,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)跳仿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門诡渴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來峰鄙,“玉大人瓷叫,你說我怎么就攤上這事唤反”谷罚” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵眼耀,是天一觀的道長英支。 經(jīng)常有香客問我,道長哮伟,這世上最難降的妖魔是什么干花? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮澈吨,結(jié)果婚禮上把敢,老公的妹妹穿的比我還像新娘寄摆。我一直安慰自己谅辣,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布婶恼。 她就那樣靜靜地躺著桑阶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪勾邦。 梳的紋絲不亂的頭發(fā)上蚣录,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天,我揣著相機(jī)與錄音眷篇,去河邊找鬼萎河。 笑死,一個胖子當(dāng)著我的面吹牛蕉饼,可吹牛的內(nèi)容都是我干的虐杯。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼昧港,長吁一口氣:“原來是場噩夢啊……” “哼擎椰!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起创肥,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤达舒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后叹侄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體巩搏,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年趾代,在試婚紗的時候發(fā)現(xiàn)自己被綠了塔猾。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡稽坤,死狀恐怖丈甸,靈堂內(nèi)的尸體忽然破棺而出糯俗,到底是詐尸還是另有隱情,我是刑警寧澤睦擂,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布得湘,位于F島的核電站,受9級特大地震影響顿仇,放射性物質(zhì)發(fā)生泄漏淘正。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一臼闻、第九天 我趴在偏房一處隱蔽的房頂上張望鸿吆。 院中可真熱鬧,春花似錦述呐、人聲如沸惩淳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽思犁。三九已至,卻和暖如春进肯,著一層夾襖步出監(jiān)牢的瞬間激蹲,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工江掩, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留学辱,地道東北人。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓环形,卻偏偏與公主長得像策泣,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子斟赚,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容