cmake入门三 模块的使用和自定义模块

工程描述

1、cmake 提供的 FindCURL 模块的使用
2、基于自己实现的libhello共享库,编写一个 FindHello.cmake模块

cmake 模块介绍

系统中提供了其他各种模块,一般情况需要使用INCLUDE指令显式的调用,FIND_PACKAGE指令是一
个特例,可以直接调用预定义的模块。其实使用纯粹依靠cmake 本身提供的基本指令来管理工程是一件非常复杂的事情,所以,cmake 设计成了可扩展的架构,可以通过编写一些通用的模块来扩展cmake。

对于系统预定义的Find.cmake模块,使用方法一般如上例所示:
每一个模块都会定义以下几个变量

_FOUND
_INCLUDE_DIR or _INCLUDES
_LIBRARY or _LIBRARIES

你可以通过_FOUND来判断模块是否被找到,如果没有找到,按照工程的需要关闭
某些特性、给出提醒或者中止编译,下面的例子就是报出致命错误并终止构建。
如果_FOUND为真,则将_INCLUDE_DIR 加入INCLUDE_DIRECTORIES,
_LIBRARY 加入 TARGET_LINK_LIBRARIES中。

使用系统预定义好的FindCURL模块

工程结构

cmake入门三 模块的使用和自定义模块_第1张图片

1.1 工程目录下CMakeLists.txt

# 指定工程名称
PROJECT(CURLTEST)

# 添加子目录,src下有编译源文件,CMakeLists.txt, 生成的可执行文件在output目录下
ADD_SUBDIRECTORY(src output)

1.2 src目录下的CMakeLists.txt

# 基于main.c生成目标程序curltest
ADD_EXECUTABLE(curltest main.c)
  
# 不使用FindCURL模块时,需要指定libcurl的头文件、链接库名称、链接路径
# 这里要注意库的信息放在ADD_EXECUTABLE后面,否则cmake报错,亲测。。

#INCLUDE_DIRECTORIES(/usr/include)
#LINK_DIRECTORIES(/usr/lib64)
#TARGET_LINK_LIBRARIES(curltest curl)

# 使用系统预定义的FindCURL模块
FIND_PACKAGE(CURL)
IF(CURL_FOUND)
        INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIR})
        TARGET_LINK_LIBRARIES(curltest ${CURL_LIBRARY})
ELSE(CURL_FOUND)
        MESSAGE(FATAL_ERROR ”CURL library not found”)
ENDIF(CURL_FOUND)

1.3 src目录下的main.c

/*
功能:这段代码的作用是通过curl取回www.linux-ren.org 的首页并写入/tmp/curl-test
文件中。
*/

#include 
#include 
#include 
#include 

FILE *fp;

int write_data(void *ptr, size_t size, size_t nmemb, void *stream)
{
        int written = fwrite(ptr, size, nmemb, (FILE *)fp);
        return written;
}

int main()
{
        const char * path = "/tmp/curl-test";
        const char * mode = "w";
        fp = fopen(path,mode);
        curl_global_init(CURL_GLOBAL_ALL);
        CURLcode res;
        CURL *curl = curl_easy_init();
        curl_easy_setopt(curl, CURLOPT_URL,"http://www.linux-ren.org");
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
        res = curl_easy_perform(curl);
        curl_easy_cleanup(curl);
}

1.4 编译目录下执行cmake

cmake入门三 模块的使用和自定义模块_第2张图片

1.4 编译完成后编译目录的结构

cmake入门三 模块的使用和自定义模块_第3张图片

自定义 FindHello.cmake模块

工程结构

cmake入门三 模块的使用和自定义模块_第4张图片

1.1 工程目录下的CMakeLists.txt

cmake_minimum_required(VERSION 3.16)

# 指定工程名称
PROJECT(CURLTEST)

# 设置动态库的生成路径 下面2种语法都可以
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)
#SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

# 生成libhello.so 动态库
SET(LIBHELLO_SRC ${PROJECT_SOURCE_DIR}/src/hello.c)
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

# 指定工程目录下自定义的 .cmake  模块
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)

# 添加子目录,src下有编译源文件,CMakeLists.txt, 生成的可执行文件在output目录下
ADD_SUBDIRECTORY(src output)

1.2 cmake 目录下自定义的FindHELLO模块 FindHELLO.cmake

# 搜索依赖库的头文件和依赖库的路径
FIND_PATH(HELLO_INCLUDE_DIR NAMES hello.h PATHS ${PROJECT_SOURCE_DIR}/include)
FIND_LIBRARY(HELLO_LIBRARY NAMES hello PATHS ${PROJECT_SOURCE_DIR}/lib) 

# 日志打印  用以调试
MESSAGE(STATUS "include: ${HELLO_INCLUDE_DIR}")
MESSAGE(STATUS "lib: ${HELLO_LIBRARY}")
MESSAGE(STATUS "dir: ${PROJECT_SOURCE_DIR}")

# 设置HELLO_FOUND模块, 在src/CMakeLists.txt 中使用
IF (HELLO_INCLUDE_DIR AND HELLO_LIBRARY)
	SET(HELLO_FOUND TRUE)
ENDIF (HELLO_INCLUDE_DIR AND HELLO_LIBRARY)

IF (HELLO_FOUND)
		MESSAGE(STATUS "Found Hello: ${HELLO_LIBRARY}")
ELSE (HELLO_FOUND)
		MESSAGE(FATAL_ERROR "Could not find hello library")
ENDIF (HELLO_FOUND)

1.3 src 目录下的CMakeLists.txt

# FIND_PACKAGE(HELLO QUIET) 指定 HELLO_FIND_QUIETLY FindHELLO.cmake中的控制逻辑
FIND_PACKAGE(HELLO)
IF(HELLO_FOUND)
	ADD_EXECUTABLE(test main.c)
	INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include)
	TARGET_LINK_LIBRARIES(test hello)
ELSE(HELLO_FOUND)
        MESSAGE(FATAL_ERROR "hello package not found")
ENDIF(HELLO_FOUND)

1.4 src目录下的main.c

#include 
int main()
{
	HelloFunc();
	return 0;
}

1.5 src 目录下的hello.c

#include "../include/hello.h"

void HelloFunc()
{
	printf("Hello World\n");
}

1.6 include 目录下的hello.h

#ifndef HELLO_H
#define HELLO_H
#include 
void HelloFunc();
#endif

1.7 编译目录下执行cmake

cmake入门三 模块的使用和自定义模块_第5张图片

1.8 编译完成后的目录结构

cmake入门三 模块的使用和自定义模块_第6张图片
cmake入门三 模块的使用和自定义模块_第7张图片
问题:这里如果要加入自定义的FindHELLO模块,需要在lib下先生成libhello.so,不然cmake报错,
cmake入门三 模块的使用和自定义模块_第8张图片
这里暂时没想到什么好的方法,只是把工程目录下CMakeLists.txt的 src包含 和 自动义FindHELLO模块屏蔽掉先生成libhello.so,然后再恢复编译
cmake入门三 模块的使用和自定义模块_第9张图片

你可能感兴趣的:(c编译,c++,开发语言,cmake)