【问题标题】:Looking for a 'cmake clean' command to clear up CMake output寻找“cmake clean”命令来清除 CMake 输出
【发布时间】:2012-03-29 15:22:30
【问题描述】:

就像make clean 删除makefile 生成的所有文件一样,我想对CMake 做同样的事情。我经常发现自己手动浏览目录,删除像 cmake_install.cmakeCMakeCache.txt 之类的文件,以及 CMakeFiles 文件夹。

是否有类似cmake clean 的命令可以自动删除所有这些文件?理想情况下,这应该遵循当前目录的CMakeLists.txt 文件中定义的递归结构。

【问题讨论】:

  • 对于 CMake 3.0 及更高版本的用户,您可以使用cmake --build <build-dir> --target clean

标签: cmake


【解决方案1】:

CMake 3.X

CMake 3.X 提供了一个“干净”的目标。

cmake --build C:/foo/build/ --target clean

来自 3.0.2 的 CMake 文档:

--clean-first  = Build target 'clean' first, then build.
                 (To clean only, use --target 'clean'.)

CMake 2.X

CMake 2.X 版中没有cmake clean

我通常将项目构建在单个文件夹中,例如“build”。所以如果我想make clean,我可以rm -rf build

与根“CMakeLists.txt”位于同一目录中的“build”文件夹通常是一个不错的选择。要构建您的项目,您只需将 CMakeLists.txt 的位置作为参数提供给 cmake。例如:cd <location-of-cmakelists>/build && cmake ..。 (来自@ComicSansMS)

【讨论】:

  • 这被称为“out of source build”,应该是首选的方式。它避免了名称冲突等
  • +1 用于源外构建。这在构建多个架构时变得至关重要。例如,您不能使用源内构建同时构建 64 位和 32 位二进制文​​件,因为这需要两个单独的 CMake 缓存层次结构。
  • 您可以将文件夹放置在您想要的任何位置,但是与根 CMakeLists.txt 位于同一目录中的构建文件夹通常是一个不错的选择。要构建,您只需将 CMakeLists.txt 的位置作为参数提供给 cmake。例如:cd <location-of-cmakelists>/build && cmake ..
  • 真的应该有一个cmake clean。曾经使用过 cmake 的每个人,即使他们习惯于进行源代码构建,也会不小心在错误的目录中运行 cmake,并且手动清理是一件非常痛苦的事情。
  • @DevSolar 但反之则不然;仅仅因为文件不受版本控制并不意味着它是由 cmake 生成的并且可以安全地删除。挑选出哪些未版本化的文件正在进行中,您需要保留哪些文件是 cmake cruft 是一件痛苦的事,尤其是当许多 cmake 文件是副本/与您的文件类似命名时。
【解决方案2】:

CMake official FAQ 状态:

使用 GNU 自动工具创建的一些构建树具有“make distclean” 清理构建并删除 Makefile 和其他的目标 生成的构建系统的一部分。 CMake 不会生成“make distclean" 目标,因为 CMakeLists.txt 文件可以运行脚本和 任意命令; CMake 无法准确跟踪哪些文件 作为运行 CMake 的一部分生成。提供 distclean 目标 会给用户一种错误的印象,即它会按预期工作。 (CMake 确实会生成一个“make clean”目标来删除生成的文件 由编译器和链接器提供。)

“make distclean”目标只是 如果用户执行源内构建是必需的。 CMake 支持 源内构建,但我们强烈鼓励用户采用这个概念 的源外构建。使用与 源代码树将阻止 CMake 在 源树。因为 CMake 不改变源代码树,所以有 不需要 distclean 目标。可以通过以下方式开始新的构建 删除构建树或创建单独的构建树。

【讨论】:

  • 最初,由 GNU autotools 引入和使用,'distclean' 目标旨在使源代码树准备好 tar 并创建 tar 分发。这样的 tar 文件用户可以下载并解压缩,然后运行 ​​'configure' 和 'make' 不需要自动工具(aclocal、automake、autoconf 等) ' 会给我们留下一个干净的源代码,可以在没有安装 cmake 的情况下构建。但是,当生成器是单目标生成器时(就像“make”目标一样),这不起作用,因为使用 cmake 的配置发生在
  • ... 运行 cmake。制作一个无法配置的发行版,甚至不做平台测试等,都是没用的。因此,cmake 不存在“distclean”目标。 cmake 必须存在于最终用户的机器上。
  • we strongly encourage users to adopt the notion of an out-of-source build -- 可惜他们当时将其设为默认行为。 (说真的,让默认行为成为你不鼓励用户做的事情是一个愚蠢的设计决定。)
【解决方案3】:

在 Git 无处不在的时代,您可能会忘记 CMake 并使用 git clean -d -f -x,这将删除所有不受源代码控制的文件。

【讨论】:

  • -x 选项。这是git 交易的绝妙技巧。虽然我个人仍然会先进行试运行,git clean -d -f -x -n。每隔一段时间,我都会将用于项目的便利文件保存在git 控制下的项目文件夹中,但这不是我想与其他人共享的东西,所以我不会git add 将它提供给项目。如果我不小心添加了-e <pattern> 选项,这将把那种文件吹走。在这方面,如果git 有一个.gitcleanignore 文件会很好。 :)
  • @CivFan 你可以尝试使用chattr +i $filename(需要root权限,之后不允许修改文件)。这样 git 将无法删除该文件,即使它尝试像 rm -f 那样删除。
  • 假设是源内构建,这本身就是要避免的。
  • 嗯但是用户忘记git add的新添加文件呢?
  • 很好的答案;你能包括组合标志参数的概念吗?即git clean -dfx。这也依赖于一个好的 .gitignore 顺便说一句
【解决方案4】:

我用谷歌搜索了大约半个小时,我想出的唯一有用的东西是调用 find 实用程序:

# Find and then delete all files under current directory (.) that:
#  1. contains "cmake" (case-&insensitive) in its path (wholename)
#  2. name is not CMakeLists.txt
find . -iwholename '*cmake*' -not -name CMakeLists.txt -delete

另外,请务必在之前调用make clean(或您正在使用的任何CMake生成器)。

:)

【讨论】:

  • 如果您正在使用的目录受版本控制,我建议不要使用这种方法:当我使用 svn 尝试这种方法时,它删除了一些存储库工作文件。
  • 可能有其他文件匹配 cmake 所以这真的不是一个通用的方法。这应该这样做: rm -rf CMakeFiles; rm -rf CMakeCache.txt; rm -rf cmake_install.cmake;
  • 我会删除 -exec rm -rf {} \+ 并使用 -delete。
  • 否决,因为此命令可能会删除一些用户文件。我确实更喜欢 honza_p 命令,而不是真的更长、更简单、风险更低。
  • @AdrienDescamps:除了它仍然在子目录中留下与 cmake 相关的垃圾。我正在做rm -rf CMakeFiles ; rm -rf */CMakeFiles ; rm -rf */*/CMakeFiles ; rm -rf */*/*/CMakeFiles,但还没有完成......
【解决方案5】:

你可以使用类似的东西:

add_custom_target(clean-cmake-files
   COMMAND ${CMAKE_COMMAND} -P clean-all.cmake
)

// clean-all.cmake
set(cmake_generated ${CMAKE_BINARY_DIR}/CMakeCache.txt
                    ${CMAKE_BINARY_DIR}/cmake_install.cmake
                    ${CMAKE_BINARY_DIR}/Makefile
                    ${CMAKE_BINARY_DIR}/CMakeFiles
)

foreach(file ${cmake_generated})

  if (EXISTS ${file})
     file(REMOVE_RECURSE ${file})
  endif()

endforeach(file)

我通常会创建一个“make clean-all”命令,在前面的示例中添加对“make clean”的调用:

add_custom_target(clean-all
   COMMAND ${CMAKE_BUILD_TOOL} clean
   COMMAND ${CMAKE_COMMAND} -P clean-all.cmake
)

不要尝试将“干净”目标添加为依赖项:

add_custom_target(clean-all
   COMMAND ${CMAKE_COMMAND} -P clean-all.cmake
   DEPENDS clean
)

因为“干净”不是 CMake 中的真正目标,而且这不起作用。

此外,您不应将此“clean-cmake-files”用作任何依赖项:

add_custom_target(clean-all
   COMMAND ${CMAKE_BUILD_TOOL} clean
   DEPENDS clean-cmake-files
)

因为,如果您这样做,所有 CMake 文件将在 clean-all 完成之前被删除,并且 make 会在搜索“CMakeFiles/clean-all.dir/build.make”时抛出错误。因此,在任何情况下,您都不能在 "anything" 之前使用 clean-all 命令:

add_custom_target(clean-all
   COMMAND ${CMAKE_BUILD_TOOL} clean
   COMMAND ${CMAKE_COMMAND} -P clean-all.cmake
)

这也不行。

【讨论】:

  • 有没有办法自动填充cmake_generated?也许,将其与 yuri.makarevich 的答案结合起来?目前,这不会删除 ${CMAKE_BINARY_DIR} 子目录中的文件。
  • 不适用于 Ninja 或 Visual Studio。我不会推荐这种方法。
  • 好主意,但这并没有删除CMakeCache.txt,也对我没有帮助,但我发现这种类似的方法可以在每个构建中更新变量,所以不需要删除CMakeCache.txtstackoverflow.com/questions/53159371/…
【解决方案6】:

简单地发出rm CMakeCache.txt 也适用于我。

【讨论】:

  • 仅删除 CMakeCache.txt 中的相关变量对我也有效。
  • 删除 CMakeCache.txt 然后运行“cmake --build /build-path”会导致“错误:无法加载缓存”。
  • @nenchev 你需要再次运行cmake /build-path
  • @Samaursa cmake --build 在需要时重新运行 cmake,此方法会破坏构建目录并且 cmake 会抱怨。我的回答进一步告诉您删除 CMakeFiles/ 目录,这会导致干净的重建和 cmake 自动重新运行。
  • @nenchev 我明白你的意思,我同意。
【解决方案7】:

可能有点过时了,但是因为这是你googlecmake clean时的第一次点击,我会添加这个:

因为您可以使用指定目标在构建目录中启动构建

cmake --build . --target xyz

你当然可以跑

cmake --build . --target clean

在生成的构建文件中运行clean 目标。

【讨论】:

    【解决方案8】:

    我同意外源构建是最好的答案。但是在你必须进行源代码构建的时候,我编写了一个可用的 Python 脚本here,它:

    1. 运行“make clean”
    2. 在顶级目录中删除特定的 CMake 生成的文件,例如 CMakeCache.txt
    3. 对于每个包含 CMakeFiles 目录的子目录,它会删除 CMakeFiles、Makefile、cmake_install.cmake。
    4. 删除所有空子目录。

    【讨论】:

    • 谢谢。我想在您的脚本中添加一行,当由于先前的清理而没有 Makefile 存在时(即,使此脚本具有幂等性),使 make 静音。只需在第 24 行之前添加一行(适当间隔):if os.path.isfile(os.path.join(directory,'Makefile')):args = [,当然在刚刚添加的行之后缩进函数体的其余部分。仅当正在清理的当前目录中存在Makefile 时,才会执行make ... clean。否则,脚本是完美的!
    • “但在你必须进行源代码构建的时候” 但是,这些时间到底是什么时候?我希望这些天它们很少而且相距甚远,并且每当你遇到一个时,你都会向维护人员提交一个错误,要求他们修复他们的构建工具。至少,任何使用 CMake 的项目都需要支持源外构建,否则他们的代码与ExternalProject 一起使用是一件苦差事(需要BUILD_IN_SOURCE,隐含山羊牺牲),我什至不确定它是否可以使用FetchContent,因为它缺少类似的选项。
    【解决方案9】:

    我最近发现的一个解决方案是将外源构建概念与 Makefile 包装器相结合。

    在我的顶级 CMakeLists.txt 文件中,我包含以下内容以防止源内构建:

    if ( ${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR} )
        message( FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt." )
    endif()
    

    然后,我创建一个顶级 Makefile,并包含以下内容:

    # -----------------------------------------------------------------------------
    # CMake project wrapper Makefile ----------------------------------------------
    # -----------------------------------------------------------------------------
    
    SHELL := /bin/bash
    RM    := rm -rf
    MKDIR := mkdir -p
    
    all: ./build/Makefile
        @ $(MAKE) -C build
    
    ./build/Makefile:
        @  ($(MKDIR) build > /dev/null)
        @  (cd build > /dev/null 2>&1 && cmake ..)
    
    distclean:
        @  ($(MKDIR) build > /dev/null)
        @  (cd build > /dev/null 2>&1 && cmake .. > /dev/null 2>&1)
        @- $(MAKE) --silent -C build clean || true
        @- $(RM) ./build/Makefile
        @- $(RM) ./build/src
        @- $(RM) ./build/test
        @- $(RM) ./build/CMake*
        @- $(RM) ./build/cmake.*
        @- $(RM) ./build/*.cmake
        @- $(RM) ./build/*.txt
    
    ifeq ($(findstring distclean,$(MAKECMDGOALS)),)
        $(MAKECMDGOALS): ./build/Makefile
        @ $(MAKE) -C build $(MAKECMDGOALS)
    endif
    

    通过键入make 调用默认目标all,并调用目标./build/Makefile

    目标./build/Makefile 所做的第一件事是使用$(MKDIR) 创建build 目录,这是mkdir -p 的一个变量。目录build 是我们将执行我们的源代码外构建的地方。我们提供参数-p 以确保mkdir 不会因为我们试图创建一个可能已经存在的目录而大喊大叫。

    目标./build/Makefile 所做的第二件事是将目录更改为build 目录并调用cmake

    回到all 目标,我们调用$(MAKE) -C build,其中$(MAKE) 是为make 自动生成的Makefile 变量。 make -C 在做任何事情之前更改目录。因此,使用$(MAKE) -C build就相当于使用cd build; make

    总而言之,用make allmake 调用这个Makefile 包装器相当于这样做:

    mkdir build
    cd build
    cmake ..
    make 
    

    目标distclean 调用cmake ..,然后调用make -C build clean,最后从build 目录中删除所有内容。我相信这正是您在问题中所要求的。

    Makefile 的最后一部分评估用户提供的目标是否为distclean。如果没有,它会在调用它之前将目录更改为build。这是非常强大的,因为用户可以键入,例如,make clean,Makefile 会将其转换为 cd build; make clean 的等价物。

    总之,这个 Makefile 包装器与强制的源外构建 CMake 配置相结合,使用户无需与命令cmake 进行交互。此解决方案还提供了一种优雅的方法来从 build 目录中删除所有 CMake 输出文件。

    附:在 Makefile 中,我们使用前缀 @ 来抑制 shell 命令的输出,使用前缀 @- 来忽略 shell 命令的错误。当使用rm 作为distclean 目标的一部分时,如果文件不存在,该命令将返回错误(它们可能已经使用带有rm -rf build 的命令行被删除,或者它们从未在第一次生成地方)。这个返回错误将强制我们的 Makefile 退出。我们使用前缀@- 来防止这种情况。如果文件已经被删除是可以接受的;我们希望我们的 Makefile 继续运行并删除其余部分。

    另外需要注意的是:如果您使用可变数量的 CMake 变量来构建您的项目,此 Makefile 可能无法工作,例如,cmake .. -DSOMEBUILDSUSETHIS:STRING="foo" -DSOMEOTHERBUILDSUSETHISTOO:STRING="bar"。此 Makefile 假定您以一致的方式调用 CMake,可以通过键入 cmake .. 或提供 cmake 一致数量的参数(可以包含在 Makefile 中)。

    最后,信用到期。这个 Makefile 包装器改编自 C++ Application Project Template 提供的 Makefile。

    【讨论】:

      【解决方案10】:

      如果您在生成构建文件时将-D 参数传递给CMake并且不想删除整个构建/目录:

      只需删除构建目录中的 CMakeFiles/ 目录即可。

      rm -rf CMakeFiles/
      cmake --build .
      

      这会导致 CMake 重新运行,并重新生成构建系统文件。您的构建也将从头开始。

      【讨论】:

      • 这还不够。 CMakeCache.txt 也必须被删除(就像找到的库一样)。
      【解决方案11】:

      当然,源外构建是 Unix Makefile 的首选方法,但如果您使用其他生成器(例如 Eclipse CDT),它更喜欢您构建源内构建。在这种情况下,您需要手动清除 CMake 文件。试试这个:

      find . -name 'CMakeCache.txt' -o -name '*.cmake' -o -name 'Makefile' -o -name 'CMakeFiles' -exec rm -rf {} +
      

      或者,如果您使用 shopt -s globstar 启用了 globstar,请尝试使用这种不那么恶心的方法:

      rm -rf **/CMakeCache.txt **/*.cmake **/Makefile **/CMakeFiles
      

      【讨论】:

      • 我昨天的选择是将 repo 克隆到一个新文件夹,更新 CMakeLists.txt 以从子文件夹 build 构建。它比那些命令花费了更长的时间,但我只需要执行一次 :)
      【解决方案12】:

      尝试使用: cmake --clean-first path-of-CMakeLists.txt-file -B output-dir

      --clean-first:先构建目标clean,然后构建。
      (要仅清理,请使用 --target clean。)

      【讨论】:

      • 该屏幕截图仅显示文本。然而,你截取它的屏幕截图,为任何带着屏幕阅读器来到这里的人打破了答案。请放下那张图片,复制/粘贴文本,然后花 1 分钟时间正确格式化输入内容。
      【解决方案13】:

      有趣的是,这个问题得到了如此多的关注和复杂的解决方案,这确实表明没有一个干净的 cmake 方法很痛苦。

      嗯,你绝对可以cd build_work 来做你的工作,然后在你需要清洁的时候做一个rm -rf *。然而,rm -rf * 是一个危险的命令,因为许多人通常不知道他们在哪个目录。

      如果你先是cd ..rm -rf build_work,然后是mkdir build_work,然后是cd build_work,那就太打字了。

      所以一个好的解决方案是离开构建文件夹并告诉 cmake 路径:
      配置:cmake -B build_work
      构建:cmake --build build_work
      安装:cmake --install build_work
      清理:rm -rf build_work
      重新创建构建文件夹:您甚至不需要mkdir build_work,只需使用cmake -B build_work 配置即可。

      【讨论】:

        【解决方案14】:

        我为此目的使用以下 shell 脚本:

        #!/bin/bash
        
        for fld in $(find -name "CMakeLists.txt" -printf '%h ')
        do
            for cmakefile in CMakeCache.txt cmake_install.cmake CTestTestfile.cmake CMakeFiles Makefile
            do
                rm -rfv $fld/$cmakefile
            done
        done
        

        如果您使用的是 Windows,请使用 Cygwin 编写此脚本。

        【讨论】:

          【解决方案15】:

          为了在使用“源代码外”构建(即在build 目录中构建)时简化清理,我使用以下脚本:

          $ cat ~/bin/cmake-clean-build
          #!/bin/bash
          
          if [ -d ../build ]; then
              cd ..
              rm -rf build
              mkdir build
              cd build
          else
              echo "build directory DOES NOT exist"
          fi
          

          每次需要清理时,都应该从build 目录获取此脚本:

          . cmake-clean-build
          

          【讨论】:

          • 又好又安全。由于我可能在文件管理器中打开了构建目录,我建议将cd .. ; rm ; mkdir ; cd 序列替换为cd .. ; rm -rf build/*
          【解决方案16】:

          如果您有自定义定义并希望在清理之前保存它们,请在构建目录中运行以下命令:

          sed -ne '/variable specified on the command line/{n;s/.*/-D \0 \\/;p}' CMakeCache.txt
          

          然后创建一个新的构建目录(或删除旧的构建目录并重新创建它),最后运行 cmake 并使用上面脚本获得的参数。

          【讨论】:

            【解决方案17】:

            如果你跑了

            cmake .
            

            它将重新生成 CMake 文件。例如,如果您将新文件添加到 *.cc 选择的源文件夹中,这是必需的。

            虽然这本身不是“清理”,但它确实通过重新生成缓存来“清理”CMake 文件。

            【讨论】:

            • 它不会清理 wrt。编译状态:如果 1200 个文件中的 500 个已编译,则在 "cmake ." 之后。它将继续处理最后 700 个文件。
            【解决方案18】:

            cmake 主要是做一个Makefile,可以将rm 添加到clean PHONY

            例如,

            [root@localhost hello]# ls
            CMakeCache.txt  CMakeFiles  cmake_install.cmake  CMakeLists.txt  hello  Makefile  test
            [root@localhost hello]# vi Makefile
            clean:
                    $(MAKE) -f CMakeFiles/Makefile2 clean
                    rm   -rf   *.o   *~   .depend   .*.cmd   *.mod    *.ko   *.mod.c   .tmp_versions *.symvers *.d *.markers *.order   CMakeFiles  cmake_install.cmake  CMakeCache.txt  Makefile
            

            【讨论】:

              【解决方案19】:

              这已经很老了,但是如果你完全删除了 cmake-build-debug 文件夹,当你使用 cmake 编译时,它应该会自动创建一个新的 cmake-build-debug 文件夹,里面有你需要的一切。在 CLion 中效果特别好。

              【讨论】:

                【解决方案20】:

                这是我使用的。它包含在一个函数中,它是跨平台的,它演示了如何查找匹配的文件名或文件夹名称,以防您想进行任何简单的调整。这个函数在我每次构建脚本时都会运行,并且可以完美地满足我的需求。

                function(DELETE_CACHE)
                    if(CMAKE_HOST_WIN32)
                        execute_process(COMMAND cmd /c for /r %%i in (CMakeCache.*) do del "%%i" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
                        execute_process(COMMAND cmd /c for /d /r %%i in (*CMakeFiles*) do rd /s /q "%%i" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
                    else()
                        execute_process(COMMAND find . -name "CMakeCache.*" -delete WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
                        execute_process(COMMAND "rm -rf `find . -type d -name CMakeFiles`" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
                    endif()
                endfunction()
                

                【讨论】:

                  【解决方案21】:

                  我的 shell rc 文件中有这个(.bashrc.zshrc):

                  t-cmake-clean() {
                      local BUILD=$(basename $(pwd))
                      cd ..
                      rm -rf $BUILD
                      mkdir $BUILD && cd $BUILD
                  }
                  

                  您应该将它用于非源代码构建。假设您为此目的有一个名为build/ 的目录。然后你只需要在其中运行t-cmake-clean

                  【讨论】:

                    【解决方案22】:

                    我使用zsxwing's answer成功解决了以下问题:

                    我有在多个主机上构建的源代码(在 Raspberry Pi Linux 板上、在 VMware Linux 虚拟机上等)

                    我有一个 Bash 脚本,它根据机器的主机名创建临时目录,如下所示:

                    # Get hostname to use as part of directory names
                    HOST_NAME=`uname -n`
                    
                    # Create a temporary directory for cmake files so they don't
                    # end up all mixed up with the source.
                    
                    TMP_DIR="cmake.tmp.$HOSTNAME"
                    
                    if [ ! -e $TMP_DIR ] ; then
                      echo "Creating directory for cmake tmp files : $TMP_DIR"
                      mkdir $TMP_DIR
                    else
                      echo "Reusing cmake tmp dir : $TMP_DIR"
                    fi
                    
                    # Create makefiles with CMake
                    #
                    # Note: switch to the temporary dir and build parent 
                    #       which is a way of making cmake tmp files stay
                    #       out of the way.
                    #
                    # Note 2: to clean up cmake files, it is OK to
                    #        "rm -rf" the temporary directories
                    
                    echo
                    echo Creating Makefiles with cmake ...
                    
                    cd $TMP_DIR
                    
                    cmake ..
                    
                    # Run makefile (in temporary directory)
                    
                    echo
                    echo Starting build ...
                    
                    make
                    

                    【讨论】:

                      【解决方案23】:

                      创建一个临时构建目录,例如build_cmake。因此,您所有的构建文件都将在此文件夹中。

                      然后在您的主 CMake 文件中添加以下命令。

                      add_custom_target(clean-all
                          rm -rf *
                      )
                      

                      因此在编译时做

                      cmake ..
                      

                      然后清理:

                      make clean-all
                      

                      【讨论】:

                      • 如果有人不小心会在源代码中构建而不是在源代码之外构建,那么删除所有项目的好方法
                      • 是的。此方法只能用于“out of source build”
                      • 糟糕的推荐。不应作为答案存在。
                      • @AnnevanRossum 同意
                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2011-04-24
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2020-09-20
                      相关资源
                      最近更新 更多