xmake v2.2.5, 更加完善的 C/C++包依赖管理,有玩 C/C++的同学快进来。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
waruqi
V2EX    程序员

xmake v2.2.5, 更加完善的 C/C++包依赖管理,有玩 C/C++的同学快进来。

  •  2
     
  •   waruqi
    waruqi 2019-04-02 07:39:26 +08:00 2664 次点击
    这是一个创建于 2384 天前的主题,其中的信息可能已经有所发展或是发生改变。

    此版本耗时四个多月,对包依赖管理进行了重构改进,官方仓库新增了 mysql,ffmpeg 等常用依赖包,并且新增了大量新特性。

    最近我打算对 xmake 的包仓库xmake-repo扩充一些常用的 C/C++包。

    大家有哪些经常使用到的包,都可以提到 https://github.com/xmake-io/xmake-repo/issues/10 里面去,或者在 V2EX 下留言,我之后会优先入库进去,提供给用户快速集成和使用依赖包。

    关于新特性的详细说明见文章下文。

    第三方包管理器支持

    新版本对内置的包管理进行了重构,已经支持的非常完善了,我们可以通过

    add_requires("libuv master", "ffmpeg", "zlib 1.20.*")` 

    方便的安装使用依赖包,但是官方的包仓库xmake-repo目前收录的包还非常少,因此为了扩充 xmake 的包仓库, xmake 新增了对第三方包管理器的内置支持,通过包命名空间显式指定其他包管理器中的包,目前支持对conan::brew::vcpkg::包管理中的包进行安装。

    安装 homebrew 的依赖包

    add_requires("brew::zlib", {alias = "zlib"}}) add_requires("brew::pcre2/libpcre2-8", {alias = "pcre2"}}) target("test") set_kind("binary") add_files("src/*.c") add_packages("pcre2", "zlib") 

    安装 vcpkg 的依赖包

    add_requires("vcpkg::zlib", "vcpkg::pcre2") target("test") set_kind("binary") add_files("src/*.c") add_packages("vcpkg::zlib", "vcpkg::pcre2") 

    不过需要注意的是,使用 vcpkg,需要先对 vcpkg 与 xmake 进行集成才行,详细操作如下:

    windows 上用户装完 vcpkg 后,执行$ vcpkg integrate install,xmake 就能自动从系统中检测到 vcpkg 的根路径,然后自动适配里面包。

    当然,我们也可以手动指定 vcpkg 的根路径来支持:

    $ xmake f --vcpkg=f:\vcpkg 

    安装 conan 的依赖包

    新版本实现了对 conan 的 generator,来集成获取 conan 中的包信息,我们在 xmake 中使用也是非常的方便,并且可以传递 conan 包的所有配置参数。

    add_requires("conan::zlib/1.2.11@conan/stable", {alias = "zlib", debug = true}) add_requires("conan::OpenSSL/1.0.2n@conan/stable", {alias = "openssl", cOnfigs= {optiOns= "OpenSSL:shared=True"}}) target("test") set_kind("binary") add_files("src/*.c") add_packages("openssl", "zlib") 

    执行 xmake 进行编译后:

    ruki:test_package ruki$ xmake checking for the architecture ... x86_64 checking for the Xcode directory ... /Applications/Xcode.app checking for the SDK version of Xcode ... 10.14 note: try installing these packages (pass -y to skip confirm)? -> conan::zlib/1.2.11@conan/stable (debug) -> conan::OpenSSL/1.0.2n@conan/stable please input: y (y/n) => installing conan::zlib/1.2.11@conan/stable .. ok => installing conan::OpenSSL/1.0.2n@conan/stable .. ok [ 0%]: ccache compiling.release src/main.c [100%]: linking.release test 

    内置依赖包查找支持

    之前的版本提供了lib.detect.find_package来对依赖库进行查找,但是这需要通过 import 后才能使用,并且一次只能查找一个包,比较繁琐:

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

    而新版本中通过内置find_packages接口,对lib.detect.find_package进行了进一步的封装,来提升易用性:

    target("test") set_kind("binary") add_files("src/*.c") on_load(function (target) target:add(find_packages("openssl", "zlib")) end) 

    并且还支持从指定的第三方包管理器中进行查找:

    find_packages("conan::OpenSSL/1.0.2n@conan/stable", "brew::zlib") 

    参数配置依赖包安装

    新版本中对内置的包管理进行了大规模重构和升级,并且对参数可配置编译安装依赖包进行了更好的支持,我们可以在包仓库中定义一些编译安装配置参数,来定制安装包。

    例如, 我们以 pcre2 的包为例:

     package("pcre2") set_homepage("https://www.pcre.org/") set_description("A Perl Compatible Regular Expressions Library") set_urls("https://ftp.pcre.org/pub/pcre/pcre2-$(version).zip", "ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre2-$(version).zip") add_versions("10.23", "6301a525a8a7e63a5fac0c2fbfa0374d3eb133e511d886771e097e427707094a") add_versions("10.30", "3677ce17854fffa68fce6b66442858f48f0de1f537f18439e4bd2771f8b4c7fb") add_versions("10.31", "b4b40695a5347a770407d492c1749e35ba3970ca03fe83eb2c35d44343a5a444") add_configs("shared", {description = "Enable shared library.", default = false, type = "boolean"}) add_configs("jit", {description = "Enable jit.", default = true, type = "boolean"}) add_configs("bitwidth", {description = "Set the code unit width.", default = "8", values = {"8", "16", "32"}}) 

    上面我们通过add_configs定义了三个条件配置参数,使得用户在集成使用 pcre2 库的时候,可以定制化选择是否需要启用 jit 版本、bit 位宽版本等,例如:

    add_requires("pcre2", {cOnfigs= {jit = true, bitwidth = 8}}) 

    而且,配置参数是强约束检测的,如果传的值不对,会提示报错,避免传递无效的参数进来,像 bitwidth 参数配置,被限制了只能在values = {"8", "16", "32"}里面取值。

    那么,用户如何知道我们的包当前支持哪些配置参数呢,很简单,我们可以通过下面的命令,快速查看 pcre2 包的所有信息:

    $ xmake require --info pcre2 

    输出结果如下:

    The package info of project: require(pcre2): -> description: A Perl Compatible Regular Expressions Library -> version: 10.31 -> urls: -> https://ftp.pcre.org/pub/pcre/pcre2-10.31.zip -> b4b40695a5347a770407d492c1749e35ba3970ca03fe83eb2c35d44343a5a444 -> ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre2-10.31.zip -> b4b40695a5347a770407d492c1749e35ba3970ca03fe83eb2c35d44343a5a444 -> repo: local-repo /Users/ruki/projects/personal/xmake-repo/ -> cachedir: /Users/ruki/.xmake/cache/packages/p/pcre2/10.31 -> installdir: /Users/ruki/.xmake/packages/p/pcre2/10.31/23b52ca1c6c8634f5f935903c9e7ea0e -> fetchinfo: 10.31, system, optional -> linkdirs: /usr/local/Cellar/pcre2/10.32/lib -> defines: PCRE2_CODE_UNIT_WIDTH=8 -> links: pcre2-8 -> version: 10.32 -> includedirs: /usr/local/Cellar/pcre2/10.32/include -> platforms: linux, macosx -> requires: -> plat: macosx -> arch: x86_64 -> configs: -> vs_runtime: MT -> shared: false -> jit: true -> bitwidth: 8 -> debug: false -> configs: -> shared: Enable shared library. (default: false) -> jit: Enable jit. (default: true) -> bitwidth: Set the code unit width. (default: 8) -> values: {"8","16","32"} -> configs (builtin): -> debug: Enable debug symbols. (default: false) -> cflags: Set the C compiler flags. -> cxflags: Set the C/C++ compiler flags. -> cxxflags: Set the C++ compiler flags. -> asflags: Set the assembler flags. -> vs_runtime: Set vs compiler runtime. (default: MT) -> values: {"MT","MD"} 

    其中,里面的configs:部分,就是目前可提供配置的参数描述以及取值范围,而configs (builtin):中是一些 xmake 内置的配置参数,用户也可直接配置用。

    例如最常用的 debug 模式包:

    add_requires("pcre2", {cOnfigs= {debug = true}}) 

    由于这个太过于常用,xmake 提供了更方便的配置支持:

    add_requires("pcre2", {debug = true}) 

    另外requires:里面的内容,就是当前依赖包的配置状态,方便用户查看当前使用了哪个模式的包。

    预处理模板配置文件

    xmake 提供了三个新的接口 api,用于在编译前,添加一些需要预处理的配置文件,用于替代set_config_header等老接口。

    • add_configfiles
    • set_configdir
    • set_configvar

    其中add_configfiles相当于 cmake 中的configure_file接口,xmake 中参考了它的 api 设计,并且在其基础上进行了扩展支持,提供更多的灵活性。

    此接口相比以前的set_config_header更加的通用,不仅用于处理 config.h 的自动生成和预处理,还可以处理各种文件类型,而set_config_header仅用于处理头文件,并且不支持模板变量替换。

    先来一个简单的例子:

    target("test") set_kind("binary") add_files("src/*.c") set_configdir("$(buildir)/config") add_configfiles("src/config.h.in") 

    上面的设置,会在编译前,自动的将config.h.in这个头文件配置模板,经过预处理后,生成输出到指定的build/config/config.h

    这个接口的一个最重要的特性就是,可以在预处理的时候,对里面的一些模板变量进行预处理替换,例如:

    config.h.in

    #define VAR1 "${VAR1}" #define VAR2 "${VAR2}" #define HELLO "${HELLO}" 
    set_configvar("VAR1", "1") target("test") set_kind("binary") add_files("main.c") set_configvar("VAR2", 2) add_configfiles("config.h.in", {variables = {hello = "xmake"}}) add_configfiles("*.man", {copyOnly= true}) 

    通过set_configvar接口设置模板变量,裹着通过{variables = {xxx = ""}}中设置的变量进行替换处理。

    预处理后的文件config.h内容为:

    #define VAR1 "1" #define VAR2 "2" #define HELLO "xmake" 

    {copyOnly= true}设置,会强制将*.man作为普通文件处理,仅在预处理阶段 copy 文件,不进行变量替换。

    默认的模板变量匹配模式为${var},当然我们也可以设置其他的匹配模式,例如,改为@var@匹配规则:

    target("test") add_configfiles("config.h.in", {pattern = "@(.-)@"}) 

    我们也有提供了一些内置的变量,即使不通过此接口设置,也是可以进行默认变量替换的:

    ${VERSION} -> 1.6.3 ${VERSION_MAJOR} -> 1 ${VERSION_MINOR} -> 6 ${VERSION_ALTER} -> 3 ${VERSION_BUILD} -> set_version("1.6.3", {build = "%Y%m%d%H%M"}) -> 201902031421 ${PLAT} and ${plat} -> MACOS and macosx ${ARCH} and ${arch} -> ARM and arm ${MODE} and ${mode} -> DEBUG/RELEASE and debug/release ${DEBUG} and ${debug} -> 1 or 0 ${OS} and ${os} -> IOS or ios 

    例如:

    config.h.in

    #define CONFIG_VERSION "${VERSION}" #define CONFIG_VERSION_MAJOR ${VERSION_MAJOR} #define CONFIG_VERSION_MINOR ${VERSION_MINOR} #define CONFIG_VERSION_ALTER ${VERSION_ALTER} #define CONFIG_VERSION_BUILD ${VERSION_BUILD} 

    config.h

    #define CONFIG_VERSION "1.6.3" #define CONFIG_VERSION_MAJOR 1 #define CONFIG_VERSION_MINOR 6 #define CONFIG_VERSION_ALTER 3 #define CONFIG_VERSION_BUILD 201902031401 

    我们还可以对#define定义进行一些变量状态控制处理:

    config.h.in

    ${define FOO_ENABLE} 
    set_configvar("FOO_ENABLE", 1) -- or pass true set_configvar("FOO_STRING", "foo") 

    通过上面的变量设置后,${define xxx}就会替换成:

    #define FOO_ENABLE 1 #define FOO_STRING "foo" 

    或者(设置为 0 禁用的时候)

    /* #undef FOO_ENABLE */ /* #undef FOO_STRING */ 

    这种方式,对于一些自动检测生成 config.h 非常有用,比如配合 option 来做自动检测:

    option("foo") set_default(true) set_description("Enable Foo") set_configvar("FOO_ENABLE", 1) -- 或者传递 true,启用 FOO_ENABLE 变量 set_configvar("FOO_STRING", "foo") target("test") add_configfiles("config.h.in") -- 如果启用 foo 选项 -> 添加 FOO_ENABLE 和 FOO_STRING 定义 add_options("foo") 

    config.h.in

    ${define FOO_ENABLE} ${define FOO_STRING} 

    config.h

    #define FOO_ENABLE 1 #define FOO_STRING "foo" 

    关于 option 选项检测,以及 config.h 的自动生成,有一些辅助函数,可以看下: https://github.com/xmake-io/xmake/issues/342

    除了#define,如果想要对其他非#define xxx也做状态切换处理,可以使用 ${default xxx 0} 模式,设置默认值,例如:

    HAVE_SSE2 equ ${default VAR_HAVE_SSE2 0} 

    通过set_configvar("HAVE_SSE2", 1)启用变量后,变为HAVE_SSE2 equ 1,如果没有设置变量,则使用默认值:HAVE_SSE2 equ 0

    关于这个的详细说明,见:https://github.com/xmake-io/xmake/issues/320

    更加方便的特性检测

    我们通过add_configfiles配合 option 检测,可以做到检测一些头文件、接口函数、类型、编译器特性是否存在,如果存在则自动写入 config.h 中,例如:

    option("foo") set_default(true) set_description("Has pthread library") add_cincludes("pthread.h") add_cfuncs("pthread_create") add_links("pthread") set_configvar("HAS_PTHREAD", 1) target("test") add_configfiles("config.h.in") add_options("pthread") 

    config.h.in

    ${define HAS_PTHREAD} 

    config.h

    #define HAS_PTHREAD 1 

    上面的配置,我们通过 option 检测 pthread.h 里面的接口以及 link 库是否都存在,如果能正常使用 pthread 库,那么自动在 config.h 中定义HAS_PTHREAD,并且 test target 中追加上相关的 links。

    上面的 option 可以支持各种检测,但是配置上少许复杂繁琐了些,为了让 xmake.lua 更加的简洁直观,对于一些常用检测,xmake 通过扩展includes接口, 提供了一些内置封装好的辅助接口函数,来快速实现上面的 option 检测,写入 config.h 的功能。

    上面的代码我们可以简化为:

    includes("check_cfuncs.lua") target("test") add_configfiles("config.h.in") configvar_check_cfuncs("HAS_PTHREAD", "pthread_create", {includes = "pthread.h", links = "pthread"}) 

    除了configvar_check_cfuncs,我们还有check_cfuncs函数,仅吧检测结果直接在编译时候追加,不再写入 configfiles 文件中。

    我们再来看个综合性的例子:

    includes("check_links.lua") includes("check_ctypes.lua") includes("check_cfuncs.lua") includes("check_features.lua") includes("check_csnippets.lua") includes("check_cincludes.lua") target("test") set_kind("binary") add_files("*.c") add_configfiles("config.h.in") configvar_check_ctypes("HAS_WCHAR", "wchar_t") configvar_check_cincludes("HAS_STRING_H", "string.h") configvar_check_cincludes("HAS_STRING_AND_STDIO_H", {"string.h", "stdio.h"}) configvar_check_ctypes("HAS_WCHAR_AND_FLOAT", {"wchar_t", "float"}) configvar_check_links("HAS_PTHREAD", {"pthread", "m", "dl"}) configvar_check_csnippets("HAS_STATIC_ASSERT", "_Static_assert(1, \"\");") configvar_check_cfuncs("HAS_SETJMP", "setjmp", {includes = {"signal.h", "setjmp.h"}}) configvar_check_features("HAS_CONSTEXPR", "cxx_constexpr") configvar_check_features("HAS_CONSEXPR_AND_STATIC_ASSERT", {"cxx_constexpr", "c_static_assert"}, {languages = "c++11"}) 

    config.h.in

    ${define HAS_STRING_H} ${define HAS_STRING_AND_STDIO_H} ${define HAS_WCHAR} ${define HAS_WCHAR_AND_FLOAT} ${define HAS_PTHREAD} ${define HAS_STATIC_ASSERT} ${define HAS_SETJMP} ${define HAS_CONSTEXPR} ${define HAS_CONSEXPR_AND_STATIC_ASSERT} 

    config.h

    /* #undef HAS_STRING_H */ #define HAS_STRING_AND_STDIO_H 1 /* #undef HAS_WCHAR */ /* #undef HAS_WCHAR_AND_FLOAT */ #define HAS_PTHREAD 1 #define HAS_STATIC_ASSERT 1 #define HAS_SETJMP 1 /* #undef HAS_CONSTEXPR */ #define HAS_CONSEXPR_AND_STATIC_ASSERT 1 

    可以看到,xmake 还提供了其他的辅助函数,用于检测:c/c++类型,c/c++代码片段,c/c++函数接口,链接库,头文件是否存在,甚至是 c/c++编译器特性支持力度等。

    关于这块的更加完整的说明,可以看下:https://github.com/xmake-io/xmake/issues/342

    配置自定义安装文件

    对于xmake install/uninstall命令,xmake 新增了add_installfiles接口来设置一些安装文件,比起on_install,此接口用起来更加的方便简洁,基本能够满足大部分安装需求。

    比如我们可以指定安装各种类型的文件到安装目录:

    target("test") add_installfiles("src/*.h") add_installfiles("doc/*.md") 

    默认在 linux 等系统上,我们会安装到/usr/local/*.h, /usr/local/*.md,不过我们也可以指定安装到特定子目录:

    target("test") add_installfiles("src/*.h", {prefixdir = "include"}) add_installfiles("doc/*.md", {prefixdir = "share/doc"}) 

    上面的设置,我们会安装到/usr/local/include/*.h, /usr/local/share/doc/*.md

    我们也可以通过()去提取源文件中的子目录来安装,例如:

    target("test") add_installfiles("src/(tbox/*.h)", {prefixdir = "include"}) add_installfiles("doc/(tbox/*.md)", {prefixdir = "share/doc"}) 

    我们把src/tbox/*.h中的文件,提取tbox/*.h子目录结构后,在进行安装:/usr/local/include/tbox/*.h, /usr/local/share/doc/tbox/*.md

    当然,用户也可以通过set_installdir接口,来配合使用。

    关于此接口的详细说明,见: https://github.com/xmake-io/xmake/issues/318

    CMakelists.txt 导出

    新版本对xmake project工程生成插件进行了扩展,新增了对 CMakelists.txt 文件的导出支持,方便使用 xmake 的用户可以快速导出 CMakelists.txt 提供给 cmake, 以及 CLion 等一些支持 cmake 的工具使用,使用方式如下:

    $ xmake project -k cmakelists 

    即可在当前工程目录下,生成对应的 CMakelists.txt 文件。

    更新内容

    新特性

    • 添加string.serializestring.deserialize去序列化,反序列化对象,函数以及其他类型
    • 添加xmake g --menu去图形化配置全局选项
    • #283: 添加target:installdir()set_installdir()接口
    • #260: 添加add_platformdirs接口,用户现在可以自定义扩展编译平台
    • #310: 新增主题设置支持,用户可随意切换和扩展主题样式
    • #318: 添加add_installfiles接口到 target 去自定义安装文件
    • #339: 改进add_requiresfind_package使其支持对第三方包管理的集成支持
    • #327: 实现对 conan 包管理的集成支持
    • 添加内置 API find_packages("pcre2", "zlib")去同时查找多个依赖包,不需要通过 import 导入即可直接调用
    • #320: 添加模板配置文件相关接口,add_configfilesset_configvar
    • #179: 扩展xmake project插件,新增 CMakelist.txt 生成支持
    • #361: 增加对 vs2019 preview 的支持
    • #368: 支持private, public, interface属性设置去继承 target 配置
    • #284: 通过add_configs()添加和传递用户自定义配置到package()
    • #319: 添加add_headerfiles接口去改进头文件的设置
    • #342: 为includes()添加一些内置的辅助函数,例如:check_cfuncs

    改进

    • 针对远程依赖包,改进版本和调试模式切换
    • #264: 支持在 windows 上更新 dev/master 版本,xmake update dev
    • #293: 添加xmake f/g --mingw=xxx 配置选线,并且改进 find_mingw 检测
    • #301: 改进编译预处理头文件以及依赖头文件生成,编译速度提升 30%
    • #322: 添加option.add_features, option.add_cxxsnippetsoption.add_csnippets
    • 移除 xmake 1.x 的一些废弃接口, 例如:add_option_xxx
    • #327: 改进lib.detect.find_package增加对 conan 包管理器的支持
    • 改进lib.detect.find_package并且添加内建的find_packages("zlib 1.x", "openssl", {xxx = ...})接口
    • 标记set_modes()作为废弃接口, 我们使用add_rules("mode.debug", "mode.release")来替代它
    • #353: 改进target:set, target:add 并且添加target:del去动态修改 target 配置
    • #356: 添加qt_add_static_plugins()接口去支持静态 Qt sdk
    • #351: 生成 vs201x 插件增加对 yasm 的支持
    • 重构改进整个远程依赖包管理器,更加快速、稳定、可靠,并提供更多的常用包

    Bugs 修复

    • 修复无法通过 set_optimize() 设置优化选项,如果存在add_rules("mode.release")的情况下
    • #289: 修复在 windows 下解压 gzip 文件失败
    • #296: 修复option.add_includedirs对 cuda 编译不生效
    • #321: 修复 PATH 环境改动后查找工具不对问题
    11 条回复    2019-04-02 10:59:49 +08:00
    yksoft1ex
        1
    yksoft1ex  
       2019-04-02 08:39:17 +08:00
    支不支持 MSYS1 环境?
    araraloren
        2
    araraloren  
       2019-04-02 08:39:40 +08:00
    支持,虽然不用。。
    waruqi
        3
    waruqi  
    OP
       2019-04-02 08:44:41 +08:00 via Android
    @yksoft1ex 支持 msys mingw 以及 交叉编译都支持
    不过 win 直接 原生 cmd 不就好了,也是直接支持的
    xiaoyiyu
        4
    xiaoyiyu  
       2019-04-02 09:09:59 +08:00   1
    支持一下
    waruqi
        5
    waruqi  
    OP
       2019-04-02 09:14:50 +08:00
    @xiaoyiyu 谢谢支持
    hellowmykami
        6
    hellowmykami  
       2019-04-02 09:46:27 +08:00
    star :)
    yksoft1ex
        7
    yksoft1ex  
       2019-04-02 10:05:57 +08:00
    @waruqi 我 Windows 的东西基本只在 MSYS1 下。
    waruqi
        8
    waruqi  
    OP
       2019-04-02 10:23:51 +08:00 via Android
    @yksoft1ex msys 只是个 shell xmake 不管在哪都能执行的,无所谓是否在 msys 执行,xmake 仅依赖编译工具链,其他都不依赖,msys 下的 path 下如果有特定编译工具,在 cmd 下通过传参配置交叉编译路径,也是可以直接调用到的
    binbex
        9
    binbex  
       2019-04-02 10:2:40 +08:00   1
    给 LZ 点赞
    georgetso
        10
    georgetso  
       2019-04-02 10:29:06 +08:00   1
    xmake 是真好用
    waruqi
        11
    waruqi  
    OP
       2019-04-02 10:59:49 +08:00
    @georgetso
    @binbex 谢谢
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     963 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 84ms UTC 19:01 PVG 03:01 LAX 12:01 JFK 15:01
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86