linux上使用cmake编译的方法

news2025/1/5 16:07:50

一、hello 例程仅基于一个cpp文件

C++文件或工程进行编译时可以使用g++指令(需要对每一个程序和源文件分别使用g++指令编译),当程序变大时,一个工程文件往往会包含很文件夹和源文件,这时我们需要的编译指令将越来越长,整个编译过程会变得异常繁琐。因此对于C++项目,使用一些工程管理工具会更加高效。

cmake就是一个在工程上被广泛使用的C++工程管理工具,很多库都用cmake管理源代码,因此了解cmake的指令和过程是很重要的。

1.1 简单的例子直接调用

我们以编译一个简单的C++程序为例说明cmake的使用。

在Linux系统根目录下新建一个cppSpace文件夹,在该文件夹中新建一个HelloWorld.cpp文件

//这是一个实例文件
#include <iostream>
using namespace std;
int main()
{
    cout <<"Hello world!"<< endl;
    return 0;
}

在cppSpace文件夹下新建一个CMakeLists.txt文件(注意该文件的命名不能自己随便改,不然编译时会报错),打开该文件使用cmake语法编写一下内容。CMakeLists.txt文件作用是告诉cmake要对这个文件夹(cppSpace文件夹)下的文件做什么。

# 声明要求的cmake最低版本
cmake_minimum_required( VERSION 2.8 )

# 声明一个cmake工程
project( HelloWorld )

# 添加一个可执行程序
# 语法为: add_executable( 程序名  源代码文件 )
add_executable(Helloworld HelloWorld.cpp)

创建好上面两个文件。在 cppSpace下,创建一个build文件,并进行编译

# 新建一个中间目录 build
mkdir build
# 使终端进入该中间目录
cd build
# 使用cmake对工程进行编译(注意最后是两个"..",表示对上一层目录进行编译)
cmake ..
# 最后使用make指令进行编译
make

运行编译好的文件 。在build文件夹下执行 ./Helloworld

到此,最简单的仅仅使用一个cpp文件的基于cmake的编译就完成了。

1.2 带接口的基于python的调用

创建一个cpp,命名为tj.cpp

#include "string.h"
#include <iostream>
#include <sstream> 
#include <stdio.h>
using namespace std;
extern"C" int addtest( int a ,int b);
int addtest( int a ,int b)
{
    cout<<a<<endl;
    cout<<b<<endl;  
    return a+b;
}

 创建CMakeLists.txt文件内容如下:

# cmake needs this line
cmake_minimum_required(VERSION 3.23.1)

# Define project name
project(tj)

add_library(tj SHARED tj.cpp)

使用py文件调用

from ctypes import *
import sys
dll_test = CDLL("/data/sdv2/tangjunjun/mmdet2.19/cmake/dll1/build/libtj.so")
a=dll_test.addtest(4,5)
print(a)

使用python调用so文件结果:

 

 二、基于.h文件和.cpp文件的cmake编译的方法

一般来说,一个标准的C++项目包括三个文件夹和一个CMakeLists.txt。

include文件夹下存在以.h开头的头文件(头文件可能也会以.hh,.hpp开头)

src存放的往往是包括.cu,.cpp,.c为后缀的主文件

build文件夹是空的

CMakeLists.txt则编写相关的编译原则来实现编译效果。文件的放置的样子如下图所示:

 下面举个例子,同时包含头文件,源文件进行cmake的编译

include/hello.h文件:

#pragma once // 只编译一次

void printHello(); // 在.h文件申明函数

src/main.cpp文件

#include <iostream>   //C++的头文件
#include "cpuHello.h" //该文件有prinHello函数的申明
int main()
{
    printHello();
    return 0;
}
void printHello() // printHello函数定义写在下面,如果该函数定义写在main函数前面,就不需要申明了
{
    std::cout << "hello world\n"
              << std::endl;
}

CMakeLists.txt文件

cmake_minimum_required(VERSION 3.18) # CMake最低版本号要求  
project(helloWorld) # 项目名字  
  
# 设置C++标准  
set(CMAKE_CXX_STANDARD 11)  
set(CMAKE_CXX_STANDARD_REQUIRED ON)  
  
# 添加头文件搜索路径  
include_directories(include)  
  
# 寻找./src下面所有.cpp为后缀的源文件,并且保存到SRC变量里面  
file(GLOB_RECURSE SRC ./src/*.cpp)  
  
# 编译SRC变量存储的源文件,编译生成目标文件命名为hello  
add_executable(hello ${SRC})

有了上面的三个文件以后,下面开始编译代码:

cd build进入build文件夹(注意build文件夹刚开始是一个空文件夹)

cmake ../这个命令会在build里面生成对应的Makefile以及其他文件

make这个命令会直接寻找build文件夹内的Makefile文件执行编译过程

上面三个命令结束以后build会产生一个hello的可执行文件,然后./hello就可以执行打印了。

我们注意到CMakeLists.txt里面只是定义了不同文件的位置以及编译方式,其实没有指定编译器,但是系统会自动根据这个CMakeLists.txt寻找编译器编译文件,这个就是CMakeLists.txt优越简单的地方。

如果涉及到多种.cu .c等文件,可以参考以下链接实现

https://zhuanlan.zhihu.com/p/690410193

三、使用opencv库的编译 

创建了一个工程文件夹,在文件夹中创建三个目录 images、out、src 分别用来存放 需要处理和保存的图像,编译输出的可执行文件

 进入src目录中,创建两个目录 include、source,和CMakeLists.txt 文件。其中source用来存放程序的源文件,include用于存放头文件。

整个工程的目录结构如下:

创建两个源文件 main.cpp 文件 ColChange.cpp 文件,存放在在source目录中,在include目录中创建 ColChange.h文件

main.cpp

#include <stdio.h>
#include <opencv2/opencv.hpp>
#include "ColChange.h"

//using namespace cv;
using namespace std;


int main(int argc, char** argv )
{
  //读取图片,将图片存为Mat类的image实例中
  Mat image = imread("../images/123.jpg");

  if(image.empty()){
    printf("could not load image...\n");
    return -1;
  }
  //实例化一个QuickDemo
  QuickDemo qd;

  //qd.colorSpace_Demo(image);
  //qd.mat_creat_demo(image);
  qd.pixel_visit_demo(image);

  //创建窗口SSJ
  //cv::namedWindow("SSJ",WINDOW_FREERATIO);

  //在SSJ窗口上,显示图片
  //cv::imshow("SSJ", image);
  //显示状态阻塞
  cv::waitKey(0);

  return 0;
}

ColChange.cpp

#include "ColChange.h"

/*
 * Author:SSJ-xiaoguoke
 * Funtion:转换图像的色彩空间,transform the color space of the image
 */
void QuickDemo::colorSpace_Demo(Mat &image)
{
  Mat gray,hsv;

  cvtColor(image,hsv,COLOR_BGR2HSV);
  cvtColor(image, gray,COLOR_BGR2GRAY);

  imshow("HSV",hsv);
  imshow("huidu",gray);

  imwrite("../images/hsv.jpg",hsv);
  imwrite("../images/gray.jpg",gray);

}

/*
 * Author:SSJ-xiaoguoke
 * Funtion:创建Mat对象,Creating an image object
 */
void QuickDemo::mat_creat_demo(Mat &image)
{
    Mat m1,m2;

    m1 = image.clone();
    image.copyTo(m2);

/*
 * Size(8,8):创建的矩阵尺寸为 8*8
 * CV_8UC1:8位 U:无符号unsigned C:char型 1:单通道
 */
    //Mat m3 = Mat::zeros(Size(8,8),CV_8UC1);
    /*三通道*/
    Mat m3 = Mat::zeros(Size(500,500),CV_8UC3);
    /*创建一个值全是1的矩阵*/
    //Mat m3 = Mat::ones(Size(8,8),CV_8UC1);

    m3 = Scalar(0,0,255);
    //std::cout << m3 << std::endl;

    imshow("red",m3);

}

/*
 * Author:SSJ-xiaoguoke
 * Funtion:像素操作,Pixel operations
 */
void QuickDemo::pixel_visit_demo(Mat &image)
{
    int W = image.cols;
    int h = image.rows;
    int dims = image.channels();

    /*for(int row=0; row < h; row++){
        for(int col=0; col<W; col++){
            if(dims==1){

                int pv = image.at<uchar>(row,col);
                image.at<uchar>(row,col) = 255 - pv;

            }
            if(dims==3){

                Vec3b bgr = image.at<Vec3b>(row,col);
                image.at<Vec3b>(row,col)[0] = 255 - bgr[0];
                image.at<Vec3b>(row,col)[1] = 255 - bgr[1];
                image.at<Vec3b>(row,col)[2] = 255 - bgr[2];

            }
        }
    }*/
    /*通过指针的方法实现*/
    for(int row=0;row < h; row++){

        uchar* current_row = image.ptr<uchar>(row);

        for(int col=0;col < W;col++){
            if(dims==1){
                int pv = *current_row;
                *current_row++ = 255-pv;

            }
            if(dims==3){
                *current_row++ = 255 - *current_row;
                *current_row++ = 255 - *current_row;
                *current_row++ = 255 - *current_row;
            }
        }
    }

    imshow("Pixel operations",image);

}

 ColChange.h

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

class QuickDemo {
    public:
        void colorSpace_Demo(Mat &image);

        void mat_creat_demo(Mat &image);

        void pixel_visit_demo(Mat &image);

};

代码编写完成之后,进入src目录中,执行指令编译工程 

1 cmake ./
2 make

如果没有安装opencv则会报错,编译失败,需要先安装opencv。安装方法参考链接:OpenCV介绍及安装(linux)_linux opencv-CSDN博客

如果安装了opencv则会正常编译,编译完成之后会在out目录下输出一个叫 test的可执行文件。在image下面放一张图片 改名为123.jpg(可以修改代码来修改加载的图片名字)
进入out目录,执行下面的语句:

./test

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2270307.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Speech Recognition vs. Voice Recognition | 语音识别工作原理 | 模型训练 | 应用

注&#xff1a;Speech Recognition 与 Voice Recognition 机翻混淆&#xff0c;未校。 Speech Recognition vs. Voice Recognition: In Depth Comparison 语音识别与语音识别&#xff1a;深度比较 Calendar12 July 2023 Have you ever stopped to think about how your voice…

Tushare提示本接口即将停止更新,请尽快使用Pro版接口:https://tushare.pro/document/2

1、解决办法 tushare pro版本需要注册登录后获取tocken然后在代码中配置接口即可。 2、如何获取tushare&#xff1f; tushare是免费、开源的python财经数据接口&#xff0c;现在使用需要先注册tushare账号 1、跳转到tushare注册页面 Tusharez注册 Tushare数据 2、注册成功…

高频 SQL 50 题(基础版)_1068. 产品销售分析 I

销售表 Sales&#xff1a; (sale_id, year) 是销售表 Sales 的主键&#xff08;具有唯一值的列的组合&#xff09;。 product_id 是关联到产品表 Product 的外键&#xff08;reference 列&#xff09;。 该表的每一行显示 product_id 在某一年的销售情况。 注意: price 表示每…

【Ubuntu】Ubuntu server 18.04 搭建Slurm并行计算环境(包含NFS)

Ubuntu server 18.04 搭建Slurm并行计算环境&#xff08;包含NFS&#xff09; 一、Munge 认证模块 1.1、安装 munge 主节点和子节点都安装munge #安装 sudo apt update && sudo apt install munge libmunge-dev#设置开机启动 sudo systemctl enable munge sudo syste…

电脑主机后置音频插孔无声?还得Realtek高清晰音频管理器调教

0 缘起 一台联想电脑&#xff0c;使用Windows 10 专业版32位&#xff0c;电脑主机后置音频插孔一直没有声音&#xff0c;所以音箱是接在机箱前面版的前置音频插孔上的。 一天不小心捱到了音箱的音频线&#xff0c;音频线头断在音频插孔里面了&#xff0c;前置音频插孔因此用不…

Flink源码解析之:如何根据算法生成StreamGraph过程

Flink源码解析之&#xff1a;如何根据算法生成StreamGraph过程 在我们日常编写Flink应用的时候&#xff0c;会首先创建一个StreamExecutionEnvironment.getExecutionEnvironment()对象&#xff0c;在添加一些自定义处理算子后&#xff0c;会调用env.execute来执行定义好的Flin…

矩阵运算提速——玩转opencv::Mat

介绍:用Eigen或opencv::Mat进行矩阵的运算&#xff0c;比用cpp的vector或vector进行矩阵运算要快吗? 使用 Eigen 或 OpenCV 的 cv::Mat 进行矩阵运算通常比使用 std::vector<int> 或 std::vector<double> 更快。这主要有以下几个原因&#xff1a; 优化的底层实现…

Spire.PDF for .NET【页面设置】演示:向 PDF 添加平铺背景图像

平铺背景通常是指用一个或多个小图像重复填充的背景。在本文中&#xff0c;您将学习如何在 PDF 中平铺图像&#xff0c;并使用 C# 和 VB.NET 为您的 PDF 创建平铺背景。 Spire.PDF for .NET 是一款独立 PDF 控件&#xff0c;用于 .NET 程序中创建、编辑和操作 PDF 文档。使用 …

文件本地和OSS上传

这里写目录标题 前端传出文件后端本地存储阿里云OSS存储上传Demo实现上传ConfigurationProperties 前端传出文件 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>上传文件</title> </head&g…

SpringCloud源码分析-Gateway

Gateway核心原理&#xff0c;请求经过一系列的责任链最后到达服务端。

两个等号和三个等号(待查资料)

1太癫了&#xff0c;居然时要才行&#xff0c;都不行 2. 三等号的结果 .。。。。毁灭吧

什么是神经网络?神经网络的基本组成部分训练神经网络激活函数有哪些局限性和挑战

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c; 忍不住分享一下给大家。点击跳转到网站 学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把…

《Java核心技术II》流中的filter、map和flatMap方法

filter、map和flatMap方法 filter filter通过转换产生过滤后的新流,将字符串流转化为只包含长单词的另一个流。 List words ...; Stream longWords words.stream().filter(w->w.length()>12) filter类型是Predicate(谓词&#xff0c;表示动作)类型对象&#xff0c…

linux进阶

目录 变量 shell变量 环境变量 预定义变量 位置变量 其他 管道与重定向 管道 重定向 shell脚本 分支结构 循环结构 数组 脚本实例 变量 shell变量 shell变量&#xff1a;shell程序在内存中存储数据的容器 shell变量的设置&#xff1a;colorred 将命令的结果赋值…

阿赵的MaxScript学习笔记分享十六《MaxScript和WinForm交互》

MaxScript学习笔记目录 大家好&#xff0c;我是阿赵。   之前有网友给我留言说MaxScript和DotNet的WinForm界面交互有问题。我回头看了一下&#xff0c;发现之前的MaxScript文章是漏了这部分没有说明&#xff0c;这里补充一下。这里的内容主要是用C#写一个WinForm界面&#x…

出海新势力:巴西短剧的崛起与出海系统开发平台的赋能

在全球短剧蓬勃发展的浪潮中&#xff0c;巴西短剧宛如一颗耀眼的新星&#xff0c;迅速在拉美文娱的天空中崭露头角&#xff0c;成为备受瞩目的潜力股&#xff0c;正以独特的魅力吸引着越来越多观众的目光&#xff0c;在国际舞台上绽放出属于自己的光彩。 巴西短剧缘何火爆&…

HTML5新特性|01 音频视频

音频 1、Audio (音频) HTML5提供了播放音频文件的标准 2、control(控制器) control 属性供添加播放、暂停和音量控件 3、标签: <audio> 定义声音 <source> 规定多媒体资源,可以是多个<!DOCTYPE html> <html lang"en"> <head><…

多模态论文笔记——Coca

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍多模态模型Coca&#xff0c;在DALLE 3中使用其作为captioner基准模型的原因和优势。 文章目录 ALBEF论文模型结构组成训练目标 CoCa​论文模型结构CoCa…

Flutter 调试环境下浏览器网络请求跨域问题解决方案

本篇文章主要讲解&#xff0c;Flutter调试环境情况下&#xff0c;浏览器调试报错跨域问题的解决方法&#xff0c;通过本篇文章你可以快速掌握Flutter调试环境情况下的跨域问题。 日期&#xff1a;2024年12月28日 作者&#xff1a;任聪聪 报错现象&#xff1a; 报文信息&#xf…

在K8S中,如何部署kubesphere?

在Kubernetes集群中&#xff0c;对于一些基础能力较弱的群体来说K8S控制面板操作存在一定的难度&#xff0c;此时kubesphere可以有效的解决这类难题。以下是部署kubesphere的操作步骤&#xff1a; 操作部署&#xff1a; 1. 部署nfs共享存储目录 yum -y install nfs-server e…