ROS下的CMakeList.txt編寫(xiě)

一、 概述

CMake構(gòu)建系統(tǒng)通過(guò)ROS包中的CMakeList.txt來(lái)構(gòu)建軟件包。互相依賴(lài)的包都包含一個(gè)或者多個(gè)CMakeList.txt來(lái)描述如何編譯代碼和如何安裝产雹。在catkin 項(xiàng)目中,CMakeList.txt 符合標(biāo)準(zhǔn)的vanilla CMakeList.txt 格式翁锡,但稍微有點(diǎn)不同蔓挖。

二、 整體結(jié)構(gòu)和命令一覽

在編寫(xiě)CMakeLists.txt時(shí)必須遵循特定的格式馆衔,否則軟件包將無(wú)法正確構(gòu)建和編譯瘟判。一個(gè)完整的ROS下CMakeList.txt由下面內(nèi)容組成

  1. 所需CMake版本(cmake_minimum_required)
  2. 軟件包名稱(chēng)(project())
  3. 查找構(gòu)建所需的其他CMake / Catkin軟件包(find_package())
  4. 啟用Python模塊支持(catkin_python_setup())
  5. 消息/服務(wù)/動(dòng)作生成器(add_message_files(),add_service_files()角溃,add_action_files())
  6. 生成消息/服務(wù)/動(dòng)作等自定義消息(generate_messages())
  7. 指定包的構(gòu)建信息輸出(catkin_package())
  8. 要建立的庫(kù)/可執(zhí)行文件(add_library()/ add_executable()/ target_link_libraries())
  9. 測(cè)試(catkin_add_gtest())
  10. 安裝規(guī)則(install())

三拷获、 CMake版本

CMakeLists.txt文件必須以CMake的版本開(kāi)頭。下面表示的是Catkin需要2.8.3或更高的版本减细。

cmake_minimum_required(VERSION 2.8.3)

四匆瓜、 軟件包名稱(chēng)

繼而需要指定CMake工程名,一般取作包名。例如我們的項(xiàng)目名叫做robot_brain

project(robot_brain)

而在CMake中陕壹,可以在CMake文本中使用變量${PROJECT_NAME}來(lái)引用項(xiàng)目名稱(chēng)。

五树埠、 查找相關(guān)的CMake包

接下來(lái)我們要用find_package指令來(lái)指定在構(gòu)建項(xiàng)目過(guò)程中依賴(lài)了哪些其他的包糠馆,在ROS中,catkin必備依賴(lài),所以雷打不打地我們寫(xiě)上catkin REQUIRED

find_package(catkin REQUIRED)

在此基礎(chǔ)上怎憋,如果我們還需要依賴(lài)其他包(或者組件)又碌,我們就在 上述的包后面繼續(xù)添加包(組件)名即可:

find_package(catkin REQUIRED COMPONENTS nodelet)

或者可以寫(xiě)成

find_package(catkin REQUIRED)
find_package(nodelet REQUIRED)

值得注意一點(diǎn)的是:這里添加的包用于構(gòu)建包使用,而不是添加運(yùn)行時(shí)依賴(lài)項(xiàng)绊袋。

你也可以做:

find_package(catkin REQUIRED)
find_package(nodelet REQUIRED)

如何寫(xiě)毕匀,看個(gè)人習(xí)慣吧,如果不考慮篇幅癌别,其實(shí)我更喜歡把所有包(組件)列成一列皂岔,直觀。在普通的CMakeLists.txt中是沒(méi)有find_package()的展姐,那么躁垛,catkin中的這個(gè)語(yǔ)句有啥作用呢?

5.1 那find_package()作何用圾笨?

如果CMake通過(guò)find_package找到一個(gè)包教馆,則會(huì)自動(dòng)生成有關(guān)包所在路徑的CMake環(huán)境變量,環(huán)境變量描述了包中頭文件的位置擂达,源文件的位置土铺,包所依賴(lài)的庫(kù)以及這些庫(kù)的路徑。
這些變量名稱(chēng)以< PACKAGE NAME >_< PROPERTY >的形式出現(xiàn):
- < NAME >_FOUND - 如果找到庫(kù)板鬓,則設(shè)置為true悲敷,否則為false
- < NAME > _INCLUDE_DIRS或<NAME> _INCLUDES - 包導(dǎo)出的包含路徑
- < NAME > _LIBRARIES或<NAME> _LIBS - 由包導(dǎo)出的庫(kù)
- < NAME > _DEFINITIONS -
- ...

5.2為啥Catkin包是組件形式穗熬?

實(shí)際上镀迂,Catkin的包并不是catkin的真正組成部分。而catkin采用CMake的組件功能唤蔗,主要是為了節(jié)省打字時(shí)間探遵。
將Catkin的包作為一種組件看待是很有好處的,當(dāng)你找到包的時(shí)候妓柜,各種以catkin為前綴的添加到CMakeLists.txt中了箱季。以前述nodelet包為例:

find_package(catkin REQUIRED COMPONENTS nodelet)

catkin執(zhí)行到這個(gè)語(yǔ)句時(shí),就會(huì)導(dǎo)出的nodelet的include路徑棍掐,庫(kù)等也添加到catkin前綴的變量中藏雏。例如,catkin_INCLUDE_DIRS不僅包含catkin的include路徑作煌,還包含了nodelet掘殴,這在后面會(huì)用到赚瘦。
當(dāng)然,我們可以只選擇找nodelet的:

find_package(nodelet)

很可惜這樣的做法會(huì)令nodelet路徑奏寨,庫(kù)等不會(huì)被添加到catkin變量中起意,從而生成了例如nodelet_INCLUDE_DIRS,nodelet_LIBRARIES這樣的變量等病瞳。

5.3Boost庫(kù)

如果使用C ++和Boost揽咕,則需要用find_package()來(lái)找Boost庫(kù),并指定Boost中的組件套菜。 舉個(gè)栗子亲善,如果想使用Boost線(xiàn)程,就可以寫(xiě)成:

find_package(Boost REQUIRED COMPONENTS thread)

六逗柴、catkin_package()

catkin_package()是一個(gè)catkin提供的CMake宏蛹头,用于將catkin特定的信息信息輸出到構(gòu)建系統(tǒng)上,用于生成pkg配置文件以及CMake文件嚎于。

這個(gè)命令必須在add_library()或者add_executable()之前調(diào)用掘而,該函數(shù)有5個(gè)可選參數(shù):

  • INCLUDE_DIRS - 導(dǎo)出包的include路徑
  • LIBRARIES - 導(dǎo)出項(xiàng)目中的庫(kù)
  • CATKIN_DEPENDS - 該項(xiàng)目依賴(lài)的其他catkin項(xiàng)目
  • DEPENDS - 該項(xiàng)目所依賴(lài)的非catkin CMake項(xiàng)目。
  • CFG_EXTRAS - 其他配置選項(xiàng)

舉個(gè)栗子:

catkin_package(
   INCLUDE_DIRS include
   LIBRARIES ${PROJECT_NAME}
   CATKIN_DEPENDS roscpp nodelet
   DEPENDS eigen opencv)

這表示包文件夾中的文件夾“include”是導(dǎo)出頭文件的地方于购。 ${PROJECT_NAME}根據(jù)project中的內(nèi)容生成袍睡,此處是rrobot_brain±呱“roscpp”+“nodelet”是用來(lái)構(gòu)建/運(yùn)行此程序包的catkin包斑胜,而“eigen”+“opencv”是用于構(gòu)建/運(yùn)行此程序包的非catkin包。

七嫌吠、指定構(gòu)建目標(biāo)

構(gòu)建目標(biāo)可以有多種形式止潘,但通常主要有以下兩種:

  • 執(zhí)行文件目標(biāo) - 可以運(yùn)行的程序
  • 庫(kù)目標(biāo) - 可在構(gòu)建和/或運(yùn)行時(shí)給可執(zhí)行目標(biāo)使用的庫(kù)

7.1目標(biāo)命名

值得重點(diǎn)關(guān)注的是,catkin中的構(gòu)建目標(biāo)的名稱(chēng)必須是唯一的辫诅,但是凭戴,但構(gòu)建目標(biāo)命名的唯一性只能在CMake內(nèi)部進(jìn)行】话可以使用set_target_properties()函數(shù)將目標(biāo)重命名為其他目標(biāo):
再舉個(gè)栗子:

set_target_properties(rviz_image_view
                      PROPERTIES OUTPUT_NAME image_view
                      PREFIX "")

這時(shí)就將rviz_image_view的名稱(chēng)更改為image_view了么夫。

7.2自定義輸出目錄

一般情況下,令輸出目標(biāo)目錄保持默認(rèn)就可以了肤视,但有時(shí)遇到一些特定情況就得因地制宜档痪。再再舉個(gè)栗子,一個(gè)包含了Python bindings的庫(kù)必須防止在不同的文件夾邢滑,才能夠被導(dǎo)入Python中腐螟,因此可以通過(guò)下述方式進(jìn)行:

set_target_properties(python_module_library
  PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION})

7.3包含路徑和庫(kù)路徑

在生成目標(biāo)之前,請(qǐng)記得先寫(xiě)好包含路徑和庫(kù)路徑,不然編譯會(huì)失敗乐纸。

  • 包括路徑 - 頭文件
  • 庫(kù)路徑 - 構(gòu)建對(duì)象需要用到的庫(kù)
include_directories(<dir1>衬廷,<dir2>,...汽绢,<dirN>)
link_directories(<dir1>泵督,<dir2>,...庶喜,<dirN>)

7.3.1 include_directories()

include_directories()中的參數(shù)應(yīng)該是調(diào)用find_package調(diào)用時(shí)生成的* _INCLUDE_DIRS變量。 如果使用catkin和Boost救鲤,那么include_directories()調(diào)用應(yīng)該如下所示:

include_directories(include ${Boost_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS})

第一個(gè)參數(shù)“include”表示包中的include /目錄也是路徑的一部分久窟。

7.3.2 link_directories()

link_directories()函數(shù)可用于添加額外的庫(kù)路徑,但通常不推薦這樣做本缠,因?yàn)?所有catkin和CMake軟件包在find_packaged時(shí)都會(huì)自動(dòng)添加鏈接信息斥扛。 只需寫(xiě)target_link_libraries()中就可以了。但真要寫(xiě)丹锹,就按照下面那樣來(lái)寫(xiě):

link_directories(~/my_libs)

7.4 可執(zhí)行目標(biāo)

要指定必須構(gòu)建的可執(zhí)行目標(biāo)稀颁,我們必須使用add_executable()CMake函數(shù)。

add_executable(myProgram 
                src/main.cpp 
                src/some_file.cpp)

構(gòu)建myProgram的目標(biāo)可執(zhí)行文件楣黍,3個(gè)源文件構(gòu)建:src / main.cpp匾灶,src / some_file.cpp和src / another_file.cpp。

7.5 庫(kù)目標(biāo)

add_library() 用于指定要構(gòu)建的庫(kù)租漂。

add_library(${PROJECT_NAME} ${${PROJECT_NAME}_SRCS})

7.6 target_link_libraries()

target_link_libraries()來(lái)指定可執(zhí)行目標(biāo)鏈接的庫(kù)阶女。 通常在add_executable()調(diào)用之后完成。 如果找不到ros哩治,則添加$ {catkin_LIBRARIES}秃踩。

target_link_libraries(<executableTargetName>, <lib1>, <lib2>, ... <libN>)
add_executable(foo src/foo.cpp)
add_library(moo src/moo.cpp)
target_link_libraries(foo moo)  -- This links foo against libmoo.so

請(qǐng)注意,在大多數(shù)情況中不需要使用link_directories()业筏,因?yàn)閒ind_package()自動(dòng)拉入憔杨。

八、消息蒜胖、服務(wù)和響應(yīng)

消息(.msg)消别,服務(wù)(.srv)和響應(yīng)(.action)文件在ROS包構(gòu)建和使用之前需要一個(gè)特殊的預(yù)處理器構(gòu)建步驟。 這些宏的要點(diǎn)是生成編程語(yǔ)言特定的文件翠勉,以便可以利用其選擇的編程語(yǔ)言中的消息妖啥,服務(wù)和動(dòng)作。 構(gòu)建系統(tǒng)將使用生成器(例如gencpp对碌,genpy荆虱,genlisp等)生成綁定。

提供了三個(gè)宏來(lái)分別處理消息,服務(wù)和響應(yīng):

  • add_message_files
  • add_service_files
  • add_action_files

而在之后必須在下面寫(xiě)下面宏怀读,catkin時(shí)候會(huì)在devel的include文件夾中生成對(duì)應(yīng)的頭文件:

generate_messages()

8.1 使用條件

為了能夠正常生成相應(yīng)的文件诉位,這些宏必須在catkin_package()宏之前,

find_package(catkin REQUIRED COMPONENTS ...)
 add_message_files(...)
 add_service_files(...)
 add_action_files(...)
 generate_messages(...)
 catkin_package(...)`

在catkin_package()宏中寫(xiě)上CATKIN_DEPENDS message_runtime

catkin_package(
 ...
 CATKIN_DEPENDS message_runtime ...
 ...)

并且在find_package()寫(xiě)上message_generation組件:

find_package(catkin REQUIRED COMPONENTS message_generation)

package.xml文件中加上

    <build_depend>message_generation</build_depend>
    <run_depend>message_runtime</run_depend>

如果構(gòu)建的對(duì)象依賴(lài)于其他需要構(gòu)建消息/服務(wù)/響應(yīng)的構(gòu)建對(duì)象菜枷,則需要向目標(biāo)catkin_EXPORTED_TARGETS添加明確的依賴(lài)關(guān)系苍糠,以便它們以正確的順序構(gòu)建。 這種情況比較常用啤誊,除非您的包真的不使用ROS的任何部分岳瞭。 但這種依賴(lài)關(guān)系不能自動(dòng)傳遞。 (some_target是由add_executable()設(shè)置的目標(biāo)的名稱(chēng)):

 add_dependencies(some_target${catkin_EXPORTED_TARGETS})

如果需要構(gòu)建消息或服務(wù)的包以及使用這些消息和/或服務(wù)的可執(zhí)行文件蚊锹,則需要為自動(dòng)生成的消息目標(biāo)創(chuàng)建明確的依賴(lài)關(guān)系瞳筏,以便以正確的順序構(gòu)建它們。 (some_target是由add_executable()設(shè)置的目標(biāo)的名稱(chēng)):

add_dependencies(some_target ${${PROJECT_NAME}_EXPORTED_TARGETS})

如果您的catkin包滿(mǎn)足上述兩個(gè)條件牡昆,則需要添加以下兩個(gè)依賴(lài)關(guān)系姚炕,即:

add_dependencies(some_target ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

8.2 例子

現(xiàn)在有兩個(gè)依賴(lài)于std_msgssensor_msgs的消息MyMessage1.msgMyMessage2.msg,還有一個(gè)自定義服務(wù)MyService.srv丢烘, message_program是使用這些消息和服務(wù)的指令柱宦,以及生成不使用自定義消息、服務(wù)的程序do_not_use_local_messages_programcatkin包播瞳,那么CMakeLists.txt應(yīng)該寫(xiě)成:

# 構(gòu)建時(shí)依賴(lài)項(xiàng)
find_package(catkin REQUIRED COMPONENTS          
             message_generation 
             std_msgs 

# 聲明要構(gòu)建哪些消息
add_message_files(FILES
                  MyMessage1.msg
                  MyMessage2.msg)
                  
# 聲明構(gòu)建哪些服務(wù)
add_service_files(FILES
                  MyService.srv)

# 聲明生成上述消息掸刊、服務(wù)需要依賴(lài)的消息以及服務(wù)
generate_messages(DEPENDENCIES 
                    std_msgs 
                    sensor_msgs)

# 聲明運(yùn)行時(shí)依賴(lài)項(xiàng)
catkin_package(CATKIN_DEPENDS 
                message_runtime 
                std_msgs sensor_msgs)

# 聲明構(gòu)建生成的可執(zhí)行文件名稱(chēng)以及依賴(lài)項(xiàng)
add_executable(message_program src/main.cpp)
add_dependencies(message_program ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

# 聲明構(gòu)建不需要使用自定義消息、服務(wù)的可執(zhí)行文件
add_executable(does_not_use_local_messages_program src/main.cpp)
add_dependencies(does_not_use_local_messages_program ${catkin_EXPORTED_TARGETS})

如果要構(gòu)建響應(yīng)赢乓,則在包中“action”目錄中創(chuàng)建有一個(gè)名為“MyAction.action”的文件痒给,則必須將actionlib_msgs添加到使用catkin進(jìn)行find_package的組件列表中,然后在CMakeList.txt中加上下面兩行:

add_action_files(FILES
                 MyAction.action)

此外骏全,該包必須具有對(duì)actionlib_msgs的構(gòu)建依賴(lài)苍柏。

九、啟用Python模塊支持

如果catkin包使用一些Python模塊姜贡,您應(yīng)該創(chuàng)建一個(gè)setup.py文件试吁,并在調(diào)用catkin_python_setup()之后調(diào)用generate_messages()和catkin_package()。

十楼咳、單位測(cè)試

有一個(gè)catkin-specific宏用于處理名為catkin_add_gtest()的基于gtest的單元測(cè)試熄捍。

catkin_add_gtest(myUnitTest test / utest.cpp)

十一、可選步驟:指定可安裝的目標(biāo)

構(gòu)建后母怜,構(gòu)建目標(biāo)通常被放置在catkin工作區(qū)中余耽。但有時(shí)候我們希望將目標(biāo)安裝到系統(tǒng)其他地方(有關(guān)安裝路徑的信息可以在REP 122中找到),以便其他人或本地文件夾可以使用它們來(lái)測(cè)試苹熏。換句話(huà)說(shuō)碟贾,如果你想要做一個(gè)“make install”的代碼币喧,你需要指定目標(biāo)應(yīng)該生成到哪里。
這是使用CMake install()函數(shù)作為參數(shù)完成的:

目標(biāo) - 目標(biāo)是安裝
ARCHIVE DESTINATION - 靜態(tài)庫(kù)和DLL(Windows).lib存根
LIBRARY DESTINATION - 非DLL共享庫(kù)和模塊
RUNTIME DESTINATION - 可執(zhí)行目標(biāo)和DLL(Windows)樣式共享庫(kù)

舉個(gè)栗子:

install(TARGETS ${PROJECT_NAME}
  ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
  LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
  RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

除了這些標(biāo)準(zhǔn)目標(biāo)袱耽,一些文件必須安裝到特殊文件夾杀餐。即一個(gè)包含Python綁定的庫(kù)必須安裝到不同的文件夾中才能在Python中導(dǎo)入:

install(TARGETS python_module_library
  ARCHIVE DESTINATION ${CATKIN_PACKAGE_PYTHON_DESTINATION}
  LIBRARY DESTINATION ${CATKIN_PACKAGE_PYTHON_DESTINATION}
)

11.1 安裝Python可執(zhí)行腳本

對(duì)于Python代碼,安裝規(guī)則看起來(lái)是不同的朱巨,因?yàn)闆](méi)有使用add_library()和add_executable()函數(shù)史翘,以便CMake確定哪些文件是目標(biāo)以及它們是什么類(lèi)型的目標(biāo)。 而是在您的CMakeLists.txt文件中使用以下內(nèi)容:

catkin_install_python(PROGRAMS scripts/myscript
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})

有關(guān)安裝python腳本和模塊的詳細(xì)信息以及文件夾布局的最佳做法冀续,請(qǐng)參見(jiàn)catkin手冊(cè)琼讽。

如果您只安裝Python腳本并且不提供任何模塊,則不需要?jiǎng)?chuàng)建上述setup.py文件洪唐,也不需要調(diào)用catkin_python_setup()跨琳。

11.2 安裝頭文件

標(biāo)題文件也必須安裝到“include”文件夾中,這通常是通過(guò)安裝整個(gè)文件夾的文件來(lái)完成的(可選地桐罕,按文件名模式過(guò)濾,不包括SVN子文件夾)桂敛。 這可以通過(guò)如下所示的安裝規(guī)則完成:

install(DIRECTORY include/{PROJECT_NAME}/ DESTINATION{CATKIN_PACKAGE_INCLUDE_DESTINATION}
PATTERN ".svn" EXCLUDE
)
或者如果包含的子文件夾與包名稱(chēng)不匹配:
install(DIRECTORY include/
DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION}
PATTERN ".svn" EXCLUDE
)

11.3 安裝roslaunch文件或其他資源

其他資源(如啟動(dòng)文件)可以安裝到

$ {CATKIN_PACKAGE_SHARE_DESTINATION
install(DIRECTORY launch/
  DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
  PATTERN ".svn" EXCLUDE)

參考文章:
1.ROS中的CMakeLists.txt
2.catkinCMakeLists.txt

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末功炮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子术唬,更是在濱河造成了極大的恐慌薪伏,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粗仓,死亡現(xiàn)場(chǎng)離奇詭異嫁怀,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)借浊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)塘淑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人蚂斤,你說(shuō)我怎么就攤上這事存捺。” “怎么了曙蒸?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵捌治,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我纽窟,道長(zhǎng)肖油,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任臂港,我火速辦了婚禮森枪,結(jié)果婚禮上视搏,老公的妹妹穿的比我還像新娘。我一直安慰自己疲恢,他們只是感情好凶朗,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著显拳,像睡著了一般棚愤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上杂数,一...
    開(kāi)封第一講書(shū)人閱讀 51,521評(píng)論 1 304
  • 那天宛畦,我揣著相機(jī)與錄音,去河邊找鬼揍移。 笑死次和,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的那伐。 我是一名探鬼主播踏施,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼罕邀!你這毒婦竟也來(lái)了畅形?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤诉探,失蹤者是張志新(化名)和其女友劉穎日熬,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體肾胯,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡竖席,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了敬肚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毕荐。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖艳馒,靈堂內(nèi)的尸體忽然破棺而出东跪,到底是詐尸還是另有隱情,我是刑警寧澤鹰溜,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布虽填,位于F島的核電站,受9級(jí)特大地震影響曹动,放射性物質(zhì)發(fā)生泄漏斋日。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一墓陈、第九天 我趴在偏房一處隱蔽的房頂上張望恶守。 院中可真熱鬧第献,春花似錦、人聲如沸兔港。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)衫樊。三九已至飒赃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間科侈,已是汗流浹背载佳。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留臀栈,地道東北人蔫慧。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像权薯,于是被迫代替她去往敵國(guó)和親姑躲。 傳聞我的和親對(duì)象是個(gè)殘疾皇子吕嘀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

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