环境搭建配置、入门API以及示例代码
Cmake为跨平台创建工程的,很多开源的项目,都采用Cmake来编译,opencv,libjpeg,QT部分等,非常有必要学习一下了,Cmake简单的关系图
对cmake和qmake来说,他们用普通语法让用户来添加编译选项,cmake对应CMakeList,qmake对应.pro文件
参考资料:https://blog.csdn.net/dbzhang800/article/details/6314073
郑重感谢此文博主,本文后半部分是将其笔记(1)进行C++文件的实现和所用API的梳理,简单解释了几个没有详细说的API,还有小的疏忽bug,顺便给修复了
Cmake安装和配置
Cmake最重要就是跨平台的使用了,统一套代码,在不同的平台下,生成工程文件,在Windows下生成的即使Visual Studio 工程,在linux下即生成MakeFile,方便在不同平台下管理代码
linux
在linux下,现在主流的操作系统的源里都包含,cmake,直接安装即可,安装,ccmake后面跟个参数,即CMakeList.txt所在文件夹(linux 下严格区分大小写,这点和windows 不同一定要注意),执行后就能生成Makefile 。以最简单的HelloWord为例,因为主要目的是为了学习Cmake,后续就不再写linux示例,所有试验均以windows的GUI的操作为准
我只写了一个CmakeHelloWord.cpp
// An highlighted block
#include <stdio.h>
#include <tchar.h>
int main()
{
printf("Hello World!\n");
return 0;
}
CMakeList.txt:
// An highlighted block
project(HELLO)
set(SRC_LIST CmakeHelloWord.cpp)
add_executable(hello ${SRC_LIST})
执行 came + list所在路径,就可以的倒Makefile
Makefile(读起来费劲,知道咋回事得了。。。):
// An highlighted block
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 2.8
# Default target executed when no arguments are given to make.
default_target: all
.PHONY : default_target
#=============================================================================
# Special targets provided by cmake.
# Disable implicit rules so canonical targets will work.
.SUFFIXES:
# Remove some rules from gmake that .SUFFIXES does not remove.
SUFFIXES =
.SUFFIXES: .hpux_make_needs_suffix_list
# Suppress display of executed commands.
$(VERBOSE).SILENT:
# A target that is always out of date.
cmake_force:
.PHONY : cmake_force
#=============================================================================
# Set environment variables for the build.
# The shell in which to execute make rules.
SHELL = /bin/sh
# The CMake executable.
CMAKE_COMMAND = /usr/bin/cmake
# The command to remove a file.
RM = /usr/bin/cmake -E remove -f
# Escaping for special characters.
EQUALS = =
# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = /home/irisking/桌面/CmakeTest/1HelloWord/CmakeHelloWord
# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = /home/irisking/桌面/CmakeTest/1HelloWord
#=============================================================================
# Targets provided globally by CMake.
# Special rule for the target edit_cache
edit_cache:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running interactive CMake command-line interface..."
/usr/bin/cmake -i .
.PHONY : edit_cache
# Special rule for the target edit_cache
edit_cache/fast: edit_cache
.PHONY : edit_cache/fast
# Special rule for the target rebuild_cache
rebuild_cache:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
/usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : rebuild_cache
# Special rule for the target rebuild_cache
rebuild_cache/fast: rebuild_cache
.PHONY : rebuild_cache/fast
# The main all target
all: cmake_check_build_system
$(CMAKE_COMMAND) -E cmake_progress_start /home/irisking/桌面/CmakeTest/1HelloWord/CMakeFiles /home/irisking/桌面/CmakeTest/1HelloWord/CMakeFiles/progress.marks
$(MAKE) -f CMakeFiles/Makefile2 all
$(CMAKE_COMMAND) -E cmake_progress_start /home/irisking/桌面/CmakeTest/1HelloWord/CMakeFiles 0
.PHONY : all
# The main clean target
clean:
$(MAKE) -f CMakeFiles/Makefile2 clean
.PHONY : clean
# The main clean target
clean/fast: clean
.PHONY : clean/fast
# Prepare targets for installation.
preinstall: all
$(MAKE) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall
# Prepare targets for installation.
preinstall/fast:
$(MAKE) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall/fast
# clear depends
depend:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
.PHONY : depend
#=============================================================================
# Target rules for targets named hello
# Build rule for target.
hello: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 hello
.PHONY : hello
# fast build rule for target.
hello/fast:
$(MAKE) -f CMakeFiles/hello.dir/build.make CMakeFiles/hello.dir/build
.PHONY : hello/fast
CmakeHelloWord.o: CmakeHelloWord.cpp.o
.PHONY : CmakeHelloWord.o
# target to build an object file
CmakeHelloWord.cpp.o:
$(MAKE) -f CMakeFiles/hello.dir/build.make CMakeFiles/hello.dir/CmakeHelloWord.cpp.o
.PHONY : CmakeHelloWord.cpp.o
CmakeHelloWord.i: CmakeHelloWord.cpp.i
.PHONY : CmakeHelloWord.i
# target to preprocess a source file
CmakeHelloWord.cpp.i:
$(MAKE) -f CMakeFiles/hello.dir/build.make CMakeFiles/hello.dir/CmakeHelloWord.cpp.i
.PHONY : CmakeHelloWord.cpp.i
CmakeHelloWord.s: CmakeHelloWord.cpp.s
.PHONY : CmakeHelloWord.s
# target to generate assembly for a file
CmakeHelloWord.cpp.s:
$(MAKE) -f CMakeFiles/hello.dir/build.make CMakeFiles/hello.dir/CmakeHelloWord.cpp.s
.PHONY : CmakeHelloWord.cpp.s
# Help Target
help:
@echo "The following are some of the valid targets for this Makefile:"
@echo "... all (the default if no target is provided)"
@echo "... clean"
@echo "... depend"
@echo "... edit_cache"
@echo "... hello"
@echo "... rebuild_cache"
@echo "... CmakeHelloWord.o"
@echo "... CmakeHelloWord.i"
@echo "... CmakeHelloWord.s"
.PHONY : help
Windows
从官网下载,安装包,安装成功后(有时因为权限问题,需要cmd管理安装),使用GUI界面,配置好顶端的
Where is the source code:需要配置,源码所在路径,即根 CMakeList所在路径
Where to build the binaries:配置希望生成的工程所在位置
然后依次点击Configure ,选择需要生成的VS版本,点击Generate即可生产VS工程文件
示例工程
该系列工程,参考顶端参考资料链接,将其中代码自己实现了一遍,前面讲过的API后面不再重复
HelloWord
CmakeHelloWord.cpp:
// An highlighted block
#include <stdio.h>
#include <tchar.h>
int main()
{
printf("Hello World!\n");
return 0;
}
CMakeList.txt:
// An highlighted block
project(HELLO)
set(SRC_LIST CmakeHelloWord.cpp)
add_executable(hello ${SRC_LIST})
project:用来设置解决方案的名称 .sln
set:Cmake语法,将变量SRC_LIST 设置为CmakeHelloWord.cpp .vs@!#@$#
add_executable:在解决方案‘HELLO’下,建立一个应用程序工程hello,所需文件是SRC_LIST
将HelloWord拆成三个文件
Hello.cpp:
#include <stdio.h>
#include "hello.hpp"
void hello(const char * name)
{
printf ("Hello %s!\n", name);
}
Hello.hpp:
#ifndef MSK_HELLO_
#define MSK_HELLO_
void hello(const char* name);
#endif //MSK_HELLO_
CmakeHelloWord.cpp:
// An highlighted block
#include "hello.hpp"
int main()
{
hello("World");
return 0;
}
CMakeList.txt:
// An highlighted block
project(HELLO)
set(SRC_LIST CmakeHelloWord.cpp Hello.cpp)
add_executable(hello ${SRC_LIST})
与测试一没有什么区别,无非是SRC_LIST增加了一个文件Hello.cpp
HelloWord方法封装成一个静态库
CMakeList.txt:
project(HELLO)
set(LIB_SRC Hello.cpp)
set(APP_SRC CmakeHelloWord.cpp)
add_library(libhello ${LIB_SRC})
add_executable(hello ${APP_SRC})
target_link_libraries(hello libhello)
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
如果想改变生成的文件名,可以增加:
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
add_library:解决方案下,增加一个静态库工程
target_link_libraries:是hello依赖libhello库
set_target_properties:更改生成文件名,即VS里,属性->常规->目标文件名,有个比较神奇的地方是,set_target_properties也会修改,app里依赖的动态库文件名
OUTPUT_NAME 也可以改为PREFIX,用来增加前缀
拆分源码路径
在源文件目录,应用所需源码放在src文件夹,库所需文件夹放在libhello
最外层目录的CMakeList.txt
project(HELLO)
add_subdirectory(src)
add_subdirectory(libhello)
src中的CMakeList.txt
include_directories(${PROJECT_SOURCE_DIR}/libhello)
set(APP_SRC CmakeHelloWord.cpp)
add_executable(hello ${APP_SRC})
target_link_libraries(hello libhello)
libhello中的CMakeList.txt
set(LIB_SRC hello.cpp)
add_library(libhello ${LIB_SRC})
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
add_subdirectory:按顺序执目录里的CMakeList
修改文件输出路径
一种办法是修改根目录的 CMakeList.txt 文件
project(HELLO)
add_subdirectory(src bin)
add_subdirectory(libhello lib)
另一种方法是,修改各自工程的CMakeList文件
include_directories(${PROJECT_SOURCE_DIR}/libhello)
set(APP_SRC CmakeHelloWord.cpp)
add_executable(hello ${APP_SRC})
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
target_link_libraries(hello libhello)
set(LIB_SRC hello.cpp)
add_library(libhello ${LIB_SRC})
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
EXECUTABLE_OUTPUT_PATH
LIBRARY_OUTPUT_PATH
CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG
CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG
这几个之间有区别,下次单独说
修改为动态库
只需要在add_library命令中加入一个SHARED参数:
add_library(libhello SHARED ${LIB_SRC})
修改 hello.hpp 文件
#ifndef MSK_HELLO_
#define MSK_HELLO_
#if defined _WIN32
#if LIBHELLO_BUILD
#define LIBHELLO_API __declspec(dllexport)
#else
#define LIBHELLO_API __declspec(dllimport)
#endif
#else
#define LIBHELLO_API
#endif
LIBHELLO_API void hello(const char* name);
#endif //MSK_HELLO_
修改 libhello/CMakeList.txt 文件
set(LIB_SRC hello.cpp)
add_definitions("-DLIBHELLO_BUILD")
add_library(libhello SHARED ${LIB_SRC})
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
add_definitions:增加预处理的宏定义,相当于,VS里的预编译头