【Linux】CMakeLists.txt编写

学习博客:https://blog.csdn.net/wzzfeitian/article/details/40963457

一、使用方法 
一般把CMakeLists.txt文件放在工程目录下,使用时,先创建一个叫build的文件夹(这个并非必须,只是生成的Makefile等文件放在build里比较整齐),然后执行下列操作: 
cd build 
cmake .. 
make 
其中cmake .. 在build里生成Makefile,make应当在有Makefile的目录下,根据Makefile生成可执行文件。

二、编写方法

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

# 添加c++11标准支持
set( CMAKE_CXX_FLAGS "-std=c++11" )

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

 MESSAGE(STATUS "Project: SERVER")               #打印相关消息消息

# 找到后面需要库和头文件的包
find_package(包的名称及最低版本)
# 例如find_package(OpenCV 2.4.3 REQUIRED)


# 头文件
include_directories("路径")
# 例如
#include_directories(
# ${PROJECT_SOURCE_DIR}
# ${PROJECT_SOURCE_DIR}/include
# ${EIGEN3_INCLUDE_DIR}
)

# 设置路径(下面生成共享库的路径)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)
# 即生成的共享库在工程文件夹下的lib文件夹中

# 创建共享库(把工程内的cpp文件都创建成共享库文件,方便通过头文件来调用)
add_library(${PROJECT_NAME} SHARED
src/cpp文件名
……
)
# 这时候只需要cpp,不需要有主函数
# ${PROJECT_NAME}是生成的库名 表示生成的共享库文件就叫做 lib工程名.so
# 也可以专门写cmakelists来编译一个没有主函数的程序来生成共享库,供其它程序使用

# 链接库
# 把刚刚生成的${PROJECT_NAME}库和所需的其它库链接起来
target_link_libraries(${PROJECT_NAME}
/usr/lib/i386-linux-gnu/libboost_system.so
)

# 编译主函数,生成可执行文件

# 先设置路径
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)

# 可执行文件生成
add_executable(要生成的可执行文件名 从工程目录下写起的主函数文件名)

# 这个可执行文件所需的库(一般就是刚刚生成的工程的库咯)
target_link_libraries(可执行文件名 ${PROJECT_NAME})

cmake中一些预定义变量

  • PROJECT_SOURCE_DIR 工程的根目录
  • PROJECT_BINARY_DIR 运行cmake命令的目录,通常是${PROJECT_SOURCE_DIR}/build
  • CMAKE_INCLUDE_PATH 环境变量,非cmake变量
  • CMAKE_LIBRARY_PATH 环境变量
  • CMAKE_CURRENT_SOURCE_DIR 当前处理的CMakeLists.txt所在的路径
  • CMAKE_CURRENT_BINARY_DIR target编译目录
    使用ADD_SURDIRECTORY(src bin)可以更改此变量的值
    SET(EXECUTABLE_OUTPUT_PATH <新路径>)并不会对此变量有影响,只是改变了最终目标文件的存储路径
  • CMAKE_CURRENT_LIST_FILE 输出调用这个变量的CMakeLists.txt的完整路径
  • CMAKE_CURRENT_LIST_LINE 输出这个变量所在的行
  • CMAKE_MODULE_PATH 定义自己的cmake模块所在的路径
    SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake),然后可以用INCLUDE命令来调用自己的模块
  • EXECUTABLE_OUTPUT_PATH 重新定义目标二进制可执行文件的存放位置
  • LIBRARY_OUTPUT_PATH 重新定义目标链接库文件的存放位置
  • PROJECT_NAME 返回通过PROJECT指令定义的项目名称
  • CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS 用来控制IF ELSE语句的书写方式

 假设当前的项目代码在src 目录。 src 下有子目录:server, utility, lib, bin, build

      server -----  存放项目的主功能类文件

      utility  -----  存放项目要用到相关库文件,便已成为库文件存放到子目录lib 中

      lib       -----  存放utility 生成的库

      bin      -----  存放association 生成的二进制文件

      build   -----  编译目录,存放编译生成的中间文件   

      cmake 要求工程主目录和所有存放源代码子目录下都要编写CMakeLists.txt 文件,注意大小写(cm 大写,list中l 大写且落下s).

      src/CMakeLists.txt 文件如下:

#cmake file for project association #表示注释

#author:>---double__song

#created:>--2011/03/01


CMAKE_MINIMUM_REQUIRED(VERSION 2.8) #cmake 最低版本要求,低于2.6 构建过程会被终止。


PROJECT(server_project) #定义工程名称


MESSAGE(STATUS "Project: SERVER") #打印相关消息消息

MESSAGE(STATUS "Project Directory: ${PROJECT_SOURCE_DIR}")

SET(CMAKE_BUILE_TYPE DEBUG) #指定编译类型

SET(CMAKE_C_FLAGS_DEBUG "-g -Wall") #指定编译器


ADD_SUBDIRECTORY(utility) #添加子目录

ADD_SUBDIRECTORY(server)

 

      相关解释:

      1. CMakeLists.txt 文件中不区分大小写

      2. PROJECT(project_name)    定义工程名称

          语法:project(projectname [cxx] [c] [java])

          可以指定工程采用的语言,选项分别表示:C++, C, java, 如不指定默认支持所有语言

      3. MESSAGE(STATUS, "Content")  打印相关消息

          输出消息,供调试CMakeLists.txt 文件使用。

      4. SET(CMAKE_BUILE_TYPE DEBUG)  设置编译类型debug 或者release。 debug 版会生成相关调试信息,可以使用GDB 进行 

          调试;release不会生成调试信息。当无法进行调试时查看此处是否设置为debug.

      5. SET(CMAKE_C_FLAGS_DEBUG "-g -Wall") 设置编译器的类型

          CMAKE_C_FLAGS_DEBUG            ----  C 编译器

          CMAKE_CXX_FLAGS_DEBUG        ----  C++ 编译器

       6. ADD_SUBDIRECTORY(utility) 添加要编译的子目录

           为工程主目录下的存放源代码的子目录使用该命令,各子目录出现的顺序随意。

       如上便是工程server_project 主目录src 下的CMakeLists.txt 文件,下一篇我们解释子目录utiltiy中的CMakeLists.txt 文件。

 

子目录utility 下的CMakeLists.txt 文件如下:

#Cmake file for library utility.a

#Author: double__song

#Created: 2011/3/3


SET(SOURCE_FILES #设置变量,表示所有的源文件

ConfigParser.cpp

StrUtility.cpp

)

INCLUDE_DIRECTORIES( #相关头文件的目录

/usr/local/include

${PROJET_SOURCE_DIR}/utility

)


LINK_DIRECTORIES( #相关库文件的目录

/usr/local/lib

)


ADD_LIBRARY(association ${SOURCE_FILES}) #生成静态链接库libassociation.a

TARGET_LINK_LIBRARY(association core) #依赖的库文件


SET_TARGET_PROPERTIES(utility PROPERTIES #表示生成的执行文件所在路径

RUNTIME_OUTPUT_DIRECTORY> "${PROJECT_SOURCE_DIR}/lib")

 

    相关解释:

    1. SET(SOURCE_FILES .....)  

    表示要编译的源文件,所有的源文件都要罗列到此处。set 设置变量,变量名SOURCE_FILES自定义。

    2. INCLUDE_DIRECTORY(...)  

    include头文件时搜索的所有目录

    变量PROJECT_SOURCE_DIR 表示工程所在的路径,系统默认的变量

    3. LINK_DIRECTORIES(...)

     库文件存放的目录,在程序连接库文件的时候要再这些目录下寻找对应的库文件

    4. ADD_LIBRARY(...) 

     表示生成静态链接库libassociaiton.a,由${PROJECT_SOURCE_DIR}代表的文件生成。

     语法:ADD_LIBRARY(libname [SHARED|STATIC]

     SHARED 表示生成动态库, STATIC表示生成静态库。

    5. TARGET_LINK_LIBRARY(association core) 

     表示库association 依赖core库文件

     6. SET_TARGET_PROPERTIES

     设置编译的库文件存放的目录,还可用于其他属性的设置。如不指定,

     生成的执行文件在当前编译目录下的各子目录下的build目录下,好拗口!简单一点:

     如指定在: ./src/lib 下

     不指定在: ./src/build/utility/build 目录下

     生成的中间文件在./src/build/utilty/build 目录下,不受该命令额影响

 

     子目录server 下的CMakeLists.txt 文件:

--------------------------------------------------------------------------------------------

SET(SOURCE_FILES

Gassociation.cpp

ConfigurationHandler.cpp

)

INCLUDE_DIRECTORIES(

/usr/local/include

${PROJECT_SOURCE_DIR}/utility

${PROJECT_SOURCE_DIR}/association

)

LINK_LIBRARIES(

/usr/local/lib

${PROJECT_SOURCE_DIR}/lib

)

ADD_EXECUTABLE(server ${SOURCE_FILES})

TARGET_LINK_LIBRARIES(server

utility

)

SET_TARGET_PROPERTIES(server PROPERTIES #表示生成的执行文件所在路径

RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/bin")

     相关解释:

     1. ADD_EXECUTABLE()     #指定要生成的执行文件的名称server

      其他用法同utilty/CMakeLists.txt

     2. SET_TARGET_PROPERTIES

      设置生成的执行文件存放的路径,

      注意:

      执行文件server 依赖的子目录utility 子目录生成的静态库libutility.a,在指定的时候要写成:
      TARGET_LINK_LIBRARIES(server   utility)

      而不能写成:

      TARGET_LINK_LIBRARIES(server   libutility.a)

      否则编译总会提示找不到libutility库文件。

      但使用第三方的库却要指定成具体的库名,如:libACE-6.0.0.so

      这一点很诡异,暂时还没找到原因。

      完成对应的CMakeLists.txt 文件编写后,便可以进行编译了。

      编译:

            进入 ./src/build

            执行cmake ..

            make

 configure --prefix=/:作用:

 

指定安装路径
不指定prefix,则可执行文件默认放在/usr /local/bin,库文件默认放在/usr/local/lib,配置文件默认放在/usr/local/etc。其它的资源文件放在/usr /local/share。你要卸载这个程序,要么在原来的make目录下用一次make uninstall(前提是make文件指定过uninstall),要么去上述目录里面把相关的文件一个个手工删掉。
指定prefix,直接删掉一个文件夹就够了。

demo2:

#include "opencv2/objdetect.hpp"   //36007bytes      26
#include "opencv2/highgui.hpp"     //36215  动态链接库24
#include "opencv2/imgproc.hpp"     //228169          24
#include <iostream>
//所用动态链接库  107916
//haarcascade_frontalface_alt2.xml   540616
//可执行文件 42216 bytess
using namespace std;
using namespace cv;
class Face_detect{
private:
    bool tryflip;
    CascadeClassifier cascade;
    double scale;
    string cascadeName;
public:
    Face_detect(string casfile1,int scale1=1,bool tryflip1=true){
        cascadeName =casfile1;
        scale =scale1;
        tryflip =tryflip1;
    }
    int init(){
        if (!cascade.load(samples::findFile(cascadeName)))
        {
            cerr << "ERROR: Could not load classifier cascade" << endl;
            help();
            return 0;
        }
        return 1;
    }
    void help()
        {
             cout << "\nThis program demonstrates the use of cv::CascadeClassifier class to detect objects (Face + eyes). You can use Haar or LBP features.\n"
            "This classifier can recognize many kinds of rigid objects, once the appropriate classifier is trained.\n"
            "It's most known use is for faces.\n"
            "Usage:\n"
            "./facedetect [--cascade=<cascade_path> this is the primary trained classifier such as frontal face]\n"
               "   [--scale=<image scale greater or equal to 1, try 1.3 for example>]\n"
               "   [--try-flip]\n"
               "   [filename|camera_index]\n\n"
            "see facedetect.cmd for one call:\n"
            "./facedetect --cascade=\"../haarcascade_frontalface_alt.xml\" --scale=1.3\n\n"
            "During execution:\n\tHit any key to quit.\n"
            "\tUsing OpenCV version " << CV_VERSION << "\n" << endl;
        }
        int detectFaces(Mat& img)
        {
             double t = 0;
            vector<Rect> faces;
            const static Scalar colors[] =
            {
                Scalar(255,0,0),
                Scalar(255,128,0),
                Scalar(255,255,0),
                Scalar(0,255,0),
                Scalar(0,128,255),
                Scalar(0,255,255),
                Scalar(0,0,255),
                Scalar(255,0,255)
            };
            Mat gray, smallImg;

            cvtColor( img, gray, COLOR_BGR2GRAY );
            double fx = 1 / scale;
            resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR_EXACT );
            equalizeHist( smallImg, smallImg ); //直方图均衡化,,用于提高图像的质量

            t = (double)getTickCount();
            cascade.detectMultiScale( smallImg, faces,
               1.1, 2, 0
              //|CASCADE_FIND_BIGGEST_OBJECT
              //|CASCADE_DO_ROUGH_SEARCH
              |CASCADE_SCALE_IMAGE,
              Size(30, 30) );
             t = (double)getTickCount() - t;
            printf( "detection time = %g ms\n", t*1000/getTickFrequency());
            int facesSize=faces.size();
            if(facesSize>0)
                cout<<"检测到人脸数目为:\t"<<facesSize<<endl;
            else cout<<"w未检测到行人"<<endl;
            return facesSize;
        }
        void detectAndDraw( Mat& img )
        {
            double t = 0;
            vector<Rect> faces;
            const static Scalar colors[] =
            {
                Scalar(255,0,0),
                Scalar(255,128,0),
                Scalar(255,255,0),
                Scalar(0,255,0),
                Scalar(0,128,255),
                Scalar(0,255,255),
                Scalar(0,0,255),
                Scalar(255,0,255)
            };
            Mat gray, smallImg;

            cvtColor( img, gray, COLOR_BGR2GRAY );
            double fx = 1 / scale;
            cout<<"scale\t"<<scale<<" \t fx \t "<<fx<<"\tINTER_LINEAR_EXACT:\t"<<INTER_LINEAR_EXACT<<endl;
            if(gray.empty ()) {
                cout<<"gray frame is empty,ERROR happened"<<endl;
                cout<<"gray.size\t"<<gray.depth ()<<endl;
                //return -1;
            }else{
                cout<<"gray frame isnot empty,go on"<<endl;
            }
            resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR_EXACT );
            equalizeHist( smallImg, smallImg ); //直方图均衡化,,用于提高图像的质量

            t = (double)getTickCount();
            cascade.detectMultiScale( smallImg, faces,
               1.1, 2, 0
              //|CASCADE_FIND_BIGGEST_OBJECT
              //|CASCADE_DO_ROUGH_SEARCH
              |CASCADE_SCALE_IMAGE,
              Size(30, 30) );
             t = (double)getTickCount() - t;
            printf( "detection time = %g ms\n", t*1000/getTickFrequency());
            int count=faces.size();
            cout<<"检测到人脸\t"<<count<<"\t 个人脸"<<endl;
            for ( size_t i = 0; i < count; i++ )
            {
                cout<<"正在处理第\t"<<i<<"\t 个人脸"<<endl;
                Rect r = faces[i];
                Mat smallImgROI;
                Point center;
                Scalar color = colors[i%8];
                int radius;

                double aspect_ratio = (double)r.width/r.height;
                rectangle( img, Point(cvRound(r.x*scale), cvRound(r.y*scale)),
                       Point(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)),
                       color, 3, 8, 0);
                putText(img, "people detected",         //输入参数为图像、文本、位置、字体、大小、颜色数组、粗细
                Point(r.x*scale, r.y),
                FONT_HERSHEY_COMPLEX,1, // font face and scale
                Scalar(220, 20, 60), // 
                2, LINE_AA); // line thickness and type   
            }
            imshow( "result", img );
    }
};

int main( int argc, const char** argv )
{
    VideoCapture capture;
    Mat frame, image;
    string casfile1="../haarcascade_frontalface_alt2.xml";
    string casfile2="../haarcascade_frontalface_default.xml";
    string casfile3="../haarcascade_frontalface_alt_tree.xml";
    int camera =0;
    Face_detect *detect=new Face_detect(casfile1,1,true);
    if(!detect->init())
    {
        cout<<"Face_detect ERROR,can't load the cv::CascadeClassifier file"<<casfile1<<endl;
        return -1;
    }
    if(!capture.open(camera))
    {
        cout << "Capture from camera #" <<  camera << " didn't work" << endl;
        return 1;
    }
    if( capture.isOpened() )
    {
        cout << "Video capturing has been started ..." << endl;

        for(;;)
        {
            capture >> frame;
            if( frame.empty() )
                break;

            Mat frame1 = frame.clone();
            detect->detectAndDraw( frame1);

            char c = (char)waitKey(10);
            if( c == 27 || c == 'q' || c == 'Q' )
                break;
        }
    }
    return 0;
}


 目录结构如下:

编写CMakeLists.txt文件如下:

# cmake needs this line
cmake_minimum_required(VERSION 3.1)

# Enable C++11
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)

# Define project name
project(facedetect_project)

# Find OpenCV, you may need to set OpenCV_DIR variable
# to the absolute path to the directory containing OpenCVConfig.cmake file
# via the command line or GUI
#set(${OpenCV_DIR} )
set(OpenCV_VERSION 4.1)
set(OpenCV_LIBS lib)
set(OpenCV_INCLUDE_DIRS include)
set(LINK_DIR lib)
INCLUDE_DIRECTORIES(
    include
    )
link_directories(${LINK_DIR})

set(PROJECT_NAME
    opencv_core
    opencv_features2d
    opencv_highgui
    opencv_objdetect
    # opencv_imgcodecs
    opencv_imgproc
    # opencv_photo
    opencv_videoio
    opencv_video
)
# If the package has been found, several variables will
# be set, you can find the full list with descriptions
# in the OpenCVConfig.cmake file.
# Print some message showing some of them
message(STATUS "OpenCV library status:")
message(STATUS "    config: ${OpenCV_DIR}")
message(STATUS "    version: ${OpenCV_VERSION}")
message(STATUS "    libraries: ${OpenCV_LIBS}")
message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")

# Declare the executable target built from your sources
add_executable(facedetect face_detect.cpp)
#add_executable(opencv_example main.cpp)
# Link your application with OpenCV libraries
target_link_libraries(facedetect ${PROJECT_NAME})

 

如果不清楚需要依赖什么动态链接库,可以根据错误提示进行添加修改

Makefile编写:

每一个c'p'p文件都对应相应的.o文件

TOPDIR  := .
CROSS_COMPILE=arm-linux-
AS      =$(CROSS_COMPILE)as
LD      =$(CROSS_COMPILE)ld
CC      =$(CROSS_COMPILE)gcc
CPP     =$(CC) -E
AR      =$(CROSS_COMPILE)ar
NM      =$(CROSS_COMPILE)nm
STRIP   =$(CROSS_COMPILE)strip
OBJCOPY =$(CROSS_COMPILE)objcopy
OBJDUMP =$(CROSS_COMPILE)objdump

EXTRA_LIBS += -lpthread

EXEC= test_led
OBJS= keyboard.o get_key.o test_led.o

all: $(EXEC)

$(EXEC): $(OBJS)
	$(CC)  -o $@ $(OBJS)  $(EXTRA_LIBS)

install:
	$(EXP_INSTALL) $(EXEC) $(INSTALL_DIR)


clean:
	-rm -f $(EXEC) *.elf *.gdb *.o


clean:
	rm -f *.o *~ core .depend

 

  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路途…

点滴记录

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值