Android.mk 上手指南

Android.mk是Android源碼中提供的一套用于編譯Android系統(tǒng)、子模塊的基于makefile語法規(guī)則的腳本文件。作為一名Android系統(tǒng)工程師,我們必須要了解Android.mk的語法規(guī)則挺据,這樣才能得心應(yīng)手的修改Android系統(tǒng)取具。

一個工程中的源文件不計其數(shù),其按類型扁耐、功能暇检、模塊分別放在若干個目錄中,makefile定義了一系列的規(guī)則來指定哪些文件需要先編譯婉称,哪些文件需要后編譯块仆,哪些文件需要重新編譯,甚至于進(jìn)行更復(fù)雜的功能操作王暗,因為 makefile就像一個Shell腳本一樣悔据,也可以執(zhí)行操作系統(tǒng)的命令
《百度百科:makefile》

雖然Android 7.0 之后Google提供了一種基于新語法結(jié)構(gòu)Android.bp腳本來替代語法結(jié)構(gòu)繁雜的Android.mk俗壹,但是即使是Android 10 中依然有大量模塊還在使用Android.mk進(jìn)行構(gòu)建科汗,預(yù)計今后一段時間內(nèi),Android.mkAndroid.bp依然會同時存在于Android源碼中绷雏。有關(guān)Android.bp的使用头滔,請參考這里Android.bp入門教程

一涎显、最基礎(chǔ)的Android.mk構(gòu)成

在詳細(xì)了解語法之前坤检,最好先了解 Android.mk 文件所含內(nèi)容的基本信息。為此期吓,我們先從一個最簡單的Android.mk入手缀蹄,來逐步了解mk的語法結(jié)構(gòu)。

LOCAL_PATH := $(call my-dir)  
include $(CLEAR_VARS)  
LOCAL_SRC_FILES := hello-jni.c
LOCAL_MODULE    := hello-jni    
include $(BUILD_SHARED_LIBRARY)  

Android.mk 文件必須先定義 LOCAL_PATH 變量

LOCAL_PATH := $(call my-dir)

此變量表示源文件在開發(fā)樹中的位置缺前。在上述命令中,構(gòu)建系統(tǒng)提供的宏函數(shù) my-dir 將返回當(dāng)前目錄(Android.mk 文件本身所在的目錄)的路徑悬襟。

聲明 CLEAR_VARS 變量

include $(CLEAR_VARS)

CLEAR_VARS 變量指向一個特殊的 GNU Makefile衅码,后者會為您清除許多 LOCAL_XXX 變量,例如 LOCAL_MODULE脊岳、LOCAL_SRC_FILESLOCAL_STATIC_LIBRARIES逝段。請注意,GNU Makefile 不會清除 LOCAL_PATH割捅。此變量必須保留其值奶躯,因為系統(tǒng)在單一 GNU Make 執(zhí)行上下文(其中的所有變量都是全局變量)中解析所有構(gòu)建控制文件。在描述每個模塊之前亿驾,您必須聲明(重新聲明)此變量嘹黔。

聲明LOCAL_SRC_FILES變量

LOCAL_SRC_FILES := hello-jni.c

構(gòu)建系統(tǒng)生成模塊時所用的源文件,可以是單個源文件莫瞬,也可以是一個文件夾儡蔓。

聲明LOCAL_MODULE變量

LOCAL_MODULE := hello-jni

LOCAL_MODULE 變量存儲您要構(gòu)建的模塊的名稱郭蕉。請在應(yīng)用的每個模塊中使用一次此變量。每個模塊名稱必須唯一喂江,且不含任何空格召锈。構(gòu)建系統(tǒng)在生成最終共享庫文件時,會對您分配給 LOCAL_MODULE 的名稱自動添加正確的前綴和后綴获询。例如涨岁,上述示例會生成名為 libhello-jni.so 的庫。

注意:如果模塊名稱的開頭已經(jīng)是 lib吉嚣,構(gòu)建系統(tǒng)不會添加額外的 lib 前綴卵惦;而是按原樣采用模塊名稱,并添加 .so 擴(kuò)展名瓦戚。因此,比如原來名為 libfoo.c 的源文件仍會生成名為 libfoo.so 的共享對象文件丛塌。此行為是為了支持 Android 平臺源文件根據(jù) Android.mk 文件生成的庫较解;所有這些庫的名稱都以 lib 開頭。

LOCAL_SRC_FILES 變量必須包含要構(gòu)建到模塊中的源文件列表赴邻。

聲明include $(BUILD_SHARED_LIBRARY)

include $(BUILD_SHARED_LIBRARY)  

通過include $(BUILD_SHARED_LIBRARY) 編譯工具印衔,會將上面設(shè)定的一切連接到一起BUILD_SHARED_LIBRARY 變量指向一個 GNU Makefile 腳本,該腳本會收集您自最近 include 以來在 LOCAL_XXX 變量中定義的所有信息姥敛。此腳本確定要構(gòu)建的內(nèi)容以及構(gòu)建方式奸焙。

上面這些就組成了一個最基礎(chǔ)的Android.mk,下面我們繼續(xù)介紹Android.mk中出現(xiàn)的各種關(guān)鍵字含義和用法彤敛。

二与帆、模塊

在Android.mk中我們把以include $(CLEAR_VARS)標(biāo)記開頭,到include $(BUILD_XXX)標(biāo)記結(jié)束墨榄,這中間描述的所有行為玄糟,稱為一個模塊。

例如:下列mk中包含了袄秩,兩個模塊阵翎。

  • 模塊一:源碼第2行至第9行,用于編譯一個java類庫
  • 模塊二:源碼第12行至第26行之剧,用于編譯一個apk安裝包
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
        $(call all-logtags-files-under, src)

LOCAL_MODULE := settings-logtags
## 構(gòu)建一個 java 類庫
include $(BUILD_STATIC_JAVA_LIBRARY)

# 構(gòu)建一個apk文件
include $(CLEAR_VARS)

LOCAL_PACKAGE_NAME := Settings
#省略其它描述...
LOCAL_USE_AAPT2 := true

LOCAL_SRC_FILES := $(call all-java-files-under, src)

LOCAL_STATIC_ANDROID_LIBRARIES := \
    androidx-constraintlayout_constraintlayout \
#省略其它描述...
include frameworks/base/packages/SettingsLib/common.mk
include frameworks/base/packages/SettingsLib/search/common.mk

include $(BUILD_PACKAGE)

三郭卫、include變量

CLEAR_VARS

用于取消位于include $(CLEAR_VARS)之前定義的所有的LOCAL_XXX變量中定義的值,但是LOCAL_PATH中定義的值不會被取消背稼。
在描述新的模塊前贰军,需要用include包含此變量。

BUILD_JAVA_LIBRARY

include $(BUILD_JAVA_LIBRARY)用于構(gòu)建java類庫蟹肘,該類庫中的代碼會以dex的形式存在谓形,如圖所示

image

BUILD_STATIC_JAVA_LIBRARY

include $(BUILD_STATIC_JAVA_LIBRARY)用于構(gòu)建java類庫灶伊,該類庫中代碼會以class文件的形式存在.
如果編譯出jar是用于app的開發(fā),應(yīng)該使用該變量描述寒跳。

BUILD_PACKAGE

include $(BUILD_PACKAGE)用于構(gòu)建Android 應(yīng)用程序安裝包聘萨。

BUILD_MULTI_PREBUILT

include $(BUILD_MULTI_PREBUILT)用于構(gòu)建預(yù)制庫,這些庫一般可以指定在lib文件夾下童太。

BUILD_STATIC_LIBRARIES

include $(BUILD_STATIC_LIBRARIES)用于構(gòu)建native靜態(tài)庫米辐。

四、模塊描述變量

LOCAL_PATH

此變量用于指定當(dāng)前文件的路徑书释。必須在 Android.mk 文件開頭定義此變量翘贮。以下示例演示了如何定義此變量:

LOCAL_PATH := $(call my-dir)

CLEAR_VARS 所指向的腳本不會清除此變量。因此爆惧,即使 Android.mk 文件描述了多個模塊狸页,也只需定義此變量一次。

LOCAL_MODULE

此變量用于設(shè)定模塊的名稱扯再。指定的名稱在所有模塊名稱中必須唯一芍耘,并且不得包含任何空格。必須先定義該名稱熄阻,然后才能添加其它的腳本(CLEAR_VARS 的腳本除外)斋竞。如下定義在配合include $(BUILD_STATIC_JAVA_LIBRARY)使用時會編譯時生成一個libsettings-logtags的類庫,lib是編譯時系統(tǒng)自動加上的秃殉。

LOCAL_MODULE := settings-logtags

LOCAL_MODULE_FILENAME

此變量能夠替換構(gòu)建系統(tǒng)為其生成的文件默認(rèn)使用的名稱坝初。例如,如果 LOCAL_MODULE 的名稱為 settings-logtags钾军,你可以強(qiáng)制系統(tǒng)將其生成的文件命名為 settingslib鳄袍。

LOCAL_MODULE := settings-logtags
LOCAL_MODULE_FILENAME := settingslib

LOCAL_SRC_FILES

此變量包含構(gòu)建系統(tǒng)生成模塊時所用的源文件列表。

LOCAL_SRC_FILES := \
        $(call all-logtags-files-under, src)

LOCAL_PACKAGE_NAME

此變量用于指定編譯后生成的Android APK的名字吏恭。例如畦木,如下方式,會生成一個Settings.apk的文件砸泛。

LOCAL_PACKAGE_NAME := Settings

LOCAL_CERTIFICATE

此變量用于指定APK的簽名方式十籍。如果不指定,默認(rèn)使用testkey簽名。

LOCAL_CERTIFICATE := platform

Android中共有四中簽名方式:

  • testkey:普通APK,默認(rèn)使用該簽名狰晚。
  • platform:該APK完成一些系統(tǒng)的核心功能。經(jīng)過對系統(tǒng)中存在的文件夾的訪問測試围俘,這種方式編譯出來的APK所在進(jìn)程的UID為system。
  • shared:該APK需要和home/contacts進(jìn)程共享數(shù)據(jù)。
  • media:該APK是media/download系統(tǒng)中的一環(huán)界牡。

LOCAL_PRODUCT_MODULE

為true表示將此apk安裝到priv-app目錄下簿寂。

LOCAL_PRODUCT_MODULE := true

LOCAL_SDK_VERSION

標(biāo)記SDK 的version 狀態(tài)。取值范圍有四個current system_current test_current core_current 宿亡。

LOCAL_SDK_VERSION := current

LOCAL_PRIVATE_PLATFORM_APIS

設(shè)置后常遂,會使用sdk的hide的api?肀嘁搿1嘁氳牧PK中使用了系統(tǒng)級API挽荠,必須設(shè)定該值克胳。

LOCAL_PRIVATE_PLATFORM_APIS := true

LOCAL_USE_AAPT2

此值用于設(shè)定是否開啟AAPT2打包APK,AAPT是Android Asset Packaging Tool的縮寫圈匆,AAPT2在AAPT的基礎(chǔ)做了優(yōu)化漠另。

LOCAL_USE_AAPT2 := true

LOCAL_STATIC_ANDROID_LIBRARIES

此值用于設(shè)定依賴的靜態(tài)Android庫

LOCAL_STATIC_ANDROID_LIBRARIES := \
    androidx-constraintlayout_constraintlayout \
    androidx.slice_slice-builders \

LOCAL_JAVA_LIBRARIES

此值用于設(shè)定依賴的共享java類庫。LOCAL_JAVA_LIBRARIES引用的外部Java庫在編譯時可以找到相關(guān)的東西跃赚,但并不打包到本模塊笆搓,在runtime時需要從別的地方查找,這個別的地方就是在編譯時將引用的外部Java庫的模塊名添加到PRODUCT_BOOT_JARS纬傲。

LOCAL_JAVA_LIBRARIES := \
    telephony-common \
    ims-common

LOCAL_STATIC_JAVA_LIBRARIES

此值用于設(shè)定依賴的靜態(tài)java類庫满败。LOCAL_STATIC_JAVA_LIBRARIES會把引用的外部Java庫直接編譯打包到本模塊中,在runtime時可以直接從本模塊中找到相關(guān)的jar嘹锁。

LOCAL_STATIC_JAVA_LIBRARIES := \
    androidx-constraintlayout_constraintlayout-solver \
    androidx.lifecycle_lifecycle-runtime \
    androidx.lifecycle_lifecycle-extensions \

LOCAL_PROGUARD_FLAG_FILES

此值用于設(shè)定混淆的標(biāo)志。

LOCAL_PROGUARD_FLAG_FILES := proguard.flags

Android.mk中以LOCAL_XXX開頭的描述變量非常多着裹,這里只列舉了一些常用的變量领猾。

五、函數(shù)宏

Android系統(tǒng)中提供了大量的宏函數(shù)骇扇,使用 $(call <function>) 可以對其進(jìn)行求值摔竿,返回文本信息。

my-dir

這個宏返回最后包括的 makefile 的路徑少孝,通常是當(dāng)前 Android.mk 的目錄继低。my-dir 可用于在 Android.mk 文件開頭定義 LOCAL_PATH。例如:

LOCAL_PATH := $(call my-dir)

由于 GNU Make 的工作方式稍走,這個宏實際返回的是構(gòu)建系統(tǒng)解析構(gòu)建腳本時包含的最后一個 makefile 的路徑袁翁。因此,包括其他文件后就不應(yīng)調(diào)用 my-dir婿脸。

例如:

LOCAL_PATH := $(call my-dir)
# ... declare one module
include $(LOCAL_PATH)/foo/`Android.mk`
LOCAL_PATH := $(call my-dir)
# ... declare another module

這里的問題在于粱胜,對 my-dir 的第二次調(diào)用將 LOCAL_PATH 定義為 $PATH/foo,而不是 $PATH狐树,因為這是其最近的 include 所指向的位置焙压。

Android.mk 文件中的任何其他內(nèi)容后指定額外的 include 可避免此問題。例如:

LOCAL_PATH := $(call my-dir)
# ... declare one module
LOCAL_PATH := $(call my-dir)
# ... declare another module
# extra includes at the end of the Android.mk file
include $(LOCAL_PATH)/foo/Android.mk

如果以這種方式構(gòu)造文件不可行,請將第一個 my-dir 調(diào)用的值保存到另一個變量中涯曲。例如:

MY_LOCAL_PATH := $(call my-dir)
LOCAL_PATH := $(MY_LOCAL_PATH)
# ... declare one module
include $(LOCAL_PATH)/foo/`Android.mk`
LOCAL_PATH := $(MY_LOCAL_PATH)#
 ... declare another module

all-java-files-under

返回位于<name>目錄下的所有java文件野哭。如果不指定<name>,怎么返回my-dir目錄下所有的java文件幻件。

include $(call all-java-files-under,<name>)

all-makefiles-under

返回位于當(dāng)前 <name> 路徑下所有目錄中的 Android.mk 文件列表拨黔。利用此函數(shù),可以為構(gòu)建系統(tǒng)提供深度嵌套的源目錄層次結(jié)構(gòu)傲武。默認(rèn)情況下蓉驹,系統(tǒng)只在 Android.mk 文件所在的目錄中查找文件。

include $(call all-makefiles-under,<name>)

六揪利、常見疑問

引入lib文件夾下的第三方庫

在實際開發(fā)中态兴,我們經(jīng)常需要在app中引入第三方的jar或aar,在Android.mk中疟位,可以按照如下的方式描述:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
# ...
LOCAL_STATIC_JAVA_LIBRARIES := \
    contextualcards # 給引入的jar或aar 起一個別名
# ...
include $(BUILD_PACKAGE)
# ====  預(yù)制類庫 ========================
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
    contextualcards:libs/contextualcards.aar # 指定contextualcards的實際路徑
include $(BUILD_MULTI_PREBUILT)

這里需要特別注意一點:在android.mk中引入aar瞻润,編譯時只會引入aar包中的java文件,資源文件如:icon甜刻、xml等都不會被編譯到apk中绍撞。

引入AndroidX庫

開發(fā)過程如果想要引入AndroidX的類庫可以參考下面的方式編寫。

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
# ...
LOCAL_STATIC_ANDROID_LIBRARIES := \
    androidx-constraintlayout_constraintlayout \
    androidx.appcompat_appcompat \

LOCAL_STATIC_JAVA_LIBRARIES := \
    androidx-constraintlayout_constraintlayout-solver \
# ...
include $(BUILD_PACKAGE)
# ...

上面的mk中主要是引入了AndroidX下的appcompatconstraintlayout庫得院。其中constraintlayout不僅需要在LOCAL_STATIC_ANDROID_LIBRARIES引入androidx-constraintlayout_constraintlayout傻铣,還需要在LOCAL_STATIC_JAVA_LIBRARIES中引入androidx-constraintlayout_constraintlayout-solver

在控制臺使用指令 find prebuilts/sdk/ -name Android.bp|xargs grep "name.粗略的名字",查詢類庫的引入方式祥绞。使用之前需要先 # source build/envsetup.sh # lunch非洲,不然無法執(zhí)行find指令。
使用示例:find prebuilts/sdk/ -name Android.bp|xargs grep "name.
constraintlayout"

七蜕径、參考『系統(tǒng)設(shè)置』的Android.mk

Android.mk的編寫两踏,我們很多時候可以參考系統(tǒng)中已有的Android.mk,例如下面給的就是Android R中系統(tǒng)設(shè)置的Android.mk兜喻。

該mk的位于 packages/apps/Settings 下

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
        $(call all-logtags-files-under, src)

LOCAL_MODULE := settings-logtags
# 構(gòu)建一個 libsettings-logtags的靜態(tài)java類庫
include $(BUILD_STATIC_JAVA_LIBRARY)

# 構(gòu)建一個Settings.apk
include $(CLEAR_VARS)

LOCAL_PACKAGE_NAME := Settings
LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_CERTIFICATE := platform
LOCAL_PRODUCT_MODULE := true
LOCAL_PRIVILEGED_MODULE := true
LOCAL_REQUIRED_MODULES := privapp_whitelist_com.android.settings
LOCAL_MODULE_TAGS := optional
LOCAL_USE_AAPT2 := true

LOCAL_SRC_FILES := $(call all-java-files-under, src)

LOCAL_STATIC_ANDROID_LIBRARIES := \
    androidx-constraintlayout_constraintlayout \
    androidx.slice_slice-builders \
    androidx.slice_slice-core \
    androidx.slice_slice-view \
    androidx.core_core \
    androidx.appcompat_appcompat \
    androidx.cardview_cardview \
    androidx.preference_preference \
    androidx.recyclerview_recyclerview \
    com.google.android.material_material \
    setupcompat \
    setupdesign

LOCAL_JAVA_LIBRARIES := \
    telephony-common \
    ims-common

LOCAL_STATIC_JAVA_LIBRARIES := \
    androidx-constraintlayout_constraintlayout-solver \
    androidx.lifecycle_lifecycle-runtime \
    androidx.lifecycle_lifecycle-extensions \
    guava \
    jsr305 \
    settings-contextual-card-protos-lite \
    settings-log-bridge-protos-lite \
    contextualcards \
    settings-logtags \
    zxing-core-1.7

LOCAL_PROGUARD_FLAG_FILES := proguard.flags

ifneq ($(INCREMENTAL_BUILDS),)
    LOCAL_PROGUARD_ENABLED := disabled
    LOCAL_JACK_ENABLED := incremental
    LOCAL_JACK_FLAGS := --multi-dex native
endif

include frameworks/base/packages/SettingsLib/common.mk
include frameworks/base/packages/SettingsLib/search/common.mk

include $(BUILD_PACKAGE)

# ====  prebuilt library  ========================
include $(CLEAR_VARS)

LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
    contextualcards:libs/contextualcards.aar
include $(BUILD_MULTI_PREBUILT)

# Use the following include to make our test apk.
ifeq (,$(ONE_SHOT_MAKEFILE))
include $(call all-makefiles-under,$(LOCAL_PATH))
endif

八梦染、參考資料

Android.mk | Android NDK | Android Developers (google.cn)
編譯_tanliyin的博客-CSDN博客
Android.mk 使用 環(huán)境 小結(jié)_快樂&&平凡-CSDN博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市朴皆,隨后出現(xiàn)的幾起案子帕识,更是在濱河造成了極大的恐慌,老刑警劉巖遂铡,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件渡冻,死亡現(xiàn)場離奇詭異,居然都是意外死亡忧便,警方通過查閱死者的電腦和手機(jī)族吻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門帽借,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人超歌,你說我怎么就攤上這事砍艾。” “怎么了巍举?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵脆荷,是天一觀的道長。 經(jīng)常有香客問我懊悯,道長蜓谋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任炭分,我火速辦了婚禮桃焕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘捧毛。我一直安慰自己观堂,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布呀忧。 她就那樣靜靜地躺著师痕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪而账。 梳的紋絲不亂的頭發(fā)上胰坟,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機(jī)與錄音泞辐,去河邊找鬼笔横。 笑死,一個胖子當(dāng)著我的面吹牛铛碑,可吹牛的內(nèi)容都是我干的狠裹。 我是一名探鬼主播虽界,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼汽烦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了莉御?” 一聲冷哼從身側(cè)響起撇吞,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎礁叔,沒想到半個月后牍颈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡琅关,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年煮岁,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡画机,死狀恐怖冶伞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情步氏,我是刑警寧澤响禽,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站荚醒,受9級特大地震影響芋类,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜界阁,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一侯繁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧铺董,春花似錦巫击、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至重付,卻和暖如春顷级,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背确垫。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工弓颈, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人删掀。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓翔冀,卻偏偏與公主長得像,于是被迫代替她去往敵國和親披泪。 傳聞我的和親對象是個殘疾皇子纤子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345

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