My CMake Tutorial 2

其实我的感觉是大家都被我第一篇给蒙骗了……从第二篇开始我就要开始走非主流路线。

如何 make uninstall

cmake是没有make uninstall支持的。

你可能觉得很无语。不过还是有方法的,这个方法也被应用于fcitx的每个项目当中。另外如果你使用KDE的话 – find_package(KDE4) – 那么KDE也会自动提供uninstall,不用你麻烦了。

那么现在来看看这是怎么实现的。

在make install的时候,cmake会生成一个文件 install_manifest.txt ,里面是要安装的文件。而uninstall的基本思想就是读他,然后把里面列出的文件删掉。

一般而言我会这么做,新建一个文件夹叫cmake,然后在里面放上以下内容的文件,命名为cmake_uninstall.cmake.in。

if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
    message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")

file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach (file ${files})
    message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
    if (EXISTS "$ENV{DESTDIR}${file}" OR IS_SYMLINK "$ENV{DESTDIR}${file}")
        execute_process(
            COMMAND @CMAKE_COMMAND@ -E remove "$ENV{DESTDIR}${file}"
            OUTPUT_VARIABLE rm_out
            RESULT_VARIABLE rm_retval
        )
        if(NOT ${rm_retval} EQUAL 0)
            message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
        endif (NOT ${rm_retval} EQUAL 0)
    else (EXISTS "$ENV{DESTDIR}${file}" OR IS_SYMLINK "$ENV{DESTDIR}${file}")
        message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
    endif (EXISTS "$ENV{DESTDIR}${file}" OR IS_SYMLINK "$ENV{DESTDIR}${file}")
endforeach(file)

然后在你的源代码根目录的CMakeLists.txt 里面写上

# uninstall target
configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
    "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
    IMMEDIATE @ONLY)

add_custom_target(uninstall
    COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)

就大功告成了。

顺带一提,这里列出的版本比cmake wiki上的好用,大家可以自行对比(http://www.cmake.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F

那么原理是什么?就从主文件的CMakeLists.txt 开始吧。首先是 configure_file 命令。熟悉autotools的同学知道,经常有些内容是配置完才能决定的,configure_file就是这样的命令,甚至语法和autotools都一样(采用@扩起需要替换的部分)。

第一个,第二个参数分别是输入和输出文件,考虑和cmake向下兼容性的问题,请使用绝对路径,否则2.6之前的版本是构建根目录,2.8则是相对当前CMakeLists.txt的目录。@ONLY 表示只对使用 @ 括起的变量进行替换。

add_custom_target 则是建立一个自己的target,并且对应的命令为COMMAND后面指定的命令。target的概念熟悉Makefile的人都知道了。

This entry was posted in cmake and tagged . Bookmark the permalink.

3 Responses to My CMake Tutorial 2

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.