为什么要选择QT Creator?方便,方便,方便~~~~
陆陆续续使用QT已经4,5年了,如果一直还停留在傻瓜化的鼠标添加删除配置阶段,也太Low B了吧,还是赶紧学点高级货,因为Android Studio里面就是CMake,哦嚯嚯,有点儿兴趣了~~~~
学习CMake躲不开CMakeLists.txt的书写,来看看QT Creator向导给我们的内容:
project(TestFaceDetect)#工程名字
cmake_minimum_required(VERSION 2.8)#CMAKE版本
#源码路径
aux_source_directory(. SRC_LIST)
#编译成EXE
add_executable(${PROJECT_NAME} ${SRC_LIST})
什么?源文件都没有啊,怎么就编译成了我想要的exe/.out?看上面注释!!!
10:35:07: 为项目TestFaceDetect执行步骤 ...
10:35:07: 正在启动 "C:\Program Files (x86)\CMake\bin\cmake.exe" --build . --target clean
10:35:07: 进程"C:\Program Files (x86)\CMake\bin\cmake.exe"正常退出。
10:35:07: 正在启动 "C:\Program Files (x86)\CMake\bin\cmake.exe" --build . --target all
Scanning dependencies of target TestFaceDetect
[ 33%] Building CXX object CMakeFiles/TestFaceDetect.dir/main.cpp.obj
main.cpp
[100%] Linking CXX executable TestFaceDetect.exe
[100%] Built target TestFaceDetect
10:35:09: 进程"C:\Program Files (x86)\CMake\bin\cmake.exe"正常退出。
10:35:09: Elapsed time: 00:02.
好,知道了最基本的CMakeLists.txt内容,我们more一点,添加一个C++类Person:
#ifndef PERSON_H
#define PERSON_H
#ifdef _WIN32
#ifdef LIBPERSON_BUILD
#define LIBPERSON_API __declspec(dllexport)
#else
#define LIBPERSON_API __declspec(dllimport)
#endif
#else
#define LIBPERSON_API
#endif
#include <string>
using namespace std;
//
class /*LIBPERSON_API*/ Person
{
public:
Person(int age, string name);
public:
int getAge();
string getName();
protected:
private:
int age;
string name;
};
#endif // PERSON_H
#include "person.h"
Person::Person(int age, string name)
{
this->age = age;
this->name = name;
}
int Person::getAge()
{
return age;
}
string Person::getName()
{
return name;
}
简单的一个类,在main.cpp中加入调用:
#include <iostream>
using namespace std;
#include "person.h"
int main(int argc, char *argv[])
{
cout << "Hello World!" << endl;
Person juan(18,"Juan");
cout<<"My name is "<<juan.getName()<<", "<<juan.getAge()<<" years old!"<<endl;
return 0;
}
再次执行编译运行,又一次成功了,输出:
Hello World!
My name is Juan, 18 years old!
你说,这也太简单了,我要尝试把Person类生成静态库调用,“上帝说要有光就有了光”,于是乎,CMakeLists.txt变成了:
project(TestFaceDetect)#工程名字
cmake_minimum_required(VERSION 2.8)#CMAKE版本
#源码文件(手工指定)
set(LIB_SRC person.cpp)
set(APP_SRC main.cpp)
#将person.cpp编译成静态库
add_library(libperson ${LIB_SRC})
#将main.cpp编译成exe
add_executable(${PROJECT_NAME} ${APP_SRC})
#exe链接时的依赖库
target_link_libraries(${PROJECT_NAME} libperson)
编译,也没有问题!!!
怎么?你还不满足?是的,我们都知道,动态库才是我的最爱!!!
好好好,满足你!!!
继续修改CMakeLists.txt 既然上面都已经使用了add_library,会不会右add_shared_library之类的?遗憾的是,没有!!!那就只能在add_library参数上下功夫了,想到这里就对了,我们要得到dll/so库,只需要一个SHARED参数就OK了。
因此,CMakeLists.txt内容变为:
project(TestFaceDetect)#工程名字
cmake_minimum_required(VERSION 2.8)#CMAKE版本
#源码路径
#aux_source_directory(. SRC_LIST)
#源码文件(手工指定)
set(LIB_SRC person.cpp)
set(APP_SRC main.cpp)
#编译成EXE
#add_executable(${PROJECT_NAME} ${SRC_LIST})
#编译成静态库
#add_library(${PROJECT_NAME} ${SRC_LIST})
#将person.cpp编译成静态库
#add_library(libperson ${LIB_SRC})
#将person.cpp编译成动态库
add_library(libperson SHARED ${LIB_SRC})
#将main.cpp编译成exe
add_executable(${PROJECT_NAME} ${APP_SRC})
#exe依赖库
target_link_libraries(${PROJECT_NAME} libperson)
编译,咦???怎么不通过啊???
10:06:29: 为项目TestFaceDetect执行步骤 ...
10:06:29: 正在启动 "C:\Program Files (x86)\CMake\bin\cmake.exe" --build . --target all
Scanning dependencies of target libperson
[ 25%] Building CXX object CMakeFiles/libperson.dir/person.cpp.obj
person.cpp
[ 50%] Linking CXX shared library libperson.dll
[ 50%] Built target libperson
Scanning dependencies of target TestFaceDetect
[ 75%] Building CXX object CMakeFiles/TestFaceDetect.dir/main.cpp.obj
main.cpp
NMAKE : fatal error U1073: 不知道如何生成“libperson.lib”
Stop.
NMAKE : fatal error U1077: “"E:\Visual Studio 2015 Enterprise\VC\BIN\nmake.exe"”: 返回代码“0x2”
Stop.
NMAKE : fatal error U1077: “"E:\Visual Studio 2015 Enterprise\VC\BIN\nmake.exe"”: 返回代码“0x2”
Stop.
10:06:31: 进程"C:\Program Files (x86)\CMake\bin\cmake.exe"退出,退出代码 2 。
Error while building/deploying project TestFaceDetect (kit: Desktop Qt 5.4.1 VS12 x86)
When executing step "Make"
10:06:31: Elapsed time: 00:02.
不知道怎么生成lib库,发现生成的dll库确实是没有导出任何函数的,用过VS的都知道需要指明dll导出规则,即Person.h开头的那一段:
#ifdef _WIN32
#ifdef LIBPERSON_BUILD
#define LIBPERSON_API __declspec(dllexport)
#else
#define LIBPERSON_API __declspec(dllimport)
#endif
#else
#define LIBPERSON_API
#endif
把导出类声明成:
class LIBPERSON_API Person
{
public:
Person(int age, string name);
public:
int getAge();
string getName();
protected:
private:
int age;
string name;
};
project(TestFaceDetect)#工程名字
cmake_minimum_required(VERSION 2.8)#CMAKE版本
#源码路径
#aux_source_directory(. SRC_LIST)
#源码文件(手工指定)
set(LIB_SRC person.cpp)
set(APP_SRC main.cpp)
#编译成EXE
#add_executable(${PROJECT_NAME} ${SRC_LIST})
#编译成静态库
#add_library(${PROJECT_NAME} ${SRC_LIST})
#将person.cpp编译成静态库
add_library(libperson ${LIB_SRC})
#将person.cpp编译成动态库
#宏定义方法,任选一种
add_definitions("-DLIBPERSON_BUILD")
#set(CMAKE_C_FLAGS "")#c程序的
#set(CMAKE_CXX_FLAGS "-DLIBPERSON_BUILD")#c++程序的
add_library(libperson SHARED ${LIB_SRC})
#将main.cpp编译成exe
add_executable(${PROJECT_NAME} ${APP_SRC})
#exe依赖库
target_link_libraries(${PROJECT_NAME} libperson)
编译,通过!!!运行结果和静态库一致!!!
OK!!!
高级点,引入外部第三方库:
#引入第三方库
include_directories(${PROJECT_SOURCE_DIR}/fcsdk)
#首先要添加库,重要
add_library(libface SHARED IMPORTED)
#再设置库的位置
#引入dll库,特有的
set_target_properties(libface
PROPERTIES
IMPORTED_IMPLIB
${PROJECT_SOURCE_DIR}/fcsdk/FaceCapture.lib)
##
#set_property(TARGET
# libface
# PROPERTY
# IMPORTED_IMPLIB
# ${PROJECT_SOURCE_DIR}/fcsdk/FaceCapture.lib)
#引入第三方so库,任选一
#set_property(TARGET
# libface
# PROPERTY
# IMPORTED_LOCATION
# ${PROJECT_SOURCE_DIR}/fcsdk/FaceCapture.so)
##
#set_target_properties(libface
# PROPERTIES
# IMPORTED_LOCATION
# ${PROJECT_SOURCE_DIR}/fcsdk/FaceCapture.so)
#将main.cpp编译成exe
add_executable(${PROJECT_NAME} ${APP_SRC})
#exe依赖库
target_link_libraries(${PROJECT_NAME}
libperson
libface)#引入的第三方库别名
注意,上面的要引入dll需要设置
IMPORTED_IMPLIB (https://cmake.org/cmake/help/v3.0/prop_tgt/IMPORTED_IMPLIB.html)
其他,直接设置
IMPORTED_LOCATION (https://cmake.org/cmake/help/v3.0/prop_tgt/IMPORTED_LOCATION.html)
本文参考:
http://blog.csdn.net/dbzhang800/article/details/6314073
http://blog.csdn.net/fan_hai_ping/article/details/42524205