linux上使用cmake编译的方法

一、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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(vue)el-table-column type=“selection“表格选框怎么根据条件添加禁选

(vue)el-table-column type"selection"表格选框怎么根据条件添加禁选 html <el-table:data"tableData"style"width: 100%"><el-table-columntype"selection"width"55":selectable"checkSelectable">…

linux nginx 安装后,发现SSL模块未安装,如何处理?

&#x1f468;‍⚕ 主页&#xff1a; gis分享者 &#x1f468;‍⚕ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕ 收录于专栏&#xff1a;运维工程师 文章目录 前言SSL模块安装 前言 nginx 安装后&#xff0c;发现SSL模块未安装&…

kubeneters-循序渐进Cilium网络(二)

文章目录 概要IP 地址配置接口配置解析结论 概要 接续前一章节&#xff0c;我们还是以这张图继续深入Cilium网络世界 IP 地址配置 通过检查 Kubernetes 集群的当前环境&#xff0c;可以获取实际的 IP 地址和配置信息。这些信息将被补充到之前的网络示意图中&#xff0c;以使…

虚拟机使用MQ及介绍

mq官网&#xff1a;https://www.rabbitmq.com 一、虚拟机与 MQ 的结合优势 隔离与安全&#xff1a;虚拟机为 MQ 的运行提供了一个独立的环境&#xff0c;与宿主机以及其他虚拟机相互隔离。这意味着即使 MQ 所在的虚拟机出现故障或遭受安全威胁&#xff0c;也不会直接影响到宿主…

比亚迪夏直插家用MPV腹地,“迪王”开启全面销冠新征程

文/王俣祺 导语&#xff1a;比亚迪前脚刚收获2024年的全面成功&#xff0c;后脚立刻就开始布局2025年的产品矩阵了。比亚迪夏的横空出世&#xff0c;看来家用MPV市场也要感受“迪王”的恐怖如斯了。 家用MPV市场的“意外之喜” 1月8日&#xff0c;比亚迪夏终于在万众瞩目之下…

c++入门之 命名空间与输入输出

1、命名空间 1.1使用命名空间的原因 先看一个例子&#xff1a; #include <iostream>int round 0;int main() {printf("%d", round);return 0; }请问&#xff0c;这个程序能跑起来吗&#xff1f; 答案是否定的 原因是&#xff0c;当我们想创建一个全局变量 …

php 使用simplexml_load_string转换xml数据格式失败

本文介绍如何使用php函数解析xml数据为数组。 <?php$a <xml><ToUserName><![CDATA[ww8b77afac71336111]]></ToUserName><FromUserName><![CDATA[sys]]></FromUserName><CreateTime>1736328669</CreateTime><Ms…

12 USART串口通讯

1 串口物理层 两个设备的“DB9接口”之间通过串口信号建立连接&#xff0c;串口信号线中使用“RS232标准”传输数据信号。由于RS232电平标准的信号不能直接被控制器直接识别&#xff0c;所以这些信号会经过“电平转换芯片”转换成控制器能识别的“TTL校准”的电平信号&#xff…

FreePBX 17 on ubuntu24 with Asterisk 20

版本配置&#xff1a; FreePBX 17&#xff08;最新&#xff09; Asterisk 20&#xff08;最新Asterisk 22&#xff0c;但是FreePBX 17最新只支持Asterisk 21&#xff0c;但是21非LTS版本&#xff0c;所以选择Asterisk 20&#xff09; PHP 8.2 Maria DB (v10.11) Node J…

搜广推面经五

饿了么推荐算法 一、介绍InfoNCE Loss、InfoNCE温度系数的作用 InfoNCE Loss&#xff08;Information Noise Contrastive Estimation Loss&#xff09;是一种常用于自监督学习和对比学习中的损失函数&#xff0c;特别是在信息论和无监督学习中有广泛应用。 它的核心思想是通过…

机器学习免费使用的数据集及网站链接

机器学习领域存在许多可以免费使用的数据集&#xff0c;这些数据集来自于学习、研究、比赛等目的。 一、综合性数据集平台 1.Kaggle 网址&#xff1a;Kaggle 数据集https://www.kaggle.com/datasets Kaggle是一个数据科学竞赛和社区平台&#xff0c;提供了大量的数据集供用…

浅尝Appium自动化框架

浅尝Appium自动化框架 Appium自动化框架介绍Appium原理Appium使用安装平台驱动实战 坑 Appium自动化框架介绍 Appium 是一个开源的自动化测试框架&#xff0c;最初设计用于移动应用的测试&#xff0c;但现在它也扩展了对桌面端应用的支持。Appium 使得自动化测试变得更加简单&…

ubuntu 20.04 安装docker--小白学习之路

更新包 sudo apt-get update # 安装需要的软件包以使apt能够通过HTTPS使用仓库 sudo apt-get install ca-certificates curl gnupg lsb-release 使用清华大学源 # 添加Docker官方的GPG密钥 curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg | sudo…

MMDetection框架下的常见目标检测与分割模型综述与实践指南

目录 综述与实践指南 SSD (Single Shot MultiBox Detector) 基本配置和使用代码 RetinaNet 基本配置和使用代码 Faster R-CNN 基本配置和使用代码 Mask R-CNN 基本配置和使用代码 Cascade R-CNN 基本配置和使用代码 总结 综述与实践指南 MMDetection是一个基于Py…

语音机器人外呼的缺点

也许是因为经济形式变差&#xff0c;大部分都是消费降级的策略。企业也一样&#xff0c;开源不行就只能重点节流。以前10个人做的工作&#xff0c;希望能用2个语音机器人就能完成。确实语音机器人是可以大幅提升外呼效率的&#xff0c;节约成本也很明显&#xff0c;但是今天不说…

微机原理期末复习(一)

编程题 汇编语言程序的整体结构 STACK SEGMENT STACK STACKDW 100H DUP(?) TOP LABEL WORD ; 使用LEBEL获取栈的尾部偏移地址存储到TOP中&#xff0c;以便初始化sp STACK ENDSDATA SEGMENT... ; 用户定义的变量 DATA ENDSCODE SEGMENTASSUME CS: CODE, DS: DATA, ES: DATA, …

UML(统一建模语言)

目录 一、用例图&#xff08;Use Case Diagram&#xff09; 二、类图&#xff08;Class Diagram&#xff09; 2.1、泛化&#xff08;Generalization&#xff09; 2.2、实现&#xff08;Realization&#xff09; 2.3、关联&#xff08;Association&#xff09; 2.4、聚合&…

流浪猫流浪狗领养PHP网站源码

源码介绍 流浪猫流浪狗领养PHP网站源码&#xff0c;适合做猫狗宠物类的发信息发布。当然其他信息发布也是可以的。 导入数据库&#xff0c;修改数据库配置/application/database.php 设置TP伪静态&#xff0c;设置运行目录&#xff0c; 后台&#xff1a;/abcd.php/dashboard?…

轻量级适合阅读的优秀 C++ 开源项目

CTPL 这是一个现代简易版的、高效的C线程池库&#xff0c;代码行数500行左右。 代码示例&#xff1a; void first(int id) { std::cout << "hello from " << id << \n; } struct Second { void operator()(int id) const { std::cout << &q…

下载导出Tomcat上的excle文档,浏览器上显示下载

目录 1.前端2.Tomcat服务器内配置3.在Tomcat映射的文件内放置文件4.重启Tomcat&#xff0c;下载测试 1.前端 function downloadFile() {let pictureSourceServer "http://192.168.1.1:8080/downFile/";let fileName "测试文档.xlsx";let fileURL pictu…