Autotools 工具

概述

GNU構建系統(tǒng),是利用腳本和make程序在特定的平臺上構建軟件的過程。一般過程是configure戈轿,make,make install 三部曲阵子。這種方式成為一種習慣思杯,被廣泛使用。
為了簡化可移植構建的難度挠进,早期有一套AutoTools的工具幫助程序員構建軟件色乾。configure,make领突,make install三部曲暖璧,大多都是基于Auto Tools來構建的。Auto Tools是GNU程序的標準構建系統(tǒng)君旦。


不同視角的程序構建

用戶視角

configure腳本是由軟件開發(fā)者維護并發(fā)布的給用戶使用的shell腳本澎办。該腳本的作用是檢測系統(tǒng)環(huán)境嘲碱,最終目的是生成Make file和configure.h。
make通過讀取Make file文件局蚀,開始構建軟件麦锯。
make install可以將軟件安裝到默認或者指定的系統(tǒng)路徑

作為用戶,我們就是通過上述三步將軟件安裝到我們系統(tǒng)中的


  • 在上圖中琅绅,開發(fā)者在分發(fā)源碼包時扶欣,除了源代碼中的頭文件(.h)和程序源文件(.c),還有許多支持軟件構建的文件和工具千扶。
  • 最重要的就是Makefile.in和config.h料祠。
  • configure腳本執(zhí)行時,將為每一個.in文件處理成對應的非.in文件澎羞,即生成:Makefile术陶,src/Makefile,config.h 煤痕。大部分情況下梧宫,只有Makefile和config.h。
  • Makefile用于被make程序識別并構建軟件摆碉,而config.h中定義的宏塘匣,有助于軟件通過預編譯來改變自身代碼,來適應目標平臺某些特殊性巷帝。
    有些軟件在configure階段忌卤,還可以生成其他文件,這完全取決于軟件本身楞泼。
configure

一般而言棍厂,configure主要檢查當前目標平臺的程序张漂,庫漠畜,頭文件躯喇,函數(shù)等的兼容性。這些結果將作用于config.h和Makefile文件的生成,從而影響最終的編譯屑宠。
用戶可以通過configure配置參數(shù),來定制需要包含或者不需要包含的組件嚣崭,安裝路徑等笨触。大概可以分為五組:

  • 安裝路徑相關
  • 程序名配置
  • 跨平臺編譯
  • 動靜態(tài)庫選項
  • 程序組件

configure在執(zhí)行過程中,除了生成Makefile外雹舀,還會生成芦劣,但是不限于以下文件:

  • config.log日志文件
  • config.cache緩存文件。提高下一次configure的速度说榆,-C指定
  • config.status實際調用編譯工具構建軟件的shell腳本

如果軟件通過libtool構建虚吟,還會生成libtool腳本寸认。

開發(fā)者視角

開發(fā)者除了編寫軟件本身的代碼外,還需要負責生成構建軟件所需要的文件和工具串慰。因此對于開發(fā)者而言偏塞,要么自己編寫構建用的腳本,要么選擇部分依賴工具邦鲫。Auto tools就是這樣的工具灸叼。

Autotools包括了autoconf和automake等命令

autoreconf

autoreconf程序能夠自動按照合理的順序調用autoconf,automake庆捺,aclocal程序


configure.ac

configure.ac用于生成configure腳本古今,autoconf工具用來完成這一步。

例如下列的例子

AC_PREREQ
AC_PREREQ([2.63]) 
AC_INIT([st], [1.0], [zhoupingtkbjb@163.com]) 
AC_CONFIG_SRCDIR([src/main.c]) 
AC_CONFIG_HEADERS([src/config.h]) 
AM_INIT_AUTOMAKE([foreign]) 
 # Checks for programs. 
AC_PROG_CC 
AC_PROG_LIBTOOL 
 # Checks for libraries.
# Checks for header files. 
 # Checks for typedefs, structures, and compiler characteristics. 
 # Checks for library functions.  
AC_CONFIG_FILES([Makefile 
          src/Makefile 
          src/a/Makefile 
           src/b/Makefile]) 
AC_OUTPUT 

其中以AC_開頭的類似函數(shù)調用一樣的代碼滔以,實際上時被稱為“宏”的調用捉腥。
這里的宏,與C語言中的宏概念類似你画,會被替換展開抵碟。
configure.ac文件的一般布局是:

  • AC_INIT
  • 測試程序
  • 測試函數(shù)庫
  • 測試頭文件
  • 測試類型定義
  • 測試結構
  • 測試編譯器特性
  • 測試庫函數(shù)
  • 測試系統(tǒng)調用
  • AC_OUTPUT

configure.ac標簽說明

標簽 說明
AC_PREREQ 聲明autoconf要求的版本號
AC_INIT 定義軟件名稱,版本號坏匪,聯(lián)系方式
AM_INIT_AUTOMAKE 必須要的拟逮,參數(shù)為軟件名和版本號
AC_CONFIG_SCRDIR 該宏用來偵測所指定的源碼文件是否存在,來確定源碼有效性剥槐。
AC_CONFIG_HEADER 該宏用來生成config.h文件唱歧,以便autoheader命令使用
AC_PROG_CC 指定編譯器,默認GCC
AC_CONFIG_FILE 生成相應的Makefile文件粒竖,不同目錄下通過空格分隔
AC_OUTPUT 用來設定configure所要產生的文件颅崩,如果是makefile,config會把它檢查出來的結果帶入makefile.in文件蕊苗,產生合適的makefile

m4是一個經典的宏工具沿后。autoconf正是構建在m4之上,可以理解為autoconf預先定義了大量的朽砰,用戶檢查系統(tǒng)可移植性的宏尖滚,這些宏在展開就是大量的shell腳本。

所以編寫configure.ac就需要對這些宏掌握熟練瞧柔,并且合理調用漆弄。

autoscan和configure.scan

可以通過調用autoscan命令,得到一個初始化的configure.scan文件造锅。然后重命名為configure.ac后撼唾,在此基礎上編輯configure.ac。
autoscan會掃描源碼哥蔚,并生成一些通用的宏調用倒谷,輸入的聲明蛛蒙,以及輸出的聲明。盡管autoscan十分方便渤愁,但是沒人能夠在構建之前牵祟,就把源碼完全寫好。
因此,autoscan通常用于初始化configure.ac抖格,即生成configure.ac的雛形文件configure.scan

autoheader和configure.h

autoheader命令掃描configure.ac文件诺苹,并確定如何生成config.h.in。每當configure.ac變化時他挎,都可以通過執(zhí)行autoheader更新config.h.in筝尾。
在configure.ac通過AC_CONFIG_HEADERS([config.h])告訴autoheader應當生成config.h.in的路徑
config.h包含了大量的宏定義捡需,其中包括軟件包的名字等信息办桨,程序可以直接使用這些宏。更重要的是站辉,程序可以根據(jù)其中的對目標平臺的可移植相關的宏呢撞,通過條件編譯,動態(tài)的調整編譯行為饰剥。

automake和Makefil.am

手工編寫Makefile是一件相當繁瑣的事情殊霞,并且隨著項目的復雜程序變大,編寫難度越來越大汰蓉。automake工具應運而生绷蹲。
可以編輯Makefile.am文件,并依靠automake來生成Makefile.in

aclocal

configure.ac實際是依靠宏展開來得到configure顾孽。因此祝钢,能否成功生成,取決于宏定義是否能夠找到若厚。
autoconf會從自身安裝路徑下尋找事先定義好的宏拦英。然而對于像automake,libtool测秸,gettex等第三方擴展宏疤估,autoconf便無從知曉。
因此霎冯,aclocal將在configure.ac同一個目錄下生成aclocal.m4铃拇,在掃描configure.ac過程中,將第三方擴展和開發(fā)者自己編寫的宏定義復制進去沈撞。
如此一來慷荔,autoconf遇到不認識的宏時,就會從aclocal.m4中查找

libtool

libtool試圖解決不同平臺下关串,庫文件的差異拧廊。libtool實際是一個shell腳本监徘,實際工作中,調用了目標平臺的cc編譯器和鏈接器吧碾,以及給予合適的命令行參數(shù)凰盔。
libtool可以單獨使用,也可以跟autotools集成使用倦春。

輔助文件

clocal.m4 該宏定義文件包含了第三方宏定義户敬,用于autoconf展開configure.ac
NEWS,README睁本,AUTHORS尿庐,ChangeLog GNU軟件標配
config.guess,config.sub 由automake產生呢堰,兩個用于目標平臺檢查的腳本
depcomp install-sh 由automake產生抄瑟,用于完成編譯和安裝的腳本
missing 由automake產生
ltmain.sh 由libtoolize產生,用于在configure階段枉疼,配置生成可運行于目標平臺的libtool腳本
ylwrap 由automake產生
autogen.sh 早期autoreconf并不存在皮假,軟件開發(fā)者就自己編寫腳本,按照順序調用autoconf骂维,autoheader惹资,automake等工具。這個文件就是這樣的腳本航闺。

makefile文件生成的基本流程

基本命令具體介紹

autoscan 命令

該命令主要用來生成初步configure.in
該命令參數(shù)

 -h, --help
              print this help, then exit

       -V, --version
              print version number, then exit

       -v, --verbose
              verbosely report processing

       -d, --debug
              don't remove temporary files

   Library directories:
       -B, --prepend-include=DIR
              prepend directory DIR to search path

       -I, --include=DIR
              append directory DIR to search path

通過autoscan 生成的文件是autoscan.log configure.scan
這里我們只編譯一個main.c,我們看看configure.scan 文件

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([main.c])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.
AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_OUTPUT
AC_INIT
Macro: AC_INIT (package, version, [bug-report], [tarname], [url])

這個宏定義至少要有兩個參數(shù) package 褪测,和version
bug-report ,tarname潦刃,url是可選參數(shù)

AC_PACKAGE_NAME, PACKAGE_NAME
      Exactly package. 
AC_PACKAGE_TARNAME, PACKAGE_TARNAME
    Exactly tarname, possibly generated from package. 
AC_PACKAGE_VERSION, PACKAGE_VERSION
    Exactly version. 
AC_PACKAGE_STRING, PACKAGE_STRING
    Exactly ‘package version’. 
AC_PACKAGE_BUGREPORT, PACKAGE_BUGREPORT
    Exactly bug-report, if one was provided. Typically an email address, or URL to a bug management web page. 
AC_PACKAGE_URL, PACKAGE_URL
  Exactly url, if one was provided. If url was empty, but package begins with ‘GNU ’, then this defaults to ‘http://www.gnu.org/software/tarname/’, otherwise, no URL is assumed.
AC_PREREQ

配置版本
這個宏用于宏AC_INIT 之前

舉例
AC_PREREQ([2.69])

AC_COPYRIGHT 和 AC_REVISION

該兩個宏定義是可選的侮措,用來管理配置腳本的版本號

For example, this line in configure.ac:
          AC_REVISION([$Revision: 1.30 $])
produces this in configure:
          #!/bin/sh
          # From configure.ac Revision: 1.30
AC_CONFIG_SRCDIR
Macro: AC_CONFIG_SRCDIR (unique-file-in-source-dir)

配置文件入口

AC_OUTPUT

該宏定義沒有參數(shù)在.ac文件的末尾。

AM_INIT_AUTOMAKE([OPTIONS])

Runs many macros required for proper operation of the generated Makefiles.

Today, AM_INIT_AUTOMAKE is called with a single argument: a space-separated list of Automake options that should be applied to every <samp>Makefile.am</samp> in the tree. The effect is as if each option were listed in AUTOMAKE_OPTIONS (see Options).

This macro can also be called in another, deprecated form: AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]). In this form, there are two required arguments: the package and the version number. This usage is mostly obsolete because the <var style="font-style: italic; font-weight: inherit;">package</var> and <var style="font-style: italic; font-weight: inherit;">version</var> can be obtained from Autoconf’s AC_INIT macro. However, differently from what happens for AC_INIT invocations, this AM_INIT_AUTOMAKE invocation supports shell variables’ expansions in the PACKAGE and VERSION arguments (which otherwise defaults, respectively, to the PACKAGE_TARNAME and PACKAGE_VERSION defined via the AC_INIT invocation; see The AC_INIT macro in <cite style="font-style: inherit; font-weight: inherit;">The Autoconf Manual</cite>); and this can be still be useful in some selected situations. Our hope is that future Autoconf versions will improve their support for package versions defined dynamically at configure runtime; when (and if) this happens, support for the two-args AM_INIT_AUTOMAKE invocation will likely be removed from Automake.

If your configure.ac has:

AC_INIT([src/foo.c])
AM_INIT_AUTOMAKE([mumble], [1.5])
you should modernize it as follows:

AC_INIT([mumble], [1.5])
AC_CONFIG_SRCDIR([src/foo.c])
AM_INIT_AUTOMAKE

文件生成

我們從開發(fā)者角度的圖例來看福铅,我們需要的文件有configure.ac 萝毛,Makefile.am ,aclocal.m4
而作為用戶滑黔,我們需要的文件是 makefile.in config.h.in 文件

因此這里我們看看每個文件是如何生成的

  • configure.ac
  • Makefile.am
  • aclocal.m4
  • makefile.in
  • config.h.in

準備工作

我們暫時就準備一個main.c printC.h printC.c 文件
main.c 的內容是

#include <stdio.h>
#include "printC.h"
int main(int argc, const char * argv[]) {
    fputs("nihao\n", stderr);
    printCFuncition();
    return 0;
}

同目錄下笆包,還有printC.h 和printC.m 文件,printC.h

#ifndef printC_h
#define printC_h

#include <stdio.h>
void printCFuncition(void);

#endif /* printC_h */

printC.c


#include "printC.h"


void printCFuncition(void){
    fputs("printC.c/n", stderr);
}

打開終端進入到該目錄下

$ls
main.c printC.h printC.c

configure.ac

該文件生成是通過 autoscan 命令生成的 略荡,具體如下
在中斷命令輸入autoscan 命令

$ autoscan && ls
autoscan.log    configure.scan  main.c      printC.c    printC.h

然后重新命名 configure.scan 文件

$ mv configure.scan configure.ac && ls
autoscan.log    configure.ac    main.c      printC.c    printC.h

我們獲取到了configure.ac 文件了庵佣。

這里我們還是需要修改下configure.ac 內容,為以后生成makefile文件做準備
我們在AC_INIT 下面添加macro AM_INIT_AUTOMAKE汛兜。
在 AC_CONFIG_HEADERS 行下面添加mocro AC_CONFIG_FILES([Makefile])
見下圖


Makefile.am

該文件是我們手動需要創(chuàng)建的文件
文件內容是

AUTOMAKE_OPTIONS=foreign
bin_PROGRAMS=maket
maket_SOURCES=main.c  printC.h printC.c

maket 就是未來生成的程序名稱
maket_SOURCES 是該名稱所使用的源文件

假設我們工程里面有很多文件巴粪,那么我們手動寫文件很容易遺漏,因此,建議最好自己寫個shell腳本自動生成該文件肛根。不是很復雜

aclocal.m4

aclocal.m4 文件是我們通過aclocal 命令生成的

$ aclocal && ls
Makefile.am autom4te.cache  configure.ac
aclocal.m4  autoscan.log    main.c printC.h printC.m

到這里辫塌,我們開發(fā)者需要的文件都已經生成。我們可以通過命令生成 configure ,config.h.in Makefile.in 文件了,這些文件是用戶需要的文件派哲。生成過程如下

config.h.in

config.h.in 文件是通過autoheader 命令生成的

$ autoheader && ls
Makefile.am autom4te.cache  config.h.in main.c      printC.h
aclocal.m4  autoscan.log    configure.ac    printC.c

makefile.in

makefile.in 文件是通過automake命令生成的

$ automake --add-missing && ls

Makefile.am autom4te.cache  config.h.in install-sh  printC.c
Makefile.in autoscan.log    configure.ac    main.c      printC.h
aclocal.m4  compile     depcomp     missing

這里我們發(fā)現(xiàn)生成了makefile.in 文件了

configure

這里我們通過autoconf 命令生成 configure文件

autoconf && ls
Makefile.am autom4te.cache  config.h.in depcomp     missing
Makefile.in autoscan.log    configure   install-sh  printC.c
aclocal.m4  compile     configure.ac    main.c      printC.h

makefile

makefile 文件是通過 configure 來生成的

$ ./configure && ls
Makefile    autom4te.cache  config.h.in configure.ac    missing
Makefile.am autoscan.log    config.log  depcomp     printC.c
Makefile.in compile     config.status   install-sh  printC.h
aclocal.m4  config.h    configure   main.c      stamp-h1

make

使用make 命令生成最終的包

$make && ls
Makefile    autoscan.log    config.status   main.c      printC.h
Makefile.am compile     configure   main.o      printC.o
Makefile.in config.h    configure.ac    maket       stamp-h1
aclocal.m4  config.h.in depcomp     missing
autom4te.cache  config.log  install-sh  printC.c

運行 maket 包

$./maket
nihao
printC.c

文件依賴和命令之間的依賴關系

完全沒有依賴的文件是

Makefile.am 該文件是自己手動生成的
configure.ac 該文件是通過autoscan 命令生成

aclocal 命令依賴文件

configure.ac 通過該命令和依賴文件我們可以生成aclocal.m4 文件臼氨。該文件是autoconf autoheader 和automake命令依賴文件,因此芭届,執(zhí)行上述三個命令前要執(zhí)行aclocal文件生成aclocal.m4 文件

autoconf命令依賴文件

configure.ac
aclocal.m4
有兩個文件我們執(zhí)行autoconf 命令储矩,生成configure文件

autoheader 命令依賴文件

configure.ac
aclocal.m4
這兩個文件通過autoheader 命令生成config.h.in 文件

automake 命令依賴文件

Makefile.am
通過該命令我們能生成 Makefile.in文件

./configure 腳本依賴文件

Makefile.in
config.h.in
通過該命令我們就能生產所需要的Makefile文件了

make 命令依賴文件

makefile文件
通過 make命名使用makefile文件,生成最終的可執(zhí)行文件

automake 支持的文件結構

automake支持三種文件夾層次:flat褂乍、shallow和deep持隧。

  • flat(平),指的是全部文件都位于同一個文件夾中
    就是全部源文件逃片、頭文件以及其它庫文件都位于當前文件夾中屡拨,且沒有子文件夾。上述實例就是這樣的

  • shallow(淺)题诵,指的是基本的源碼都儲存在頂層文件夾洁仗,其它各個部分則儲存在子文件夾中
    就是主要源文件在當前文件夾中层皱,而其他一些實現(xiàn)各部分功能的源文件位于各自不同的文件夾性锭。automake本身就是這一類。

  • deep(深)叫胖,指的是全部源碼都被儲存在子文件夾中草冈;頂層文件夾主要包括配置信息

不管對于上述那種方式,最簡單的方式如下

假設目錄結構如下


image.png

這里我們只需要修改下Makeflile.am文件就可以了

以前的makefile.am 文件

AUTOMAKE_OPTIONS=foreign
bin_PROGRAMS=maket
maket_SOURCES=main.c  printC.h printC.c

修改成如下就可以了

AUTOMAKE_OPTIONS=foreign
bin_PROGRAMS=maket
maket_SOURCES=main.c  printC.h printC.c deepfile/deepPrint.h deepfile/deepPrint.c

其他操作命令不變瓮增。

多個Makefile.am文件共同作用

格式模板

對于可執(zhí)行文件和靜態(tài)庫類型怎棱,如果只想編譯,不想安裝到系統(tǒng)中绷跑,可以用noinst_PROGRAMS代替bin_PROGRAMS拳恋,noinst_LIBRARIES代替lib_LIBRARIES。

Makefile.am還提供了一些全局變量供所有的目標體使用:

image.png

在Makefile.am中盡量使用相對路徑砸捏,系統(tǒng)預定義了兩個基本路徑:

image.png

automake設置了默認的安裝路徑:

  • 標準安裝路徑 默認安裝路徑為:(prefix) = /usr/local谬运,可以通過./configure –prefix=的方法來覆蓋。 其它的預定義目錄還包括:bindir =(prefix)/bin, libdir = (prefix)/lib, datadir = +(prefix)/share, sysconfdir = (prefix)/etc等等垦藏。 定義一個新的安裝路徑 比如test, 可定義testdir =(prefix)/test, 然后test_DATA =test1 test2梆暖,則test1,test2會作為數(shù)據(jù)文件安裝到$(prefix)/ /test目錄下掂骏。

clang 編譯make
深層路徑

deep automake
automake
參考文章

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末轰驳,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌级解,老刑警劉巖冒黑,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異勤哗,居然都是意外死亡薛闪,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門俺陋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來豁延,“玉大人,你說我怎么就攤上這事腊状∮沼剑” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵缴挖,是天一觀的道長袋狞。 經常有香客問我,道長映屋,這世上最難降的妖魔是什么苟鸯? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮棚点,結果婚禮上早处,老公的妹妹穿的比我還像新娘。我一直安慰自己瘫析,他們只是感情好砌梆,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著贬循,像睡著了一般咸包。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上杖虾,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天烂瘫,我揣著相機與錄音,去河邊找鬼奇适。 笑死坟比,一個胖子當著我的面吹牛,可吹牛的內容都是我干的滤愕。 我是一名探鬼主播温算,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼间影!你這毒婦竟也來了注竿?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎巩割,沒想到半個月后裙顽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡宣谈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年愈犹,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片闻丑。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡漩怎,死狀恐怖,靈堂內的尸體忽然破棺而出嗦嗡,到底是詐尸還是另有隱情勋锤,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布侥祭,位于F島的核電站叁执,受9級特大地震影響,放射性物質發(fā)生泄漏矮冬。R本人自食惡果不足惜谈宛,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望胎署。 院中可真熱鬧吆录,春花似錦、人聲如沸硝拧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽障陶。三九已至,卻和暖如春聊训,著一層夾襖步出監(jiān)牢的瞬間抱究,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工带斑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鼓寺,地道東北人。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓勋磕,卻偏偏與公主長得像妈候,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子挂滓,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內容