【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
更多推荐
所有评论(0)