CMake如何简化生成过程:第2部分(高级编译系统)

本文介绍如何使用CMake简化复杂的项目构建过程,包括共享库、示例应用与单元测试的构建。通过自动化处理MOC文件生成及链接Qt库,提高了构建效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我以前的帖子解释Cmake是如何管理一个简单的项目(只包含一个定义和实现文件)。现在,我们可以在一个复杂的项目看,含有一个共同的共享库,示例和单元测试。在这种情况下,而不是一个愚蠢的HelloWorld项目,我选择了Itemviews-NG的项目,这是一个实验性项目,由Qt实验室主办,并且目前使用qmake作为构建系统。该项目本身包含以下内容:

n         共享库包含一个共同的基类;

n         库的每一个类实例的集合;

n         库的每一个类单元测试集合;

 

注意:文档将不被创建了 -Itemview- NG使用qdoc生成文档,AFAIK还没有很好地和CMake整合呢。这儿有另外一个替代,在Cmake中使用doxygen,连同lcov封面和gcov HTML输出相结合。

 

作为一个起点,该项目本身包含了需要由MOC处理各种文件。为了简化这个过程中,可以使用CMake的工具,它会使用automoc工具自动找到所需的文件进行预处理,并包含它们在目标编译中。 Qt和包含文件也提供了的Qt4 cmake包(内置)。要使用的Qt4automoc CMake软件包,你可以包括在项目上的根目录下的CMakeFiles.txt以下代码:

# Qt4 package is mandatory
find_package(Qt4 REQUIRED)
include(${QT_USE_FILE})
 
# Automoc4 is also mandatory
find_package(Automoc4 REQUIRED)

 

现在让我们看看src目录CMakeFiles.txt的变化

set(CMAKE_INCLUDE_CURRENT_DIR ON)
 
# Create a variable containing a list of all implementation files
file(GLOB itemviews-ng_SOURCES *.cpp)
 
# The same applies for headers which generates MOC files (excluding private implementation ones)
file(GLOB itemviews-ng HEADERS *[^_p].h)
 
# Now the magic happens: The function below is responsible for generating the MOC files)
automoc4_moc_headers(itemviews-ng ${itemviews-ng_HEADERS})
 
# Creates a target itemviews-ng which creates a shard library with the given sources
automoc4_add_library(itemviews-ng SHARED ${itemviews-ng_SOURCES})
 
# Tells the shared library to be linked against Qt ones
target_link_libraries(itemviews-ng ${QT_LIBRARIES})
 
# Installs the header files into the {build_dir}/include/itemviews-ng directory
install(FILES ${itemviews-ng_HEADERS} DESTINATION include/itemviews-ng)
 
# Installs the target file (libitemviews-ng.so) into the {build_dir}/lib directory
install(TARGETS itemviews-ng LIBRARY DESTINATION lib)

 

现在,该项目使用的每一个例子或测试可以使用目标itemviews-ng作为联系的依赖。由于每个例子和测试是在一个类似的方法编译,我们可以使用函数从而简化编译过程。以下是这些函数的例子:

function(example example_NAME example_SOURCES example_HEADERS)
automoc4_moc_headers(${example_NAME}_example ${examples_HEADERS})
# The third argument (resource files) is optional:
set(example_RESOURCES ${ARGV3})
if(example_RESOURCES)
    automoc4_add_executable(${example_NAME}_example
        ${example_SOURCES} {example_RESOURCES})
else(example_RESOURCES)
    automoc4_add_executable(${example_NAME}_example
        ${example_SOURCES})    endif(example_RESOURCES)
    target_link_libraries(${example_NAME}_example itemviews-ng
       {QT_LIBRARIES})
endfunction(example)
 
function(test test_NAME test_SOURCES)
set(test_RESOURCES ${ARGV2})
if(test_RESOURCES)
    automoc4_add_executable(${test_NAME}_test
        {test_SOURCES} ${test_RESOURCES})
else(test_RESOURCES)
    automoc4_add_executable(${test_NAME}_test
        ${test_SOURCES})    endif(test_RESOURCES)
    target_link_libraries(${test_NAME}_test itemviews-ng
        ${QT_LIBRARIES})
include_directories(${itemviews-ng_BINARY_DIR}/tests/${test_NAME})
add_test(${test_NAME} ${test_NAME}_test)
add_dependencies(check ${test_NAME}_test)
endfunction(test)

 

上述功能可以插入到.cmake文件中(如:InternalMacros.cmake)。这就需要cmake/ modules目录中去找。要加载它,在根目录的CMakeLists.txt加上以下行:

include(InternalMacros)

 

现在,你创建的每一个例子的CmakeLists.txt 像这样:

set(mycustomexample_SOURCES mycustomexample.cpp main.cpp )
set(mycustomexample_HEADERS mycustomexample.h )
example(mycustomexample "${mycustomexample_SOURCES}" "${mycustomexample_HEADERS}")

 

这同样适用于测试:

test(mycustomtest "${mycustomtest_SOURCES}")

 

我已经在我的个人gitorious网站itemviews-ng clone上创建一个cmake分支。你可以看看,看看如何解释上面的代码的行为。

 

附:原文及原文地址:

http://cabledogs.org/abinader/2009/12/09/how-cmake-simplifies-the-build-process-part-2-advanced-build-system/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值