Jekyll2024-03-12T07:17:05+00:00https://blog.ismisv.com/feed.xml挖井挖一口属于自己的井湖州龙之梦乐园跨年2024-01-01T00:00:00+00:002024-01-01T00:00:00+00:00https://blog.ismisv.com/2024/01/hu-zhou-long-zhi-meng-le-yuan-trip<p>节假日不用回老家真是太好了,29号晚上才决定去湖州龙之梦乐园玩一下,在网上团了酒店房间,虽然网上都说那边商业化很严重,似乎评价不高的样子,但总归要自己去过才知道到底行不行,反正离得不远,自驾1个半小时就行了。</p>
<h1 id="住">住</h1>
<p>我们订了瑞峰国际大酒店的大床房,面朝太湖古镇的那一边房间要比另一边面朝大山的房间贵100块钱一天,主要是可以晚上直接在阳台上观赏烟花表演,但我们没选,因为可以很方便地在酒店外的地面上观看。</p>
<h1 id="行">行</h1>
<p>无论是打车还是公交,都比较方便,公交大多2元随便坐,也可以自己开车,就会有找停车位的麻烦,另外就是晚上水秀和烟花秀时段,太湖古镇那一路段会交通管制,要等9点半表演结束后才放开,那时乌泱泱的人和车,最好避开这个时段。</p>
<p>值得吐槽的是,在一些明显需要红绿灯的地方,只有斑马线,没有红绿灯,而那边的车辆基本不会停下礼让行人,反而开得飞快,生怕行人挡了他们的路似的。</p>
<p>有一次我在斑马线上等了好几分钟,直到有2辆私家车主动减速停在斑马线前,我老婆看了一眼说:“果然是沪牌。”</p>
<p>再后来又一次过斑马线,趁着车流量较大,车速不快,我们强行穿过斑马线,我老婆看了一眼停下的车说:“像这些牌的就只能被动逼停。”</p>
<p>感觉到了浓浓的地域歧视,哈哈。</p>
<h1 id="吃">吃</h1>
<p>非常不好,一则是没找到好吃的,别说堂食了,外卖都没什么好吃的,晚上居然看到不少人排队在酒店一楼的超市买泡面。二则是很贵,无论是连锁的肯德基、必胜客,还是小馆子,价格都比其他地方贵不少。如果想吃得好点可以跑到湖州市区去,比如吾悦广场,大概10公里左右。感觉这点是这个度假区最大的败笔,如果让我说一个不想再去第二次的理由,或者劝阻别人去那里的理由,我就说这点。</p>
<h1 id="游">游</h1>
<p>我只去了动物园,排队一个多小时坐了小火车,花了120块钱买了投喂动物的食物,反正我挺反感这点的,感觉就是拿捏住小孩家长的命脉使劲薅羊毛,还那么贵,诛心点说,怪不得越来越多的人不想生小孩了。</p>
<h1 id="演">演</h1>
<p>看了大马戏,还是挺精彩的,或者说紧张刺激的,但我看那些高空杂技表演的时候一直心惊胆战的。期间有熊出来表演,旁边一些人在那说“好可爱”,我就联想到前些天在网上看到日本熊吃人的新闻,总归心里不大舒服。</p>
<p>两天晚上都看了喷泉表演,感觉还不如上海爱琴海购物公园门口的喷泉表演呢。</p>
<p>烟花表演倒还不错,就是时间短了点,几十架航拍的无人机在头顶闪着灯,别有一番趣味。</p>missdeer节假日不用回老家真是太好了,29号晚上才决定去湖州龙之梦乐园玩一下,在网上团了酒店房间,虽然网上都说那边商业化很严重,似乎评价不高的样子,但总归要自己去过才知道到底行不行,反正离得不远,自驾1个半小时就行了。修改DNS去广告2023-08-01T00:00:00+00:002023-08-01T00:00:00+00:00https://blog.ismisv.com/2023/08/dns-block-ads<p>以前也尝试过在DNS上做手脚拦截广告,但因为误杀太多以及漏网之鱼太多,觉得还不如不折腾呢。</p>
<p>最近偶然发现了<a href="https://github.com/missdeer/blocklist">一组列表</a>,又尝试了一番,发现效果挺不错的,手机开屏广告绝大多数不见,浏览网页时Google Ads也基本没有了,真是让我喜出望外。所以以前效果不好的原因只是因为使用的黑名单列表不好而已。</p>
<p>我是在路由器上的<a href="https://github.com/missdeer/coredns_custom_build">CoreDNS</a>使用<a href="https://github.com/missdeer/ads">ads</a>插件设置拦截的,所有接入的设备都可以享受到这个效果。用到3组黑名单源,分别是<a href="https://anti-ad.net">Anti-ad</a>,<a href="https://github.com/AdguardTeam">AdGuard</a>和<a href="https://github.com/easylist/easylist/">EasyList</a>,然后自己写了点代码将列表规整了一下,转成<a href="https://github.com/missdeer/blocklist">hosts文件的格式</a>后合并为一个文件,<a href="https://github.com/missdeer/ads">ads</a>插件可以直接通过http协议加载hosts格式的文件。CoreDNS的配置文件增加ads就行了:</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre><span class="err">#</span><span class="nx">blocklist</span> <span class="nx">domains</span><span class="p">.</span><span class="nx">txt</span>
<span class="nx">ads</span> <span class="p">{</span>
<span class="nx">blacklist</span> <span class="nx">https</span><span class="p">:</span><span class="c1">//cdn.jsdelivr.net/gh/missdeer/blocklist@master/convert/alldomains.txt</span>
<span class="nx">nxdomain</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>missdeer以前也尝试过在DNS上做手脚拦截广告,但因为误杀太多以及漏网之鱼太多,觉得还不如不折腾呢。Debian上使用Nginx搭建WebDav服务要点2023-07-18T00:00:00+00:002023-07-18T00:00:00+00:00https://blog.ismisv.com/2023/07/debian-nginx-webdav-tips<p>要点:</p>
<ol>
<li>不要用Nginx官方的源,而是用Debian的源安装Nginx</li>
<li>一键安装Nginx及扩展:<code class="language-plaintext highlighter-rouge">sudo aptitude -y install nginx-full nginx-extras libnginx-mod-http-dav-ext libnginx-mod-http-auth-pam</code></li>
<li>配置要给zone分配内存:<code class="language-plaintext highlighter-rouge">dav_ext_lock_zone zone=webdav:10m;</code></li>
</ol>
<p>最容易出问题的就是以上3点,其他配置从网上抄一下就行,大体如下:</p>
<pre><code class="language-txt">location / {
root /home/missdeer/;
dav_methods PUT DELETE MKCOL COPY MOVE;
dav_ext_methods PROPFIND OPTIONS LOCK UNLOCK;
dav_access user:rw group:rw all:rw;
dav_ext_lock zone=webdav;
client_max_body_size 102400M;
create_full_put_path on;
client_body_temp_path /tmp/;
set $dest $http_destination;
if (-d $request_filename) {
rewrite ^(.*[^/])$ $1/;
set $dest $dest/;
}
if ($request_method ~ (MOVE|COPY)) {
more_set_input_headers 'Destination: $dest';
}
if ($request_method ~ MKCOL) {
rewrite ^(.*[^/])$ $1/ break;
}
auth_pam "Restricted";
auth_pam_service_name "common-auth";
index index.html index.htm index.php admin.php;
}
</code></pre>
<p>最后启用Nginx:<code class="language-plaintext highlighter-rouge">sudo systemctl restart nginx</code>。</p>
<p>如果起不来,先看一下配置文件是否有问题:<code class="language-plaintext highlighter-rouge">sudo /sbin/nginx -t</code>。</p>missdeer要点:武夷山之旅2023-06-24T00:00:00+00:002023-06-24T00:00:00+00:00https://blog.ismisv.com/2023/06/wuyishan-trip<p>端午节最终决定去武夷山游玩,对旅游这块确实既没多大兴趣,更没什么经验,都是老婆一手操办下来的。这个决定做的比较晚,导致买高铁票都是老婆花了不少日子靠在app上抢来,好在总体而言还算顺利,叫上两边的老人一起,浩浩荡荡7个人。</p>
<h2 id="住">住</h2>
<p>住宿是在一个叫一同山居的民墅,环境和服务都感觉不错,还可以提前让他们帮忙订《印象大红袍》的门票,可以讲价,当然羊毛出在羊身上,毕竟还有大头房费呢,看怎么谈更划算。高铁坐到南平市站,然后转K1线公交车到茶博园站下车。周围很多类似的民墅,和酒店的经营方式非常相似,有前台,有自己的停车场,有电梯,有自己的餐厅提供早餐,当然还有当地特色的茶厅,可以自己泡茶。价格不是很贵,估计是受疫情影响生意比以前差了,反正在这3天里我只见过另两个客人。</p>
<h2 id="吃">吃</h2>
<p>22号中饭是在茶人村吃的,环境挺好的,菜的口味也还好,份量也大。晚饭则是在五小厨,环境就比较一般,菜的口味还好,但份量不如茶人村那么足。两家店总的说来都是价格实惠,大概人均50元就够了,习惯了上海的馆子的价格后,这样的真算得上价廉物美了。23号中饭是在一家叫闽味私厨的馆子吃的,只有2个大妈服务员,服务差点,味道差不多,价格也差不多,结账的时候和老板聊了几句,老板说2010年-2018年就在上海开店的,后来回了老家云云。因为中饭吃得晚,晚上又要看表演,就没吃晚饭,特别跑去网上推荐的旧街小光饼,一个非常非常小的店铺,只有一个烤炉,说这炉在烤的都已经被订了,要么等50分钟出下一炉,老婆居然还犹豫,真是无法想像那些为个网红小吃等几个小时的人是怎样的脑回路,就算时间是用来浪费的,也可以浪费在更有趣的事情上啊,我直接拉她到路对面的另一个小光饼梅干菜饼店买了20块钱的饼。表演结束后回到住处,在饿了么上点夜宵,非常贵,就是专砍游客的,非常不推荐,应该去店里吃的。</p>
<h2 id="游">游</h2>
<p>比较恼火的是天气不好,一直在下午,22号吃过中饭,下午冒着大雨去了一下大红袍景点,看到了传说中的几株母树。23号本来想去天游峰的,但是因为我妈身体不好,我和我爸只好爬到1/3的路程返回,我老婆和丈人丈母娘带着我儿子居然爬上去了,结果因为我妈爬不了山,到哪都是要爬山的,跑去水帘洞,走了不少路,发现最后也是要爬山的,只能原路返回,直到我老婆他们下山。</p>
<h2 id="演">演</h2>
<p>这一趟最值的是晚上看《印象大红袍》表演了,天公作美,表演期间没有下雨,这种表演形式也新奇,感觉是这次到武夷山旅游最值得的一个项目了。非常推荐!</p>
<h2 id="行">行</h2>
<p>最想吐槽的是交通状况,那边红绿灯非常少,斑马线也非常少,要横穿马路就是裸奔,全靠司机素质好,遇到行人肯停车等待。另一个是高德地图的实时公交功能不能用,对于在上海用惯这功能的人来说,简直变成了瞎子。24号赶高铁,在公交站等了十几分钟没等到K1线,老婆就着急忙慌打了个车先走了,结果不到2分钟后我刚在高德地图下了单,K1线就过来了,上了车就接到接单出租车司机的电话,连忙取消订单。这个体验太差了。</p>missdeer端午节最终决定去武夷山游玩,对旅游这块确实既没多大兴趣,更没什么经验,都是老婆一手操办下来的。这个决定做的比较晚,导致买高铁票都是老婆花了不少日子靠在app上抢来,好在总体而言还算顺利,叫上两边的老人一起,浩浩荡荡7个人。配置Debian路由器双WAN接入2022-11-03T00:00:00+00:002022-11-03T00:00:00+00:00https://blog.ismisv.com/2022/11/dual-wan-internet-access<p>鉴于移动免费送了1年200M的一条宽带,没多犹豫决定还是要用起来。经过一番折腾,基本搞好了,目前的情况大概是这样的:</p>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="1090px" preserveAspectRatio="none" version="1.1" viewBox="0 0 1099 1090" width="1099px" zoomAndPan="magnify"><defs /><g><rect fill="none" height="26.2969" id="_title" rx="2.5" ry="2.5" style="stroke:#000000;stroke-width:1.0;" width="100" x="492.5" y="5" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="90" x="497.5" y="22.9951">家中网络拓扑</text><!--cluster ???--><g id="cluster_弱电箱"><polygon fill="none" points="687,490.2969,697,480.2969,1082,480.2969,1082,734.2969,1072,744.2969,687,744.2969,687,490.2969" style="stroke:#181818;stroke-width:1.0;" /><line style="stroke:#181818;stroke-width:1.0;" x1="1072" x2="1082" y1="490.2969" y2="480.2969" /><line style="stroke:#181818;stroke-width:1.0;" x1="687" x2="1072" y1="490.2969" y2="490.2969" /><line style="stroke:#181818;stroke-width:1.0;" x1="1072" x2="1072" y1="490.2969" y2="744.2969" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="45" x="858" y="506.292">弱电箱</text></g><!--entity CTModem--><g id="elem_CTModem"><polygon fill="#F1F1F1" points="953,530.2969,963,520.2969,1053,520.2969,1053,556.5938,1043,566.5938,953,566.5938,953,530.2969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="1043" x2="1053" y1="530.2969" y2="520.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="953" x2="1043" y1="530.2969" y2="530.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="1043" x2="1043" y1="530.2969" y2="566.5938" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="60" x="968" y="553.292">电信光猫</text></g><!--entity CMModem--><g id="elem_CMModem"><polygon fill="#F1F1F1" points="953,692.2969,963,682.2969,1053,682.2969,1053,718.5938,1043,728.5938,953,728.5938,953,692.2969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="1043" x2="1053" y1="692.2969" y2="682.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="953" x2="1043" y1="692.2969" y2="692.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="1043" x2="1043" y1="692.2969" y2="728.5938" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="60" x="968" y="715.292">移动光猫</text></g><!--entity R86S--><g id="elem_R86S"><polygon fill="#F1F1F1" points="940,611.2969,950,601.2969,1066,601.2969,1066,637.5938,1056,647.5938,940,647.5938,940,611.2969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="1056" x2="1066" y1="611.2969" y2="601.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="940" x2="1056" y1="611.2969" y2="611.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="1056" x2="1056" y1="611.2969" y2="647.5938" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="86" x="955" y="634.292">R86S软路由</text></g><!--entity TPLinkSG1210P--><g id="elem_TPLinkSG1210P"><polygon fill="#F1F1F1" points="703,590.7969,713,580.7969,880,580.7969,880,657.6875,870,667.6875,703,667.6875,703,590.7969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="870" x2="880" y1="590.7969" y2="580.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="703" x2="870" y1="590.7969" y2="590.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="870" x2="870" y1="590.7969" y2="667.6875" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="137" x="718" y="613.792">TP-Link SG1210P</text><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="703" x2="870" y1="617.0938" y2="617.0938" /><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="870" x2="880" y1="617.0938" y2="607.0938" /><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="97" x="718" y="634.0889">PoE千兆交换机</text><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="56" x="718" y="650.3857">@弱电箱</text></g><!--entity TPLinkSwitch--><g id="elem_TPLinkSwitch"><polygon fill="#F1F1F1" points="468,362.7969,478,352.7969,643,352.7969,643,413.3906,633,423.3906,468,423.3906,468,362.7969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="633" x2="643" y1="362.7969" y2="352.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="468" x2="633" y1="362.7969" y2="362.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="633" x2="633" y1="362.7969" y2="423.3906" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="135" x="483" y="385.792">TP-Link千兆交换机</text><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="468" x2="633" y1="389.0938" y2="389.0938" /><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="633" x2="643" y1="389.0938" y2="379.0938" /><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="42" x="483" y="406.0889">@客厅</text></g><!--entity TPLinkSwitchBD--><g id="elem_TPLinkSwitchBD"><polygon fill="#F1F1F1" points="233,476.7969,243,466.7969,408,466.7969,408,527.3906,398,537.3906,233,537.3906,233,476.7969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="398" x2="408" y1="476.7969" y2="466.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="233" x2="398" y1="476.7969" y2="476.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="398" x2="398" y1="476.7969" y2="537.3906" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="135" x="248" y="499.792">TP-Link千兆交换机</text><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="233" x2="398" y1="503.0938" y2="503.0938" /><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="398" x2="408" y1="503.0938" y2="493.0938" /><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="42" x="248" y="520.0889">@主卧</text></g><!--entity HTPC--><g id="elem_HTPC"><polygon fill="#F1F1F1" points="250,354.7969,260,344.7969,391,344.7969,391,421.6875,381,431.6875,250,431.6875,250,354.7969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="381" x2="391" y1="354.7969" y2="344.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="250" x2="381" y1="354.7969" y2="354.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="381" x2="381" y1="354.7969" y2="431.6875" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="42" x="265" y="377.792">HTPC</text><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="250" x2="381" y1="381.0938" y2="381.0938" /><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="381" x2="391" y1="381.0938" y2="371.0938" /><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="84" x="265" y="398.0889">一些服务程序</text><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="101" x="265" y="414.3857">如Git Server等</text></g><!--entity APBedRoom1--><g id="elem_APBedRoom1"><polygon fill="#F1F1F1" points="485,468.7969,495,458.7969,626,458.7969,626,535.6875,616,545.6875,485,545.6875,485,468.7969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="616" x2="626" y1="468.7969" y2="458.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="485" x2="616" y1="468.7969" y2="468.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="616" x2="616" y1="468.7969" y2="545.6875" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="101" x="500" y="491.792">主卧86面板AP</text><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="485" x2="616" y1="495.0938" y2="495.0938" /><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="616" x2="626" y1="495.0938" y2="485.0938" /><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="54" x="500" y="512.0889">5G WIFI</text><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="56" x="500" y="528.3857">以太网口</text></g><!--entity APBedRoom2--><g id="elem_APBedRoom2"><polygon fill="#F1F1F1" points="485,590.7969,495,580.7969,626,580.7969,626,657.6875,616,667.6875,485,667.6875,485,590.7969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="616" x2="626" y1="590.7969" y2="580.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="485" x2="616" y1="590.7969" y2="590.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="616" x2="616" y1="590.7969" y2="667.6875" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="101" x="500" y="613.792">次卧86面板AP</text><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="485" x2="616" y1="617.0938" y2="617.0938" /><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="616" x2="626" y1="617.0938" y2="607.0938" /><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="54" x="500" y="634.0889">5G WIFI</text><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="56" x="500" y="650.3857">以太网口</text></g><!--entity APDinnerRoom--><g id="elem_APDinnerRoom"><polygon fill="#F1F1F1" points="483,712.7969,493,702.7969,628,702.7969,628,779.6875,618,789.6875,483,789.6875,483,712.7969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="618" x2="628" y1="712.7969" y2="702.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="483" x2="618" y1="712.7969" y2="712.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="618" x2="618" y1="712.7969" y2="789.6875" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="101" x="498" y="735.792">餐厅86面板AP</text><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="483" x2="618" y1="739.0938" y2="739.0938" /><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="618" x2="628" y1="739.0938" y2="729.0938" /><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="105" x="498" y="756.0889">2.4G & 5G WIFI</text><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="56" x="498" y="772.3857">以太网口</text></g><!--entity APLivingRoom--><g id="elem_APLivingRoom"><polygon fill="#F1F1F1" points="483,854.7969,493,844.7969,628,844.7969,628,921.6875,618,931.6875,483,931.6875,483,854.7969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="618" x2="628" y1="854.7969" y2="844.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="483" x2="618" y1="854.7969" y2="854.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="618" x2="618" y1="854.7969" y2="931.6875" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="101" x="498" y="877.792">客厅86面板AP</text><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="483" x2="618" y1="881.0938" y2="881.0938" /><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="618" x2="628" y1="881.0938" y2="871.0938" /><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="105" x="498" y="898.0889">2.4G & 5G WIFI</text><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="56" x="498" y="914.3857">以太网口</text></g><!--entity TLAC100--><g id="elem_TLAC100"><polygon fill="#F1F1F1" points="36,53.2969,46,43.2969,153,43.2969,153,79.5938,143,89.5938,36,89.5938,36,53.2969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="143" x2="153" y1="53.2969" y2="43.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="36" x2="143" y1="53.2969" y2="53.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="143" x2="143" y1="53.2969" y2="89.5938" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="77" x="51" y="76.292">TL-AC100</text></g><!--entity MacMini--><g id="elem_MacMini"><polygon fill="#F1F1F1" points="41,134.7969,51,124.7969,148,124.7969,148,185.3906,138,195.3906,41,195.3906,41,134.7969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="138" x2="148" y1="134.7969" y2="124.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="41" x2="138" y1="134.7969" y2="134.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="138" x2="138" y1="134.7969" y2="195.3906" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="67" x="56" y="157.792">MacMini</text><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="41" x2="138" y1="161.0938" y2="161.0938" /><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="138" x2="148" y1="161.0938" y2="151.0938" /><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="56" x="56" y="178.0889">吃灰备用</text></g><!--entity TinyMonster--><g id="elem_TinyMonster"><polygon fill="#F1F1F1" points="16,240.7969,26,230.7969,173,230.7969,173,291.3906,163,301.3906,16,301.3906,16,240.7969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="163" x2="173" y1="240.7969" y2="230.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="16" x2="163" y1="240.7969" y2="240.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="163" x2="163" y1="240.7969" y2="301.3906" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="117" x="31" y="263.792">Windows小主机</text><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="16" x2="163" y1="267.0938" y2="267.0938" /><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="163" x2="173" y1="267.0938" y2="257.0938" /><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="70" x="31" y="284.0889">主力开发机</text></g><!--entity Debian--><g id="elem_Debian"><polygon fill="#F1F1F1" points="18.5,346.7969,28.5,336.7969,170.5,336.7969,170.5,413.6875,160.5,423.6875,18.5,423.6875,18.5,346.7969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="160.5" x2="170.5" y1="346.7969" y2="336.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="18.5" x2="160.5" y1="346.7969" y2="346.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="160.5" x2="160.5" y1="346.7969" y2="423.6875" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="55" x="33.5" y="369.792">Debian</text><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="18.5" x2="160.5" y1="373.0938" y2="373.0938" /><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="160.5" x2="170.5" y1="373.0938" y2="363.0938" /><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="112" x="33.5" y="390.0889">曾经的主力旁路由</text><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="42" x="33.5" y="406.3857">@PVE</text></g><!--entity FreeBSD--><g id="elem_FreeBSD"><polygon fill="#F1F1F1" points="39.5,468.7969,49.5,458.7969,149.5,458.7969,149.5,535.6875,139.5,545.6875,39.5,545.6875,39.5,468.7969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="139.5" x2="149.5" y1="468.7969" y2="458.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="39.5" x2="139.5" y1="468.7969" y2="468.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="139.5" x2="139.5" y1="468.7969" y2="545.6875" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="66" x="54.5" y="491.792">FreeBSD</text><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="39.5" x2="139.5" y1="495.0938" y2="495.0938" /><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="139.5" x2="149.5" y1="495.0938" y2="485.0938" /><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="70" x="54.5" y="512.0889">学习实验用</text><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="42" x="54.5" y="528.3857">@PVE</text></g><!--entity NetBSD--><g id="elem_NetBSD"><polygon fill="#F1F1F1" points="39.5,590.7969,49.5,580.7969,149.5,580.7969,149.5,657.6875,139.5,667.6875,39.5,667.6875,39.5,590.7969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="139.5" x2="149.5" y1="590.7969" y2="580.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="39.5" x2="139.5" y1="590.7969" y2="590.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="139.5" x2="139.5" y1="590.7969" y2="667.6875" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="60" x="54.5" y="613.792">NetBSD</text><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="39.5" x2="139.5" y1="617.0938" y2="617.0938" /><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="139.5" x2="149.5" y1="617.0938" y2="607.0938" /><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="70" x="54.5" y="634.0889">学习实验用</text><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="42" x="54.5" y="650.3857">@PVE</text></g><!--entity OpenBSD--><g id="elem_OpenBSD"><polygon fill="#F1F1F1" points="38,712.7969,48,702.7969,151,702.7969,151,779.6875,141,789.6875,38,789.6875,38,712.7969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="141" x2="151" y1="712.7969" y2="702.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="38" x2="141" y1="712.7969" y2="712.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="141" x2="141" y1="712.7969" y2="789.6875" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="73" x="53" y="735.792">OpenBSD</text><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="38" x2="141" y1="739.0938" y2="739.0938" /><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="141" x2="151" y1="739.0938" y2="729.0938" /><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="70" x="53" y="756.0889">学习实验用</text><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="42" x="53" y="772.3857">@PVE</text></g><!--entity DragonflyBSD--><g id="elem_DragonflyBSD"><polygon fill="#F1F1F1" points="19,834.7969,29,824.7969,170,824.7969,170,901.6875,160,911.6875,19,911.6875,19,834.7969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="160" x2="170" y1="834.7969" y2="824.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="19" x2="160" y1="834.7969" y2="834.7969" /><line style="stroke:#000000;stroke-width:1.0;" x1="160" x2="160" y1="834.7969" y2="911.6875" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="111" x="34" y="857.792">DragonflyBSD</text><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="19" x2="160" y1="861.0938" y2="861.0938" /><line style="stroke:#000000;stroke-width:1.0;stroke-dasharray:1.0,2.0;" x1="160" x2="170" y1="861.0938" y2="851.0938" /><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="70" x="34" y="878.0889">学习实验用</text><text fill="#000000" font-family="" font-size="14" lengthAdjust="spacing" textLength="42" x="34" y="894.3857">@PVE</text></g><!--entity WinDesktop--><g id="elem_WinDesktop"><polygon fill="#F1F1F1" points="16,957.2969,26,947.2969,173,947.2969,173,983.5938,163,993.5938,16,993.5938,16,957.2969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="163" x2="173" y1="957.2969" y2="947.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="16" x2="163" y1="957.2969" y2="957.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="163" x2="163" y1="957.2969" y2="993.5938" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="117" x="31" y="980.292">Windows台式机</text></g><!--entity TLIPC40CFocus--><g id="elem_TLIPC40CFocus"><polygon fill="#F1F1F1" points="233,713.2969,243,703.2969,408,703.2969,408,739.5938,398,749.5938,233,749.5938,233,713.2969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="398" x2="408" y1="713.2969" y2="703.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="233" x2="398" y1="713.2969" y2="713.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="398" x2="398" y1="713.2969" y2="749.5938" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="135" x="248" y="736.292">TP-Link监控摄像头</text></g><!--entity TLIPC40C--><g id="elem_TLIPC40C"><polygon fill="#F1F1F1" points="233,794.2969,243,784.2969,408,784.2969,408,820.5938,398,830.5938,233,830.5938,233,794.2969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="398" x2="408" y1="794.2969" y2="784.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="233" x2="398" y1="794.2969" y2="794.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="398" x2="398" y1="794.2969" y2="830.5938" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="135" x="248" y="817.292">TP-Link监控摄像头</text></g><!--entity Chromecast--><g id="elem_Chromecast"><polygon fill="#F1F1F1" points="252,875.2969,262,865.2969,389,865.2969,389,901.5938,379,911.5938,252,911.5938,252,875.2969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="379" x2="389" y1="875.2969" y2="865.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="252" x2="379" y1="875.2969" y2="875.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="379" x2="379" y1="875.2969" y2="911.5938" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="97" x="267" y="898.292">Chromecast</text></g><!--entity SonyTV--><g id="elem_SonyTV"><polygon fill="#F1F1F1" points="278,956.2969,288,946.2969,363,946.2969,363,982.5938,353,992.5938,278,992.5938,278,956.2969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="353" x2="363" y1="956.2969" y2="946.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="278" x2="353" y1="956.2969" y2="956.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="353" x2="353" y1="956.2969" y2="992.5938" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="45" x="293" y="979.292">电视机</text></g><!--entity DoorLock--><g id="elem_DoorLock"><polygon fill="#F1F1F1" points="270.5,1037.2969,280.5,1027.2969,370.5,1027.2969,370.5,1063.5938,360.5,1073.5938,270.5,1073.5938,270.5,1037.2969" style="stroke:#000000;stroke-width:1.0;" /><line style="stroke:#000000;stroke-width:1.0;" x1="360.5" x2="370.5" y1="1037.2969" y2="1027.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="270.5" x2="360.5" y1="1037.2969" y2="1037.2969" /><line style="stroke:#000000;stroke-width:1.0;" x1="360.5" x2="360.5" y1="1037.2969" y2="1073.5938" /><text fill="#000000" font-family="" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="60" x="285.5" y="1060.292">智能门锁</text></g><!--link R86S to CTModem--><g id="link_R86S_CTModem"><path codeLine="129" d="M1003,601.1989 C1003,589.5889 1003,583.9779 1003,572.3669 " fill="none" id="R86S-to-CTModem" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="1003,566.3669,999,575.3669,1003,571.3669,1007,575.3669,1003,566.3669" style="stroke:#181818;stroke-width:1.0;" /></g><!--reverse link CMModem to R86S--><g id="link_CMModem_R86S"><path codeLine="130" d="M1003,676.1989 C1003,664.5889 1003,658.9779 1003,647.3669 " fill="none" id="CMModem-backto-R86S" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="1003,682.1989,1007,673.1989,1003,677.1989,999,673.1989,1003,682.1989" style="stroke:#181818;stroke-width:1.0;" /></g><!--link TPLinkSG1210P to R86S--><g id="link_TPLinkSG1210P_R86S"><path codeLine="131" d="M880.133,624.2969 C900.204,624.2969 915.136,624.2969 933.874,624.2969 " fill="none" id="TPLinkSG1210P-to-R86S" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="939.874,624.2969,930.874,620.2969,934.874,624.2969,930.874,628.2969,939.874,624.2969" style="stroke:#181818;stroke-width:1.0;" /></g><!--link TPLinkSwitch to TPLinkSG1210P--><g id="link_TPLinkSwitch_TPLinkSG1210P"><path codeLine="132" d="M620.187,423.7979 C628.173,429.2519 635.989,435.1349 643,441.2969 C690.354,482.9179 730.8543,536.0258 758.2383,575.5048 " fill="none" id="TPLinkSwitch-to-TPLinkSG1210P" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="761.658,580.4349,759.8152,570.76,758.8083,576.3265,753.2418,575.3195,761.658,580.4349" style="stroke:#181818;stroke-width:1.0;" /></g><!--link APBedRoom1 to TPLinkSG1210P--><g id="link_APBedRoom1_TPLinkSG1210P"><path codeLine="133" d="M626.074,538.5709 C651.402,551.7759 674.9777,564.067 701.4077,577.847 " fill="none" id="APBedRoom1-to-TPLinkSG1210P" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="706.728,580.6209,700.5968,572.9132,702.2944,578.3093,696.8983,580.0069,706.728,580.6209" style="stroke:#181818;stroke-width:1.0;" /></g><!--link APBedRoom2 to TPLinkSG1210P--><g id="link_APBedRoom2_TPLinkSG1210P"><path codeLine="134" d="M626.074,624.2969 C650.189,624.2969 671.54,624.2969 696.916,624.2969 " fill="none" id="APBedRoom2-to-TPLinkSG1210P" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="702.916,624.2969,693.916,620.2969,697.916,624.2969,693.916,628.2969,702.916,624.2969" style="stroke:#181818;stroke-width:1.0;" /></g><!--link APDinnerRoom to TPLinkSG1210P--><g id="link_APDinnerRoom_TPLinkSG1210P"><path codeLine="135" d="M628.298,708.8639 C653.152,695.9059 675.9017,684.0447 701.6187,670.6367 " fill="none" id="APDinnerRoom-to-TPLinkSG1210P" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="706.939,667.8629,697.1093,668.4768,702.5054,670.1744,700.8077,675.5705,706.939,667.8629" style="stroke:#181818;stroke-width:1.0;" /></g><!--link APLivingRoom to TPLinkSG1210P--><g id="link_APLivingRoom_TPLinkSG1210P"><path codeLine="136" d="M605.7,844.4639 C618.204,832.7249 631.381,819.8109 643,807.2969 C685.202,761.8419 725.6599,710.6279 754.5149,672.6369 " fill="none" id="APLivingRoom-to-TPLinkSG1210P" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="758.144,667.8589,749.515,672.6066,755.1198,671.8406,755.8858,677.4454,758.144,667.8589" style="stroke:#181818;stroke-width:1.0;" /></g><!--link HTPC to TPLinkSwitch--><g id="link_HTPC_TPLinkSwitch"><path codeLine="137" d="M391.092,388.2969 C415.229,388.2969 436.592,388.2969 461.928,388.2969 " fill="none" id="HTPC-to-TPLinkSwitch" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="467.928,388.2969,458.928,384.2969,462.928,388.2969,458.928,392.2969,467.928,388.2969" style="stroke:#181818;stroke-width:1.0;" /></g><!--link TPLinkSwitchBD to APBedRoom1--><g id="link_TPLinkSwitchBD_APBedRoom1"><path codeLine="138" d="M408.261,502.2969 C433.491,502.2969 454.715,502.2969 478.755,502.2969 " fill="none" id="TPLinkSwitchBD-to-APBedRoom1" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="484.755,502.2969,475.755,498.2969,479.755,502.2969,475.755,506.2969,484.755,502.2969" style="stroke:#181818;stroke-width:1.0;" /></g><!--link TLAC100 to TPLinkSwitchBD--><g id="link_TLAC100_TPLinkSwitchBD"><path codeLine="139" d="M153.162,88.8659 C160.752,93.9419 167.717,100.0349 173,107.2969 C263.784,232.0899 146.198,321.7019 233,449.2969 C237.359,455.7039 238.2335,457.5538 244.2135,462.7168 " fill="none" id="TLAC100-to-TPLinkSwitchBD" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="248.755,466.6379,244.5568,457.7286,244.9704,463.3703,239.3287,463.784,248.755,466.6379" style="stroke:#181818;stroke-width:1.0;" /></g><!--link WinDesktop to TPLinkSwitchBD--><g id="link_WinDesktop_TPLinkSwitchBD"><path codeLine="140" d="M153.115,947.1429 C160.615,942.1639 167.565,936.2549 173,929.2969 C241.48,841.6299 195.822,791.1439 233,686.2969 C251.875,633.0669 278.154,579.8112 297.303,543.3702 " fill="none" id="WinDesktop-to-TPLinkSwitchBD" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="300.094,538.0589,292.3666,544.1652,297.7682,542.485,299.4484,547.8865,300.094,538.0589" style="stroke:#181818;stroke-width:1.0;" /></g><!--link Debian to TPLinkSwitchBD--><g id="link_Debian_TPLinkSwitchBD"><path codeLine="141" d="M170.712,421.2609 C197.784,436.0049 222.8128,449.6372 248.9668,463.8812 " fill="none" id="Debian-to-TPLinkSwitchBD" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="254.236,466.7509,248.2453,458.9335,249.845,464.3594,244.419,465.9591,254.236,466.7509" style="stroke:#181818;stroke-width:1.0;" /></g><!--link FreeBSD to TPLinkSwitchBD--><g id="link_FreeBSD_TPLinkSwitchBD"><path codeLine="142" d="M149.724,502.2969 C174.584,502.2969 198.674,502.2969 226.575,502.2969 " fill="none" id="FreeBSD-to-TPLinkSwitchBD" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="232.575,502.2969,223.575,498.2969,227.575,502.2969,223.575,506.2969,232.575,502.2969" style="stroke:#181818;stroke-width:1.0;" /></g><!--link NetBSD to TPLinkSwitchBD--><g id="link_NetBSD_TPLinkSwitchBD"><path codeLine="143" d="M149.724,594.7639 C181.188,577.6279 215.7588,558.7986 248.9378,540.7286 " fill="none" id="NetBSD-to-TPLinkSwitchBD" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="254.207,537.8589,244.39,538.6507,249.816,540.2503,248.2163,545.6763,254.207,537.8589" style="stroke:#181818;stroke-width:1.0;" /></g><!--link OpenBSD to TPLinkSwitchBD--><g id="link_OpenBSD_TPLinkSwitchBD"><path codeLine="144" d="M151.031,705.1399 C158.654,698.7659 166.192,692.0489 173,685.2969 C220.389,638.2969 263.691,581.2906 291.205,542.8806 " fill="none" id="OpenBSD-to-TPLinkSwitchBD" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="294.699,538.0029,286.2062,542.9901,291.7873,542.0676,292.7098,547.6488,294.699,538.0029" style="stroke:#181818;stroke-width:1.0;" /></g><!--link DragonflyBSD to TPLinkSwitchBD--><g id="link_DragonflyBSD_TPLinkSwitchBD"><path codeLine="145" d="M156.834,824.5399 C162.659,819.0909 168.18,813.3079 173,807.2969 C177.611,801.5469 262.5112,622.6817 300.0502,543.4037 " fill="none" id="DragonflyBSD-to-TPLinkSwitchBD" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="302.618,537.9809,295.1512,544.4032,300.4782,542.4999,302.3816,547.8269,302.618,537.9809" style="stroke:#181818;stroke-width:1.0;" /></g><!--link MacMini to TPLinkSwitchBD--><g id="link_MacMini_TPLinkSwitchBD"><path codeLine="146" d="M148.036,188.4659 C157.457,195.5099 166.37,203.8109 173,213.2969 C234.996,302.0059 168.801,362.1689 233,449.2969 C237.701,455.6769 238.8095,457.6158 245.0465,462.8018 " fill="none" id="MacMini-to-TPLinkSwitchBD" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="249.66,466.6379,245.2971,457.8081,245.8154,463.4411,240.1823,463.9594,249.66,466.6379" style="stroke:#181818;stroke-width:1.0;" /></g><!--link TinyMonster to TPLinkSwitchBD--><g id="link_TinyMonster_TPLinkSwitchBD"><path codeLine="147" d="M155.066,301.9299 C161.577,307.2569 167.739,313.0719 173,319.2969 C214.077,367.8979 190.719,401.7399 233,449.2969 C238.617,455.6149 240.3924,457.7959 247.3304,463.0699 " fill="none" id="TinyMonster-to-TPLinkSwitchBD" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="252.107,466.7009,247.3628,458.07,248.1265,463.6751,242.5214,464.4388,252.107,466.7009" style="stroke:#181818;stroke-width:1.0;" /></g><!--link TLIPC40CFocus to APDinnerRoom--><g id="link_TLIPC40CFocus_APDinnerRoom"><path codeLine="148" d="M408.261,733.7439 C432.844,735.8539 453.342,737.6137 476.922,739.6377 " fill="none" id="TLIPC40CFocus-to-APDinnerRoom" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="482.9,740.1509,474.2751,735.3958,477.9183,739.7233,473.5909,743.3665,482.9,740.1509" style="stroke:#181818;stroke-width:1.0;" /></g><!--link DoorLock to APLivingRoom--><g id="link_DoorLock_APLivingRoom"><path codeLine="149" d="M370.715,1030.2384 C383.219,1024.4199 396.393,1017.6353 408,1010.2969 C443.95,987.569 476.2575,960.9285 503.9675,936.0365 " fill="none" id="DoorLock-to-APLivingRoom" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="508.431,932.0269,499.0626,935.0656,504.7114,935.3682,504.4088,941.017,508.431,932.0269" style="stroke:#181818;stroke-width:1.0;" /></g><!--link SonyTV to APLivingRoom--><g id="link_SonyTV_APLivingRoom"><path codeLine="150" d="M363.156,954.8159 C396.273,943.3029 437.7147,928.8961 476.9017,915.2731 " fill="none" id="SonyTV-to-APLivingRoom" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="482.569,913.3029,472.7546,912.48,477.8462,914.9447,475.3815,920.0364,482.569,913.3029" style="stroke:#181818;stroke-width:1.0;" /></g><!--link TLIPC40C to APLivingRoom--><g id="link_TLIPC40C_APLivingRoom"><path codeLine="151" d="M387.957,830.3999 C417.549,840.6869 446.7916,850.8539 476.9866,861.3499 " fill="none" id="TLIPC40C-to-APLivingRoom" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="482.654,863.3199,475.4663,856.5866,477.9312,861.6782,472.8396,864.1431,482.654,863.3199" style="stroke:#181818;stroke-width:1.0;" /></g><!--link Chromecast to APLivingRoom--><g id="link_Chromecast_APLivingRoom"><path codeLine="152" d="M389.206,888.2969 C418.632,888.2969 447.126,888.2969 476.97,888.2969 " fill="none" id="Chromecast-to-APLivingRoom" style="stroke:#181818;stroke-width:1.0;" /><polygon fill="#181818" points="482.97,888.2969,473.97,884.2969,477.97,888.2969,473.97,892.2969,482.97,888.2969" style="stroke:#181818;stroke-width:1.0;" /></g><!--SRC=[dLHRJnf157wVNp5FVSE2KUE3CGeeDG6x4Q8FJHyGHfq0CsPPDQPfeaLjl22IcfXMRQgbOcoz9RrOqFfdTdRbNtHtPvTTO5kDl73sV9UTFNFEIQC92KeKYdXoIe99BAA4X2a1sHGcqt4nde4IbjB8JyKa4aVe34a6g4YG23lTAR4fd4WHbCr2dpiXGDDKXEFfU285XcaIGNPzgMx_KCykuIjWy20x-obVdQetHRMwfwo_KrQBd1c8HRI_37m1UiPxDOryUy2MLzMDhprFntl1IvCKSPBALRPst4eQwUwA6WGzkBivl_jrhcvVEXan8On9AXhojVky0ZUB2Huz1ysamMxJVa2W0ooVOyihSgMav0-LlGhegt-LPlYwmN8EIucf1iSciMtSnyuEsUQoPj7gu0y-q4E-gh9ysVgkPp4Xm8LwPDFagmMviglivTdQWNgypYe5m8xUXB04eqYSHQ9wkcfPz0j-b1oXDECpVBX_TrTj_r3Pl-rtrAKp1CU61eU0NFt2IYVQVRB2vnQJTiD4-NRmA9CW9aJlIvenR6gbBQrURZRjRHqX-0J-tosCPp6PhBlnwZ_IBHRk3_YyNdv7OO_nu6omI3mHmGGRk1dR_cmhfovUiD9RTVkuReZ9V8IIh8H4GpI6IPBEPTb5GRk1XYlNRsHjbrqli49HRqRJ88Z6SPmOMXxQ2cNtZrejg1-Mk5JPMUGJ0Vg4qG5BFoWYv8y63GCpTfpuz4Z-_OcTVQoTREY7DeLSEOmaIyZ31-gUJoDY2StuWSgW69-aP28zRycTYNiz30kjla6KJKbq6ZRKkt31hWjMlUkNFIG4Eho1GPgOoJh7KjqjAfjbfRZ4SWLM-kwckPzkBhOfaMPG8fwL38Nzw3IDKZ8V6xKMv5rvfUcWGKh5C4sa-2SfxojtkPlQpd5jUz5awGlH8s9FhxLiUIQDj8ovMK7ZRlHuUerz2Xhscvvjv05xRsZWlx1sDyoUSZVKdjfML5zoTfOV3JIjKGstZmRCkMqIQJHWDuGBo2VA1J0dnGNXe-02cAtkzXP75xl0vXvnGHpBmmrrjgzH3hlYm6eP8s_N6l1MQyvQLirvkrsRaBy0]--></g></svg>
<p>2年前也写过<a href="/2020/04/add-tl-ac100/">文章</a>提到过家里的网络拓扑,大的变化没有,只是加了一些新设备。现在在原有电信宽带的情况下,新增一条移动宽带,主要就是把接入路由器换了,原本的TP-Link R470GP只能接入一个WAN,正好目前R86S比较火,买了个最便宜的版本,先不考虑自己折腾猫棒,能双线以太网口接入就行。另外从闲鱼收了一个TP-Link SG1210P,索性把所有面板都从同一个交换机连上,情况会简单很多。</p>
<p>TP-Link SG1210P有3种工作模式,其中VLAN模式和视频监控模式,LAN中的设备只能与上游接入设备通信,我这里客厅的HTPC要与主卧的诸多设备互通,所以要把TP-Link SG1210P切换到标准模式。</p>
<p>剩下的工作就是把R86S配置好,顺便把原来HTPC/Debian上的科学上网工作也移到R86S上。我给R86S装了最新的Debian 11,网上看其他做软路由的文章/视频99.9%是刷OpenWRT,我为什么不用呢,有几个原因:</p>
<ol>
<li>首先最重要的是,Debian是我最喜欢的Linux发行版,没有之一。从图上可以看到,客厅的HTPC,主卧的曾经的主力旁路由,都是装的Debian,我所有的VPS上也都用的Debian。</li>
<li>其次,我觉得OpenWRT的可玩性不如Debian好,Debian做路由系统需要自己动手做的事更多,但另一方面讲也更自由。</li>
<li>Debian官方仓库的软件包更多更可信,OpenWRT这方面差一点,系统和软件包的魔改版本太多,全都自己编译的话太费时费力。</li>
<li>最后,对OpenWRT的质量不太信任,之前<a href="/2021/01/gl-inet-mt1300/">买了个GL.iNet MT1300</a>,刷的是厂商定制的OpenWRT,升级系统没一次是没问题的。而我这么多不同硬件环境下的Debian系统大版本升级没一次是有问题的。</li>
</ol>
<p>再来讲如何将Debian配置成一个路由器。我的R86S是最低配的那款,只有3个以太网口,规划好3个口的用途,将外壳上标记的eth0和eth1作为WAN口,连接运营商的光猫,eth2作为LAN口,连接屋内的交换机。</p>
<p>首先,在sysctl中将包转发功能打开(我不使用IPv6,不实用),root打开文件<code class="language-plaintext highlighter-rouge">/etc/sysctl.conf</code>,顺便把BBR也打开:</p>
<pre><code class="language-txt">net.ipv4.ip_forward=1
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
</code></pre>
<p>再运行一下<code class="language-plaintext highlighter-rouge">sysctl -p</code>使其生效。</p>
<p>然后配置网络连接,我有3个网口,分别是<code class="language-plaintext highlighter-rouge">enp1s0</code>,<code class="language-plaintext highlighter-rouge">enp2s0</code>,<code class="language-plaintext highlighter-rouge">enp3s0</code>,前2个分别接入电信和移动宽带,第3个作为LAN,编辑<code class="language-plaintext highlighter-rouge">/etc/network/interfaces</code>:</p>
<pre><code class="language-txt"># The loopback network interface
auto lo
iface lo inet loopback
# The primary network interface
auto enp1s0
iface enp1s0 inet dhcp
#iface enp1s0 inet6 dhcp
auto enp2s0
iface enp2s0 inet dhcp
#iface enp2s0 inet6 dhcp
auto enp3s0
iface enp3s0 inet static
address 192.168.233.1
netmask 255.255.255.0
</code></pre>
<p>如果想用IPv6,可以把<code class="language-plaintext highlighter-rouge">inet6</code>那两行注释去掉,我不用,所以就注释掉了,都使用DHCP从光猫获取IP。把内网网段设为<code class="language-plaintext highlighter-rouge">192.168.233.x</code>,本机作为路由器即网关,就用<code class="language-plaintext highlighter-rouge">192.168.233.1</code>。再设置一下iptables转发参数,运行命令:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre>iptables <span class="nt">-t</span> nat <span class="nt">-A</span> POSTROUTING <span class="nt">-o</span> enp1s0 <span class="nt">-j</span> MASQUERADE
iptables <span class="nt">-t</span> nat <span class="nt">-A</span> POSTROUTING <span class="nt">-o</span> enp2s0 <span class="nt">-j</span> MASQUERADE
</pre></td></tr></tbody></table></code></pre></div></div>
<p>这时已经可以上网了,比如敲个命令<code class="language-plaintext highlighter-rouge">curl www.baidu.com</code>看一下,可以得到返回的内容。如果有其他设备接入enp3s0的口,并手动将IP和子网掩码,网关分别设置到<code class="language-plaintext highlighter-rouge">192.168.233.x</code>,<code class="language-plaintext highlighter-rouge">255.255.255.0</code>,<code class="language-plaintext highlighter-rouge">192.168.233.1</code>,其中x是[2,255]间的整数。</p>
<p>接着使用dnsmasq作为DHCP服务器。安装好后编辑配置文件<code class="language-plaintext highlighter-rouge">/etc/dnsmasq.conf</code>:</p>
<pre><code class="language-txt">interface=enp3s0
dhcp-range=192.168.233.200,192.168.233.250,255.255.255.0,12h
dhcp-option=option:router,192.168.233.1
dhcp-option=option:dns-server,192.168.233.1
</code></pre>
<p>内容很简单:第1行,将服务绑定到第3个网口,第2行,设定自由分由的IP地址池以及有效时间,第3行,告知客户端使用的网关IP,第4行,告知客户端使用的DNS服务器地址。还可以绑定IP和mac地址,这样可以在后续针对某个设备做些特殊的设置:</p>
<pre><code class="language-txt">dhcp-host=00:e0:4c:68:2a:5f,192.168.233.166
dhcp-host=00:e0:4c:68:2a:60,192.168.233.66
dhcp-host=00:1E:65:41:73:C2,192.168.233.16
</code></pre>
<p>这里我将本机作为DNS服务器,dnsmasq本身也是一个DNS服务器程序,但我习惯使用CoreDNS,在<a href="/2019/07/coredns-no-dns-poisoning/">以前的文章</a>中详细讲过。</p>
<p>最后是配置一下分流策略,我没拿双线做负载均衡和故障转移,因为我觉得电信1000M和移动200M接入以我家里平常的使用习惯,以及凭目前的服务质量可能一年都碰不到一次需要用另一根线的情况。而流量分流的话,可能在访问某一些服务器时延迟能减少几毫秒(误!我的策略很简单,如果目的IP是归属移动的,则走移动线,否则走电信线。需要分本机流量和非本机流量两种情况处理,先处理非本机的情况,从<code class="language-plaintext highlighter-rouge">https://ispip.clang.cn/</code>下载归属移动的IP地址段列表,然后添加到一个ipset中,命令如下:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre><span class="nb">rm</span> <span class="nt">-f</span> /tmp/cmroute.txt
curl <span class="nt">-sSL</span> https://ispip.clang.cn/cmcc_cidr.txt | <span class="k">while </span><span class="nb">read </span>line
<span class="k">do
</span><span class="nb">echo</span> <span class="s2">"add cmroute </span><span class="nv">$line</span><span class="s2">"</span> <span class="o">>></span> /tmp/cmroute.txt
<span class="k">done
</span>ipset create cmroute <span class="nb">hash</span>:net family inet hashsize 1024 maxelem 512
ipset restore <span class="nt">-f</span> /tmp/cmroute.txt
</pre></td></tr></tbody></table></code></pre></div></div>
<p>然后给<code class="language-plaintext highlighter-rouge">enp3s0</code>的流入流量打个标签:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>iptables <span class="nt">-A</span> PREROUTING <span class="nt">-i</span> enp3s0 <span class="nt">-t</span> mangle <span class="nt">-m</span> <span class="nb">set</span> <span class="nt">--match-set</span> cmroute dst <span class="nt">-j</span> MARK <span class="nt">--set-mark</span> 10
</pre></td></tr></tbody></table></code></pre></div></div>
<p>再给移动线建一个新的路由表(假设叫table 10)并打了标签的流量都导到这个路由上去(192.168.1.6是移动光猫分配出来的IP):</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre>ip rule add from 192.168.1.6 table 10
ip rule add fwmark 10 table 10
ip route add 192.168.1.0/24 dev enp2s0 src 192.168.1.6 table 10
ip route add default via 192.168.1.1 dev enp2s0 table 10
</pre></td></tr></tbody></table></code></pre></div></div>
<p>这时接入到enp3s0口的设备访问移动网络的IP时就会走移动线路了,可以打开移动官网或手机app,感觉似乎真的快了一点点呢!</p>
<p>最后,把本机的流量也分一下,直接改主路由表就行了:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre>curl <span class="nt">-sSL</span> https://ispip.clang.cn/cmcc_cidr.txt | <span class="k">while </span><span class="nb">read </span>line
<span class="k">do
</span>ip route add <span class="nv">$line</span> dev enp2s0
<span class="k">done</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>路由器的基本设置就完成了。另外还可以弄一下科学上网等,这是另一个话题了,暂且略过。</p>missdeer鉴于移动免费送了1年200M的一条宽带,没多犹豫决定还是要用起来。经过一番折腾,基本搞好了,目前的情况大概是这样的:关于Qt/CMake的一个经验2022-10-01T00:00:00+00:002022-10-01T00:00:00+00:00https://blog.ismisv.com/2022/10/a-tip-for-qt-cmake<p>不要使用Qt安装器中提供的CMake,而是自己另外安装一份,比如从CMake官网下载,或者macOS上可使用Homebrew在线安装。</p>
<p>也许你一直用Qt安装器中的那个CMake用得好好的,那没关系。如果有一天突然遇到莫名其妙的CMake配置错误,可以试试使用其他安装的版本,哪怕是被qt-cmake调用的情况下。</p>missdeer不要使用Qt安装器中提供的CMake,而是自己另外安装一份,比如从CMake官网下载,或者macOS上可使用Homebrew在线安装。Windows上编译Zeal2022-04-04T00:00:00+00:002022-04-04T00:00:00+00:00https://blog.ismisv.com/2022/04/build-zeal-on-windows<p>鉴于最近买了个梯子,不大稳定,速度也没以前的快,直接打开在线的开发文档就感觉不大舒服了,想在本地弄个快的。今天编译试用了一下<a href="https://github.com/zealdocs/zeal">Zeal</a>,感觉不错,比当时刚出来的时候好多了,不会随便动两下就遇到奇怪的bug,界面也不那么丑了。</p>
<p>官网上的安装包是3年半前的了,要最新的需要自己编译,看一下文档说明,还算简单。</p>
<p>首先需要准备好MSVC和Qt5。</p>
<p>然后下载依赖项<a href="https://www.libarchive.org/">libarchive</a>和<a href="https://sqlite.org/download.html">sqlite3</a>。都下载官方预编译的包就行了,sqlite3稍微麻烦一点,只能下载到<code class="language-plaintext highlighter-rouge">.h</code>,<code class="language-plaintext highlighter-rouge">.dll</code>和<code class="language-plaintext highlighter-rouge">.def</code>文件,没有<code class="language-plaintext highlighter-rouge">.lib</code>文件,需要自己用命令从<code class="language-plaintext highlighter-rouge">.def</code>生成<code class="language-plaintext highlighter-rouge">sqlite3.lib</code>:</p>
<pre><code class="language-cmd">lib /DEF:sqlite3.def /OUT:sqlite3.lib /MACHINE:x64
</code></pre>
<p>最后安装工具cmake,就可以开始编译了。</p>
<p>打开cmd命令行窗口,假设libarchive和sqlite3分别存放在<code class="language-plaintext highlighter-rouge">C:\Project\libarchive</code>和<code class="language-plaintext highlighter-rouge">C:\Project\sqlite-dll-win64-x64</code>,进入zeal代码所在目录,敲命令:</p>
<pre><code class="language-cmd">cd zeal
set Qt5_DIR=C:\Qt\5.15.2\msvc2019_64
cmake.exe -B build -DLibArchive_LIBRARY=C:\Project\libarchive\lib\archive.lib -DLibArchive_INCLUDE_DIR=C:\Project\libarchive\include -DSQLite_LIBRARY=C:\Project\sqlite-dll-win64-x64\sqlite3.lib -DSQLite_INCLUDE_DIR=C:\Project\sqlite-dll-win64-x64 -DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl -DCMAKE_C_FLAGS="/utf-8" -DCMAKE_CXX_FLAGS="/utf-8"
cmake.exe --build build --config Release
</code></pre>
<p>这样应该就能编译出来<code class="language-plaintext highlighter-rouge">zeal.exe</code>了。</p>
<p>如果有<code class="language-plaintext highlighter-rouge">Ninja</code>,则可以指定cmake使用ninja以便并行编译项目,加快编译速度:</p>
<pre><code class="language-cmd">cd zeal
set Qt5_DIR=C:\Qt\5.15.2\msvc2019_64
cmake.exe -B build -DLibArchive_LIBRARY=C:\Project\libarchive\lib\archive.lib -DLibArchive_INCLUDE_DIR=C:\Project\libarchive\include -DSQLite_LIBRARY=C:\Project\sqlite-dll-win64-x64\sqlite3.lib -DSQLite_INCLUDE_DIR=C:\Project\sqlite-dll-win64-x64 -DCMAKE_MAKE_PROGRAM=C:\Tools\ninja.exe -DCMAKE_BUILD_TYPE=Release -G"Ninja" -DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl -DCMAKE_C_FLAGS="/utf-8" -DCMAKE_CXX_FLAGS="/utf-8"
cmake.exe --build build
</code></pre>
<p>可以看到两种方法的区别,前一种方法cmake生成了MSVC的工程文件,cmake编译时调用MSVC的构建工具,所以可以在编译命令中加<code class="language-plaintext highlighter-rouge">--config Release</code>指定编译variant,后一种方法生成的是Ninja工程文件,直接指定了编译variant,后面的编译命令不需要再指定编译variant,然后cmake调用了ninja进行编译,ninja会自己根据当前CPU的核数自动启动多个并行编译任务。</p>
<p>编译出<code class="language-plaintext highlighter-rouge">zeal.exe</code>后,要把<code class="language-plaintext highlighter-rouge">archive.dll</code>、<code class="language-plaintext highlighter-rouge">sqlite3.dll</code>拷贝到相同目录,再用Qt的<code class="language-plaintext highlighter-rouge">windeployqt.exe</code>把依赖的Qt库都拷过来,最后把Qt的Tools目录下的OpenSSL两个文件<code class="language-plaintext highlighter-rouge">libcrypto-1_1-x64.dll</code>和<code class="language-plaintext highlighter-rouge">libssl-1_1-x64.dll</code>拷贝过来,就能双击运行<code class="language-plaintext highlighter-rouge">zeal.exe</code>了,跑起来的界面大概是这个样子:</p>
<p><img src="https://blogassets.ismisv.com/media/2022-04-04/zeal.png" alt="zeal" /></p>missdeer鉴于最近买了个梯子,不大稳定,速度也没以前的快,直接打开在线的开发文档就感觉不大舒服了,想在本地弄个快的。今天编译试用了一下Zeal,感觉不错,比当时刚出来的时候好多了,不会随便动两下就遇到奇怪的bug,界面也不那么丑了。Windows上cmake适配多种构建工具和编译器2022-01-10T00:00:00+00:002022-01-10T00:00:00+00:00https://blog.ismisv.com/2022/01/adapter-compilers-with-cmake-on-windows<p>用CMake的好处一是屏蔽了多种常见编译器的编译选项和命令行参数差异,二是可以选择目标构建工具。我前段时间要写一个SDK,希望SDK能在主流操作系统(Windows,Linux,macOS)上跑,能用常见的编译器套件(MSVC,GCC,Clang,Intel C编译器等等)编译,这正好是CMake的用武之地。</p>
<h2 id="使用不同的构建工具">使用不同的构建工具</h2>
<h3 id="nmake">NMake</h3>
<p>以Windows为例,我想用MSVC编译,则用如下命令行:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre><span class="nb">mkdir </span>build
<span class="nb">cd </span>build
cmake.exe <span class="nt">-DCMAKE_BUILD_TYPE</span><span class="o">=</span>Release <span class="nt">-G</span><span class="s2">"NMake Makefiles"</span> <span class="nt">-DCMAKE_PREFIX_PATH</span><span class="o">=</span>U:<span class="se">\b</span>oost_1_77_0 ..
nmake
</pre></td></tr></tbody></table></code></pre></div></div>
<h3 id="jom">JOM</h3>
<p>如果嫌<code class="language-plaintext highlighter-rouge">nmake</code>编译速度慢,Qt提供了一个跟<code class="language-plaintext highlighter-rouge">nmake</code>相近但允许像<code class="language-plaintext highlighter-rouge">GNU make</code>一样加<code class="language-plaintext highlighter-rouge">-j</code>参数并行编译的工具<a href="https://download.qt.io/official_releases/jom/">JOM</a>,命令行如下:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre><span class="nb">mkdir </span>build
<span class="nb">cd </span>build
cmake.exe <span class="nt">-DCMAKE_BUILD_TYPE</span><span class="o">=</span>Release <span class="nt">-G</span><span class="s2">"NMake Makefiles JOM"</span> <span class="nt">-DCMAKE_PREFIX_PATH</span><span class="o">=</span>U:<span class="se">\b</span>oost_1_77_0 <span class="nt">-DCMAKE_MAKE_PROGRAM</span><span class="o">=</span>C:<span class="se">\Q</span>t<span class="se">\T</span>ools<span class="se">\Q</span>tCreator<span class="se">\b</span><span class="k">in</span><span class="se">\j</span>om<span class="se">\j</span>om.exe ..
jom.exe <span class="nt">-j</span> 12
</pre></td></tr></tbody></table></code></pre></div></div>
<h3 id="ninja">Ninja</h3>
<p>也可以用现在很流行的另一个构建工具<a href="https://github.com/ninja-build/ninja">Ninja</a>,它默认自动进行并行编译,命令行如下:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre><span class="nb">mkdir </span>build
<span class="nb">cd </span>build
cmake.exe <span class="nt">-DCMAKE_BUILD_TYPE</span><span class="o">=</span>Release <span class="nt">-G</span><span class="s2">"Ninja"</span> <span class="nt">-DCMAKE_PREFIX_PATH</span><span class="o">=</span>U:<span class="se">\b</span>oost_1_77_0 <span class="nt">-DCMAKE_MAKE_PROGRAM</span><span class="o">=</span>C:<span class="se">\T</span>ools<span class="se">\n</span>inja.exe ..
ninja.exe
</pre></td></tr></tbody></table></code></pre></div></div>
<h2 id="使用不同的编译器">使用不同的编译器</h2>
<h3 id="clang-for-windows">Clang for Windows</h3>
<p>前面是用了MSVC,如果想用Clang,Clang在Windows上有2种,一种是使用MSVC的套件,前端命令工具是<code class="language-plaintext highlighter-rouge">clang-cl</code>,另一种是使用MinGW,前端命令工具是<code class="language-plaintext highlighter-rouge">clang</code>,在cmake中只要参数设置一下就可以了:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre><span class="nb">mkdir </span>build
<span class="nb">cd </span>build
cmake.exe <span class="nt">-DCMAKE_BUILD_TYPE</span><span class="o">=</span>Release <span class="nt">-G</span><span class="s2">"NMake Makefiles"</span> <span class="nt">-DCMAKE_PREFIX_PATH</span><span class="o">=</span>U:<span class="se">\b</span>oost_1_77_0 <span class="nt">-DCMAKE_CXX_COMPILER</span><span class="o">=</span>clang-cl ..
nmake
</pre></td></tr></tbody></table></code></pre></div></div>
<h3 id="intel-oneapi-compiler">Intel oneAPI Compiler</h3>
<p>以前Intel C编译器只在Linux上是免费的,现在Windows和macOS上也有免费<a href="https://www.intel.com/content/www/us/en/developer/tools/oneapi/base-toolkit-download.html">安装包下载</a>了,有在线安装和离线安装包2种,根据自己网络情况下载后安装,然后从开始菜单找到<code class="language-plaintext highlighter-rouge">Intel oneAPI command prompt for Intel 64 for Visual Studio 2019</code>,它的工具命令行是<code class="language-plaintext highlighter-rouge">icx</code>,但后面接了<code class="language-plaintext highlighter-rouge">clang</code>,所以也是<code class="language-plaintext highlighter-rouge">clang-cl</code>,这点不需要关心,知道是这回事就行,命令行如下:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre><span class="nb">mkdir </span>build
<span class="nb">cd </span>build
cmake.exe <span class="nt">-DCMAKE_BUILD_TYPE</span><span class="o">=</span>Release <span class="nt">-G</span><span class="s2">"NMake Makefiles"</span> <span class="nt">-DCMAKE_PREFIX_PATH</span><span class="o">=</span>U:<span class="se">\b</span>oost_1_77_0 <span class="nt">-DCMAKE_CXX_COMPILER</span><span class="o">=</span>icx ..
nmake
</pre></td></tr></tbody></table></code></pre></div></div>
<p>用Intel oneAPI编译出来的可执行文件相比MSVC和官方Clang编译出来的可执行文件多链接了一个<code class="language-plaintext highlighter-rouge">libmmd.dll</code>,可能这是Intel家特有的一个优化点。</p>
<h3 id="gccclang-with-mingw">GCC/Clang with MinGW</h3>
<p>MinGW在Windows上有<a href="https://www.msys2.org/docs/environments/">多套环境</a>,不同环境又有GCC和Clang这2种C++编译器,CMake都支持了这总共4种编译套件,构建工具可以使用MinGW官方的<code class="language-plaintext highlighter-rouge">mingw32-make</code>,注意一定要用官方CMake包,不要用msys2中的CMake,会有奇怪的问题。</p>
<h4 id="64位gcc">64位GCC</h4>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre><span class="nb">mkdir </span>mingw64-gcc-build
<span class="nb">cd </span>mingw64-gcc-build
<span class="nb">env </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:/mingw64/bin cmake.exe <span class="nt">-G</span><span class="s2">"Unix Makefiles"</span> <span class="nt">-DCMAKE_BUILD_TYPE</span><span class="o">=</span>Release <span class="nt">-DCMAKE_CXX_COMPILER</span><span class="o">=</span>gcc <span class="nt">-DCMAKE_MAKE_PROGRAM</span><span class="o">=</span>/mingw64/bin/mingw32-make.exe ..
<span class="nb">env </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:/mingw64/bin /mingw64/bin/mingw32-make.exe <span class="nt">-j</span> <span class="sb">`</span><span class="nb">nproc</span><span class="sb">`</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<h4 id="64位clang">64位Clang</h4>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre><span class="nb">mkdir </span>mingw64-clang-build
<span class="nb">cd </span>mingw64-clang-build
<span class="nb">env </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:/clang64/bin cmake.exe <span class="nt">-G</span><span class="s2">"Unix Makefiles"</span> <span class="nt">-DCMAKE_BUILD_TYPE</span><span class="o">=</span>Release <span class="nt">-DCMAKE_CXX_COMPILER</span><span class="o">=</span>clang <span class="nt">-DCMAKE_MAKE_PROGRAM</span><span class="o">=</span>/clang64/bin/mingw32-make.exe ..
<span class="nb">env </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:/clang64/bin /clang64/bin/mingw32-make.exe <span class="nt">-j</span> <span class="sb">`</span><span class="nb">nproc</span><span class="sb">`</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<h4 id="32位gcc">32位GCC</h4>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre><span class="nb">mkdir </span>mingw32-gcc-build
<span class="nb">cd </span>mingw32-gcc-build
<span class="nb">env </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:/mingw32/bin cmake.exe <span class="nt">-G</span><span class="s2">"Unix Makefiles"</span> <span class="nt">-DCMAKE_BUILD_TYPE</span><span class="o">=</span>Release <span class="nt">-DCMAKE_CXX_COMPILER</span><span class="o">=</span>gcc <span class="nt">-DCMAKE_MAKE_PROGRAM</span><span class="o">=</span>/mingw32/bin/mingw32-make.exe ..
<span class="nb">env </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:/mingw32/bin /mingw32/bin/mingw32-make.exe <span class="nt">-j</span> <span class="sb">`</span><span class="nb">nproc</span><span class="sb">`</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<h4 id="32位clang">32位Clang</h4>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre><span class="nb">mkdir </span>mingw32-clang-build
<span class="nb">cd </span>mingw32-clang-build
<span class="nb">env </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:/clang32/bin cmake.exe <span class="nt">-G</span><span class="s2">"Unix Makefiles"</span> <span class="nt">-DCMAKE_BUILD_TYPE</span><span class="o">=</span>Release <span class="nt">-DCMAKE_CXX_COMPILER</span><span class="o">=</span>clang <span class="nt">-DCMAKE_MAKE_PROGRAM</span><span class="o">=</span>/clang32/bin/mingw32-make.exe ..
<span class="nb">env </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:/clang32/bin /clang32/bin/mingw32-make.exe <span class="nt">-j</span> <span class="sb">`</span><span class="nb">nproc</span><span class="sb">`</span>
</pre></td></tr></tbody></table></code></pre></div></div>missdeer用CMake的好处一是屏蔽了多种常见编译器的编译选项和命令行参数差异,二是可以选择目标构建工具。我前段时间要写一个SDK,希望SDK能在主流操作系统(Windows,Linux,macOS)上跑,能用常见的编译器套件(MSVC,GCC,Clang,Intel C编译器等等)编译,这正好是CMake的用武之地。把玩BSD2021-12-27T00:00:00+00:002021-12-27T00:00:00+00:00https://blog.ismisv.com/2021/12/cross-compile-for-dragonflybsd<p>前些时间脑子发热在淘宝上买了个DeskMini X300,但是出于预算方面的原因,选了个最低档的CPU——AMD 3000G,到手后发现跑Windows10非常慢,有点后悔没有多加千把块钱配个好点的CPU。</p>
<p>我买DeskMini的原因倒不是为了跑Windows,而是为了跑Linux之类的当服务器,然后刚好了解了一下PVE,于是一番折腾,先装了PVE,再陆续装了5个虚拟系统,分别是Debian 11,FreeBSD 13,NetBSD 9.2,OpenBSD 7以及DragonflyBSD 6,而且只装了命令行界面,所有图形界面组件全都没有装,这样一来机器性能就不是什么大问题了。</p>
<p>这些年一直在VPS和HTPC上跑着Debian 11,虽然不是很熟练,但也不陌生。但几个BSD系统,只有好些年前在Thinkpad T43装过一回,也没怎么用,基本属于完全不了解的程度,不过好在安装过程非常简单,连资料都不用看也能基本顺利地完成安装。</p>
<p>安装完成之后,便是设置普通用户,设置服务等等,除了一些Linux上可以使用的命令没有外,日常使用基本上不是特别难的问题,上网都能搜到一些资料。不过到目前为止还遗留一个问题:在Linux上建的NFS server,在BSD上挂载后只有只读,但在Linux下可以挂载为读写。</p>
<p>我比较关心的是在各个系统上编写自己的程序是否方便,发现FreeBSD和OpenBSD都默认使用较新版本的clang,NetBSD默认安装某个旧版本gcc,但可以自行用pkgin安装最新的clang。但是DragonflyBSD就比较懒了,默认安装了某个很旧版本的gcc,还没现成的clang安装包。</p>
<p>既没有DragonflyBSD上可用的clang安装包,又不想自己编译一个clang,也不想用老旧的gcc,只能想想在其他平台用clang给DragonflyBSD做交叉编译了。</p>
<p>首先mount好DragonflyBSD的安装镜像ISO,这在Linux和FreeBSD上有一点区别,FreeBSD需要先创建一个回环设备:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span>mdconfig <span class="nt">-a</span> <span class="nt">-t</span> vnode <span class="nt">-f</span> DragonFly-x86_64-LATEST-ISO.iso
</pre></td></tr></tbody></table></code></pre></div></div>
<p>这时会返回新创建的回环设备名称,比如<code class="language-plaintext highlighter-rouge">md0</code>,再mount这个设备:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span><span class="nb">mkdir </span>iso
<span class="nv">$ </span>mount <span class="nt">-t</span> cd9660 <span class="nt">-o</span> ro /dev/md0 ./iso
</pre></td></tr></tbody></table></code></pre></div></div>
<p>如果是Linux上则可以直接mount这个iso文件:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span><span class="nb">mkdir </span>iso
<span class="nv">$ </span>mount <span class="nt">-o</span> loop,ro DragonFly-x86_64-LATEST-ISO.iso ./iso
</pre></td></tr></tbody></table></code></pre></div></div>
<p>写一个经典的<code class="language-plaintext highlighter-rouge">Hello world</code>,代码如下:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre><span class="cp">#include <stdio.h>
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Hello World</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>然后就可以用clang编译了:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span>clang <span class="nt">-I</span>./iso/usr/include <span class="se">\</span>
<span class="nt">-L</span>./iso/usr/lib <span class="nt">-L</span>./iso/usr/lib/gcc47 <span class="se">\</span>
<span class="nt">-B</span>./iso/usr/lib <span class="nt">-B</span>./iso/usr/lib/gcc47 <span class="se">\</span>
<span class="nt">-target</span> x86_64-pc-dragonfly-elf <span class="se">\</span>
<span class="nt">-o</span> helloworld helloworld.c
</pre></td></tr></tbody></table></code></pre></div></div>
<p>如果没问题的话,这时应该生成了一个可执行文件<code class="language-plaintext highlighter-rouge">helloworld</code>,可以用<code class="language-plaintext highlighter-rouge">file</code>命令看一下文件类型:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span>file helloworld
/home/missdeer/helloworld: ELF 64-bit LSB executable, x86-64, version 1 <span class="o">(</span>SYSV<span class="o">)</span>, statically linked, interpreter /usr/libexec/ld-elf.so.2, <span class="k">for </span>DragonFly 6.0.0, not stripped
</pre></td></tr></tbody></table></code></pre></div></div>
<p>大体过程就是这样了。但是最好还是编译一套原生的clang吧。</p>missdeer前些时间脑子发热在淘宝上买了个DeskMini X300,但是出于预算方面的原因,选了个最低档的CPU——AMD 3000G,到手后发现跑Windows10非常慢,有点后悔没有多加千把块钱配个好点的CPU。使用cmake构建Qt5程序的一些坑2021-07-20T00:00:00+00:002021-07-20T00:00:00+00:00https://blog.ismisv.com/2021/07/cmake-tips-with-qt5<p>突然想试一下CLion上写Qt5程序是什么体验,反正有JB家的全家桶License。CLion使用cmake作为构建工具,而Qt官方也开始支持cmake,但使用过程中还是遇到一些坑,记录一下。</p>
<h1 id="读qt的cmake使用帮助">读Qt的cmake使用帮助</h1>
<p>这点很重要,一些最重要的问题在使用帮助中已经提到了,一定要逐字逐句读一遍。</p>
<h2 id="设置qt路径">设置Qt路径</h2>
<p>这个在网上随便搜一下就能找到很多文章都提到了,就是设置到<code class="language-plaintext highlighter-rouge">CMAKE_PREFIX_PATH</code>或<code class="language-plaintext highlighter-rouge">Qt5_DIR</code>中,注意设置到系统环境变量中与作为命令行参数传给cmake效果是有区别的,我发现作为命令行参数传递比较省事。</p>
<h2 id="编译可执行文件或动态库">编译可执行文件或动态库</h2>
<p>如果编译的项目是个exe或动态库,需要将Qt模块添加到目标链接库列表中,这样cmake就会自动把Qt的头文件路径和库文件路径添加到编译器的搜索路径列表中:</p>
<div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="nb">target_link_libraries</span><span class="p">(</span>MyProgram Qt::Widgets Qt::Network Qt::Xml<span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<h2 id="编译静态库">编译静态库</h2>
<p>如果要编译的项目是个静态库,没法用<code class="language-plaintext highlighter-rouge">target_link_libraries</code>,但光是设置<code class="language-plaintext highlighter-rouge">CMAKE_PREFIX_PATH</code>仍然会在编译过程中报错找不到Qt的头文件,需要自己加入头文件搜索路径:</p>
<div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre><span class="nb">include_directories</span><span class="p">(</span>
<span class="si">${</span><span class="nv">Qt5Widgets_INCLUDE_DIRS</span><span class="si">}</span>
<span class="si">${</span><span class="nv">Qt5Network_INCLUDE_DIRS</span><span class="si">}</span>
<span class="si">${</span><span class="nv">Qt5Xml_INCLUDE_DIRS</span><span class="si">}</span>
<span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>其中<code class="language-plaintext highlighter-rouge">Qt5Widgets_INCLUDE_DIRS</code>一项就包含了<code class="language-plaintext highlighter-rouge">Widgets</code>,<code class="language-plaintext highlighter-rouge">Core</code>和<code class="language-plaintext highlighter-rouge">Gui</code>三个模块。</p>
<h2 id="编译qt-plugin项目">编译Qt plugin项目</h2>
<p>如果要编译的项目是以QtPlugin形式写成的库,要自己定义一个宏<code class="language-plaintext highlighter-rouge">QT_STATICPLUGIN</code>,这样写就可以:</p>
<div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="nf">add_compile_definitions</span><span class="p">(</span>QT_STATICPLUGIN=1<span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<h2 id="生成mac-bundle">生成mac bundle</h2>
<p>macOS上的bundle要多打包图标等一些资源,稍微麻烦一点:</p>
<div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="rouge-code"><pre><span class="nb">if</span> <span class="p">(</span>APPLE<span class="p">)</span>
<span class="nb">set</span><span class="p">(</span>MACOSX_BUNDLE true<span class="p">)</span>
<span class="nb">set</span><span class="p">(</span>MACOSX_BUNDLE_BUNDLE_NAME MyProgram<span class="p">)</span>
<span class="nb">set</span><span class="p">(</span>MACOSX_BUNDLE_GUI_IDENTIFIER <span class="s2">"com.ismisv.myprogram"</span><span class="p">)</span>
<span class="nb">set</span><span class="p">(</span>MACOSX_BUNDLE_ICON_FILE <span class="s2">"MyProgram.icns"</span><span class="p">)</span>
<span class="nb">set</span><span class="p">(</span>MACOSX_BUNDLE_INFO_STRING <span class="s2">"MyProgram"</span><span class="p">)</span>
<span class="nb">set</span><span class="p">(</span>MACOSX_BUNDLE_LONG_VERSION_STRING <span class="s2">"1.0.0.1"</span><span class="p">)</span>
<span class="nb">set</span><span class="p">(</span>MACOSX_BUNDLE_SHORT_VERSION_STRING <span class="s2">"1.0"</span><span class="p">)</span>
<span class="nb">set</span><span class="p">(</span>MACOSX_BUNDLE_BUNDLE_VERSION <span class="s2">"1.0"</span><span class="p">)</span>
<span class="nb">set_source_files_properties</span><span class="p">(</span><span class="s2">"</span><span class="si">${</span><span class="nv">CMAKE_CURRENT_SOURCE_DIR</span><span class="si">}</span><span class="s2">/MyProgram.icns"</span> PROPERTIES MACOSX_PACKAGE_LOCATION Resources<span class="p">)</span>
<span class="nb">set_target_properties</span><span class="p">(</span>
MyProgram
PROPERTIES
RESOURCE <span class="s2">"./MyProgram.icns"</span>
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
<span class="p">)</span>
<span class="nb">endif</span><span class="p">()</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<h2 id="指定当前项目使用的编程语言">指定当前项目使用的编程语言</h2>
<p>Cmake可以指定当前项目使用的编程语言,比如:</p>
<div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="nb">project</span><span class="p">(</span>MyProgram LANGUAGES CXX<span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>这样cmake只会编译<code class="language-plaintext highlighter-rouge">.cpp</code>,<code class="language-plaintext highlighter-rouge">.cxx</code>这些C++编译器认的文件,如果项目中有一些<code class="language-plaintext highlighter-rouge">.c</code>文件,则会被忽略,所以干脆不写就能编译所有类型的文件:</p>
<div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="nb">project</span><span class="p">(</span>MyProgram<span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>missdeer突然想试一下CLion上写Qt5程序是什么体验,反正有JB家的全家桶License。CLion使用cmake作为构建工具,而Qt官方也开始支持cmake,但使用过程中还是遇到一些坑,记录一下。