<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Llvm on Chen</title><link>https://hechen.github.io/zh-cn/tags/llvm/</link><description>Recent content in Llvm on Chen</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Thu, 03 Jan 2019 21:19:24 +0000</lastBuildDate><atom:link href="https://hechen.github.io/zh-cn/tags/llvm/index.xml" rel="self" type="application/rss+xml"/><item><title>在 Swift Framework 中使用 C 文件的过程探索</title><link>https://hechen.github.io/zh-cn/post/swift-and-modules/</link><pubDate>Thu, 03 Jan 2019 21:19:24 +0000</pubDate><guid>https://hechen.github.io/zh-cn/post/swift-and-modules/</guid><description>&lt;h2 id="问题描述"&gt;问题描述&lt;/h2&gt;
&lt;p&gt;我们在开发线上诊断工具需求的时候，是以单个 Pod 的形式提供支持，并且代码文件中只有纯 Swift 文件，但是其中需要用到系统的 C 库的一些功能，本次就是使用了系统 C 库中 &lt;code&gt;resolv.h&lt;/code&gt; 这个文件来进行 DNS 解析所用。&lt;/p&gt;
&lt;p&gt;当后期 Pod 功能完善之后，在 Example 工程中也已经编译通过之后，接入主项目中之后遇到了下面这个编译错误：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Error When Compile" loading="lazy" src="https://i.imgur.com/ADh0sy6.png"&gt;&lt;/p&gt;
&lt;p&gt;具体文字错误信息如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plaintext" data-lang="plaintext"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/Users/chen/Repos/Work/ZHDiagnosisTool/ZHDiagnosisTool/Classes/Core/Network/ZHDiagnosisTool-Network-Header.h:8:10:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Include of non-modular header inside framework module &amp;#39;Diagnosis.ZHDiagnosisTool_Network_Header&amp;#39;: &amp;#39;/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.1.sdk/usr/include/resolv.h&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;大概的意思就是在 Umbrella Header 中加入的 Bridging header 指定了 include 一个 C 文件，而该 C 文件本身并不是 Modular Header， 因此编译无法通过。这就涉及了目前 iOS 生态中普遍使用的 Modules 概念。&lt;/p&gt;
&lt;h2 id="几个概念"&gt;几个概念&lt;/h2&gt;
&lt;h3 id="modules"&gt;Modules&lt;/h3&gt;
&lt;p&gt;Modules 的概念是 XCode 5 带到 iOS 开发者面前的，从那时起 LLVM 编译器就已经内在支持了，具体关于其历史在 &lt;a href="https://onevcat.com/2013/06/new-in-xcode5-and-objc/"&gt;WWDC 2013 Session笔记 - Xcode5和ObjC新特性&lt;/a&gt; 这篇文章中已经讲解的非常详细了，不再赘述，总结一句话就是：&lt;/p&gt;</description></item><item><title>如何制作 Send to 2Do 的 Safari 书签</title><link>https://hechen.github.io/zh-cn/post/send-to-2do/</link><pubDate>Mon, 26 Nov 2018 14:59:50 +0000</pubDate><guid>https://hechen.github.io/zh-cn/post/send-to-2do/</guid><description>&lt;p&gt;使用鼠标拖拽下面这个链接到你的 Favorites Bar 上，默认点击行为实际上是模拟在当前页面进行导航，而目标地址由 &lt;code&gt;avascript:window.location&lt;/code&gt; 来指定，目标地址实际上就是各个 App 的 URL Scheme。
你可以在 &lt;a href="https://app-talk.com/"&gt;AppTalk&lt;/a&gt;查看各个主流 App 的 URL Scheme。&lt;/p&gt;
&lt;h2 id="2do"&gt;2Do&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://hechen.github.io/zh-cn/post/send-to-2do/#ZgotmplZ"&gt;Send to 2Do&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;然后编辑地址，将其替换为如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;javascript:window.location=&amp;#39;twodo://x-callback-url/add?task=&amp;#39;+encodeURIComponent(document.title)+&amp;#39;&amp;amp;note=&amp;#39;+encodeURIComponent(window.location)+&amp;#39;&amp;amp;action=url:&amp;#39;+encodeURIComponent(window.location)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img alt="Change Value" loading="lazy" src="https://i.imgur.com/7M0xN1g.jpg"&gt;&lt;/p&gt;
&lt;p&gt;所以，本质上是执行了一段 JS 代码，结合当前文档的上下文信息，调用 URL Scheme，其中&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;document.title&lt;/code&gt; 为标题&lt;/li&gt;
&lt;li&gt;&lt;code&gt;window.location&lt;/code&gt; 为当前页面链接&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="things"&gt;Things&lt;/h2&gt;
&lt;p&gt;我们知道 Things 的 URL Scheme 的规则如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;/// add a todo due when tomorrow
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nl"&gt;things&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;///add?title=iamtitle&amp;amp;notes=iamnotes&amp;amp;when=tomorrow
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://hechen.github.io/zh-cn/post/send-to-2do/#ZgotmplZ"&gt;Add a todo to Things&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;比如你可以把链接内容改为支持 Send To Things：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;javascript&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;things:///add?title=&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;amp;notes=&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;amp;when=today&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="omnifocus"&gt;OmniFocus&lt;/h2&gt;
&lt;p&gt;同理，可以有 Send To OmniFocus ，如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;javascript&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;omnifocus:///add?note=&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;amp;name=&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://hechen.github.io/zh-cn/post/send-to-2do/#ZgotmplZ"&gt;Add a todo to OmniFocus&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;或者直接去 &lt;a href="http://people.omnigroup.com/kc/OmniFocus/SendToOmniFocusBookmarklet.html"&gt;OmniFocus 页面&lt;/a&gt; 用相同方式把起已经设置好正确 Value 的链接拖到上方工具条上即可。&lt;/p&gt;</description></item><item><title>阅读流程</title><link>https://hechen.github.io/zh-cn/post/reading-process/</link><pubDate>Tue, 16 Oct 2018 17:01:44 +0000</pubDate><guid>https://hechen.github.io/zh-cn/post/reading-process/</guid><description>&lt;p&gt;最近统一了一下自己的阅读流程，更新一下，具体用到的工具有&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;DEVONThink Pro&lt;/li&gt;
&lt;li&gt;PDFExpert&lt;/li&gt;
&lt;li&gt;MarginNote&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;其中 1 是输入和归档源，3 是输出源。 大概就是如下所示：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Reading Process" loading="lazy" src="https://i.imgur.com/SrcVtP1.png"&gt;&lt;/p&gt;
&lt;h2 id="采集素材"&gt;采集素材&lt;/h2&gt;
&lt;p&gt;在平时浏览网页的时候，看到自己喜欢的文章之后，想进行一些标记或者做笔记，大概有几个选择：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;印象笔记直接 clip 当前网页，之后在印象笔记里进行阅读或者标记&lt;/li&gt;
&lt;li&gt;放进稍后读服务中，比如 Pocket 或者 Instapaper 等；&lt;/li&gt;
&lt;li&gt;用 Safari 自带的 Save as PDF 之后再用单独的 PDF 工具查看；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;而最近几个月，因为 MarginNote 3 的发布，由于其提供的大纲脑图的自动生成，给我提供了一种便利的拆书功能，因此会把平时看到的文章都归集到一处来看。&lt;/p&gt;
&lt;p&gt;借助 DEVONthink 的 Clip To DEVONthink 的插件可以很方便的把文章归集到 DEONThink 中，最主要的是因为它能保存 WebArchive，即使后续文章被删除也没关系。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Clip To DEVONthink" loading="lazy" src="https://i.imgur.com/Kw7CoBl.png"&gt;&lt;/p&gt;
&lt;p&gt;当按下 Cmmd + S 进行归档之后，DEVONThink 对应 Group 里就会把该原始页面保存起来。&lt;/p&gt;
&lt;p&gt;&lt;img alt="DEVONthink" loading="lazy" src="https://i.imgur.com/m3jM9kx.png"&gt;&lt;/p&gt;
&lt;p&gt;由于 WebArchive 无法做 Highlight 标记，这时候就用到了 DEVONthink 提供的 OCR 功能，将 WebArchive 提取为 PDF 文件。&lt;/p&gt;</description></item><item><title>Swift 中几种不同的依赖注入方式</title><link>https://hechen.github.io/zh-cn/post/different-flavors-of-dependency-injection-in-swift/</link><pubDate>Mon, 16 Jul 2018 13:57:24 +0000</pubDate><guid>https://hechen.github.io/zh-cn/post/different-flavors-of-dependency-injection-in-swift/</guid><description>&lt;blockquote&gt;
&lt;p&gt;原文：&lt;a href="https://www.swiftbysundell.com/articles/different-flavors-of-dependency-injection-in-swift/"&gt;Different flavors of dependency injection in Swift&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;原作者 &amp;amp; Copyright &lt;a href="https://twitter.com/johnsundell"&gt;@johnsundell&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在之前的几篇博客中，我们已经了解了几种使用依赖注入方式使得某个 swift app 拥有一个更加解耦可测试的架构。比如在 &lt;a href="https://hechen.github.io/2017/11/19/Dependency-injection-using-factories-in-Swift/"&gt;在 Swift 中使用工厂模式进行依赖注入&lt;/a&gt; 中和工厂模式结合，以及在&lt;a href="https://hechen.github.io/2018/07/16/Avoiding-singletons-in-Swift/"&gt;避免在 Swift 中使用单例&lt;/a&gt;中替换程序中的单例对象等方式进行依赖注入。&lt;/p&gt;
&lt;p&gt;到目前为止，大部分我的博文以及例子中都使用了基于初始化的依赖注入方式。然而，就像大部分的编程技巧一样，还有很多 “口味” 的进行依赖注入的方式 ── 每一种都有其优缺点。 这周，让我们来看看其中三种方式以及如何在 Swift 中使用它们。&lt;/p&gt;
&lt;h3 id="基于初始化方法"&gt;基于初始化方法&lt;/h3&gt;
&lt;p&gt;让我们快速回顾一下用的最为广泛的依赖注入方式 ── initializer-based。这个想法是在某个类被初始化的时候传入其所需的依赖的方式。这种形式最大的好处就是，它保证了能够立即满足该类完成其功能所需要的所有东西。&lt;/p&gt;
&lt;p&gt;让我们建一个类 ── FileLoader 来从磁盘加载文件。为了实现该 Loader 的功能，需要两个依赖项，系统所提供的实例对象 ── &lt;strong&gt;FileManager&lt;/strong&gt; 和 &lt;strong&gt;Cache&lt;/strong&gt;。使用基于初始化的依赖注入的执行代码如下所示：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FileLoader&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;fileManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FileManager&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Cache&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FileManager&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Cache&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;init&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kc"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fileManager&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fileManager&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kc"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;可以关注下初始化方法里默认参数的设置，其可以避免每次都需要自行创建的问题。这样能够简化我们在生产环境下使用 &lt;strong&gt;FileLoader&lt;/strong&gt; 类创建文件加载器的工作，而且也能够能够传入 mock 数据或者我们的测试代码中的创建的实例进行测试。&lt;/p&gt;
&lt;h3 id="基于属性"&gt;基于属性&lt;/h3&gt;
&lt;p&gt;虽然前一种基于初始化的依赖注入形式常常给我们自定义类带来很多好处，但是有时候，当你不得不继承自某个系统类的时候会遇到一些困难。其中一个例子就是，当我们构建 view controller，尤其是你在使用 XIB 以及 Storyboard 类定义它们的时候，因为此时你不再能够掌控它们的初始化方法了。&lt;/p&gt;
&lt;p&gt;对于这些情况，基于属性的依赖注入方式是一个更好的选择。相对于初始化的时候进行对象的依赖项注入，基于属性的形式可以在之后通过简单的赋值来做到，其能够让你减少模板代码的书写，尤其是在你确实没有必要进行注入的时候能够有更好的默认实现。&lt;/p&gt;
&lt;p&gt;让我们再来看一个例子，在这个例子中，我们在构建一个 &lt;strong&gt;PhotoEditorViewController&lt;/strong&gt; ，这个视图控制器使得用户编辑它们照片库中的图片。为了达到这个功能，该视图控制器需要用到系统提供的 PHPhotoLibrary 类型的一个实例（该类本身是一个单例）以及我们自己实现的类 &lt;strong&gt;PhotoEditorEngine&lt;/strong&gt; 的一个实例。那为了不通过自定义初始化方法进行依赖注入的话，我们可以创建一些具有默认值的可变属性，例如下面这样：&lt;/p&gt;</description></item><item><title>那些我恢复 Mac 系统之后要安装的 Apps</title><link>https://hechen.github.io/zh-cn/post/my-favorite-mac-apps/</link><pubDate>Wed, 11 Jul 2018 12:58:37 +0000</pubDate><guid>https://hechen.github.io/zh-cn/post/my-favorite-mac-apps/</guid><description>&lt;p&gt;记录一下自己常用的 Mac Apps，每次重装之后到了用的时候发现忘记安装了(不是每次都用 TimeMachine 恢复)，而且强烈简易大家如果某个 App 有对应的独立安装版本的话，购买其独立安装版本为好，沙盒环境以及和 Apple ID 绑定的特性就使得功能性以及灵活度大减。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;更新时间 2018-10-07
更换图床，更新图片&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;更新时间 2018-08-10
不久前，已经订阅了一年的 Setapp，发现上面好多 App 自己都之前买过了，Sigh！
如果你使用 Ulysses 或者 MoneyWiz 3.0 的话，订阅 Setapp 就会非常的值得！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt="Mac Apps" loading="lazy" src="https://i.imgur.com/q3yToeZ.png"&gt;&lt;/p&gt;
&lt;h2 id="办公工具"&gt;办公工具&lt;/h2&gt;
&lt;p&gt;离开这些工具，貌似无法办公的。&lt;/p&gt;
&lt;h3 id="airmail"&gt;AirMail&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://itunes.apple.com/cn/app/airmail-3/id918858936?l=en&amp;amp;mt=12"&gt;下载地址&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="AirMai" loading="lazy" src="https://i.imgur.com/19ADIxn.jpg"&gt;&lt;/p&gt;
&lt;p&gt;邮箱客户端，看中 AirMail 主要是因为其强大的第三方服务集成。&lt;/p&gt;
&lt;h3 id="slack"&gt;Slack&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://itunes.apple.com/cn/app/slack/id803453959?mt=12"&gt;下载地址&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Slack" loading="lazy" src="https://i.imgur.com/W1wtsje.jpg"&gt;&lt;/p&gt;
&lt;p&gt;公司的日常沟通交流主要战场，其实整个操作体验我是不太适应的，不过它强大在第三方服务的集成上，可以做很多自动化的事情。&lt;/p&gt;
&lt;h3 id="fantastical-2"&gt;Fantastical 2&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://flexibits.com/fantastical"&gt;下载地址&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Fantastical" loading="lazy" src="https://i.imgur.com/1naxpaM.jpg"&gt;&lt;/p&gt;
&lt;p&gt;日历工具，查看满满的一屏幕日程，你会感觉很舒服的。&lt;/p&gt;
&lt;h4 id="tunnelblick"&gt;Tunnelblick&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://tunnelblick.net/downloads.html"&gt;下载地址&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Tunnelblick-menu" loading="lazy" src="https://i.imgur.com/ghIEHNQ.png"&gt;&lt;/p&gt;
&lt;p&gt;公司需要使用该 App 来接入办公室网络。远程办公必备。&lt;/p&gt;
&lt;h4 id="office-三件套"&gt;Office 三件套&lt;/h4&gt;
&lt;p&gt;微软的 Office 三件套，Word，Excel，PowerPoint。 用的频率不高，但是用的时候得有。&lt;/p&gt;
&lt;h2 id="gtd"&gt;GTD&lt;/h2&gt;
&lt;p&gt;日常 GTD 工具，基本就是各家评测常提起的几款 App。&lt;/p&gt;
&lt;h3 id="2do"&gt;2Do&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.2doapp.com/"&gt;下载地址&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="2Do on Mac" loading="lazy" src="https://i.imgur.com/st89Smb.jpg"&gt;&lt;/p&gt;
&lt;p&gt;最近才完全转向 2Do，这个 GTD 工具是我最早买入的，但是后来因为其自动化太弱，被打入冷宫。最近几个月又开始捡起来了，吸引我的几个点：&lt;/p&gt;</description></item><item><title>What is LLVM</title><link>https://hechen.github.io/zh-cn/post/what-is-llvm/</link><pubDate>Tue, 10 Jul 2018 12:05:58 +0000</pubDate><guid>https://hechen.github.io/zh-cn/post/what-is-llvm/</guid><description>&lt;h1 id="什么是-llvm隐藏在-swiftrustclang-等语言背后的奥秘"&gt;什么是 LLVM？隐藏在 Swift，Rust，Clang 等语言背后的奥秘&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;了解编译器是如何生成机器原生代码会使得倒腾新语言或者加强已经存在的编程语言变得比以往更加容易了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;新的编程语言，针对现存语言的优化如同雨后春笋般产生。 Mozilla 的 &lt;strong&gt;Rust&lt;/strong&gt;， Apple 的 &lt;strong&gt;Swift&lt;/strong&gt;，JetBrain 的 &lt;strong&gt;Kotlin&lt;/strong&gt;等语言给开发者提供了在速度，安全性，便捷性，可移植性以及性能等方面更多的选择。&lt;/p&gt;
&lt;p&gt;为什么是这个时间点呢？一个重大的原因是那些构建具体语言相关的新式工具的出现。在这一堆工具中，最重要的就是 LLVM，其全称是 Low-Level Virtual Machine，它是一个开源项目，其最早是由 Swift 语言的发明人 Chris Lattner 在伊利诺斯州州立大学期间的一个研究项目而来。&lt;/p&gt;
&lt;p&gt;LLVM 不仅仅使得创建新式语言更加容易，也使得针对现存编程语言进行增强完善更加便捷。它提供了一堆工具使得创造语言的过程中需要的那些令人头疼的事情变得自动化：创建一个编译器，输出代码需要适配多平台和架构，编写代码处理语言当中通常都存在的那些比较晦涩的部分，比如异常。LLVM 的自由开发许可使得它可以被自由的作为一个软件组件或者被部署成服务来使用。&lt;/p&gt;
&lt;p&gt;使用了 LLVM 的编程语言花名册种有很多熟悉的名字。Apple 的 Swift 语言使用 LLVM 作为其编译器框架，Rust 语言使用 LLVM 作为其工具链中的一个核心组件。同样，许多编译器也有其 LLVM 版本，例如 Clang，一个 C/C++ 编译器，它是和 LLVM 功能特别相近的一个项目。还有 Kotlin 语言，其名义上是一门 JVM 语言，也正在开发该语言的一个版本： &lt;a href="https://www.infoworld.com/article/3187370/application-development/kotlin-compiles-directly-to-native-code-via-llvm.html"&gt;Kotlin Native&lt;/a&gt;，其使用 LLVM 编译成机器原生代码。&lt;/p&gt;
&lt;h2 id="llvm-是什么"&gt;LLVM 是什么&lt;/h2&gt;
&lt;p&gt;LLVM 最核心的功能就是，可以通过编码方式创造机器原生代码。一个开发者可以使用其 API 创造指令，该指令是一种 intermediate representation 格式，简称 IR。之后，LLVM 能够将 IR 编译成独立的二进制文件，或者对其执行即时编译以运行在另外一个程序，例如某编程语言的解释器的上下文中。&lt;/p&gt;
&lt;p&gt;很多编程语言中很常见的结构体或者模式，LLVM 的 API 都提供了原始语义的支持。例如，几乎所有的语言都有函数或者全局变量的概念，LLVM 在其 IR 中把函数和全局变量作为独立元素定义出来，因此你不需要花太多时间和精力来重复造这些特定的轮子，你只需要使用 LLVM 的实现，专注于你的语言最需要关注的地方即可。&lt;/p&gt;</description></item></channel></rss>