CMakeLists.txt写法

1 常用命令

1.1 单文件夹项目

CMAKE_MINIMUM_REQUIRED(VERSION 3.10)    #规定cmake最低版本号,其中“3.10”可变

PROJECT(demo)   #项目名称,基本没影响 

ADD_EXECUTABLE(hello hello.c)   
#hello为可执行文件的名字,hello.c为源文件,可以有多个源文件,源文件之间以空格隔开,并且只需写.c或者.cpp文件

AUX_SOURCE_DIRECTORY(./ DIR_SRC)
#意思是将当前目录下的所有源文件指代为名为“DIR_SRC"的变量
#可以配合ADD_EXECUTABLE(hello ${DIR_SRC})使用,减少输入量

1.2 多文件夹项目

ADD_LIBRARY(TEST SHARED ${DIR_LIB})
#将DIR_LIB所指代的源代码,生成libMYLIB.so动态运行库文件
#第二个参数为指代生成动态运行库,静态库参数为STATIC

ADD_SUBDIRECTORY(./sublib) #添加项目子目录,并执行子目录下的cmake文件
#一般写在父目录的cmake文件内

TARGET_LINK_LIBRARIES(hello TEST)
#将hello可执行程序连接名为TEST的动态或静态库文件
#第一个参数为ADD_EXECUTABLE生成的可执行文件名 第二个参数为动态库或静态库名

INCLUDE_DIRECTORIES(./demo/include)
#include的.h文件搜索路径使得.c文件引用可以省略前面的路径
#参数可以有多个,每个参数之间以空格隔开

LINK_DIRECTORIES(./lib)
#指明要引用的.so或.a路径,与TARGET_LINK_LIBRARIES配合使用
#参数可以有多个,每个参数之间以空格隔开

LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so")
#要引用的.so或.a文件的所在位置,每个参数都要表明全路径
#这一条命令的效果与LINK_DIRECTORIES和TARGET_LINK_LIBRARIES合体等同

ADD_DEFINITIONS(-DGPU)
#向c语言文件添加预定义宏,相当于在c文件中使用#define GPU

例子1

INCLUDE_DIRECTORIES("/opt/MATLAB/R2012a/extern/include")    
LINK_DIRECTORIES("/opt/MATLAB/R2012a/bin/glnxa64")      
ADD_EXECUTABLE(myProject main.cpp)     
target_link_libraries(myProject eng mx)     
#equals to below 
#target_link_libraries(myProject -leng -lmx) 
#target_link_libraries(myProject libeng.so libmx.so)

例子2

INCLUDE_DIRECTORIES("/opt/MATLAB/R2012a/extern/include")  
#directly link to the libraries. 
LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so") 
LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libmx.so")
#equals to below 
#LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so" "/opt/MATLAB/R2012a/bin/glnxa64/libmx.so") 
ADD_EXECUTABLE(myProject main.cpp

1.3 set 命令常用用法

(1)用法1设置普通变量

SET(OPENCL_PATH /usr/local/OpenCL) #设置OpenCL_PATH为/usr.....
#此种用法也可以为变量设置多个值,每个值以空格隔开
SET(EXECUTABLE_OUTPUT_PATH  ${PROJECT_SOURCE_DIR}\build)
#可执行文件放在源代码目录的build文件夹下
#EXECUTABLE_OUTPUT_PATH为CMake预定义宏,指代可执行文件路径
#PROJECT_SOURCE_DIR为CMake预定义宏,指代拥有project命令的cmakelists文件位置
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}\lib)
#设置library文件输出位置为build\lib目录下,与ADD_LIBRARY一起使用
#LIBRARY_OUTPUT_PATH为CMake预定义宏,指代lib文件输出文职
#PROJECT_BINARY_DIR指代build文件位置

(2)设置缓存条目
缓存条目可以通过CMAKE的GUI界面的add entry按钮来增加。缓存条目的实质为可以跨层级进行传递的变量,类似于全局变量

SET(cache_entry_val2 ON CACHE BOOL "choose ON to enable" FORCE)
#第一个参数为变量名;第二个参数为变量值;第三个参数指明为缓存条目;
#第四个参数为变量的类型,除BOOL外还有FILEPATH、PATH、STRING / STRINGS、INTERNAL;
#第五个参数是变量的解释,供阅读者理解
#第五个参数FORCE用于是否强制更新缓存里面的值,配置后,每次都会强制更新

1.4 OPTION命令

option(TEST_DEBUG "option for debug" OFF)
#设置cmake选项,可与if endif结合是使用

2 实战例子(OpenCL+CMAKE)

2.1 文件树

在这里插入图片描述

2.2 CMakeLists.txt内容

CMAKE_MINIMUM_REQUIRED(VERSION 3.10)
PROJECT(DEMO4-15-1)
INCLUDE_DIRECTORIES(/usr/include/)
LINK_DIRECTORIES(/usr/local/lib /usr/lib/aarch64-linux-gnu/)
ADD_EXECUTABLE(demo4-15-1 src/main.c)
TARGET_LINK_LIBRARIES(demo4-15-1 -lOpenCL)

2.3 main.c文件内容

#include <stdio.h>
#include <CL/cl.h>
#include <iostream>
#include "ocl_macros.h"

#define NUM_OF_ELEMENTS 32 

int main(int argc, char *argv[])
{
    cl_int status = 0;
    cl_device_type dType = CL_DEVICE_TYPE_GPU;
    cl_platform_id platform = NULL;
    cl_device_id   device;
    cl_context     context;
    cl_command_queue commandQueue;
    cl_mem clBuffer;
    cl_int hostBuffer[NUM_OF_ELEMENTS] =
    {
         0,  1,  2,  3, 
         4,  5,  6,  7,
         8,  9, 10, 11, 
        12, 13, 14, 15,
        16, 17, 18, 19,
        20, 21, 22, 23, 
        24, 25, 26, 27,
        28, 29, 30, 31, 
    };

    //Setup the OpenCL Platform, 
    //Get the first available platform. Use it as the default platform
    status = clGetPlatformIDs(1, &platform, NULL);
    LOG_OCL_ERROR(status, "clGetPlatformIDs Failed..." );

    //Get the first available device 
    status = clGetDeviceIDs (platform, dType, 1, &device, NULL);
    LOG_OCL_ERROR(status, "clGetDeviceIDs Failed..." );
    
    //Create an execution context for the selected platform and device. 
    cl_context_properties cps[3] = 
    {
        CL_CONTEXT_PLATFORM,
        (cl_context_properties)platform,
        0
    };
    context = clCreateContextFromType(
        cps,
        dType,
        NULL,
        NULL,
        &status);
    LOG_OCL_ERROR(status, "clCreateContextFromType Failed..." );

    // Create command queue
    commandQueue = clCreateCommandQueue(context,
                                        device,
                                        0,
                                        &status);
    LOG_OCL_ERROR(status, "clCreateCommandQueue Failed..." );

    //Create OpenCL device input buffer
    clBuffer = clCreateBuffer(
        context,
        CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
        sizeof(cl_uint) * NUM_OF_ELEMENTS,
        hostBuffer,
        &status); 
    LOG_OCL_ERROR(status, "clCreateBuffer Failed..." );

    //Read a 2D rectangular object from the clBuffer of 32 elements
    int hostPtr2D[6] = {0, 0, 0, 0, 0, 0};
    size_t bufferOrigin2D[3] = {1*sizeof(int), 6, 0};
    size_t hostOrigin2D[3] = {0 ,0, 0};
    size_t region2D[3] = {3* sizeof(int), 2,1};
    status = clEnqueueReadBufferRect(
                        commandQueue,
                        clBuffer,
                        CL_TRUE,
                        bufferOrigin2D, /*Start of a 2D buffer to read from*/
                        hostOrigin2D,
                        region2D,
                        (NUM_OF_ELEMENTS / 8) * sizeof(int), /*buffer_row_pitch  */
                        0,                                   /*buffer_slice_pitch*/
                        0,                                   /*host_row_pitch    */
                        0,                                   /*host_slice_pitch  */
                        static_cast<void*>(hostPtr2D),
                        0,
                        NULL,
                        NULL);
    LOG_OCL_ERROR(status, "clEnqueueReadBufferRect Failed..." );
    std::cout << "2D rectangle selected is as follows" << std::endl;
    std::cout << " " << hostPtr2D[0];
    std::cout << " " << hostPtr2D[1];
    std::cout << " " << hostPtr2D[2] << std::endl;
    std::cout << " " << hostPtr2D[3];
    std::cout << " " << hostPtr2D[4];
    std::cout << " " << hostPtr2D[5] << std::endl;

    //Read a 3D rectangular object from the clBuffer of 32 elements
    int hostPtr3D[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
    size_t bufferOrigin3D[3] = {1*sizeof(int), 1, 0};
    size_t hostOrigin3D[3] = {0 ,0, 0};
    size_t region3D[3] = {3* sizeof(int), 1,3};
    status = clEnqueueReadBufferRect(
                        commandQueue,
                        clBuffer,
                        CL_TRUE,
                        bufferOrigin3D, /*Start of a 2D buffer to read from*/
                        hostOrigin3D,
                        region3D,
                        (NUM_OF_ELEMENTS / 8) * sizeof(int), /*buffer_row_pitch  */
                        (NUM_OF_ELEMENTS / 4) * sizeof(int), /*buffer_slice_pitch*/
                        0,                                   /*host_row_pitch    */
                        0,                                   /*host_slice_pitch  */
                        static_cast<void*>(hostPtr3D),
                        0,
                        NULL,
                        NULL);
    LOG_OCL_ERROR(status, "clEnqueueReadBufferRect Failed..." );
    std::cout << "3D rectangle selected is as follows" << std::endl;
    std::cout << " " << hostPtr3D[0];
    std::cout << " " << hostPtr3D[1];
    std::cout << " " << hostPtr3D[2] << std::endl;
    std::cout << " " << hostPtr3D[3];
    std::cout << " " << hostPtr3D[4];
    std::cout << " " << hostPtr3D[5] << std::endl;
    std::cout << " " << hostPtr3D[6];
    std::cout << " " << hostPtr3D[7];
    std::cout << " " << hostPtr3D[8] << std::endl;

    return 0;
}

ocl_macros.h内容

#if !defined OCL_MACROS_H
#define OCL_MACROS_H

#define LOG_OCL_ERROR(x, STRING )  if(x!=CL_SUCCESS) {printf( "\nLine No: %d ", __LINE__ ); printf(STRING); printf("\n    Error= %d\n",x); exit(-1); }

#define LOG_OCL_COMPILER_ERROR(PROGRAM, DEVICE)                                          \
        {                                                                                \
            cl_int logStatus;                                                            \
            char * buildLog = NULL;                                                      \
            size_t buildLogSize = 0;                                                     \
            logStatus = clGetProgramBuildInfo(PROGRAM,                                   \
                                              DEVICE,                                    \
                                              CL_PROGRAM_BUILD_LOG,                      \
                                              buildLogSize,                              \
                                              buildLog,                                  \
                                              &buildLogSize);                            \
            if(logStatus != CL_SUCCESS)                                                  \
            {                                                                            \
                printf( "Error # %d logStatus", logStatus );                             \
                printf( ":: clGetProgramBuildInfo<CL_PROGRAM_BUILD_LOG> failed.");       \
                exit(1);                                                                 \
            }                                                                            \
                                                                                         \
            buildLog = (char*)malloc(buildLogSize);                                      \
            if(buildLog == NULL)                                                         \
            {                                                                            \
                printf("Failed to allocate host memory. (buildLog)\n");                  \
                exit(1);                                                                 \
            }                                                                            \
            memset(buildLog, 0, buildLogSize);                                           \
                                                                                         \
            logStatus = clGetProgramBuildInfo(PROGRAM,                                   \
                                              DEVICE,                                    \
                                              CL_PROGRAM_BUILD_LOG,                      \
                                              buildLogSize,                              \
                                              buildLog,                                  \
                                              NULL);                                     \
            if(logStatus != CL_SUCCESS)                                                  \
            {                                                                            \
                printf( "Error # %d logStatus ", logStatus);                             \
                printf( ":: clGetProgramBuildInfo<CL_PROGRAM_BUILD_LOG> failed.");       \
                exit(1);                                                                 \
            }                                                                            \
                                                                                         \
            printf(" \n\t\t\tBUILD LOG\n");                                              \
            printf(" ************************************************\n");               \
            printf("%s",buildLog);                                                            \
            printf(" ************************************************\n");               \
            free(buildLog);                                                              \
            exit(1);                                                              \
        } 

/* Get platform information and set up the Platform for the defined vendor*/                                                            
#define OCL_CREATE_PLATFORMS( PLATFORM )                                      \
    cl_uint     num_platforms;                                                        \
    if ((clGetPlatformIDs(0, NULL, &num_platforms)) == CL_SUCCESS)                    \
    {                                                                                 \
        PLATFORM = (cl_platform_id *)malloc(sizeof(cl_platform_id)*num_platforms);    \
        if(clGetPlatformIDs(num_platforms, PLATFORM, NULL) != CL_SUCCESS)             \
        {                                                                             \
            free(PLATFORM);                                                           \
            exit(-1);                                                                 \
        }                                                                             \
    }                                                                                 

/*Release the Allocated Platforms*/
#define OCL_RELEASE_PLATFORMS( PLATFORM )                                             \
    free(PLATFORM);

#define OCL_CREATE_DEVICE( PLATFORM, DEVICE_TYPE, DEVICES )                                 \
    cl_uint     num_devices;                                                                \
    if (clGetDeviceIDs( PLATFORM, DEVICE_TYPE, 0,                                           \
            NULL, &num_devices) == CL_SUCCESS)                                              \
    {                                                                                       \
        DEVICES = (cl_device_id *)malloc(sizeof(cl_device_id)*num_devices);                 \
        if (clGetDeviceIDs( PLATFORM, DEVICE_TYPE, num_devices,                             \
            DEVICES, NULL) != CL_SUCCESS)                                                   \
        {                                                                                   \
            free(DEVICES);                                                                  \
            exit(-1);                                                                       \
        }                                                                                   \
    }
    
/*Release the Allocated Device*/
#define OCL_RELEASE_DEVICES( DEVICES )                                                 \
    free(DEVICES);
    
#endif

3 参考链接

(1)demo代码下载
https://github.com/AdamWSL/CMake_Tutorial.git
(2)cmake下载地址
https://cmake.org/download/
(3)CMake官方教程— CMake 3.17.0-rc1文档
https://cmake.org/cmake/help/latest/guide/tutorial/index.html
(4)CMake入门实战
https://www.hahack.com/codes/cmake/
(5)cmake使用示例与整理总结
https://blog.csdn.net/QTVLC/article/details/82380413
(6)CMake命令/函数汇总(翻译自官方手册)
https://www.cnblogs.com/52php/p/5684588.html
(7)CMake视频教程
https://www.bilibili.com/video/BV16V411k7eF?p=2

### 回答1: CMake是一个跨平台的构建工具,用于帮助开发者生成各种不同编译工具的构建脚本。在编写CMakeLists.txt文件时,可以使用多个源文件进行编译。 首先,在CMakeLists.txt文件中使用`add_executable`或`add_library`命令来指定生成的可执行文件或库文件的名称,并将其与源文件关联起来。 例如,如果我们有两个源文件main.cpp和helper.cpp,我们可以这样写: ```cmake cmake_minimum_required(VERSION 3.12) project(MyProject) add_executable(MyExecutable main.cpp helper.cpp) ``` 这个例子中,我们使用`add_executable`命令来生成一个名为MyExecutable的可执行文件,并将main.cpp和helper.cpp这两个源文件与之关联。 如果我们的项目中有更多的源文件,我们可以继续在`add_executable`或`add_library`命令后面继续添加源文件的名称。 ```cmake add_executable(MyExecutable main.cpp helper.cpp file1.cpp file2.cpp) ``` 当我们构建项目时,CMake会自动将这些源文件编译成目标文件,并链接到生成的可执行文件或库文件中。 此外,如果项目中有多个文件夹,并且每个文件夹中都有一些源文件,可以使用`add_subdirectory`命令将这些文件夹添加到构建过程中。 ```cmake add_subdirectory(folder1) add_subdirectory(folder2) ``` 这样可以让CMake在构建过程中进入这些文件夹并执行相应的CMakeLists.txt文件。 总结起来,CMakeLists.txt文件中的多文件编译可以通过`add_executable`或`add_library`命令与源文件进行关联,以及使用`add_subdirectory`命令将多个文件夹添加到构建过程中。 ### 回答2: cmakelists.txt是用于配置CMake编译和构建项目的脚本文件,它使用简单的语法来描述项目的文件结构和依赖关系。如果需要编译多个源文件,可以按照以下步骤编写CMakeLists.txt: 1. 设置项目名称和最低CMake版本: ```cmake cmake_minimum_required(VERSION 3.10) project(MyProject) ``` 2. 添加源文件到项目中,可以使用SET命令将需要编译的源文件路径存储在变量中: ```cmake set(SOURCES src/main.cpp src/other.cpp) ``` 3. 添加可执行文件目标,并将源文件与目标进行关联: ```cmake add_executable(MyExecutable ${SOURCES}) ``` 4. 如果需要链接外部库,可以使用target_link_libraries命令来指定链接的库: ```cmake target_link_libraries(MyExecutable MyLibrary) ``` 完整示例CMakeLists.txt文件: ```cmake cmake_minimum_required(VERSION 3.10) project(MyProject) set(SOURCES src/main.cpp src/other.cpp) add_executable(MyExecutable ${SOURCES}) target_link_libraries(MyExecutable MyLibrary) ``` 以上是最基本的多文件编译的CMakeLists.txt的编写方式,根据实际项目需求,还可以添加更多的配置选项和设置,例如编译选项、包含路径、链接库等。具体的写法会因项目而异。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值