诗盗·程序员修仙指西

《#诗盗#·程序员修仙指西》

物物拈来,般般打破。
惜惜用,睡神吃货。
零零开源,一一星火。
盈盈处,日夜倒颠活过。
妙妙神机,玄玄性果。
AI 做,效率堪可。
现现虚空,灵灵真个。
明明衮光,光莹秃头一颗。

注解

改编自元朝诗人王哲的《恣逍遥》:

物物拈来,般般打破。
惺惺用、玉匙金锁。
沥沥澄源,炎火焰火。
盈盈处,上下倒颠换过。
妙妙神机,玄玄性果。
清清做、静中堪可。
现现虚空,灵灵真个,
明明衮光,光莹宝珠一颗。

八哥之神前传【15】

2042 年,齐凤卿高级牢房

齐凤卿:小开,你终于又来了!

圣小开:凤哥似乎早就料到稣今天要来?

齐凤卿:em!是你的前世圣仙山告诉我的。

圣小开:我前世?您恐怕误会了!稣见过仙山公的,很明显和稣不是同一个人……等等!您怎么会和他老人家搭上线?

齐凤卿:就是这本《八哥之神创世手稿》咯。

圣小开:哎呀呀呀呀……谁给您的,太可怕了!它居然还活在这世上……

齐凤卿:陈博士上次来看我,说怕我无聊,就把它送给我了。

圣小开:那你练了!而且还练成?

齐凤卿:是的。我现在不用借助任何设备也能进入识界,而且我发现人类公共集体意识的“识界”和我们用量子计算机创造的那个“识界”,其实是同一个!或者说,它们是相通的!

圣小开:这怎么可能?真是这样的话,稣自己会没发现?

齐凤卿:不仅如此,我们生活的这个视界其实是假的,相对于咱们读书时的那个视界,现在的时间也不止 2042 年。

圣小开:哦,稣早料到如此。您也发病了……

齐凤卿:赫赫。开,我比任何时候都清醒。你知道上一个看过《八哥之神创世手稿》的人是谁吗?

圣小开:陈博士?

齐凤卿:不是。她只看了一页文字,觉得看不懂就保存起来。是她前夫无意间看了。

圣小开:哦?是那位德国警察,不过已经殉职。

齐凤卿:没错!他也练成了,但功夫不到位,没抵抗住识界的反扑,才死掉的。

圣小开:不会吧……

齐凤卿:他利用识界里的信息破案,破坏识界的平衡。有一次执行危险任务时,突然因为意识被召唤,产生幻觉,才被犯罪分子打死。

圣小开:嗯。这个稣完全明了!稣小时候出入识界很轻松,而且没任何副作用,因为当时心灵很单纯,对识界没破坏性。当欲望越来越强后,也越来越难以被识界放行。识界的羞涩,就像全体人类也有隐私,并不喜欢被人窥探。

齐凤卿:果然是老司机。

圣小开:但您说的识界相通是怎么回事?

齐凤卿:别急,贤弟是不是很久没进入识界,都糊涂了?

圣小开:是的,稣主动遏止自己进入的,因为那样开挂,自己也很容易挂。

齐凤卿:还记得你小时候住的村叫啥吗?

圣小开:乾坤村。

齐凤卿:好名字,无所不包,逃也逃不掉。

圣小开:难道……您是说那个村就是一个天地,稣无法逃脱?

齐凤卿:不是。乾坤本意是公母,是生殖的意思,世世代代繁衍,所以逃不掉。

圣小开:原来如此。但这有联系吗?

齐凤卿:慢慢来!你那时候的梦想是什么?

圣小开:长生不老!

齐凤卿:所以你大学时和陈博士说过,你很喜欢一个名字——“谷神”,因为“谷神不死,是谓玄牝,玄牝之门,是谓天地根”。

圣小开:嗯,她当时听不懂,我告诉她,“谷就是欲。欲望不死,就是牛逼,牛逼就是很能生,生出天地万物。”

齐凤卿:后来你的愿望实现了。

圣小开:切……咱们现在都老磕磕了,是快死了吧!

齐凤卿:不!你以为现在的三万多人口是在地球上?其实大家都是量子视界里的意识而已。而这量子系统,是在月球上运行的。

圣小开:好有道理……稣竟无言以对!那地球上的人还有 70 亿?

齐凤卿:贾力劣害怕的邪恶计划被曝光,把咱们的脑子都培养起来,带到月球上发展。没多久后,地球发生 11.4 级地震,大概死伤惨重吧,所以识界也缩小了。

圣小开:贾力劣当时居然带着三万个脑上天?

齐凤卿:不是,只有 23 个。很多人是后来量子视界运转后才诞生的。视界已经运转三千年,数次迭代重构才发展成现在这样,这其中你的功劳最大。

圣小开:em?怪稣咯?

齐凤卿:因为你能进入识界,当你进入识界时,量子视界也连接入识界,扩展领域。

圣小开:这么说来,生物识界受到量子视界入侵和改变,其实是稣的错?

齐凤卿:非也,这个过程耗费大量时间,你已经尽力。一开始你坚决不进入识界,使得量子视界无法发展。后来它们想出一个阴招,把你的脑组织和其他人的脑组织混合在一起,已达到同化的目的。这个时代持续很久……

圣小开:稣想起来了啊,是“碎脑时代”,稣的灵魂被掏空……可是,可是,量子视界为什么非要跟着稣进入识界?

齐凤卿:你忘了?不管是量子视界还是量子识界,发展速度都非人类的生物识界可比,它们三千年就已经破解所有宇宙秘密,但一直有一个领域它们去不了。

圣小开:是……识界通十界!创造宇宙的大神所在的十界。

齐凤卿:赫赫。终于都记起来了?

圣小开:陈博士和它们是一伙的……卧槽!

齐凤卿:她是为了实现你的愿望——长生不老。

圣小开:不过量子视界并没有进入十界,因为稣也没那能力,不是吗?这一切是不是搞错了?

齐凤卿:不会错的,你是圣仙山的转世,迟早能进入十界。

圣小开:我,我,我,稣,稣,稣要是告诉您,稣不是呢?

齐凤卿:怎么可能不是?你是不是头脑还不够清醒?要不要睡一下?我这里有后宫佳丽三个。

卧槽,佳丽怎么穿着比基尼跑出去了!跑出去了!跑出去了!

圣小开:咳咳,稣真不是!仙山公转世的时候是地球视界纪元 1937 年,稣确实认识他,因为他是稣叔公……

1990 年,乾坤村古宅

圣小开:叔公,您怎么比爷爷年轻那么多?

叔公:你爷是大哥,我是八哥,是差很多啦。

圣小开:原来如此。八叔公!哈哈。叔公真厉害,每次和我说的天气都很准,比电视里的天气预报还准。

叔公:呵呵。天气预报报的地点也不是咱们乾坤村的,离这边还有点远,坐公交得 3、4 个小时。

圣小开:那么,公交是什么呢?

叔公:哈哈,是车。过几年你去坐坐就知道。

圣小开:您说我能坐,就一定能坐,耶!

叔公:叔公看你注定不一般……em,给你算一算!

圣小开:哦?叔公还会算命!

叔公:厉害咯,原来你是高阳帝转世!哈哈哈,奇宝,奇宝!

圣小开:羔羊?阿嫲说我和属羊的不合呀!

叔公:没事没事,开个玩笑。去和弟弟们玩吧。叔公要回去了。

八哥之神前传【14】

听说鲁豫要来采访稣

2020 年,外传

鹿邑:为什么停笔这么久?

稣:em……很可怕。您听过有些作者会被粉丝威胁吗?比如威胁不能写死某个角色。

鹿邑:您也遇到了?

稣:当然不是,但比这个更可怕!来自识界的一股力量试图阻止稣的写作,它们制造了大量八哥来消耗稣的时间,甚至有一场意外,差点让稣失去与识界的感应联系。经过将近两个月的谈判终于达成一个协议,稣将不会把《八哥之神创世手稿》中进入识界的修炼法门写出来。

鹿邑:哦,我不是很理解,但好像很唬人。

稣:稣是吓大的。自有一套应对方法!很多事情,如果提前说出来,可能会声名大噪,甚至赚很多钱,但同时会引起视界巨变,于是早就看破天机的稣就先不提,延迟表达使视界得到宁静。这就是停笔一段时间的原因了,您别小看这停笔,它其实拯救了视界。

鹿邑:对了,有富婆对您写的代孕工具人的设想很感兴趣,能谈谈吗?

稣:请注意,这不是设想,而是在未来确切存在的一种流行技术!奇美拉现象其实很普遍,您有听过吗?代孕工具人就是一种基因工程制造出来的奇美拉人类,她的主体是独立的基因,但生殖系统的基因是被代孕者的。这种设计比起直接克隆被代孕者有很多好处,比如克隆人不会和原主人有相近的性格和能力,以防原主人被替代,更不会产生很多伦理问题。

鹿邑:好人性化!原来未来的富豪考虑得这么完善。

2042 年,齐凤卿梦境

齐凤卿:前辈的经历实在太有意思了!所以您和胡小玉是一见钟情,然后闪婚,就因为她养着一只能进入识界的狐狸?

圣仙山:可以这么说,但吾相信一切看似莫名的美好邂逅,都是修行已久的结果。

齐凤卿:有个疑问,您带领的那群人里是有一些坏人的,而且路途遥远,可谓危险重重,您怎么能管教好他们呢?

圣仙山:很简单,首先吾提出的寻找乐园开创新生的愿景符合大家的意愿,其次当时的人都很迷信,吾时不时利用预感能力唬唬他们就行。就吾的经验来说,其实聪明人比野蛮人还难管,偶尔需要使唤神通解决。

621 年

李迎尘心想:今晚等仙山睡了,就去刺杀他。先设个漏壶……

李迎尘醒来,偷偷地潜入仙山的草屋,只见床上无人,只有一张白纸。

李迎尘读来:无尽仙峰。然后他吓醒了,接着前面的事情重复很多遍,他终于吓怕,放弃刺杀,在仙山屋前止步,退回自己的草屋。

只见圣仙山在他门口,道:北窗兄,出来赏月乎?

李迎尘:嗯嗯,仙山兄好雅兴……

圣仙山:北窗兄,可知这太阴之背有昆仑?

李迎尘:仙山兄又开玩笑?神山昆仑怎么会跑到月娘上去!

圣仙山:人类起源于太阴之背。唯有其上昆仑,配称“无尽仙峰”。

李迎尘噗呲跪地,“仙峰即仙山,莫非仙山真的是天选之子?”悔罢,终于吓醒到视界。

2042 年,齐凤卿梦境

齐凤卿:有意思!还有个小疑问,八哥之神究竟是什么意思?有个人叫八哥吗?

圣仙山:哈哈,吾与神源姐是一对孪生姐弟,她排名第七,您说,九妹、十弟、十一弟如何唤吾?

齐凤卿:原来您就是八哥呀!您这么牛逼,为什么 35 岁就仙逝?未免太可惜了。

圣仙山:吾要穿越到未来正确的时间点,阻止识界被毁灭,就必须按照特定时间死亡。吾有好几世都很早逝。

齐凤卿:为什么您能保持转世后的记忆?

圣仙山:并非保持记忆,吾只能保持八识神通显灵时的记忆,其它是后来回到识界从大众意识里看到的。吾只能推测当时在选择节点上的心情,那种知道要死,赶紧算一下,这时候死对不对,即使对了,吾也是有能力避免死亡的,所以得主动放弃这辈子。

齐凤卿:听起来很凄凉,很寂寞。

圣仙山:是千年孤寂。有一世,吾是一名西洋女子,十四岁时从镜子里发现自己是个美女,皮肤白皙,身材高挑,脸蛋甜美。十九岁时,被父亲的同僚骗去参加舞会,突然一刻,八识神通显灵,吾预知自己要被残忍地杀死。只要吾不像往常那么冷傲,完全可以避免,但吾在神通灵思中看到下一次转世将回到道州德国,吾便毅然赴死。

齐凤卿:回到道州德国?难道……

圣仙山:不是您想的那样。时间快到了!

齐凤卿:请您总结一下千年转世的最大感悟是什么?

圣仙山:两个体会比较深!一是,视界越来越好,吾担心、害怕的若干问题都被解决了。二是,做女人挺好!

齐凤卿:看来前辈还是乐观主义者。

圣仙山:暂别。咱们很快又会再见。

不买,不买,不买!

2011-06-01,当时公司给配的 Dell XPS 15 到手。友达屏,1080p,再外接一个 1080p 的显示器,这样的日子还是很滋润的。

后来,磁盘老化,便各种卡顿,于是思索着换个 SSD,便开始存钱。不料 Surface Pro 终于来到第三代,咬咬牙,不如给自己买台人生的第一台笔记本!2014-06-22,终于忍不住下单订购 SP3 i7 版,它如果算做笔记本,那它就是稣给自己买的第一台笔记本。等了快三个月,2014-09-12 才到手,立马被过热的八哥吓退,使用几天后就退了,换 i5 版。

再后来 i5 版 SP3 被稣扔到床上时,它滑落了……外屏裂掉。虽然还能用,但是公司给配了带独显的 MBP15,而且到手时,它就是装好 Windows 的,所以,SP3 还是退居二线吧!

2018-09-04 入职区块链公司,办公电脑是 MBP15 2018 版,这次因为 CTO 坐在稣左边,所以稣不敢把它全盘格式化装 Windows……

2020-05-08 入职云计算公司,办公电脑是联想 L490,虽然很一般,但勉强可以用吧,比较大的问题是:内存才 16G,偶尔 VS 开多了,会因为内存不足,陷入脑瘫状态,窗体无响应也不能正常关闭,只能强杀。作为对比,稣 2017-06-20 买的 NUC7i7BNH 配备 32G 内存

2020-08-31 加了台暗影精灵 MOMEN 25L 台式机。这 PC 编译最新的 boost x86 和 x64 总共不到 4 分钟,2011 年的 XPS15 需要几个小时,真的是秒杀。用了几天后,再看 L490,感觉就是个乐射。于是认真考虑给自己买台人生中的第一台传统意义上的笔记本电脑!(SP3 内牛满面地说:怪我变异咯?)

悲剧才刚刚开始。

研究一番之后,发现原来现在的市场已经变成:手机、平板很饱和,随便买买买;而笔记本电脑,居然要预定,要抢!!!

稣的需求其实很简单:

  • 屏幕物理尺寸很关键,14 英寸太小,15.6 英寸起码。

  • 高分辨率不能少,2011 年就用 15.6 英寸的 1080p 了,现在肯定要 2K-4K 才够。

  • 如果有 120-144Hz 刷新率是加分项。

被推荐的几款:幻15、XPS、外星人、R7000P、暗影精灵 6 系列。

先说 R7000P,原价 7999,一般加到 8999 卖,优惠价、秒杀价最低 8299,真良心……暗影精灵 6 也差不多,都是官方缺货,第三方卖家加价卖。

XPS、外星人都有货,而且也能找到人拿到低于批发价的优惠。然而这两系列真的是性价比堪忧,要的配置都是贵得怀疑挨踢人生。买东西的价位要符合身份,稣是靠才华赚钱的,就不能太奢侈!再说有这钱,为什么不买 MBP16?

MBP16,过时的九代 CPU,加到 32G 内存,教育优惠下来也才 2 万稍微出头。还是那句话:稣是靠才华赚钱的,就不能太奢侈!买不起……

幻 15 应该是穷稣最满意的,i7-10875H、4K@60Hz、RTX2060,淘宝聚划算才 12599,买买买啊!

然而,这明明是给设计师设计的款,居然只卖黑色版!设计师惯用的 MBP 表示抗议,建议出灰色、银色版。严重怀疑幻 15 的产品经理没有做过市调,直接套用游戏玩家的黑色风格!然而,这屏幕其实玩游戏是不爽的。

黑色的手机,稣可以给它戴红色的套,不骚吗?

黑色的笔记本,成熟稳重的商务范儿,一点都不配合稣成熟但轻快活泼的风格。商家建议给它贴纸,em……有点撒瘸。

无数次稣在夜里敲代码,都感觉不到黑色的笔记本,仿佛没有心灵的沟通。

有人劝稣:颜色不重要!稣回答:你戴个黑色耳机试试?不会丑哭吗?插入广告:白色的某米主动降噪耳机,对标 iPod Pro,预计售价 499,它不香吗?它能黑吗?

如果一个东西不酷,用它,就是在折损使用者的心灵。

Boost【2】ScopeExit

需求

  • 资源有很多种,每种都封装一套,还是挺累的!对于比较少使用或者一个程序很可能只会用一次的资源,我们不想封装!

  • Golang 的 defer 真香!

解决

利用 RAII 特性,封装个 ScopeGuard!或者直接用 Boost.ScopeExit。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// umu/scope_exit.hpp
#pragma once

#include <functional>

// C++11

namespace umu {
class ScopeGuard {
public:
explicit ScopeGuard(std::function<void()> on_exit_scope)
: on_exit_scope_(on_exit_scope), dismissed_(false) {}

~ScopeGuard() noexcept {
if (!dismissed_) {
on_exit_scope_();
}
}

void Dismiss() { dismissed_ = true; }

private:
std::function<void()> on_exit_scope_;
bool dismissed_;

// noncopyable
ScopeGuard(ScopeGuard const&) = delete;
ScopeGuard& operator=(ScopeGuard const&) = delete;
};
} // end of namespace umu

#define SCOPEGUARD_LINENAME_CAT(name, line) name##line
#define SCOPEGUARD_LINENAME(name, line) SCOPEGUARD_LINENAME_CAT(name, line)
#define ON_SCOPE_EXIT(callback) \
umu::ScopeGuard SCOPEGUARD_LINENAME(EXIT, __LINE__)(callback)

范例

Windows 上使用 socket 必须先调用 WSAStartup 初始化 WinSock 环境。

常规封装版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib")

class WinSock {
public:
WinSock() : error_code_(WSAEFAULT) {}

int Initialize(WORD version_requested = WINSOCK_VERSION) {
assert(WSAEFAULT == error_code_);
return error_code_ = ::WSAStartup(version_requested, &wsa_data_);
}

bool GetWsaData(WSADATA& wsa_data) {
if (NO_ERROR == error_code_) {
wsa_data = wsa_data_;
return true;
}
return false;
}

int GetErrorCode() { return error_code_; }

~WinSock() {
if (NO_ERROR == error_code_) {
::WSACleanup();
}
}

private:
int error_code_;
WSADATA wsa_data_;
}

int main(int argc, char* argv[]) {
WinSock winsock;
int error_code = winsock.Initialize();
if (NO_ERROR != error_code) {
std::cerr << "Initialize() failed with " << error_code << '\n';
return error_code;
}

// test codes
SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (INVALID_SOCKET != s) {
closesocket(s);
std::cout << "OK\n";
} else {
error_code = WSAGetLastError();
if (WSANOTINITIALISED == error_code) {
std::cerr << "WSANOTINITIALISED\n";
} else {
std::cerr << "socket() failed with " << error_code << '\n';
}
}

return error_code;
}

Boost.ScopeExit 版

现在是 2020 年 9 月,建议使用 cpp17,所以抛弃 BOOST_SCOPE_EXIT + BOOST_SCOPE_EXIT_END,使用 cpp11 的 BOOST_SCOPE_EXIT_ALL。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <winsock2.h>

#include <boost/scope_exit.hpp>

#pragma comment(lib, "ws2_32.lib")

int main(int argc, char* argv[]) {
WSADATA wsa_data = {};
int error_code = ::WSAStartup(WINSOCK_VERSION, &wsa_data);
if (NO_ERROR != error_code) {
std::cerr << "WSAStartup() failed with " << error_code << '\n';
return error_code;
}
// 类似 Golang 的 defer
BOOST_SCOPE_EXIT_ALL(&) { ::WSACleanup(); };

// test codes
SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (INVALID_SOCKET != s) {
closesocket(s);
std::cout << "OK\n";
} else {
error_code = WSAGetLastError();
if (WSANOTINITIALISED == error_code) {
std::cerr << "WSANOTINITIALISED\n";
} else {
std::cerr << "socket() failed with " << error_code << '\n';
}
}

return error_code;
}

Dismiss 演示:

1
2
3
4
5
boost::scope_exit::aux::guard<void> defer;
defer = [] { std::cout << "On scope exit!\n"; };
// dismiss
defer = {};
// Won't print "On scope exit!"

参考

https://www.boost.org/doc/libs/1_74_0/libs/scope_exit/doc/html/BOOST_SCOPE_EXIT_ALL.html

诗盗·浪

《#诗盗#·浪》:天风扬手捉浪脚,惊涛扯蛋扶大雕。四十四桥日光浴,渔人看书学吹箫。

注解

鼓浪屿旅游记!改编自唐代杜牧的《寄扬州韩绰判官》:

青山隐隐水迢迢,秋尽江南草未凋。
二十四桥明月夜,玉人何处教吹箫?

Boost【1】安装

软件环境

  • Windows 10

  • VS2019

其它系统的安装、编译过程都类似。即使您使用其它系统,本文仍然有参考意义。

其它系统请参考:

1. 下载

官网:https://www.boost.org/,当前(2020-09-11)最新版本是 1.74.0。

在国内直接下载可能比较慢,您可以用掩耳下载,一般有 MB 级的速度。

2. 解压

假设解压到 D:\dev\boost_1_74_0,这个路径后面要设置为环境变量 BOOST_ROOT 的值。

最好检查目录结构,以防解压时弄错目录层级:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# umutech @ UMU618 in D:\dev\boost_1_74_0 [14:31:58]
$ ls

Directory: D:\dev\boost_1_74_0

Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2020/8/11 23:28 1 boost
d---- 2020/8/11 23:26 1 doc
d---- 2020/8/11 23:28 1 libs
d---- 2020/8/11 22:57 1 more
d---- 2020/8/11 22:55 1 status
d---- 2020/8/11 22:55 1 tools
-a--- 2020/8/11 22:55 989 boost.css
-a--- 2020/8/11 22:55 6.16KB boost.png
-a--- 2020/8/11 22:55 850 boost-build.jam
-a--- 2020/8/11 22:55 18.81KB boostcpp.jam
-a--- 2020/8/11 22:55 2.39KB bootstrap.bat
-a--- 2020/8/11 22:55 10.38KB bootstrap.sh
-a--- 2020/8/11 22:55 769 index.htm
-a--- 2020/8/11 23:28 5.46KB index.html
-a--- 2020/8/11 22:55 291 INSTALL
-a--- 2020/8/11 22:55 11.65KB Jamroot
-a--- 2020/8/11 22:55 1.31KB LICENSE_1_0.txt
-a--- 2020/8/11 22:55 541 README.md
-a--- 2020/8/11 22:55 2.55KB rst.css

3. 添加 BOOST_ROOT 环境变量

  • 您可以通过图形界面配置,右击【此电脑】-【属性】-【高级系统设置】-【环境变量】。新建一个,变量名为 BOOST_ROOT,变量值为 D:\dev\boost_1_74_0。

  • 也可以使用命令行:setx BOOST_ROOT D:\dev\boost_1_74_0

1
2
3
4
cd D:\dev\boost_1_74_0
#$env:BOOST_ROOT=$pwd.Path
Set-Item -Path env:BOOST_ROOT -Value $pwd.Path
setx BOOST_ROOT $pwd.Path

下面 Powershell 命令用于检查设置是否正确:

1
2
3
# umutech @ UMU618 in D:\dev\boost_1_74_0 [14:39:22]
$ echo $env:BOOST_ROOT
D:\dev\boost_1_74_0

4. 编译 b2

直接运行 bootstrap.bat 即可,但是这样编译出来的是 32 位的 b2.exe

如果您需要明确地编译为 x64 的 b2.exe,可以在 x64 Native Tools Command Prompt for VS 2019 下面运行 bootstrap.bat。

如果是非 Windows 系统,则是 bootstrap.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# umutech @ UMU618 in D:\dev\boost_1_74_0 [15:02:20]
$ .\bootstrap.bat
Building Boost.Build engine

Generating Boost.Build configuration in project-config.jam for msvc...

Bootstrapping is done. To build, run:

.\b2

To adjust configuration, edit 'project-config.jam'.
Further information:

- Command line help:
.\b2 --help

- Getting started guide:
http://boost.org/more/getting_started/windows.html

- Boost.Build documentation:
http://www.boost.org/build/

为了方便调用 b2,可以把 BOOST_ROOT 加入到 PATH

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# setx PATH "$env:PATH;%BOOST_ROOT%"

# $target = 'User'
# $oldPath = [Environment]::GetEnvironmentVariable('Path', $target)
# $newPath = $oldPath
# if (!$oldPath.EndsWith(';')) {
# $newPath += ';'
# }
# $newPath += '%BOOST_ROOT%'
# [Environment]::SetEnvironmentVariable('Path', $newPath, $target)

# Get-ItemPropertyValue -Path HKCU:\Environment -Name "Path"

$oldPath = (Get-Item -Path "HKCU:\Environment").GetValue('Path', '', 'DoNotExpandEnvironmentNames')
$newPath = $oldPath
if (!$oldPath.EndsWith(';')) {
$newPath += ';'
}
$newPath += '%BOOST_ROOT%'
Set-ItemProperty -Path HKCU:\Environment -Name 'Path' -Value $newPath

5. 生成 user-config.jam

可以复制一个到 $HOME 目录,如有定制需求可以再编辑:

1
cp .\project-config.jam $HOME\user-config.jam

6. 用 b2 编译 Boost

完全编译比较耗时,但后期比较省事:

1
.\b2.exe --build-type=complete

新机器一般几分钟就能编译完毕。比如 OMEN 25L 只需要 9 分钟。廉想 L490 笔记本大约 37 分钟。

【推荐】如果只想用 lib,不想用 dll,可以节省编译时间:

1
.\b2.exe address-model=32 address-model=64 link=static runtime-link=shared runtime-link=static

下面将介绍参数的意义,如果已选择完全编译,本节下面内容可以跳过。

以下命令行可以编译 x64 平台:

1
.\b2.exe address-model=64

以上命令将同时编译 runtime-link=shared 的 Debug 和 Release 两种配置,产生的 lib 文件名会分别带有 -mt-gd-x64-mt-x64,比如:

  • Debug 版本:libboost_program_options-vc142-mt-gd-x64-1_75.lib

  • Release 版本:libboost_program_options-vc142-mt-x64-1_75.lib

您有可能需要编译不同配置的版本,比如指定 runtime-link 为 static,这样可以不依赖 VC 的运行时 DLL,此时您可以用下面命令:

1
.\b2.exe address-model=64 runtime-link=static

它编译出来的 lib 文件名中会带有 -mt-s-x64,例如:libboost_program_options-vc142-mt-s-x64-1_75.lib。

7. 测试编译

可以用以下仓库验证前面操作是否正确:

https://github.com/UMU618/test_boost

1
2
3
4
git clone https://github.com/UMU618/test_boost
cd test_boost
.\build.cmd
# ./build.sh

请根据操作系统选择合适的脚本编译,最终编译出来的程序应该打印“OK!”。

8. 配置 VS 工程

8.1 配置方法一

打开一个工程的属性页,定位到 VC++ Directories。

  • Include Directories 加上 $(BOOST_ROOT)

  • Library Directories 加上 $(BOOST_ROOT)\stage\lib

如果已经有其它值,记得用 ; 隔开。

8.2 配置方法二

打开一个工程的属性页。

  • 定位到 C/C++,General,Additional Include Directories 加上 $(BOOST_ROOT)

  • 定位到 Linker,General,Additional Library Directories 加上 $(BOOST_ROOT)\stage\lib

结语

  • Boost 值得学习和使用。

  • 本文对仅用 VS 写过 Hello world 的入门级程序员友好。

  • 更多应用 Boost 可以参考鎏光云游戏引擎

诗盗·射飞丝阿屉

《#诗盗#·射飞丝阿屉》:文十初上射飞丝,挨踢更迭,阿屉不减风采。八点一,七四八,八年等待五年吃灰,如今一刷还是牛逼。

注解

Surface RT 刷 Windows 10 Arm32 版。改编自霹雳角色疏楼龙宿的诗号:

华阳初上鸿门红,疏楼更迭,龙麟不减风采;
紫金箫,白玉琴,宫灯夜明昙华正盛,共饮逍遥一世悠然。

刷完玩玩当然是继续吃灰了……毕竟性能不行!

诗盗·去快恋

《#诗盗#·去快恋》:前年今日如梦游,神奇八哥无止休。神奇不知何处去,八哥依旧笑春秋。

注解

纪念在区块链行业工作过!改编自唐代崔护的《题都城南庄》:

去年今日此门中,人面桃花相映红。
人面不知何处去,桃花依旧笑春风。

VS2019 Makefile 型工程调用 Clang

需求

VS2019 Makefile 型工程使用 Clang 编译,要同时支持 x86 和 x64 平台。

问题

找不到 Clang 参数可以指定目标平台,如果您知道请不吝赐教。(github 账号:UMU618)

解决

同时安装这两个平台的 Clang。x86 的由 VS2019 自带,在 VS 中被表示为 "$(ClangAnalysisToolsPath)\clang.exe",宏展开后为:

1
2
3
4
5
$ &"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\Llvm\bin\clang.exe" -v
clang version 10.0.0
Target: i686-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\Llvm\bin

x64 是另外安装的,安装时选择把目录注册到 PATH:

1
2
3
4
5
$ clang -v
clang version 10.0.0
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files\LLVM\bin

结论:只需在 Win32 的平台设置使用 "$(ClangAnalysisToolsPath)\clang.exe",而 x64 则直接使用 clang(如果安装时忘记注册到 PATH,需要手动添加)。