提交 e538a8fe authored 作者: blu's avatar blu

feature: report status

上级 854114dd
...@@ -590,18 +590,22 @@ private: ...@@ -590,18 +590,22 @@ private:
} }
json data; json data;
json meta;
string msg = fmt::format("evcloudsvc detects cluster mgr {} offline of ipc {}", selfId, k); string msg = fmt::format("evcloudsvc detects cluster mgr {} offline of ipc {}", selfId, k);
data["msg"] = msg; data["msg"] = msg;
data["modId"] = "ALL"; data["modId"] = "ALL";
data["type"] = EV_MSG_META_TYPE_REPORT; data["type"] = EV_MSG_META_TYPE_REPORT;
data["catId"] = EV_MSG_REPORT_CATID_AVMODOFFLINE; data["catId"] = EV_MSG_REPORT_CATID_AVMGROFFLINE;
data["level"] = EV_MSG_META_VALUE_REPORT_LEVEL_ERROR; data["level"] = EV_MSG_META_VALUE_REPORT_LEVEL_ERROR;
data["time"] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count(); data["time"] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
data["status"] = "active"; data["status"] = "active";
meta["type"] = EV_MSG_META_TYPE_REPORT; if(ipcStatus["issues"].count(selfId) == 0){
meta["value"] = EV_MSG_META_VALUE_REPORT_LEVEL_ERROR; ipcStatus["issues"][selfId] = json();
ipcStatus["issues"][selfId] = data; }
ipcStatus["issues"][selfId][EV_MSG_REPORT_CATID_AVMGROFFLINE] = data;
ipcStatus["lastNReports"].push_back(data);
if(ipcStatus["lastNReports"].size() > NUM_MAX_REPORT_HISTORY) {
ipcStatus["lastNReports"].erase(0);
}
} }
} }
}else{ }else{
...@@ -630,18 +634,21 @@ private: ...@@ -630,18 +634,21 @@ private:
for(const string &modId: modIds){ for(const string &modId: modIds){
if(peerData["mod2ipc"].count(modId) == 0) { if(peerData["mod2ipc"].count(modId) == 0) {
spdlog::error("{} received report fron {} modId {} having no related ipc: {}", devSn, peerId, modId, data.dump()); spdlog::error("{} received report from {} modId {} having no related ipc: {}", devSn, peerId, modId, data.dump());
}else{ }else{
spdlog::warn("{} received report msg from {}: {}", devSn, peerId, data.dump()); spdlog::warn("{} received report msg from {}: {}", devSn, peerId, data.dump());
string ipcSn = peerData["mod2ipc"][modId]; string ipcSn = peerData["mod2ipc"][modId];
string status = data["status"]; string status = data["status"];
string catId = data["catId"]; string catId = data["catId"];
string severity = data["level"]; string severity = data["level"];
data["modId"] = modId;
if(peerData["ipcStatus"].count(ipcSn) != 0) { if(peerData["ipcStatus"].count(ipcSn) != 0) {
auto &ipcStatus = peerData["ipcStatus"][ipcSn]; auto &ipcStatus = peerData["ipcStatus"][ipcSn];
// log report, filter out ping
// log report if(catId == EV_MSG_REPORT_CATID_AVMODOFFLINE && status == "recover"){
// nop
}else{
if(ipcStatus.count("lastNReports") == 0){ if(ipcStatus.count("lastNReports") == 0){
ipcStatus["lastNReports"] = json(); ipcStatus["lastNReports"] = json();
} }
...@@ -649,27 +656,36 @@ private: ...@@ -649,27 +656,36 @@ private:
if(ipcStatus["lastNReports"].size() > NUM_MAX_REPORT_HISTORY) { if(ipcStatus["lastNReports"].size() > NUM_MAX_REPORT_HISTORY) {
ipcStatus["lastNReports"].erase(0); ipcStatus["lastNReports"].erase(0);
} }
}
// update status // update status
if(status == "active") { if(status == "active") {
if(severity == "error") {
ipcStatus["current"][modId] = false;
}
if(ipcStatus["current"][modId] != ipcStatus["expected"][modId]) {
if(ipcStatus["issues"].count(modId) == 0){ if(ipcStatus["issues"].count(modId) == 0){
ipcStatus["issues"][modId] = json(); ipcStatus["issues"][modId] = json();
} }
ipcStatus["issues"][modId][catId] = data; ipcStatus["issues"][modId][catId] = data;
if(severity == "error") {
ipcStatus["current"][modId] = false;
} }
}else{ }else{
// recover // recover
if(ipcStatus["issues"].count(modId) != 0 && if(ipcStatus["issues"].count(modId) != 0 &&
ipcStatus["issues"][modId].count(catId) != 0) { ipcStatus["issues"][modId].count(catId) != 0) {
ipcStatus["issues"][modId].erase(catId); ipcStatus["issues"][modId].erase(catId);
if(ipcStatus["issues"][modId].size() == 0) {
ipcStatus["issues"].erase(modId);
}
} }
if(catId == EV_MSG_REPORT_CATID_AVMODCONNECTED || catId == EV_MSG_REPORT_CATID_AVWRITEPIPE || (modId.find("evpuller") != string::npos && catId == EV_MSG_REPORT_CATID_AVOPENINPUT)) { if(catId == EV_MSG_REPORT_CATID_AVMODOFFLINE || catId == EV_MSG_REPORT_CATID_AVWRITEPIPE || (modId.find("evpuller") != string::npos && catId == EV_MSG_REPORT_CATID_AVOPENINPUT)) {
ipcStatus["current"][modId] = true; ipcStatus["current"][modId] = true;
} }
} }
}else{
spdlog::error("{} can't find ipc for report mod {}", devSn, modId);
} }
} }
} }
...@@ -1273,31 +1289,53 @@ public: ...@@ -1273,31 +1289,53 @@ public:
} }
} }
for(auto &[k,v]: this->peerData["ipcStatus"].items()) { // for(auto &[k,v]: this->peerData["ipcStatus"].items()) {
string tsn = v["mgrTerminal"]["sn"]; // string tsn = v["mgrTerminal"]["sn"];
if(this->peerData["online"].count(tsn) != 0 && this->peerData["online"][tsn] != 0) { // // mgr online
v["mgrTerminal"]["online"] = true; // if(this->peerData["online"].count(tsn) != 0 && this->peerData["online"][tsn] != 0) {
}else{ // v["mgrTerminal"]["online"] = true;
v["mgrTerminal"]["online"] = false; // }else{
auto &ipcStatus = v; // v["mgrTerminal"]["online"] = false;
for(auto &[m,n]:ipcStatus["current"].items()) { // auto &ipcStatus = v;
n = false; // for(auto &[m,n]:ipcStatus["current"].items()) {
} // n = false;
json data; // }
json meta; // // json data;
string msg = fmt::format("evcloudsvc detects cluster mgr {} offline of ipc {}", tsn, k); // // string msg = fmt::format("evcloudsvc detects cluster mgr {} offline of ipc {}", tsn, k);
data["msg"] = msg; // // data["msg"] = msg;
data["modId"] = "ALL"; // // data["modId"] = "ALL";
data["type"] = EV_MSG_META_TYPE_REPORT; // // data["type"] = EV_MSG_META_TYPE_REPORT;
data["catId"] = EV_MSG_REPORT_CATID_AVMODOFFLINE; // // data["catId"] = EV_MSG_REPORT_CATID_AVMGROFFLINE;
data["level"] = EV_MSG_META_VALUE_REPORT_LEVEL_ERROR; // // data["level"] = EV_MSG_META_VALUE_REPORT_LEVEL_ERROR;
data["time"] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count(); // // data["time"] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
data["status"] = "active"; // // data["status"] = "active";
meta["type"] = EV_MSG_META_TYPE_REPORT; // // if(ipcStatus["issues"].count(tsn) == 0){
meta["value"] = EV_MSG_META_VALUE_REPORT_LEVEL_ERROR; // // ipcStatus["issues"][tsn] = json();
ipcStatus["issues"][tsn] = data; // // }
}
} // // ipcStatus["issues"][tsn][EV_MSG_REPORT_CATID_AVMGROFFLINE] = data;
// // ipcStatus["lastNReports"].push_back(data);
// }
// // // clean issues with AV_LOOPRESTART
// // if(v["issues"].size()!=0) {
// // vector<string> issureModIds;
// // for(auto &[a,b]: v["issues"].items()){
// // for(auto &[c,d]: b.items()){
// // if(c == EV_MSG_REPORT_CATID_AVLOOPRESTART) {
// // auto now = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
// // auto delta = now - d["time"].get<decltype(now)>();
// // if(delta > 30) {
// // b.erase(c);
// // }
// // }
// // }
// // if(b.size() == 0) {
// // v["issues"].erase(a);
// // }
// // }
// // }
// }
ret["data"] = this->peerData["ipcStatus"]; ret["data"] = this->peerData["ipcStatus"];
} }
......
...@@ -90,6 +90,10 @@ private: ...@@ -90,6 +90,10 @@ private:
json modIdsOnline; json modIdsOnline;
json modIdsOffline; json modIdsOffline;
for(auto &[k,v]: this->peerData["status"].items()){ for(auto &[k,v]: this->peerData["status"].items()){
// ignore evmgr
if(k.find("evmgr") != string::npos) {
continue;
}
if(v != 0 && v != -1 && v != 1 && v != 2) { if(v != 0 && v != -1 && v != 1 && v != 2) {
modIdsOnline.push_back(k); modIdsOnline.push_back(k);
}else{ }else{
...@@ -97,8 +101,70 @@ private: ...@@ -97,8 +101,70 @@ private:
} }
} }
// TODO: construct reports body. // // since offline with be default status, don't need to send explicitly
// since we use event-style reports, this interval based report is not needed anymore // for(const string &k: modIdsOffline) {
// json report;
// string msg = fmt::format("evdaemon [ping] {} detects module {} offline", this->devSn, k);
// report["msg"] = msg;
// report["modId"] = k;
// report["type"] = EV_MSG_META_TYPE_REPORT;
// report["catId"] = EV_MSG_REPORT_CATID_AVMODOFFLINE;
// report["level"] = EV_MSG_META_VALUE_REPORT_LEVEL_ERROR;
// report["time"] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
// report["status"] = "active";
// report["type"] = EV_MSG_META_TYPE_REPORT;
// report["value"] = EV_MSG_META_VALUE_REPORT_LEVEL_ERROR;
// data["reports"].push_back(report);
// }
for(const string &k: modIdsOnline) {
json report;
string msg = fmt::format("evdaemon [ping] {} detects module {} online", this->devSn, k);
report["msg"] = msg;
report["modId"] = k;
report["type"] = EV_MSG_META_TYPE_REPORT;
report["catId"] = EV_MSG_REPORT_CATID_AVMODOFFLINE;
report["level"] = EV_MSG_META_VALUE_REPORT_LEVEL_ERROR;
report["time"] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
report["status"] = "recover";
report["type"] = EV_MSG_META_TYPE_REPORT;
report["value"] = EV_MSG_META_VALUE_REPORT_LEVEL_ERROR;
data["reports"].push_back(report);
}
vector<string> modIdsLoopRecover;
for(auto &[k,v] :peerData["contConn"].items()){
if(v > 4) {
// not offline
if(peerData["status"].count(k) != 0 && peerData["status"][k] != -1 && peerData["status"][k] != 2 && peerData["status"][k] != 1) {
auto now = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
auto delta = now - peerData["status"][k].get<decltype(now)>();
if(delta > 20) {
modIdsLoopRecover.push_back(k);
v = 0;
}
}
}
}
{
json report;
report["type"] = EV_MSG_META_TYPE_REPORT;
report["catId"] = EV_MSG_REPORT_CATID_AVLOOPRESTART;
report["level"] = EV_MSG_META_VALUE_REPORT_LEVEL_ERROR;
report["time"] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
report["status"] = "recover";
report["type"] = EV_MSG_META_TYPE_REPORT;
report["value"] = EV_MSG_META_VALUE_REPORT_LEVEL_ERROR;
for(auto &k: modIdsLoopRecover) {
string msg = fmt::format("evdaemon [ping] {} detects module {} recovered from loop restarting", this->devSn, k);
report["modId"] = k;
report["msg"] = msg;
data["reports"].push_back(report);
}
}
vector<vector<uint8_t> >body = {str2body("evcloudsvc:0:0"), str2body(EV_MSG_META_PING), str2body(data.dump())}; vector<vector<uint8_t> >body = {str2body("evcloudsvc:0:0"), str2body(EV_MSG_META_PING), str2body(data.dump())};
...@@ -210,7 +276,7 @@ private: ...@@ -210,7 +276,7 @@ private:
std::lock_guard<std::mutex> lock(mutSubsystem); std::lock_guard<std::mutex> lock(mutSubsystem);
if(subs.size() != 0) { if(subs.size() != 0) {
for(auto &k: subs) { for(auto &k: subs) {
if((this->peerData["status"].count(k) == 0 || this->peerData["status"][k] == 0 || this->peerData["status"][k] != -2) && this->peerData["config"].count(k) != 0 && this->peerData["enabled"].count(k) != 0 && this->peerData["enabled"][k] != 0) { if((this->peerData["status"].count(k) == 0 || this->peerData["status"][k] == 0 || (this->peerData["status"][k] != 1 && this->peerData["status"][k] != 2)) && this->peerData["config"].count(k) != 0 && this->peerData["enabled"].count(k) != 0 && this->peerData["enabled"][k] != 0) {
pid_t pid; pid_t pid;
if(this->peerData["contConn"].count(k) != 0 && this->peerData["contConn"][k] > 4) { // 4 times if(this->peerData["contConn"].count(k) != 0 && this->peerData["contConn"][k] > 4) { // 4 times
...@@ -224,7 +290,7 @@ private: ...@@ -224,7 +290,7 @@ private:
data["catId"] = EV_MSG_REPORT_CATID_AVLOOPRESTART; data["catId"] = EV_MSG_REPORT_CATID_AVLOOPRESTART;
data["level"] = EV_MSG_META_VALUE_REPORT_LEVEL_ERROR; data["level"] = EV_MSG_META_VALUE_REPORT_LEVEL_ERROR;
data["time"] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count(); data["time"] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
data["status"] = "active"; data["status"] = "recover";
meta["type"] = EV_MSG_META_TYPE_REPORT; meta["type"] = EV_MSG_META_TYPE_REPORT;
meta["value"] = EV_MSG_META_VALUE_REPORT_LEVEL_ERROR; meta["value"] = EV_MSG_META_VALUE_REPORT_LEVEL_ERROR;
z_send(pDealer, "evcloudsvc", meta.dump(), data.dump()); z_send(pDealer, "evcloudsvc", meta.dump(), data.dump());
...@@ -342,8 +408,8 @@ private: ...@@ -342,8 +408,8 @@ private:
this->peerData["status"][k] = 1; // disabled this->peerData["status"][k] = 1; // disabled
sendCmd2Peer(k, EV_MSG_META_VALUE_CMD_STOP, "0"); sendCmd2Peer(k, EV_MSG_META_VALUE_CMD_STOP, "0");
} }
else if(v == 1) { // perm stop else if(v == 1) {
this->peerData["status"][k] = 2; this->peerData["status"][k] = 2; // perm stop
this->peerData["config"].erase(k); this->peerData["config"].erase(k);
sendCmd2Peer(k, EV_MSG_META_VALUE_CMD_STOP, "0"); sendCmd2Peer(k, EV_MSG_META_VALUE_CMD_STOP, "0");
} }
...@@ -401,12 +467,12 @@ private: ...@@ -401,12 +467,12 @@ private:
data["msg"] = msg; data["msg"] = msg;
data["modId"] = modIds; data["modId"] = modIds;
data["type"] = EV_MSG_META_TYPE_REPORT; data["type"] = EV_MSG_META_TYPE_REPORT;
data["catId"] = EV_MSG_REPORT_CATID_AVMODCONNECTED; data["catId"] = EV_MSG_REPORT_CATID_AVMODOFFLINE;
data["level"] = EV_MSG_META_VALUE_REPORT_LEVEL_INFO; data["level"] = EV_MSG_META_VALUE_REPORT_LEVEL_ERROR;
data["time"] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count(); data["time"] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
data["status"] = "recover"; data["status"] = "recover";
meta["type"] = EV_MSG_META_TYPE_REPORT; meta["type"] = EV_MSG_META_TYPE_REPORT;
meta["value"] = EV_MSG_META_VALUE_REPORT_LEVEL_INFO; meta["value"] = EV_MSG_META_VALUE_REPORT_LEVEL_ERROR;
z_send(pDealer, "evcloudsvc", meta.dump(), data.dump()); z_send(pDealer, "evcloudsvc", meta.dump(), data.dump());
} }
...@@ -451,7 +517,10 @@ private: ...@@ -451,7 +517,10 @@ private:
if((peerData["status"].count(selfId) == 0 || peerData["status"][selfId] == 0||this->peerData["status"][selfId] == -1) ) { if((peerData["status"].count(selfId) == 0 || peerData["status"][selfId] == 0||this->peerData["status"][selfId] == -1) ) {
peerData["status"][selfId] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count(); peerData["status"][selfId] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
spdlog::info("evdaemon {} peer connected: {}", devSn, selfId); spdlog::info("evdaemon {} peer connected: {}", devSn, selfId);
if(selfId.find("evmgr") == string::npos) {
sendModConnectedMsg(modIds); sendModConnectedMsg(modIds);
}
if(this->peerData["tsLastConn"].count(selfId) == 0) { if(this->peerData["tsLastConn"].count(selfId) == 0) {
this->peerData["tsLastConn"][selfId] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count(); this->peerData["tsLastConn"][selfId] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
} }
...@@ -483,8 +552,10 @@ private: ...@@ -483,8 +552,10 @@ private:
spdlog::info("evdaemon {} peer {} config sent: {}", devSn,selfId, cfg); spdlog::info("evdaemon {} peer {} config sent: {}", devSn,selfId, cfg);
} }
else { else {
if(selfId.find("evmgr") == string::npos) {
sendModOfflineMsg(modIds); sendModOfflineMsg(modIds);
}
if(peerData["status"][selfId] == 1 || peerData["status"][selfId] == 2) { if(peerData["status"][selfId] == 1 || peerData["status"][selfId] == 2) {
spdlog::warn("evdaemon {} refuse to start {}: it was asked to be stopped, and is removed from cluster config", this->devSn, selfId); spdlog::warn("evdaemon {} refuse to start {}: it was asked to be stopped, and is removed from cluster config", this->devSn, selfId);
} }
......
...@@ -434,7 +434,7 @@ private: ...@@ -434,7 +434,7 @@ private:
} }
string msg = fmt::format("evpusher {} successfullywrite output header \"{}\": {}, {}", selfId, urlOut, ret, av_err2str(ret)); string msg = fmt::format("evpusher {} successfully write output header \"{}\"", selfId, urlOut);
json meta; json meta;
json data; json data;
data["msg"] = msg; data["msg"] = msg;
...@@ -533,6 +533,7 @@ protected: ...@@ -533,6 +533,7 @@ protected:
av_packet_unref(&packet); av_packet_unref(&packet);
if (ret < 0) { if (ret < 0) {
// TODO: report message to cloud // TODO: report message to cloud
bStatsSent = false;
string msg = fmt::format("evpusher {} error write stream, restreaming: {} ,{}", selfId, ret, av_err2str(ret)); string msg = fmt::format("evpusher {} error write stream, restreaming: {} ,{}", selfId, ret, av_err2str(ret));
json meta; json meta;
json data; json data;
......
...@@ -37,6 +37,7 @@ namespace zmqhelper { ...@@ -37,6 +37,7 @@ namespace zmqhelper {
#define EV_MSG_META_TYPE_REPORT "report" #define EV_MSG_META_TYPE_REPORT "report"
#define EV_MSG_REPORT_CATID_AVMGROFFLINE "AV_MGROFFLINE"
#define EV_MSG_REPORT_CATID_AVMODOFFLINE "AV_MODOFFLINE" #define EV_MSG_REPORT_CATID_AVMODOFFLINE "AV_MODOFFLINE"
#define EV_MSG_REPORT_CATID_AVMODCONNECTED "AV_MODCONNECTED" #define EV_MSG_REPORT_CATID_AVMODCONNECTED "AV_MODCONNECTED"
#define EV_MSG_REPORT_CATID_AVOPENINPUT "AV_OPENINPUT" #define EV_MSG_REPORT_CATID_AVOPENINPUT "AV_OPENINPUT"
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
# else # else
UNAME_S := $(shell uname -s) UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux) ifeq ($(UNAME_S),Linux)
LIBS += -ldl -lm -latomic LIBS += -ldl -lm -latomic -lgcrypt
endif endif
ifeq ($(UNAME_S),Darwin) ifeq ($(UNAME_S),Darwin)
NOP= NOP=
...@@ -81,7 +81,7 @@ evmlmotion_d: evmlmotion.cpp inc/common.hpp inc/av_common.hpp objs/utils.o inc/a ...@@ -81,7 +81,7 @@ evmlmotion_d: evmlmotion.cpp inc/common.hpp inc/av_common.hpp objs/utils.o inc/a
$(CPP) $(CPPFLAGS) -DDEBUG $(LD_FLAGS) -o evmlmotion_d evmlmotion.cpp objs/database.o objs/utils.o objs/zmqhelper.o $(SQLITE) $(LIBFFMPEG) $(HEADERS) $(LIBOPENCV) `pkg-config --cflags --libs vendor/lib/pkgconfig/libzmq.pc` $(LIBS) $(CPP) $(CPPFLAGS) -DDEBUG $(LD_FLAGS) -o evmlmotion_d evmlmotion.cpp objs/database.o objs/utils.o objs/zmqhelper.o $(SQLITE) $(LIBFFMPEG) $(HEADERS) $(LIBOPENCV) `pkg-config --cflags --libs vendor/lib/pkgconfig/libzmq.pc` $(LIBS)
evdaemon: evdaemon.cpp inc/common.hpp objs/utils.o objs/database.o objs/zmqhelper.o inc/tinythread.hpp database.cpp reverse_tun.hpp evdaemon: evdaemon.cpp inc/common.hpp objs/utils.o objs/database.o objs/zmqhelper.o inc/tinythread.hpp database.cpp reverse_tun.hpp
$(CPP) $(CPPFLAGS) $(LD_FLAGS) -o evdaemon evdaemon.cpp objs/database.o objs/utils.o objs/zmqhelper.o $(SQLITE) $(HEADERS) `pkg-config --cflags --libs vendor/lib/pkgconfig/libzmq.pc` $(LIBS) -lssh2 -lgcrypt $(CPP) $(CPPFLAGS) $(LD_FLAGS) -o evdaemon evdaemon.cpp objs/database.o objs/utils.o objs/zmqhelper.o $(SQLITE) $(HEADERS) `pkg-config --cflags --libs vendor/lib/pkgconfig/libzmq.pc` $(LIBS) -lssh2
evcloudsvc: evcloudsvc.cpp objs/utils.o objs/database.o objs/zmqhelper.o inc/tinythread.hpp evcloudsvc: evcloudsvc.cpp objs/utils.o objs/database.o objs/zmqhelper.o inc/tinythread.hpp
$(CPP) $(CPPFLAGS) $(LD_FLAGS) -o evcloudsvc evcloudsvc.cpp objs/utils.o objs/database.o objs/zmqhelper.o $(SQLITE) $(HEADERS) `pkg-config --cflags --libs vendor/lib/pkgconfig/libzmq.pc` $(LIBS) -lfmt $(CPP) $(CPPFLAGS) $(LD_FLAGS) -o evcloudsvc evcloudsvc.cpp objs/utils.o objs/database.o objs/zmqhelper.o $(SQLITE) $(HEADERS) `pkg-config --cflags --libs vendor/lib/pkgconfig/libzmq.pc` $(LIBS) -lfmt
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论