当前位置: 首页 > 科技观察

编程语言的支撑系统:构建系统、IDE和依赖管理

时间:2023-03-18 23:54:38 科技观察

年审临近。这段时间,我在整理一些2020年要做的事情,努力为明年做打算。在这个过程中,我发现自己所做的一些事情,无论是与工作相关的,还是探索兴趣的,都可以继续总结一些文章。在工作中,我做的很多事情都是编程语言的支撑系统。除了业余时间,我还花了一些时间和同事一起学习编程语言。在这些部分的结合下,我对整个系统端到端的实现有了一个整体的认识。作为一名专业的程序员,在我们的职业生涯中,学习一门又一门编程语言是不可避免的。虽然在大多数情况下,我们对于使用什么语言没有太多选择。但是,我们在选择语言的时候,必须要考虑一系列的要素,比如:buildsystemIDE/Editorsupportdependencymanagement...PS:当然,对于使用C/C++的人来说,这些可能是Exception:s/他认为他或她不需要这些工具,并且可以在需要时自己创建一个。因此,这些语言长期以来一直缺乏良好的依赖管理工具。在故事开始之前,让我们让Android使用的开发和构建来讲述这个故事。从Android应用的开发构建,到移动端的开发,我虽然不如这个行业的很多大佬,但是还是比较有经验的。一年中正好有一半时间花在相关项目上。所以,我是从宏观的角度来理解整个系统的。当我们开始一个新的移动应用程序时,我们会通过模板从IDE中创建一个全新的应用程序,或者从某个地方(比如GitHub)找到一个合适的模板。然后,为了验证模板的有效性,我们执行Gradle的相关命令,完成一个应用流程,运行这个Demo。(PS:这和我们用Java开发应用程序时差别不大)。在这个过程中,发生了一些事情:IDE通过某种通信机制与Gradle进行通信,执行相应的命令,比如build。Gradle收到IDE的指令后,解析build.gradle的相关内容,查找是否有对应的Task,比如这里的build。执行构建时,首先要解决依赖,比如从对应的Maven仓库下载依赖。然后,实际执行相应的构建任务,比如调用javac。这个过程看起来很简单,但是背后的细节还是很多的。构建和依赖管理当我使用CLOC工具统计Gradle工具的源码时,才发现这个工具并不简单。此外,在半潜入源代码后,我发现构建系统相当复杂。一个简单的Java应用分为以下几步:小路。而对于一些非.jar类型的依赖,比如.war,构建工具也支持解析。因此,整体流程是:判断是否有本地依赖,如果没有,则远程获取。如果存在依赖冲突,则解决,否则报错。获取依赖后,根据需要处理依赖。比如Android中的aar包的解压等。合并依赖,编译源码将需要的JavaResources从依赖的Jar中复制到指定的目录中将构建好的产品打包成新的jar包这些都只是表面功夫。为了更好的表达这个过程,需要抽象出一个任务的概念。在这个概念中,任务有输入和输出。比如解析依赖。它的输出是build.gradle文件,输出的是处理后的依赖路径。在编译任务中。它的输入是源代码,输出是一个.class文件。在打包任务中。它的输入是一堆文件夹或文件,输出是一个.jar包。……所以,有了这些基础之后,为了加快构建速度,还需要一个缓存机制。它计算输入和输出,并在两者发生变化时进行编译。否则跳过此任务。而这些只是核心功能。在非核心功能区,还有SDK版本、多入多出等变体。:语法高亮子系统关联与集成跳转引用分析intellisense重构quickfix结构化视图...在本文中,简单回顾一下它与构建系统的关系。IDE和构建系统通常有这种关系:在构建系统中解决任务。比如Gradle提供的任务,或者package.json中的脚本,并显式显示,比如IDEA中的线标记,或者独立的Gradlepannel。执行构建任务。即IDE中的UI绑定了build命令,一个典型的例子就是在IDEA中构建Android应用。动态修改构建系统(可选)。比如IDEA中的更新依赖版本依赖于解析构建系统的DSL并更新对应的DSL。相应地,与构建系统通信的机制有两种:构建API由构建系统提供。比如GradleToolingAPI,在那《Gradle IDEA 的项目模型》里,我们其实介绍了构建系统主动向IDE提供模型的方式。构建系统由IDE构建。就像IDEA如何处理Node.js一样。简单来说,复杂的系统应该由构建系统提供,而简单的构建系统不应该有这样的问题。依赖管理基础设施不同的语言有不同的依赖管理机制,但它们的原理是相似的:源码包。源码以特定格式打包发布,适合脚本语言仓库源码。方法与源码包类似,唯一不同的是使用了版本管理工具,如Golang。类二进制包。通常是其他Java包。例如,Maven可以支持其他自制包。最有意思的是Maven的机制。我可以制作自己的依赖项并上传它们。而整个仓库并不关心这个包的内容,我们只需要依赖它定义的格式即可。如果我们考虑围绕该语言设计一个依赖管理系统,我们可以用类似的方式来思考,借助像Git这样的版本工具。这样,我们就可以去中心化。本文转载自微信?「phodal」,可通过以下二维码关注。转载本文请联系phodal公众号。