亮点
- 线程安全的进度条和加载动画
- 仅头文件库。获取
include/indicators
的副本。 - 单头文件版本在
single_include/indicators
中。 - 上述GIF的源代码可以在这里找到
- MIT许可证
目录
基本进度条
要在应用程序中引入进度条,请包含indicators/progress_bar.hpp
并创建一个ProgressBar
对象。以下是进度条的一般结构:
{前缀} {开始} {填充} {引导} {剩余} {结束} {百分比} [{已用时间}<{剩余时间}] {后缀}
^^^^^^^^^^^^^ 条宽 ^^^^^^^^^^^^^^^
ProgressBar中的进度量以size_t
类型维护,范围为[0, 100]
。当进度达到100时,进度完成。
从应用程序级代码,有两种方法可以更新这个进度:
使用bar.tick()
更新进度
你可以使用bar.tick()
更新进度条,它每次将进度增加恰好1%
。
#include <indicators/progress_bar.hpp>
#include <thread>
#include <chrono>
int main() {
using namespace indicators;
ProgressBar bar{
option::BarWidth{50},
option::Start{"["},
option::Fill{"="},
option::Lead{">"},
option::Remainder{" "},
option::End{"]"},
option::PostfixText{"正在提取归档"},
option::ForegroundColor{Color::green},
option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}
};
// 更新进度条状态
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
return 0;
}
上述代码将打印一个进度条,每100毫秒增加1%,从0%到100%。
使用bar.set_progress(value)
更新进度
如果你希望以离散步骤控制进度条的进度,可以考虑使用bar.set_progress(value)
。例如:
#include <chrono>
#include <indicators/cursor_control.hpp>
#include <indicators/progress_bar.hpp>
#include <thread>
int main() {
using namespace indicators;
// 隐藏光标
show_console_cursor(false);
ProgressBar bar{
option::BarWidth{50},
option::Start{"["},
option::Fill{"■"},
option::Lead{"■"},
option::Remainder{"-"},
option::End{" ]"},
option::PostfixText{"正在加载依赖项 1/4"},
option::ForegroundColor{Color::cyan},
option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}
};
// 更新进度条状态
bar.set_progress(10); // 完成10%
// 执行一些工作
std::this_thread::sleep_for(std::chrono::milliseconds(800));
bar.set_option(option::PostfixText{"正在加载依赖项 2/4"});
bar.set_progress(30); // 完成30%
// 执行更多工作
std::this_thread::sleep_for(std::chrono::milliseconds(700));
bar.set_option(option::PostfixText{"正在加载依赖项 3/4"});
bar.set_progress(65); // 完成65%
// 执行最后一部分工作
std::this_thread::sleep_for(std::chrono::milliseconds(900));
bar.set_option(option::PostfixText{"依赖项已加载!"});
bar.set_progress(100); // 全部完成
// 显示光标
show_console_cursor(true);
return 0;
}
显示已用时间/剩余时间
indicators
中的所有进度条和加载动画都支持显示已用时间和剩余时间。受Python的tqdm模块启发,这个计时器的格式是[{已用时间}<{剩余时间}]
:
#include <chrono>
#include <indicators/cursor_control.hpp>
#include <indicators/progress_bar.hpp>
#include <thread>
int main() {
using namespace indicators;
// 隐藏光标
show_console_cursor(false);
indicators::ProgressBar bar{
option::BarWidth{50},
option::Start{" ["},
option::Fill{"█"},
option::Lead{"█"},
option::Remainder{"-"},
option::End{"]"},
option::PrefixText{"训练注视网络 👀"},
option::ForegroundColor{Color::yellow},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}
};
// 更新进度条状态
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
// 显示光标
show_console_cursor(true);
return 0;
}
不确定进度条
你可能有一个需要进度条但最大进度未知的用例,例如,你正在从一个没有公布总字节数的远程服务器下载内容。
在这种情况下使用indicators::IndeterminateProgressBar
。IndeterminateProgressBar
类似于常规进度条,只是要达到的总进度是未知的。这种进度条的tick可以无限运行。
当你知道进度完成时,只需调用bar.mark_as_completed()
。
#include <chrono>
#include <indicators/indeterminate_progress_bar.hpp>
#include <indicators/cursor_control.hpp>
#include <indicators/termcolor.hpp>
#include <thread>
int main() {
indicators::IndeterminateProgressBar bar{
indicators::option::BarWidth{40},
indicators::option::Start{"["},
indicators::option::Fill{"·"},
indicators::option::Lead{"<==>"},
indicators::option::End{"]"},
indicators::option::PostfixText{"检查更新"},
indicators::option::ForegroundColor{indicators::Color::yellow},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
indicators::show_console_cursor(false);
auto job = [&bar]() {
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
bar.mark_as_completed();
std::cout << termcolor::bold << termcolor::green
<< "系统已是最新版本!\n" << termcolor::reset;
};
std::thread job_completion_thread(job);
// 更新进度条状态
while (!bar.is_completed()) {
bar.tick();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
job_completion_thread.join();
indicators::show_console_cursor(true);
return 0;
}
块进度条
你是否需要使用Unicode块元素的平滑块进度条?使用BlockProgressBar
而不是ProgressBar
。感谢这篇博客文章使BlockProgressBar
成为该库的一个简单添加。
#include <indicators/block_progress_bar.hpp>
#include <indicators/cursor_control.hpp>
#include <thread>
#include <chrono>
int main() {
using namespace indicators;
// 隐藏光标
show_console_cursor(false);
BlockProgressBar bar{
option::BarWidth{80},
option::Start{"["},
option::End{"]"},
option::ForegroundColor{Color::white} ,
option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}
};
// 更新进度条状态
auto progress = 0.0f;
while (true) {
bar.set_progress(progress);
progress += 0.25f;
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
// 显示光标
show_console_cursor(true);
return 0;
}
多重进度
indicators
支持使用MultiProgress
类模板管理多个进度条。
template <typename Indicator, size_t count> class MultiProgress
是一个类模板,它持有多个进度条的引用,并提供一个安全的接口来更新每个进度条的状态。MultiProgress
适用于ProgressBar
和BlockProgressBar
类。
如果你在编译时知道要管理的进度条数量,请使用此类。
以下是一个管理三个ProgressBar
对象的MultiProgress
对象的示例。
#include <indicators/multi_progress.hpp>
#include <indicators/progress_bar.hpp>
int main() {
using namespace indicators;
// 配置第一个进度条
ProgressBar bar1{
option::BarWidth{50},
option::Start{"["},
option::Fill{"■"},
option::Lead{"■"},
option::Remainder{" "},
option::End{" ]"},
option::ForegroundColor{Color::yellow},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::PrefixText{"进度条 #1 "},
option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}
};
// 配置第二个进度条
ProgressBar bar2{
option::BarWidth{50},
option::Start{"["},
option::Fill{"="},
option::Lead{">"},
option::Remainder{" "},
option::End{" ]"},
option::ForegroundColor{Color::cyan},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::PrefixText{"进度条 #2 "},
option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}
};
// 配置第三个进度条
indicators::ProgressBar bar3{
option::BarWidth{50},
option::Start{"["},
option::Fill{"#"},
option::Lead{"#"},
option::Remainder{" "},
option::End{" ]"},
option::ForegroundColor{Color::red},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::PrefixText{"进度条 #3 "},
option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}
};
// 构造 MultiProgress 对象
indicators::MultiProgress<indicators::ProgressBar, 3> bars(bar1, bar2, bar3);
std::cout << "多个进度条:\n";
auto job1 = [&bars]() {
while (true) {
bars.tick<0>();
if (bars.is_completed<0>())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
};
auto job2 = [&bars]() {
while (true) {
bars.tick<1>();
if (bars.is_completed<1>())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
};
auto job3 = [&bars]() {
while (true) {
bars.tick<2>();
if (bars.is_completed<2>())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(60));
}
};
std::thread first_job(job1);
std::thread second_job(job2);
std::thread third_job(job3);
first_job.join();
second_job.join();
third_job.join();
return 0;
}
DynamicProgress
DynamicProgress
是一个容器类,类似于 MultiProgress
,用于管理多个进度条。顾名思义,使用 DynamicProgress
,您可以动态添加新的进度条。
要添加新的进度条,调用 bars.push_back(new_bar)
。这个调用将返回追加的条的索引。然后您可以使用索引运算符引用这个条,例如 bars[4].set_progress(55)
。
如果您在编译时不知道进度条的数量,请使用这个类。
下面是一个 DynamicProgress
对象的示例,它管理六个 ProgressBar
对象。其中三个条是动态添加的。
#include <indicators/dynamic_progress.hpp>
#include <indicators/progress_bar.hpp>
using namespace indicators;
int main() {
auto bar1 = std::make_unique<ProgressBar>(option::BarWidth{50},
option::ForegroundColor{Color::red},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::PrefixText{"5c90d4a2d1a8: 下载中 "},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}});
auto bar2 = std::make_unique<ProgressBar>(option::BarWidth{50},
option::ForegroundColor{Color::yellow},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::PrefixText{"22337bfd13a9: 下载中 "},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}});
auto bar3 = std::make_unique<ProgressBar>(option::BarWidth{50},
option::ForegroundColor{Color::green},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::PrefixText{"10f26c680a34: 下载中 "},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}});
auto bar4 = std::make_unique<ProgressBar>(option::BarWidth{50},
option::ForegroundColor{Color::white},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::PrefixText{"6364e0d7a283: 下载中 "},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}});
auto bar5 = std::make_unique<ProgressBar>(option::BarWidth{50},
option::ForegroundColor{Color::blue},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::PrefixText{"ff1356ba118b: 下载中 "},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}});
auto bar6 = std::make_unique<ProgressBar>(option::BarWidth{50},
option::ForegroundColor{Color::cyan},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::PrefixText{"5a17453338b4: 下载中 "},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}});
std::cout << termcolor::bold << termcolor::white << "拉取镜像 foo:bar/baz\n";
// 构造包含3个进度条。我们稍后会再添加3个
DynamicProgress<ProgressBar> bars(bar1, bar2, bar3);
// 完成时不隐藏进度条
bars.set_option(option::HideBarWhenComplete{false});
std::thread fourth_job, fifth_job, sixth_job;
auto job4 = [&bars](size_t i) {
while (true) {
bars[i].tick();
if (bars[i].is_completed()) {
bars[i].set_option(option::PrefixText{"6364e0d7a283: 拉取完成 "});
bars[i].mark_as_completed();
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
};
auto job5 = [&bars](size_t i) {
while (true) {
bars[i].tick();
if (bars[i].is_completed()) {
bars[i].set_option(option::PrefixText{"ff1356ba118b: 拉取完成 "});
bars[i].mark_as_completed();
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
};
auto job6 = [&bars](size_t i) {
while (true) {
bars[i].tick();
if (bars[i].is_completed()) {
bars[i].set_option(option::PrefixText{"5a17453338b4: 拉取完成 "});
bars[i].mark_as_completed();
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(40));
}
};
auto job1 = [&bars, &bar6, &sixth_job, &job6]() {
while (true) {
bars[0].tick();
if (bars[0].is_completed()) {
bars[0].set_option(option::PrefixText{"5c90d4a2d1a8: 拉取完成 "});
// bar1 完成,添加 bar6
auto i = bars.push_back(std::move(bar6));
sixth_job = std::thread(job6, i);
sixth_job.join();
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(140));
}
};
auto job2 = [&bars, &bar5, &fifth_job, &job5]() {
while (true) {
bars[1].tick();
if (bars[1].is_completed()) {
bars[1].set_option(option::PrefixText{"22337bfd13a9: 拉取完成 "});
// bar2 完成,添加 bar5
auto i = bars.push_back(std::move(bar5));
fifth_job = std::thread(job5, i);
fifth_job.join();
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(25));
}
};
auto job3 = [&bars, &bar4, &fourth_job, &job4]() {
while (true) {
bars[2].tick();
if (bars[2].is_completed()) {
bars[2].set_option(option::PrefixText{"10f26c680a34: 拉取完成 "});
// bar3 完成,添加 bar4
auto i = bars.push_back(std::move(bar4));
fourth_job = std::thread(job4, i);
fourth_job.join();
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
};
std::thread first_job(job1);
std::thread second_job(job2);
std::thread third_job(job3);
third_job.join();
second_job.join();
first_job.join();
std::cout << termcolor::bold << termcolor::green << "✔ 下载完成镜像 foo/bar:baz" << std::endl;
std::cout << termcolor::reset;
return 0;
}
在上面的代码中,注意选项 bars.set_option(option::HideBarWhenComplete{true});
。是的,您可以通过将此选项设置为 true
来在进度条完成时隐藏它们。如果这样做,上面的例子将看起来像这样:
进度旋转器
要在应用程序中引入进度旋转器,包含 indicators/progress_spinner.hpp
并创建一个 ProgressSpinner
对象。以下是进度旋转器的一般结构:
{前缀} {旋转器} {百分比} [{已用时间}<{剩余时间}] {后缀}
ProgressSpinner 有一个字符串向量:spinner_states
。每次更新时,旋转器将从这个序列中选择下一个字符串打印到控制台。旋转器状态可以类似于进度条进行更新:使用 tick()
或 set_progress(value)
。
#include <indicators/progress_spinner.hpp>
int main() {
using namespace indicators;
indicators::ProgressSpinner spinner{
option::PostfixText{"正在检查凭证"},
option::ForegroundColor{Color::yellow},
option::SpinnerStates{std::vector<std::string>{"⠈", "⠐", "⠠", "⢀", "⡀", "⠄", "⠂", "⠁"}},
option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}
};
// 更新旋转器状态
auto job = [&spinner]() {
while (true) {
if (spinner.is_completed()) {
spinner.set_option(option::ForegroundColor{Color::green});
spinner.set_option(option::PrefixText{"✔"});
spinner.set_option(option::ShowSpinner{false});
spinner.set_option(option::ShowPercentage{false});
spinner.set_option(option::PostfixText{"已认证!"});
spinner.mark_as_completed();
break;
} else
spinner.tick();
std::this_thread::sleep_for(std::chrono::milliseconds(40));
}
};
std::thread thread(job);
thread.join();
return 0;
}
递减进度
indicators
允许您轻松控制进度方向,即递增或递减进度,使用 option::ProgressType
。要编程一个倒计时进度条,使用 option::ProgressType::decremental
#include <chrono>
#include <indicators/progress_bar.hpp>
#include <thread>
using namespace indicators;
int main() {
ProgressBar bar{option::BarWidth{50},
option::ProgressType{ProgressType::decremental},
option::Start{"["},
option::Fill{"■"},
option::Lead{"■"},
option::Remainder{"-"},
option::End{"]"},
option::PostfixText{"正在还原系统恢复"},
option::ForegroundColor{Color::yellow},
option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}};
// 更新进度条状态
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
std::cout << termcolor::bold << termcolor::white
<< "任务成功失败\n" << termcolor::reset;
return 0;
}
使用可迭代对象
如果您想使用进度条来指示在迭代可迭代对象(例如数字列表)时的进度,可以通过使用 option::MaxProgress
来实现:
#include <chrono>
#include <indicators/block_progress_bar.hpp>
#include <indicators/cursor_control.hpp>
#include <thread>
int main() {
// 隐藏光标
indicators::show_console_cursor(false);
// 随机数字列表
std::vector<size_t> numbers;
for (size_t i = 0; i < 1259438; ++i) {
numbers.push_back(i);
}
using namespace indicators;
BlockProgressBar bar{
option::BarWidth{80},
option::ForegroundColor{Color::white},
option::FontStyles{
std::vector<FontStyle>{FontStyle::bold}},
option::MaxProgress{numbers.size()}
};
std::cout << "迭代数字列表(大小 = "
<< numbers.size() << ")\n";
std::vector<size_t> result;
for (size_t i = 0; i < numbers.size(); ++i) {
// 执行一些计算
result.push_back(numbers[i] * numbers[i]);
// 显示迭代作为后缀文本
bar.set_option(option::PostfixText{
std::to_string(i) + "/" + std::to_string(numbers.size())
});
// 更新进度条
bar.tick();
}
bar.mark_as_completed();
// 显示光标
indicators::show_console_cursor(true);
return 0;
}
Unicode 支持
indicators
支持进度条中的多字节 Unicode 字符。
如果设置了 option::BarWidth
,库会尽量遵守这个设置。在填充进度条时,如果下一个 Fill
字符串的显示宽度会超过进度条宽度,那么库会用 ' '
空格字符填充进度条的剩余部分。
以下是一些进度条的示例,每个进度条的宽度为 50,显示不同的 Unicode 字符:
#include <chrono>
#include <indicators/progress_bar.hpp>
#include <indicators/indeterminate_progress_bar.hpp>
#include <indicators/cursor_control.hpp>
#include <thread>
int main() {
indicators::show_console_cursor(false);
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
{
// 普通 ASCII
indicators::ProgressBar bar{
indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"="},
indicators::option::Lead{">"},
indicators::option::Remainder{" "},
indicators::option::End{" ]"},
indicators::option::PostfixText{"普通 ASCII"},
indicators::option::ForegroundColor{indicators::Color::green},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
// 更新进度条状态
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
{
// Unicode
indicators::ProgressBar bar{
indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"驚くばかり"},
indicators::option::Lead{">"},
indicators::option::Remainder{" "},
indicators::option::End{" ]"},
indicators::option::PostfixText{"日语"},
indicators::option::ForegroundColor{indicators::Color::yellow},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
// 更新进度条状态
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
{
// 俄语
indicators::ProgressBar bar{
indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"Потрясающие"},
indicators::option::Remainder{" "},
indicators::option::End{" ]"},
indicators::option::PostfixText{"俄语"},
indicators::option::ForegroundColor{indicators::Color::red},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
// 更新进度条状态
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
{
// 希腊语
indicators::ProgressBar bar{
indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"Φοβερός"},
indicators::option::Remainder{" "},
indicators::option::End{" ]"},
indicators::option::PostfixText{"希腊语"},
indicators::option::ForegroundColor{indicators::Color::cyan},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
// 更新进度条状态
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
{
// 中文
indicators::ProgressBar bar{
indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"太棒了"},
indicators::option::Remainder{" "},
indicators::option::End{" ]"},
indicators::option::PostfixText{"中文"},
indicators::option::ForegroundColor{indicators::Color::green},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
// 更新进度条状态
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
{
// 表情符号
indicators::ProgressBar bar{
indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"🔥"},
indicators::option::Lead{"🔥"},
indicators::option::Remainder{" "},
indicators::option::End{" ]"},
indicators::option::PostfixText{"表情符号"},
indicators::option::ForegroundColor{indicators::Color::white},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
// 更新进度条状态
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
{
// 不确定进度条
indicators::IndeterminateProgressBar bar{
indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"✯"},
indicators::option::Lead{"載入中"},
indicators::option::End{" ]"},
indicators::option::PostfixText{"加载进度条"},
indicators::option::ForegroundColor{indicators::Color::yellow},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
auto job = [&bar]() {
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
bar.mark_as_completed();
};
std::thread job_completion_thread(job);
// 更新进度条状态
while (!bar.is_completed()) {
bar.tick();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
job_completion_thread.join();
}
indicators::show_console_cursor(true);
return 0;
}
构建示例
git clone https://github.com/p-ranav/indicators
cd indicators
mkdir build && cd build
cmake -DINDICATORS_SAMPLES=ON -DINDICATORS_DEMO=ON ..
make
WinLibs + MinGW
对于 Windows,如果你像我一样使用 WinLibs,cmake 命令会像这样:
foo@bar:~$ mkdir build && cd build
foo@bar:~$ cmake -G "MinGW Makefiles" -DCMAKE_CXX_COMPILER="C:/WinLibs/mingw64/bin/g++.exe" -DINDICATORS_SAMPLES=ON -DINDICATORS_DEMO=ON ..
foo@bar:~$ make -j4
生成单头文件
python3 utils/amalgamate/amalgamate.py -c single_include.json -s .
贡献
欢迎贡献,请查看 CONTRIBUTING.md 文档以获取更多信息。
许可
该项目使用 MIT 许可证。