CMake示例——muduo库的CMake、libco的CMake和marl的CMake

    前面把CMake基本一些变量和语言简单的学了一下,但是,肯定很表面,学习语言嘛,就是学习语法,看别人的代码,最后自己写代码。所以,第二步,就是看别人的CMake怎么写的。选这几个库是因为后面想学习学习这几个库的源码,这三个库没什么逻辑关系,一个网络库,两个协程库。

参考资料:

CMake I 创建一个简单的单元测试

CMake - 单元测试和 GoogleTest 简单使用

一、muduo库的CMake

cmake_minimum_required(VERSION 2.6)

project(muduo C CXX)

enable_testing()

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE "Release")
endif()

# only build examples if this is the main project
if(CMAKE_PROJECT_NAME STREQUAL "muduo")
  option(MUDUO_BUILD_EXAMPLES "Build Muduo examples" ON)
endif()

set(CXX_FLAGS
 -g
 # -DVALGRIND
 -DCHECK_PTHREAD_RETURN_VALUE
 -D_FILE_OFFSET_BITS=64
 -Wall
 -Wextra
 -Werror
 -Wconversion
 -Wno-unused-parameter
 -Wold-style-cast
 -Woverloaded-virtual
 -Wpointer-arith
 -Wshadow
 -Wwrite-strings
 -march=native
 # -MMD
 -std=c++11
 -rdynamic
 )

if(CMAKE_BUILD_BITS EQUAL 32)
  list(APPEND CXX_FLAGS "-m32")
endif()

if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
  list(APPEND CXX_FLAGS "-Wno-null-dereference")
  list(APPEND CXX_FLAGS "-Wno-sign-conversion")
  list(APPEND CXX_FLAGS "-Wno-unused-local-typedef")
  list(APPEND CXX_FLAGS "-Wthread-safety")
  list(REMOVE_ITEM CXX_FLAGS "-rdynamic")
endif()

string(REPLACE ";" " " CMAKE_CXX_FLAGS "${CXX_FLAGS}")

set(CMAKE_CXX_FLAGS_DEBUG "-O0")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)

find_package(Boost REQUIRED)
find_package(Protobuf)
find_package(CURL)
find_package(ZLIB)
find_path(CARES_INCLUDE_DIR ares.h)
find_library(CARES_LIBRARY NAMES cares)
find_path(MHD_INCLUDE_DIR microhttpd.h)
find_library(MHD_LIBRARY NAMES microhttpd)
find_library(BOOSTTEST_LIBRARY NAMES boost_unit_test_framework)
find_library(BOOSTPO_LIBRARY NAMES boost_program_options)
find_library(BOOSTSYSTEM_LIBRARY NAMES boost_system)
find_path(TCMALLOC_INCLUDE_DIR gperftools/heap-profiler.h)
find_library(TCMALLOC_LIBRARY NAMES tcmalloc_and_profiler)
find_path(HIREDIS_INCLUDE_DIR hiredis/hiredis.h)
find_library(HIREDIS_LIBRARY NAMES hiredis)
find_path(GD_INCLUDE_DIR gd.h)
find_library(GD_LIBRARY NAMES gd)
find_program(THRIFT_COMPILER thrift)
find_path(THRIFT_INCLUDE_DIR thrift)
find_library(THRIFT_LIBRARY NAMES thrift)

if(CARES_INCLUDE_DIR AND CARES_LIBRARY)
  message(STATUS "found cares")
endif()

if(CURL_FOUND)
  message(STATUS "found curl")
endif()

if(PROTOBUF_FOUND)
  message(STATUS "found protobuf")
endif()

if(TCMALLOC_INCLUDE_DIR AND TCMALLOC_LIBRARY)
  message(STATUS "found tcmalloc")
endif()

if(ZLIB_FOUND)
  message(STATUS "found zlib")
endif()

if(HIREDIS_INCLUDE_DIR AND HIREDIS_LIBRARY)
  message(STATUS "found hiredis")
endif()

if(GD_INCLUDE_DIR AND GD_LIBRARY)
  message(STATUS "found gd")
endif()

if(THRIFT_COMPILER AND THRIFT_INCLUDE_DIR AND THRIFT_LIBRARY)
  message(STATUS "found thrift")
endif()

include_directories(${Boost_INCLUDE_DIRS})

include_directories(${PROJECT_SOURCE_DIR})

string(TOUPPER ${CMAKE_BUILD_TYPE} BUILD_TYPE)
message(STATUS "CXX_FLAGS = " ${CMAKE_CXX_FLAGS} " " ${CMAKE_CXX_FLAGS_${BUILD_TYPE}})

add_subdirectory(muduo/base)
add_subdirectory(muduo/net)

if(MUDUO_BUILD_EXAMPLES)
  add_subdirectory(contrib)
  add_subdirectory(examples)
else()
  if(CARES_INCLUDE_DIR AND CARES_LIBRARY)
    add_subdirectory(examples/cdns)
  endif()
endif()

很长,一块一块分析

1.1

cmake_minimum_required(VERSION 2.6)

project(muduo C CXX)

    这两行是设置cmake版本和工程名字,关于project,前一片文章有project原型,project可以设置版本号等等,但是设置语言的时候LANGUAGE关键词可以省略,这里设置语言是C和C++。

1.2 测试单元

enable_testing()

    这个单独放一行是因为前面没有讲过cmake的测试单元。

1.2.1 enable_testing和add_test

    enable_testing() 命令可以启用测试。但是要在根目录下的CMakeLists.txt中开启,不然执行make test时会报错。

    add_test()命令原型

add_test(NAME <name> COMMAND <command> [<arg>...]
         [CONFIGURATIONS <config>...]
         [WORKING_DIRECTORY <dir>]
         [COMMAND_EXPAND_LISTS])
  • NAME:指定本测试的名称。
  • COMMAND:指定测试命令行。如果<command>指定了一个可执行目标(由add_executable()创建),它将自动替换为生成时创建的可执行文件的位置。
  • CONFIGURATIONS :Debug/Release选项可以控制在不同的编译版本下是否进行测试。
  • WORKING_DIRECTORY:指定要在其中执行测试的工作目录。如果未指定,测试将在当前工作目录设置为与当前源目录对应的生成目录的情况下运行。
  • COMMAND_EXPAND_LISTS:3.16版新增。命令参数中的列表将展开,包括使用生成器表达式创建的列表。

    CTest遵循的标准约定是:返回零意味着成功,非零返回意味着失败。可以返回零或非零的脚本都可以做测试用例。

1.2.2 测试单元示例

    这个示例来自CMake I 创建一个简单的单元测试,复现一遍。

// sum_integers.h
#ifndef __SUM_INTEGERS_H__
#define __SUM_INTEGERS_H__

#include <vector>

int sum_integers(const std::vector<int>& integers);

#endif



// sum_integers.cpp
#include <vector>
#include "sum_integers.h"

int sum_integers(const std::vector<int> integers){
        auto sum = 0;
        for(auto i : integers){
                sum += i;
        }

        return sum;
}


// demo.cpp
#include <vector>
#include <iostream>
#include <string>

#include "sum_integers.h"

int main(int argc, char* argv[]){
        std::vector<int> integers;
        for(auto i = 1; i < argc; ++i){
                integers.push_back(std::stoi(argv[i]));
        }

        auto sum = sum_integers(integers);
        std::cout << sum << std::endl;

        return 0;
}
// test.cpp
#include <vector>
#include "sum_integers.h"

int main(){
        std::vector<int> integers = {1, 2, 3, 4, 5};
        if(sum_integers(integers) == 15){
                return 0;
        }
        else{
                return -1;
        }
}
// CMakeLists.txt
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(testUnit CXX)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_libraries(sum_integers sum_integers.cpp)

add_executable(mydemo demo.cpp)
add_link_libraries(mydemo sum_integers)

add_executable(mytest test.cpp)
target_link_libraries(mytest sum_integers)

enable_test()
add_test(NAME mytest COMMAND $<TARGET_FILE:mytest>)

运行以下指令

cmake -B build
cd ./build && make
ctest -C DEBUG

最终得到

 并且在./build文件夹下生成Testing文件,里面包括test的log文件等文件。cmake确实NB。

1.2.2 测试单元示例(采用gtest)

这个示例来自CMake - 单元测试和 GoogleTest 简单使用讲解了cmake调用gtest的使用。

1.3

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE "Release")
endif()

# only build examples if this is the main project
if(CMAKE_PROJECT_NAME STREQUAL "muduo")
  option(MUDUO_BUILD_EXAMPLES "Build Muduo examples" ON)
endif()

定义CMAKE_BUILD_TYPE。

    option;命令原型

option(<OPTION_NAME> "<help_text>" [value])

value为选项默认值,依据选项类型设置,没有给默认值则设置为OFF。这里是把MUDUO_BUILD_EXAMPLES值设置为ON。

    那么option和set有什么区别呢

  • option 命令提供了一个命令行选项,允许用户从命令行指定变量的值。例如,如果我们在 CMakeLists.txt 中使用 option 命令定义一个名为 MUDUO_BUILD_EXAMPLES 的选项,则可以在命令行上使用 -DMUDUO_BUILD_EXAMPLES=ON 或 -DMUDUO_BUILD_EXAMPLES=OFF 来指定该选项的值。

  • set 命令不提供命令行选项,只能在 CMakeLists.txt 中直接设置变量的值。例如,如果我们在 CMakeLists.txt 中使用 set 命令定义一个名为 MY_VAR 的变量,则只能在 CMakeLists.txt 中直接指定该变量的值。

    如果看过前面的set CACHE的话,这里oiption和set CACHE很像,都可以通过命令行设置变量的值,不过option有一个很像的cmake_dependent_option命令,具体见CMakeDependentOption

1.4

set(CXX_FLAGS
 -g
 # -DVALGRIND
 -DCHECK_PTHREAD_RETURN_VALUE
 -D_FILE_OFFSET_BITS=64
 -Wall
 -Wextra
 -Werror
 -Wconversion
 -Wno-unused-parameter
 -Wold-style-cast
 -Woverloaded-virtual
 -Wpointer-arith
 -Wshadow
 -Wwrite-strings
 -march=native
 # -MMD
 -std=c++11
 -rdynamic
 )

设置g++编译器的参数,简单回忆一下

-D:定义宏;-Wall:Warn all,警告全都输出出来;-Wextra:额外警告输出(编译器会判断参数使用啊,可能内存泄漏啊等等);-Werror:将警告当作错误显示;-Wconversion:从较宽类型到较窄类型的隐式转换时会产生警告(比如size_t->int);-Wno-unused-parameter:不显示未使用的参数告警;-Wold-style-cast:C风格的转换,给出警告(就是使用static_cast、dynamic_cast和const_cast转换);-Woverloaded-virtual:如果函数的声明隐藏住了基类的虚函数,就给出警告;-Wpointer-arith:对函数指针或者void *类型的指针进行算术操作时给出警告;-Wshadow:当一个局部变量遮盖住了另一个局部变量,或者全局变量时,给出警告;-Wwrite-strings:规定字符串常量的类型是const char[length],因此,把这样的地址复制给 non-const char *指针将产生警告(这些警告能在编译期间发现企图写入字符串常量的代码);-march=native:指定cpu体系结构为本地平台;-rdynamic:它将指示连接器把所有符号(而不仅仅只是程序已使用到的外部符号)都添加到动态符号表(即.dynsym表)里。

 1.5

if(CMAKE_BUILD_BITS EQUAL 32)
  list(APPEND CXX_FLAGS "-m32")
endif()

if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
  list(APPEND CXX_FLAGS "-Wno-null-dereference")
  list(APPEND CXX_FLAGS "-Wno-sign-conversion")
  list(APPEND CXX_FLAGS "-Wno-unused-local-typedef")
  list(APPEND CXX_FLAGS "-Wthread-safety")
  list(REMOVE_ITEM CXX_FLAGS "-rdynamic")
endif()

string(REPLACE ";" " " CMAKE_CXX_FLAGS "${CXX_FLAGS}")

指定是否32位编译,是否用clang编译器。最后把CMAKE_CXX_FLAGS中的“;”换成空格。

1.6

set(CMAKE_CXX_FLAGS_DEBUG "-O0")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)

设置优化方法,设置输出可执行文件的的输出路径和库的输出路径。

1.7

find_package(Boost REQUIRED)
find_package(Protobuf)
find_package(CURL)
find_package(ZLIB)
find_path(CARES_INCLUDE_DIR ares.h)
find_library(CARES_LIBRARY NAMES cares)
find_path(MHD_INCLUDE_DIR microhttpd.h)
find_library(MHD_LIBRARY NAMES microhttpd)
find_library(BOOSTTEST_LIBRARY NAMES boost_unit_test_framework)
find_library(BOOSTPO_LIBRARY NAMES boost_program_options)
find_library(BOOSTSYSTEM_LIBRARY NAMES boost_system)
find_path(TCMALLOC_INCLUDE_DIR gperftools/heap-profiler.h)
find_library(TCMALLOC_LIBRARY NAMES tcmalloc_and_profiler)
find_path(HIREDIS_INCLUDE_DIR hiredis/hiredis.h)
find_library(HIREDIS_LIBRARY NAMES hiredis)
find_path(GD_INCLUDE_DIR gd.h)
find_library(GD_LIBRARY NAMES gd)
find_program(THRIFT_COMPILER thrift)
find_path(THRIFT_INCLUDE_DIR thrift)
find_library(THRIFT_LIBRARY NAMES thrift)

找库找包。既然已经有了target_include_directories、target_link_directories和target_link_libaries为什么还要找这些东西,显然是为了程序的移植性。find_package还挺复杂,详见“轻松搞定CMake”系列之find_package用法详解使用find_package引入外部依赖包Cmake之深入理解find_package()的用法。可能还会对.cmak文件和cmake.in文件有疑问,见cmake .in文件

find_package、find_path、find_library和find_program区别:

  • find_package:会在cmake的目录下寻找.cmake文件(我的寻找路径是/usr/shared/cmake-3.16/Modules,一般都在cmake的Modules文件夹下),然后在.cmake文件中都会定义<libname>_FOUND变量、<libname>_INCLUDE_DIR或<libname>_INCLUDE变量、<libname>_LIBRARY_DIR变量,直接通过这些变量可以判断库是否存在,库include的路径和库链接的路径。
  • find_path命令原型如下
find_path (
          VAR
          NAMES name1 [name2 ...] 
          [HINTS [path | ENV var]... ]
          [PATHS [path | ENV var]... ]
          [NO_CACHE]
          [REQUIRED]
)
  • (1) VAR:用于保存命令的执行结果;(2) NAMES:要查找的头文件;(3) HINTS | PATHS    HINTS:先搜索指定路径,后搜索系统路径;PATHS:先搜索系统路径,后搜索指定路径;(4) NO_CACHE:搜索结果将存储在普通变量中而不是缓存条目(即CMakeCache.txt)中;(5) REQUIRED:如果没有找到指定头文件,就出发错误提示,变量会设为 VAR-NOTFOUND
  • find_library命令原型
find_library (
          LIBRARY_NAME
          NAMES name1 [name2 ...] 
          [NAMES_PER_DIR]
          [HINTS [path | ENV var]... ]
          [PATHS [path | ENV var]... ]
          [NO_CACHE]
          [REQUIRED]
)
  • (1) LIBRARY_NAME:库名。允许两种形式,前缀+库名+后缀、只有库名;(2) NAMES_PER_DIR:表示一个名称遍历查找一次。而不是在某个路径下,查看是否存在多个库。
  • find_program命令原型
find_program (
          VAR
          name | NAMES name1 [name2 ...] 
          [NAMES_PER_DIR]
          [HINTS [path | ENV var]... ]
          [PATHS [path | ENV var]... ]
          [NO_CACHE]
          [REQUIRED]
)

参数同理。

    总体来说区别就是,如果库构建的考虑cmake,会在cmake的Modules文件夹下构建自己的.cmake文件描述自己的库的位置,一次性可以获得所有参数(包括一些其他的参数还有依赖);而剩下三个方法则是在CMAKE的环境变量CMAKE_INCLUDE_PATH、CMAKE_LIBRARY_PATH、CMAKE_PROGRAM_PATH中寻找。

    上面muduo库cmake后从cache文档中可以看到

// Boost库——有
Boost_DIR:PATH=/usr/lib/cmake/Boost-1.80.0
Boost_INCLUDE_DIR:PATH=/usr/include

// Protobuf库——没有都是NONFOUND
Protobuf_INCLUDE_DIR:PATH=Protobuf_INCLUDE_DIR-NOTFOUND
Protobuf_LIBRARY_DEBUG:FILEPATH=Protobuf_LIBRARY_DEBUG-NOTFOUND
Protobuf_LIBRARY_RELEASE:FILEPATH=Protobuf_LIBRARY_RELEASE-NOTFOUND
Protobuf_LITE_LIBRARY_DEBUG:FILEPATH=Protobuf_LITE_LIBRARY_DEBUG-NOTFOUND
Protobuf_LITE_LIBRARY_RELEASE:FILEPATH=Protobuf_LITE_LIBRARY_RELEASE-NOTFOUND
Protobuf_PROTOC_EXECUTABLE:FILEPATH=Protobuf_PROTOC_EXECUTABLE-NOTFOUND
Protobuf_PROTOC_LIBRARY_DEBUG:FILEPATH=Protobuf_PROTOC_LIBRARY_DEBUG-NOTFOUND
Protobuf_PROTOC_LIBRARY_RELEASE:FILEPATH=Protobuf_PROTOC_LIBRARY_RELEASE-NOTFOUND

// CURL库——没有
CURL_INCLUDE_DIR:PATH=CURL_INCLUDE_DIR-NOTFOUND
CURL_LIBRARY_DEBUG:FILEPATH=CURL_LIBRARY_DEBUG-NOTFOUND
CURL_LIBRARY_RELEASE:FILEPATH=CURL_LIBRARY_RELEASE-NOTFOUND

// ZLIB库——有
ZLIB_INCLUDE_DIR:PATH=/usr/include
ZLIB_LIBRARY_DEBUG:FILEPATH=ZLIB_LIBRARY_DEBUG-NOTFOUND
ZLIB_LIBRARY_RELEASE:FILEPATH=/usr/lib/x86_64-linux-gnu/libz.so

// ares库——没有
CARES_INCLUDE_DIR:PATH=CARES_INCLUDE_DIR-NOTFOUND
CARES_INCLUDE_DIR:PATH=CARES_INCLUDE_DIR-NOTFOUND

// MHD库——没有
MHD_INCLUDE_DIR:PATH=MHD_INCLUDE_DIR-NOTFOUND
MHD_LIBRARY:FILEPATH=MHD_LIBRARY-NOTFOUND

...

 1.8

if(CARES_INCLUDE_DIR AND CARES_LIBRARY)
  message(STATUS "found cares")
endif()
if(CURL_FOUND)
  message(STATUS "found curl")
endif()
if(PROTOBUF_FOUND)
  message(STATUS "found protobuf")
endif()
if(TCMALLOC_INCLUDE_DIR AND TCMALLOC_LIBRARY)
  message(STATUS "found tcmalloc")
endif()
if(ZLIB_FOUND)
  message(STATUS "found zlib")
endif()
if(HIREDIS_INCLUDE_DIR AND HIREDIS_LIBRARY)
  message(STATUS "found hiredis")
endif()
if(GD_INCLUDE_DIR AND GD_LIBRARY)
  message(STATUS "found gd")
endif()
if(THRIFT_COMPILER AND THRIFT_INCLUDE_DIR AND THRIFT_LIBRARY)
  message(STATUS "found thrift")
endif()

判断是否找到那些库。

1.9

include_directories(${Boost_INCLUDE_DIRS})

include_directories(${PROJECT_SOURCE_DIR})

把boost库所在的include文件路径添加到顶层cmake(这是全局的变量,即使子cmake文件也是可见)。

1.10

string(TOUPPER ${CMAKE_BUILD_TYPE} BUILD_TYPE)
message(STATUS "CXX_FLAGS = " ${CMAKE_CXX_FLAGS} " " ${CMAKE_CXX_FLAGS_${BUILD_TYPE}})

就修改字符串,然后输出,告诉g++是release还是debug。

1.11

add_subdirectory(muduo/base)
add_subdirectory(muduo/net)

if(MUDUO_BUILD_EXAMPLES)
  add_subdirectory(contrib)
  add_subdirectory(examples)
else()
  if(CARES_INCLUDE_DIR AND CARES_LIBRARY)
    add_subdirectory(examples/cdns)
  endif()
endif()

调用子CMakeLists.txt内容。

1.12 muduo/base/CMakeLists.txt

set(base_SRCS
  AsyncLogging.cc
  Condition.cc
  CountDownLatch.cc
  CurrentThread.cc
  Date.cc
  Exception.cc
  FileUtil.cc
  LogFile.cc
  Logging.cc
  LogStream.cc
  ProcessInfo.cc
  Timestamp.cc
  Thread.cc
  ThreadPool.cc
  TimeZone.cc
  )

add_library(muduo_base ${base_SRCS})
target_link_libraries(muduo_base pthread rt)

#add_library(muduo_base_cpp11 ${base_SRCS})
#target_link_libraries(muduo_base_cpp11 pthread rt)
#set_target_properties(muduo_base_cpp11 PROPERTIES COMPILE_FLAGS "-std=c++0x")

install(TARGETS muduo_base DESTINATION lib)
#install(TARGETS muduo_base_cpp11 DESTINATION lib)

file(GLOB HEADERS "*.h")
install(FILES ${HEADERS} DESTINATION include/muduo/base)

if(MUDUO_BUILD_EXAMPLES)
  add_subdirectory(tests)
endif()

install详见【CMake】cmake的install指令【CMake install 命令】精通CMake安装:灵活、高效的构建和部署

对于一个项目,一般需要经过./configure、make和make install。./configure过程就是检查环境等产生本机的makefile文件,make阶段生成库文件、include文件和可执行文件。make install就算是将库文件、可执行文件和include文件写入指定路径下(一般)是usr/loacl/bin usr/local/share usr/local/include等等文件下。而make和make install所执行的东西都写在makefile文件中。cmake这些执行令就是为了生成makefile,所以install命令也是配置makefile的内容。

1.13 muduo/net/CMakeLists.txt

include(CheckFunctionExists)

check_function_exists(accept4 HAVE_ACCEPT4)
if(NOT HAVE_ACCEPT4)
  set_source_files_properties(SocketsOps.cc PROPERTIES COMPILE_FLAGS "-DNO_ACCEPT4")
endif()

set(net_SRCS
  Acceptor.cc
  Buffer.cc
  Channel.cc
  Connector.cc
  EventLoop.cc
  EventLoopThread.cc
  EventLoopThreadPool.cc
  InetAddress.cc
  Poller.cc
  poller/DefaultPoller.cc
  poller/EPollPoller.cc
  poller/PollPoller.cc
  Socket.cc
  SocketsOps.cc
  TcpClient.cc
  TcpConnection.cc
  TcpServer.cc
  Timer.cc
  TimerQueue.cc
  )

add_library(muduo_net ${net_SRCS})
target_link_libraries(muduo_net muduo_base)

#add_library(muduo_net_cpp11 ${net_SRCS})
#target_link_libraries(muduo_net_cpp11 muduo_base_cpp11)
#set_target_properties(muduo_net_cpp11 PROPERTIES COMPILE_FLAGS "-std=c++0x")

install(TARGETS muduo_net DESTINATION lib)
#install(TARGETS muduo_net_cpp11 DESTINATION lib)

set(HEADERS
  Buffer.h
  Callbacks.h
  Channel.h
  Endian.h
  EventLoop.h
  EventLoopThread.h
  EventLoopThreadPool.h
  InetAddress.h
  TcpClient.h
  TcpConnection.h
  TcpServer.h
  TimerId.h
  )
install(FILES ${HEADERS} DESTINATION include/muduo/net)

add_subdirectory(http)
add_subdirectory(inspect)

if(MUDUO_BUILD_EXAMPLES)
  add_subdirectory(tests)
endif()

if(PROTOBUF_FOUND)
  add_subdirectory(protobuf)
  add_subdirectory(protorpc)
else()
  add_subdirectory(protobuf EXCLUDE_FROM_ALL)
  add_subdirectory(protorpc EXCLUDE_FROM_ALL)
endif()

这个指令是导入.cmake文件,有些函数可能需要经常使用,所以就写入.cmake文件中,以后写cmake文件时通过include导入这个函数或者宏,就可以直接使用了,像例子中的CheckFunctionExists包含check_function_exists函数,这个函数是检查某个函数是否存在,比如

首先是include,这个指令是导入.cmake文件,有些函数可能需要经常使用,所以就写入.cmake文件中,以后写cmake文件时通过include导入这个函数或者宏,就可以直接使用了,像例子中的CheckFunctionExists包含check_function_exists函数,这个函数是检查某个函数是否存在,比如实例中是检查是否存在accept4函数。

二、libco的CMake

    coming soon

三、marl的CMake

    coming soon

  • 11
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值