cmake是用于构建、测试和软件打包的跨平台工具
自动化(提交、发布、自动化测试),准确发现集成错误

https://blog.csdn.net/u011231598/article/details/80338941
创建src源码文件和build编译文件

进入build目录下,指定版本编译src
cmake -G "MinGW Makefiles" ..\src
不指定版本默认为vs
cmake ..\src
构建:在当前目录下
cmake --build .

${VAR}引用变量CMake_开头https://cmake.org/cmake/help/latest/
https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html
设置项目名
project(<PROJECT-NAME> [<language-name>...])
project(<PROJECT-NAME>
[VERSION <major>[.<minor>[].<patch>[.<tweak>]]])
[LANGUAGES <language-name>...]
# 项目名会被存储在变量 PROJECT_NAME 和 CMAKE_PROJECT_NAME中
# PROJECT_SOURCE_DIR 等价于 <project-name>_SOURCE_DIR
# 可使用message函数输出
message(${PROJECT_NAME})
message(${PROJECT_SOURCE_DIR})
message(${demo_SOURCE_DIR})


add_executable(<name> [WIN32] [MACOSX_BUNDLE]
[EXCLUDE_FROM_ALL]
[source1] [source2 ...])
# <name>为可执行文件的名字,与项目名称无关
# win会生成<name>.exe文件
# 如:
add_executable(demo main.cpp)
message([<mode>] "message text" ...)
# 如:
message(STATUS "${PROJECT_VERSION_MAJOR}")
设置变量
set(<variable> <value>... [PARENT_SCOPE])
# 如:
set(a 1)
设置c++标准
set(CMAKE_CXX_STANDARD 11)
设置输出目录
# 设置exe文件出书目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# 设置存档目标文件的输出目录
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

定义一个开关
option(<variable> "<help_text>" [value])
# value的值为ON 或者 OFF,默认为OFF
# 如:
option(VERSION_ENABLE "output version" ON)
将输入文件进行替换并生成输出文件
configure_file(<input> <output>
[NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS |
FILE_PERMISSIONS <permissions>...]
[COPYONLY] [ESCAPE_QUOTES] [@ONLY]
[NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
# 输入文件中的 @VAR@ 或 ${VAR} 的字符串会被替换成这些变量的当前值,未定义则是空字符串
config.h.in
#define PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define PROJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@
编译后
config.h
#define PROJECT_VERSION_MAJOR 1
#define PROJECT_VERSION_MINOR 0
#cmakedefine VAR
// 会被替换成一下两者之一,取决于VAR是否被设置
#define VAR
#undef VAR


将给定的目录添加到编译器用于搜索包含文件的目录中。
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])
# 目录会被添加到当前文件的 INCLUDE_DIRECTORIES 属性中
# 当前文件的每一个目标文件的INCLUDE_DIRECTORIES 属性也会添加该目录
将包含目录添加到目标。
target_include_directories(<target> [SYSTEM] [AFTER|BEFORE]
<INTERFACE|PUBLIC|PRIVATE> [items1...]
[<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
# 目标文件有 INCLUDE_DIRECTORIES 和 INTERFACE_INCLUDE_DIRECTORIES 两个属性
# INCLUDE_DIRECTORIES 对内头文件目录
# INTERFACE_INCLUDE_DIRECTORIES 对外头文件目录
# 包含src目录到目标
target_include_directories(demo PUBLIC "${PROJECT_BINARY_DIR}")
target_include_directories(demo INTERFACE "${PROJECT_BINARY_DIR}")
target_include_directories(demo PUBLIC "${PROJECT_BINARY_DIR}")
| INCLUDE_DIRECTORIES | INTERFACE_INCLUDE_DIRECTORIES | |
|---|---|---|
| PRIVATE | √ | |
| INTERFACE | √ | |
| PUBLIC | √ | √ |
这是再引入config.h就不会报错了

target_link_libraries(<target> ... <item>... ...)
使用指定的源文件将库添加到项目中。
add_library(<name> [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
[<source>...])

# calc/CMakeLists.txt
# 使用指定的源文件将库添加到项目中。
add_library(addition STATIC add.cpp)
# CMakeLists.txt
# 设置静态文件存放目录
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
# 添加子目录
add_subdirectory(calc)
# 链接静态文件
target_link_libraries(demo PUBLIC addition)
# 将包含目录到目标
target_include_directories(demo PUBLIC ${PROJECT_SOURCE_DIR}/calc)
# target_link_libraries 这条命令一定得在add_executable后面,不然找不到target(demo)
#include<iostream>
#include "add.h"
int main()
{
std::cout << "1+2=" << add(1,2)<<std::endl;
return 0;
}
libaddition.a为静态库
与src同级目录创建other_lib,将.a和.h文件放进去
# 链接静态文件(要使用绝对路径)
target_link_libraries(demo PUBLIC D:/Desktop/demo/other_li/libaddition.a)
动态库一定.dll文件一定得与exe文件同目录下
创建目录,包含操作excel的文件

# src/excel/CMakeLists.txt
# 使用指定的源文件将库添加到项目中。
add_library(excel STATIC BasicExcel.cpp)
# 添加子目录
add_subdirectory(excel)
# 链接静态文件
target_link_libraries(demo PUBLIC excel)
# 将包含目录到目标
target_include_directories(demo PUBLIC
${PROJECT_BINARY_DIR}
${PROJECT_SOURCE_DIR}/excel
)
案例
//实例化一个表格对象
BasicExcel e;
//加载一个文件,
e.Load("test1.xls");
//指向"Sheet1"工作簿的指针
BasicExcelWorksheet* sheet1 = e.GetWorksheet("Sheet1");
double sum = 0;
if (sheet1)
{
//当前excel的总行数
size_t maxRows = sheet1->GetTotalRows();
//当前excel的总列数
size_t maxCols = sheet1->GetTotalCols();
//输出当前工作表名称(char),采用unicode编码,没有则返回0.
cout << "Dimension of " << sheet1->GetAnsiSheetName() <<"(" <<maxRows << "," << maxCols << ")" << endl;
//制表
for (size_t c = 0; c < maxCols; ++c)
printf("%10d", c + 1);
cout << endl;
/*
要想得到EXCEL表格内的值,1、获取指向某行某列的指针类型为BasicExcelCell*
2、根据调用的成员函数Type(),查看单元格内的数据类型
3、根据数据类型的不同,选择不一样的获取数据的类函数
*/
for (size_t r = 0; r < maxRows; ++r)
{
printf("%d", r + 1);
for (size_t c = 0; c < maxCols; ++c)
{
//返回指向excel单元格的指针,行如果超过65535或列超过255,则返回00.
BasicExcelCell* cell = sheet1->Cell(r, c);
//获取单元格指针内容的类型
switch (cell->Type())
{
//undefined
case BasicExcelCell::UNDEFINED:
printf(" ");
break;
//int
case BasicExcelCell::INT:
printf("%10d", cell->GetInteger()); //获取值
break;
//double
case BasicExcelCell::DOUBLE:
printf("%10.6lf", cell->GetDouble()); //获取值
break;
//string
case BasicExcelCell::STRING:
printf("%10s", cell->GetString()); //获取值
break;
//wstrig
case BasicExcelCell::WSTRING:
wprintf(L"%10s", cell->GetWString()); //获取值
break;
}
}
std::cout << endl;
}
/*计算出第二列数据的总和,并替换单元格第二列最后一行的数据*/
for (int i = 1; i < maxRows; ++i)
{
BasicExcelCell* cell = sheet1->Cell(i, 1);
sum += cell->GetDouble();
}
BasicExcelCell* cell2 = sheet1->Cell(maxRows-1, 1);
cell2->Set(sum);
}
std::cout << endl;
//e.Save();
//将修改的文件保存为"test2.xls"
e.SaveAs("test2.xls");
//创建新的工作簿,此时打开的文件中有两个excel工作簿,分别为Sheet1,Sheet2.
e.New(2);
//将ANSI编码格式的EXCEL工作表重命名为另一个ANSI名称,成功返回true,失败返回false
e.RenameWorksheet("Sheet1", "city");
e.RenameWorksheet("Sheet2", "weather");
//创建类对象e的另一个工作簿
BasicExcelWorksheet* sheet2 = e.GetWorksheet("city");
if (sheet2)
{
//声明一个指向单元格块的指针
BasicExcelCell* cell;
//表格的表头
const char *title[4] = { "china", "english", "american", "japan" };
//向单元格添加表头
for (size_t c = 0; c < 4; ++c)
{
cell = sheet2->Cell(0, c+1);
cell->SetString(title[c]);
}
//向单元格添加列头
for (size_t r = 1; r < 9; ++r)
sheet2->Cell(r, 0)->Set((int)r);
//向表格内添加元素
double cont = 0.23;
for (size_t i = 0; i < 4; ++i)
{
for (size_t j = 0; j < 8; ++j)
sheet2->Cell( j + 1, i + 1)->SetDouble(cont++);
}
}
e.SaveAs("text3.xls");
e.Load("text3.xls");
//得到当前文件内一共有多少工作簿
size_t maxSheets = e.GetTotalWorkSheets();
cout << "Total number of worksheets:" << e.GetTotalWorkSheets() << endl;
//对工作簿进行遍历
for (size_t i = 0; i < maxSheets; ++i)
{
//获取工作簿
BasicExcelWorksheet* sheet = e.GetWorksheet(i);
if (sheet)
{
//获取最大行列数
size_t maxRows = sheet->GetTotalRows();
size_t maxCols = sheet->GetTotalCols();
cout << "Dimension of " << sheet->GetAnsiSheetName() << "(" << maxRows << "," << maxCols << ")" << endl;
//列表
if (maxRows > 0)
{
for (size_t c = 0; c < maxCols; ++c)
printf("%10d", c );
cout << endl;
}
//打印表格内容
for (size_t r = 0; r < maxRows; ++r)
{
for (size_t c = 0; c < maxCols; ++c)
{
BasicExcelCell* cell = sheet->Cell(r, c);
switch (cell->Type())
{
//undefined
case BasicExcelCell::UNDEFINED:
printf(" ");
break;
//int
case BasicExcelCell::INT:
printf("%10d", cell->GetInteger()); //获取值
break;
//double
case BasicExcelCell::DOUBLE:
printf("%10.6lf", cell->GetDouble()); //获取值
break;
//string
case BasicExcelCell::STRING:
printf("%10s", cell->GetString()); //获取值
break;
//wstrig
case BasicExcelCell::WSTRING:
wprintf(L"%10s", cell->GetWString()); //获取值
break;
}
}
cout << endl;
}
//将文件以csv格式保存
if (i == 0)
{
ofstream f("text.csv");
sheet->Print(f, ',', '\0');
f.close();
}
}
cout << endl;
}
install(TARGETS <target>DESTINATION <dir>)
install(FILES <file>DESTINATION <dir>)
insta11(PROGRAMS<非目标文件的可执行程序>DESTINATION<dir>)
#如脚本
insta11(DIRECTORY<dir>DESTINATION<dir>)#安装目录
实例
install(TARGETS MathFunctions DESTINATION 1ib)
install(FILES MathFunctions.h DESTINATION include)
instal1(DIRECTORY doc/DESTINATION d)
cmake --install.
#安装到默认目录
CMAKE_INSTALL_PREFIX
cmake --install.--prefix <dir>
#安装到指定目录
CMakeLists.txt
# 安装exe文件
install(TARGETS demo DESTINATION bin)
# 安装外部头文件
# 安装外部静态文件
# 安装外部动态文件
calc/CMakeListx.txt
# 使用指定的源文件将库添加到项目中。
add_library(addition STATIC add.cpp)
add_library(sub SHARED sub.cpp)
install(TARGETS addition DESTINATION lib)
install(FILES add.h DESTINATION include)


我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po