包管理器cjpm

一、项目级编译构建能力概述

在软件开发中,一个项目往往会依赖许多不同的软件包,这些软件包可能存在版本差异,管理起来非常复杂。cjpm作为仓颉语言的包管理器,就像是一个贴心的管家,能帮我们处理这些繁琐的事情。它主要提供了两大厉害的功能:自动依赖管理和用户自定义构建,这能让我们的开发过程变得轻松又高效。

二、自动依赖管理
  1. 多版本依赖冲突问题
    在项目里,我们可能会引入不同的模块,这些模块又可能依赖同一个模块的不同版本。就好比我们装修房子,不同的装修团队可能需要不同版本的工具来施工,如果这些工具版本不兼容,就会出问题。看这个例子,我们的项目直接依赖模块A和模块B ,模块A依赖模块C的1.3版本,模块B依赖模块C的1.4版本。要是不处理这种情况,编译的时候就会因为模块C的两个版本打架,导致编译失败,整个项目就没法正常进行了。

  2. cjpm的解决方式
    cjpm会对项目里这些多版本的依赖模块进行仔细的分析。它会像一个聪明的侦探,把工程里所有的依赖关系都查得清清楚楚。然后,它会把相同模块不同版本的依赖进行合并,就好像把不同装修团队需要的工具统一起来,让大家都能用。比如说,对于模块C的不同版本,cjpm会分析之后把它们合并成一个版本来依赖。这样一来,开发者就不用自己去头疼这些依赖冲突的问题啦,只要轻松地执行cjpm build命令,就能完成项目级的构建,把更多的精力放在写代码实现功能上。
    在这里插入图片描述

三、用户自定义构建
  1. 开发者的特殊需求
    在构建仓颉项目的时候,我们可能会有各种各样的特殊需求。就像我们做饭,除了把食材煮熟,还可能要先准备调料、清洗餐具等。比如我们可能需要在编译仓颉代码之前,配置一下环境变量,或者把外部依赖库拷贝到合适的地方;要是项目依赖CFFI源码,还得先把C文件编译好。这些事情虽然和编译代码不是一回事,但也很重要,是项目构建过程中必不可少的部分。

  2. cjpm的实现机制
    cjpm很贴心地允许我们在构建的不同阶段,增加前置或者后置的自定义构建行为。我们可以在build.cj这个文件里定义自己的任务。比如说:
    在这里插入图片描述

  • 编译前自定义处理(pre build):我们可以定义一个函数叫stagePreBuild() ,在这个函数里写我们想在编译前做的事情。假如我们的项目依赖CFFI模块,就可以在里面写exec("cd ${workspace}/cffi && cmake && make install") 。这里的exec函数就像是一个小助手,能帮我们执行系统命令。cd ${workspace}/cffi是说切换到CFFI模块所在的工作空间目录;cmakemake install是编译CFFI模块常用的命令,用来把CFFI模块编译好安装好。
  • 编译后自定义处理(post build):同样的,我们定义stagePostBuild()函数来处理编译之后的事情。要是我们想在编译完之后把CFFI源码删掉,就可以写exec("rm -rf ${workspace}/cffi")rm -rf是删除文件和目录的命令,${workspace}/cffi就是要删除的CFFI源码所在的路径。当我们执行cjpm build命令的时候,cjpm就会先跑去执行stagePreBuild()任务,等编译完成了,再去执行stagePostBuild()任务。这样,我们就能按照项目的具体需求,把构建流程定制得刚刚好,不用再去找其他的构建工具啦。

调试器cjdb

一、源码级调试能力总览

在我们写代码的时候,难免会出现各种各样的错误,这时候就需要调试器来帮忙找出问题。cjdb就是仓颉语言的调试器,它能提供源码级的调试能力,就像一个厉害的医生,能帮我们检查代码里的毛病。它不仅能调试仓颉语言,还能进行跨语言调试,甚至能调试仓颉线程,功能超级强大。

二、跨语言调试
  1. 胶水代码层的处理
    当我们用仓颉语言去调用其他语言(比如C语言 )的函数时,为了让它们能顺利交流,中间会有一些胶水代码。这些胶水代码就像是不同语言之间的翻译员,但是在调试的时候,它们可能会干扰我们找到真正有问题的地方。cjdb调试器很聪明,它在单步调试的时候,能识别出这些胶水代码层。然后它会自己算出目标函数的地址,把那些我们不关心的胶水代码过滤掉。比如说,当仓颉语言调用C函数时,它不会在胶水代码那里浪费时间,而是直接跳到C函数真正的代码部分,让我们能更快找到问题。
    在这里插入图片描述

  2. 单步进入/退出与调用栈展示
    单步操作:在IDE(集成开发环境,就像我们写代码的工作室 )里用cjdb调试的时候,跨语言函数调用的单步进入和退出操作就跟调试普通函数一样简单。就像我们在一个房间里找东西,能一步一步准确地找到我们要的东西。比如在仓颉调用C函数的场景中,我们点击单步进入按钮,调试器就会稳稳地进入C函数的内部,不会走错路。
    在这里插入图片描述 调用栈展示:当程序在跨语言调用的时候停下来(比如遇到了问题或者我们设置了断点 ),cjdb能把多种语言的调用栈自动拼接起来展示给我们看。这就好比我们看一个故事的发展脉络,能清楚地看到从仓颉代码到C代码是怎么调用过来的,函数的调用顺序和上下文都一目了然。这样我们就能更好地理解程序是怎么运行的,更快地找到出错的地方。
    在这里插入图片描述

三、仓颉线程调试
  1. 仓颉线程的特点与挑战
    仓颉语言支持多线程并发编程,就像我们同时做好几件事情一样。在程序执行的时候,仓颉线程和系统线程是M:N的关系(简单理解就是好多个仓颉线程对应好多个系统线程 ),而且仓颉线程的数量往往超级多。但是仓颉线程之间的调用是异步的,啥意思呢?就像好几个人同时给你说话,你很难一下子都听清楚。所以当出现异常的时候,我们没办法像在普通程序里那样,很容易地捕获和处理问题,这就给调试带来了很大的麻烦。

  2. cjdb的解决方案
    在这里插入图片描述
    cjdb调试器针对这个麻烦,给我们提供了好办法。它支持我们对仓颉线程设置断点,断点就像是一个路标,当仓颉线程执行到这个地方的时候,程序就会停下来,我们就可以仔细检查这里的情况。同时,我们还能查看仓颉线程的调用栈。比如说,我们可以用cjthread list这个命令,就能看到仓颉线程的很多信息,像线程ID(就像每个人的身份证号 )、状态(是在运行啊还是暂停啊 ),还有当前在哪个函数里。这样我们就能更清楚地了解多线程程序是怎么运行的,更快地找到问题出在哪里,把程序调试好。

Logo

昇腾计算产业是基于昇腾系列(HUAWEI Ascend)处理器和基础软件构建的全栈 AI计算基础设施、行业应用及服务,https://devpress.csdn.net/organization/setting/general/146749包括昇腾系列处理器、系列硬件、CANN、AI计算框架、应用使能、开发工具链、管理运维工具、行业应用及服务等全产业链

更多推荐