發(fā)避坑指南)
1. 從一個(gè)把工程拷過(guò)去就跑不起來(lái)的下午說(shuō)起那天同事抱著筆記本過(guò)來(lái)找我說(shuō)他把自己電腦上的劍池CDK工程整個(gè)打包發(fā)給了新來(lái)的實(shí)習(xí)生結(jié)果實(shí)習(xí)生那邊一打開(kāi)編譯報(bào)了一屏幕的錯(cuò)不是找不到頭文件就是組件列表里一堆紅叉。文件明明一個(gè)都沒(méi)少連代碼行數(shù)都一模一樣為什么換了臺(tái)電腦就廢了我讓他把壓縮包解壓的位置、他選的workspace路徑、還有組件配置截圖都發(fā)過(guò)來(lái)。三張圖一看,問(wèn)題其實(shí)特別典型:他把代碼放進(jìn)了自己的工作空間里,而工作空間本身就帶著一層看不見(jiàn)的狀態(tài)。這件事讓我意識(shí)到,很多人上手劍池CDK的時(shí)候,把它當(dāng)成一個(gè)能寫代碼的記事本,打開(kāi)就寫,寫完就編譯,從來(lái)沒(méi)認(rèn)真想過(guò)**工作空間(Workspace)和組件(Component)**這兩個(gè)概念到底在背后管著什么。而恰恰是這兩樣?xùn)|西,決定了你的工程能不能在別人的機(jī)器上復(fù)現(xiàn),決定了你換塊芯片時(shí)要不要從頭再來(lái),也決定了你升級(jí)工具之后歷史項(xiàng)目會(huì)不會(huì)突然爛掉。這篇內(nèi)容我想把這兩個(gè)名詞講透,不是念文檔,而是掰開(kāi)揉碎地告訴你:工作空間目錄里那些名字奇怪的文件夾到底是什么、組件為什么不能簡(jiǎn)單理解成庫(kù)、以及在實(shí)際開(kāi)發(fā)里,我們應(yīng)該怎么劃分工作空間、怎么管理組件,才能少踩坑。如果你剛開(kāi)始用劍池CDK做RISC-V或者相關(guān)芯片的開(kāi)發(fā),或者你已經(jīng)用了一陣子但一直被換電腦就崩升級(jí)就報(bào)錯(cuò)折磨,那這篇應(yīng)該能幫你省下不少來(lái)回折騰的時(shí)間。2. 工作空間不是裝項(xiàng)目的文件夾,它是IDE的狀態(tài)倉(cāng)庫(kù)先說(shuō)一個(gè)最容易讓人誤解的點(diǎn):工作空間在劍池CDK里的角色,和項(xiàng)目目錄完全不是一回事。你可以把工作空間理解成一個(gè)總賬本外加辦公桌,它記錄了你打開(kāi)過(guò)哪些工程、每個(gè)工程的編譯配置、你設(shè)過(guò)的斷點(diǎn)、你改過(guò)的字體主題、你連接過(guò)的調(diào)試器參數(shù)。項(xiàng)目代碼只是這張桌子上的一部分東西,剩下大量?jī)?nèi)容是IDE自己的狀態(tài)。2.1 工作空間 元數(shù)據(jù)倉(cāng)庫(kù) 項(xiàng)目容器剛打開(kāi)劍池CDK的時(shí)候,它會(huì)彈出一個(gè)選擇工作空間的對(duì)話框,讓你指一個(gè)目錄。這個(gè)目錄一旦選定,IDE就會(huì)在里面生成一個(gè)隱藏的元數(shù)據(jù)文件夾(通常叫.metadata之類的名字,不同版本可能略有差異)。這個(gè)文件夾里存的不是你的源碼,而是IDE運(yùn)行所需的各種狀態(tài):插件配置、工程索引、搜索歷史、透視圖布局等等。這帶來(lái)一個(gè)很現(xiàn)實(shí)的后果:如果你的工作空間里的元數(shù)據(jù)壞了,哪怕每個(gè)工程的代碼都是好的,整個(gè)CDK打開(kāi)后也可能表現(xiàn)得很奇怪——工程列表是空的、組件配置界面打不開(kāi)、編譯按鈕灰掉。我遇到過(guò)好幾次,同事說(shuō)CDK壞了,結(jié)果一看,是他把工作空間目錄直接從U盤拖到了另一個(gè)盤符,元數(shù)據(jù)里的絕對(duì)路徑失效了,IDE找不到原來(lái)的工程位置,自然一片空白。所以判斷一個(gè)工作空間健不健康,別光看里面有沒(méi)有你的工程文件夾,更要看那個(gè)元數(shù)據(jù)目錄是不是完整、路徑是不是沒(méi)被搬來(lái)搬去。2.2 工作空間目錄里通常躺著哪幾類東西把一個(gè)用了一段時(shí)間的工作空間打開(kāi)看,大致能分成這么幾類內(nèi)容,搞清楚它們的歸屬,后面很多操作你就不會(huì)踩坑:內(nèi)容類型典型表現(xiàn)能不能隨便拷貝說(shuō)明IDE元數(shù)據(jù).metadata一類隱藏目錄不建議記錄插件狀態(tài)、工程索引,與絕對(duì)路徑強(qiáng)綁定工程本體你創(chuàng)建的各個(gè)工程文件夾可以,但要帶配置工程內(nèi)部通常還會(huì)引用組件組件緩存/倉(cāng)庫(kù)組件相關(guān)的目錄看情況有的組件是工程內(nèi)嵌,有的指向公共組件庫(kù)編譯輸出build、output 之類可以刪中間產(chǎn)物,重建即可用戶偏好主題、快捷鍵等可遷移換機(jī)器后重新配置也無(wú)妨我個(gè)人的習(xí)慣是:工作空間只用來(lái)放當(dāng)前正在做的這一批工程,不在里面堆歷史項(xiàng)目。做完的項(xiàng)目我會(huì)導(dǎo)出成獨(dú)立的工程包,歸檔到別的地方去。這樣工作空間的元數(shù)據(jù)不會(huì)越滾越大,打開(kāi)速度也快。2.3 默認(rèn)路徑的選擇:別把工作空間扔進(jìn)同步盤或者系統(tǒng)目錄CDK默認(rèn)會(huì)把工作空間放在用戶目錄下面某個(gè)固定位置。很多人圖省事,一路點(diǎn)下一步,結(jié)果工作空間就落在了桌面同步目錄、或者某個(gè)會(huì)被云盤實(shí)時(shí)同步的文件夾里。這里有兩個(gè)坑:第一個(gè)坑是同步?jīng)_突。元數(shù)據(jù)文件夾里會(huì)頻繁讀寫大量小文件,云盤一邊同步、IDE一邊寫,很容易出現(xiàn)文件被鎖或者版本打架,輕則工程列表錯(cuò)亂,重則元數(shù)據(jù)損壞。第二個(gè)坑是路徑里帶中文或空格。這類Eclipse系工具對(duì)非ASCII路徑的處理歷來(lái)不讓人省心,組件解析、外部工具調(diào)用時(shí)偶爾會(huì)出莫名其妙的問(wèn)題。我的建議很直接:把工作空間放到一個(gè)純英文、無(wú)空格、不在任何同步盤里的本地目錄,比如D:\cdk_ws\這種。路徑短一點(diǎn),出問(wèn)題的概率就低一點(diǎn)。這個(gè)習(xí)慣我保持了幾年,再?zèng)]遇到過(guò)打開(kāi)工程白屏這類玄學(xué)問(wèn)題。3. 切換工作空間點(diǎn)一下很容易,但背后換的是整套狀態(tài)菜單里那個(gè)切換工作空間的選項(xiàng),點(diǎn)起來(lái)和切換一個(gè)標(biāo)簽頁(yè)沒(méi)區(qū)別,但它實(shí)際上是把整個(gè)IDE的上下文換掉了——工程列表、組件配置、編譯環(huán)境、調(diào)試連接,全都跟著變。3.1 切換工作空間到底發(fā)生了什么當(dāng)你從工作空間A切到工作空間B,IDE做的事情大致是:保存A當(dāng)前的狀態(tài)、卸載A里加載的所有工程、然后從B的元數(shù)據(jù)目錄里重新加載工程索引和配置。注意關(guān)鍵詞是重新加載,不是復(fù)制。這解釋了一個(gè)常見(jiàn)困惑:有人以為切換工作空間相當(dāng)于把工程也搬過(guò)去了,結(jié)果切過(guò)去發(fā)現(xiàn)工程列表是空的。原因很簡(jiǎn)單,工程本體還躺在A的目錄里,B的工作空間根本不知道它的存在。想讓工程出現(xiàn)在新的工作空間里,你得通過(guò)導(dǎo)入的方式把它引進(jìn)來(lái)。所以要建立一個(gè)清晰的心智模型:工作空間是視角和狀態(tài),工程是實(shí)體。換視角不會(huì)搬動(dòng)實(shí)體。3.2 多芯片、多項(xiàng)目并行時(shí),工作空間該怎么切分做嵌入式開(kāi)發(fā)經(jīng)常要同時(shí)應(yīng)付好幾條線:一塊板子在調(diào)外設(shè),另一塊在跑協(xié)議棧,還有一個(gè)老項(xiàng)目隨時(shí)要修bug。這時(shí)候要不要給每條線單獨(dú)開(kāi)一個(gè)工作空間?我的經(jīng)驗(yàn)是按工具鏈芯片家族來(lái)切,而不是按每個(gè)工程切。因?yàn)橥活w芯片或同一個(gè)工具鏈版本的項(xiàng)目,共享同一套組件庫(kù)和編譯配置時(shí)最省事;而不同芯片家族、不同工具鏈版本之間,組件和編譯器差異大,混在一個(gè)工作空間里容易互相干擾。舉個(gè)例子,如果你手上既有基于某款RISC-V內(nèi)核的開(kāi)發(fā),又有一個(gè)完全不同架構(gòu)的老工程,那就干脆分成兩個(gè)工作空間,誰(shuí)也別影響誰(shuí)。反過(guò)來(lái),同一顆芯片的五個(gè)工程,放一個(gè)工作空間里切換起來(lái)反而更快,因?yàn)榻M件緩存是共用的。這里有一條我踩過(guò)坑的規(guī)則:不要用一個(gè)工作空間去管需要不同版本同一組件的工程。組件版本沖突是后面第5章要重點(diǎn)講的坑,源頭往往就在這里——為了省事把不該放一起的工程塞進(jìn)了一個(gè)工作空間。3.3 直接拷貝工作空間文件夾,是很多人翻車的起點(diǎn)回到開(kāi)頭那個(gè)同事的故事。他把工作空間整個(gè)拷給了實(shí)習(xí)生,以為這樣最全。但工作空間的元數(shù)據(jù)里記錄了大量絕對(duì)路徑,一旦目標(biāo)機(jī)器的盤符、用戶名、目錄層級(jí)對(duì)不上,IDE就會(huì)像迷路一樣找不到北。更麻煩的是,有些組件如果是以絕對(duì)路徑引用公共組件庫(kù)的,拷貝過(guò)去后引用直接斷掉。正確的遷移姿勢(shì)是遷移工程,而不是遷移工作空間。具體做法我一般這樣操作:在源機(jī)器上把要分享的工程整理好,確認(rèn)它引用的組件都是可獲取的(要么內(nèi)嵌在工程里,要么在組件庫(kù)里有明確版本)。導(dǎo)出成一個(gè)獨(dú)立的工程包,而不是連整個(gè)工作空間一起打包。在目標(biāo)機(jī)器上新建或選一個(gè)干凈的工作空間,再把這個(gè)工程導(dǎo)入進(jìn)去。導(dǎo)入后第一件事不是急著編譯,而是打開(kāi)組件配置界面,確認(rèn)組件列表沒(méi)有紅叉、沒(méi)有缺失提示。這套流程多花五分鐘,能省掉后面一兩個(gè)小時(shí)的排錯(cuò)。而且它對(duì)團(tuán)隊(duì)協(xié)作特別友好——新人拿到工程包,按部就班導(dǎo)入就能跑,不會(huì)一上來(lái)就被環(huán)境問(wèn)題勸退。4. 組件:劍池里真正讓開(kāi)發(fā)提速、也最容易讓人栽跟頭的東西聊完工作空間,來(lái)說(shuō)組件。這是劍池CDK區(qū)別于純寫代碼的編輯器最核心的地方。搞懂組件,你的開(kāi)發(fā)效率會(huì)有一個(gè)臺(tái)階式的提升;搞不懂組件,你會(huì)覺(jué)得這個(gè)IDE到處都是隱藏的坑。4.1 組件不是普通的代碼庫(kù),它帶著一套契約很多人第一反應(yīng)是:組件嘛,不就是把一些函數(shù)打包成庫(kù)讓我調(diào)用。這個(gè)理解只對(duì)了一半。在劍池這種組件化開(kāi)發(fā)框架里,一個(gè)組件除了代碼本身,還包含幾樣關(guān)鍵的東西:接口聲明:它對(duì)上層暴露哪些API、需要下層提供哪些能力。配置項(xiàng):通過(guò)圖形化配置界面暴露給用戶的開(kāi)關(guān)和參數(shù),比如是否啟用某功能緩沖區(qū)開(kāi)多大。依賴關(guān)系:它依賴哪些別的組件,以及依賴的版本范圍。元信息文件:告訴構(gòu)建系統(tǒng)我是誰(shuí)、我怎么被編譯、我要鏈接到哪里。正因?yàn)橛羞@套契約,組件才能被裝配進(jìn)工程,而不是簡(jiǎn)單粗暴地拷文件。你可以把它類比成樂(lè)高積木:每塊積木的凸點(diǎn)和凹槽尺寸都是標(biāo)準(zhǔn)化的,所以能自由拼裝;如果只是把一堆形狀各異的木頭堆在一起,那就拼不起來(lái)。組件的那套元信息和接口聲明,就是積木的凸點(diǎn)凹槽。理解了這一點(diǎn),你就能明白為什么直接手動(dòng)把某個(gè)組件的源文件拷進(jìn)工程目錄、然后改改頭文件路徑這種土辦法,往往能編譯過(guò)但運(yùn)行起來(lái)一塌糊涂——因?yàn)闃?gòu)建系統(tǒng)并不知道這個(gè)組件的存在,配置項(xiàng)沒(méi)生效,依賴也沒(méi)被拉進(jìn)來(lái)。4.2 組件是怎么被組織進(jìn)項(xiàng)目的:從組件庫(kù)到工程目錄在劍池CDK里創(chuàng)建或?qū)牍こ虝r(shí),一般會(huì)經(jīng)過(guò)一個(gè)選芯片/板級(jí)包→選組件的流程。你勾選需要的組件后,IDE會(huì)根據(jù)組件的元信息,把相應(yīng)的源碼、配置、以及生成的配置頭文件鋪設(shè)到工程目錄中。這里有個(gè)細(xì)節(jié)值得注意:組件在工程里的呈現(xiàn)形式,可能是引入引用,也可能是復(fù)制實(shí)體,還可能是生成中間配置。不同來(lái)源的組件處理方式不一樣。比如來(lái)自公共組件庫(kù)的組件,很多時(shí)候是以引用的形式掛進(jìn)來(lái)的,真正的源碼放在組件庫(kù)那邊;而某些板級(jí)相關(guān)的組件,可能是直接復(fù)制到工程內(nèi)的一個(gè)目錄里。為什么要區(qū)分這個(gè)?因?yàn)樗苯記Q定了改代碼會(huì)不會(huì)被覆蓋。如果你改的是被引用的公共組件源碼,那你改的是組件庫(kù)里的東西,可能影響其他工程;如果你改的是工程內(nèi)復(fù)制的組件,那升級(jí)或重新配置組件時(shí),你的修改可能被沖掉。改組件之前,先搞清楚你改的是哪一份,這是我在組件開(kāi)發(fā)里最重要的一條心法。4.3 組件配置生成的那套配置頭文件邏輯組件化開(kāi)發(fā)繞不開(kāi)一個(gè)機(jī)制:你在一張圖形化界面上勾勾選選、填填參數(shù),最后這些選擇會(huì)被轉(zhuǎn)換成一個(gè)或多個(gè)配置頭文件(類似xxx_config.h這種),里面是一堆#define宏。上層代碼通過(guò)判斷這些宏來(lái)決定編譯哪段邏輯。這套機(jī)制的好處是配置和代碼分離,你不用去手改代碼里的開(kāi)關(guān)。但它也有副作用:配置一旦生成,就和你的選擇綁定了。如果你手動(dòng)改了這些生成出來(lái)的頭文件,下次再點(diǎn)一次應(yīng)用配置,你的手改就沒(méi)了。我見(jiàn)過(guò)太多人圖快,直接去改生成的頭文件,過(guò)兩天重新配置組件,功能突然不work,回頭查半天才發(fā)現(xiàn)是手改被覆蓋了。所以我養(yǎng)成一個(gè)規(guī)矩:凡是帶自動(dòng)生成字樣的文件,一律不手改;要調(diào)參數(shù),回到配置界面去調(diào)。如果配置界面確實(shí)沒(méi)有你想要的那個(gè)開(kāi)關(guān),那說(shuō)明你需要的是自定義組件,而不是硬改生成文件。5. 組件開(kāi)發(fā)里最常翻車的三種場(chǎng)景,以及怎么繞開(kāi)理論講完,該上實(shí)戰(zhàn)了。下面這三種情況,幾乎每個(gè)用組件化框架的人都會(huì)遇到一次,我把排查思路和解決方式都寫清楚,你可以直接對(duì)照著用。5.1 組件和芯片/板級(jí)包不匹配,拿到手就是一堆編譯錯(cuò)誤最常見(jiàn)的一類報(bào)錯(cuò)是某符號(hào)未定義某寄存器不存在頭文件包含失敗。根源通常是組件的適配層和你選的芯片/板級(jí)包對(duì)不上。組件本身可能是通用的,但它對(duì)具體芯片的訪問(wèn)要靠板級(jí)包提供的那層抽象,兩者版本對(duì)不上,接口就對(duì)不上。排查的時(shí)候我會(huì)按這個(gè)順序走:先確認(rèn)板級(jí)包選對(duì)了沒(méi)有。這是最容易被忽略的一步,很多人換芯片時(shí)忘了同時(shí)換板級(jí)包??唇M件對(duì)板級(jí)包有沒(méi)有版本要求。組件的元信息里通常會(huì)寫明它適配的板級(jí)包版本范圍。確認(rèn)組件列表里沒(méi)有紅叉。如果有,說(shuō)明組件解析階段就沒(méi)通過(guò),先別急著編譯,把紅叉消掉。核對(duì)組件依賴是否齊全。有些組件依賴別的組件,你沒(méi)勾上,它自然編譯不過(guò)。按這個(gè)順序走,大部分拿到手就報(bào)錯(cuò)的問(wèn)題都能定位。我最怕的是有人一看到報(bào)錯(cuò)就去搜索引擎里搜錯(cuò)誤信息,結(jié)果搜到一堆不相關(guān)的答案,越改越亂。先看組件配置界面有沒(méi)有異常標(biāo)記,比搜錯(cuò)誤信息高效得多。5.2 重復(fù)定義和組件沖突:兩個(gè)組件都想管同一件事第二類坑更隱蔽:編譯鏈接時(shí)出現(xiàn)重復(fù)定義符號(hào)重名某個(gè)功能被編譯了兩遍。這通常是因?yàn)閮蓚€(gè)組件提供了同名功能,或者一個(gè)組件被以兩種方式引入。我有一次幫人排查,他加了兩個(gè)來(lái)自不同來(lái)源的組件,都提供了類似的日志輸出功能,結(jié)果鏈接時(shí)報(bào)符號(hào)沖突。解決辦法不是去改源碼,而是在組件配置里關(guān)掉其中一個(gè)的功能開(kāi)關(guān),讓它不參與編譯。這就是組件化的好處——沖突了不用刪代碼,改配置就行。還有一種情況是同一個(gè)組件被引入了兩次:一次是通過(guò)組件庫(kù)引用,一次是手動(dòng)拷了一份進(jìn)工程。這時(shí)候會(huì)出現(xiàn)兩個(gè)同名不同源的組件版本打架。解決辦法是統(tǒng)一到一種引入方式,要么都從組件庫(kù)引,要么都用工程內(nèi)嵌,別混著來(lái)。提示:遇到重復(fù)定義,先別急著刪代碼。打開(kāi)組件配置界面,按提供的功能列一遍,十個(gè)里有八個(gè)能直接看出是哪兩個(gè)組件在搶同一塊地盤。5.3 組件升級(jí)后,你的改動(dòng)去哪兒了第三類,也是最讓人心痛的:你花了兩天改好了某個(gè)組件里的一個(gè)bug,結(jié)果順手把整批組件升級(jí)了一下,改動(dòng)全沒(méi)了,而且因?yàn)槟惝?dāng)時(shí)沒(méi)提交版本管理,連找回都費(fèi)勁。這個(gè)坑的根因在 4.2 節(jié)說(shuō)的引用 vs 復(fù)制上。被引用的組件,你改的是組件庫(kù)里的那份;被復(fù)制的組件,升級(jí)時(shí)會(huì)被新的覆蓋。要改組件,先判斷它是不是會(huì)被覆蓋的那一類。如果會(huì),那就別直接改,而是:把要改的組件固化成工程內(nèi)的一段,讓它不被外部升級(jí)影響;或者把改動(dòng)做成一個(gè)自定義組件,疊加在原組件之上,而不是動(dòng)原組件的源碼;最穩(wěn)妥的,任何對(duì)組件的改動(dòng)都進(jìn)版本管理,升級(jí)前先備份、先對(duì)比。我自己是從手改組件源碼這個(gè)壞習(xí)慣里吃了大虧之后,才徹底改掉,轉(zhuǎn)向能用配置解決的絕不動(dòng)源碼,必須動(dòng)源碼的一定固化和納管。這個(gè)轉(zhuǎn)變雖然一開(kāi)始麻煩,但長(zhǎng)期看省心太多。6. 把工作空間和組件這兩條線串起來(lái)的實(shí)操建議前面拆開(kāi)講了工作空間和組件,但真正在開(kāi)發(fā)里,這兩者是交織在一起的。工作空間決定你在哪兒干活,組件決定你用什么料,兩者配合得好,整個(gè)開(kāi)發(fā)流程才順。6.1 給工作空間定一套自己的目錄規(guī)矩我現(xiàn)在基本上是這么規(guī)劃的:根目錄下一個(gè)總的工作空間目錄,里面按芯片家族或項(xiàng)目線再分幾個(gè)工作空間,比如riscv_wireless、legacy_board這樣。每個(gè)工作空間里只放這條線當(dāng)前活躍的工程。歸檔的項(xiàng)目統(tǒng)一放到工作空間外面的一個(gè)倉(cāng)庫(kù)目錄里,需要的時(shí)候再導(dǎo)入。這樣做的好處是:單個(gè)工作空間的元數(shù)據(jù)體量可控,不會(huì)因?yàn)槎蚜颂鄽v史工程而變得臃腫、打開(kāi)變慢;而且因?yàn)槊總€(gè)工作空間的組件庫(kù)是相對(duì)獨(dú)立、相對(duì)穩(wěn)定的,組件版本沖突的概率也大大降低。6.2 組件的增刪遵循小步驗(yàn)證原則加組件我從來(lái)不一次加一堆。加一個(gè)、配置一下、編譯一次、跑一下,確認(rèn)沒(méi)問(wèn)題再加下一個(gè)。因?yàn)橐坏┏鲥e(cuò),一次加五個(gè)組件你根本不知道是哪個(gè)引起的。這個(gè)小步驗(yàn)證的習(xí)慣,在組件依賴復(fù)雜的時(shí)候尤其救命。刪組件同理,刪之前先看清楚誰(shuí)依賴它。有的組件你看著沒(méi)用,其實(shí)別的組件在依賴它,一刪就鏈?zhǔn)綀?bào)錯(cuò)。組件配置界面一般會(huì)顯示依賴關(guān)系,刪之前掃一眼,能避免很多無(wú)謂的返工。6.3 團(tuán)隊(duì)協(xié)作下,把工作空間約定和組件版本寫進(jìn)文檔最后一點(diǎn)是團(tuán)隊(duì)層面的。新人加入,光給他一份工程包是不夠的,你得告訴他:工作空間該放哪、路徑不能帶中文、要用哪個(gè)版本的組件庫(kù)。否則每個(gè)人的環(huán)境都不一樣,在我這能跑的戲碼會(huì)天天上演。我的做法是在團(tuán)隊(duì)里維護(hù)一份很短的約定:工作空間統(tǒng)一放在D盤一個(gè)固定目錄,純英文路徑;組件只從團(tuán)隊(duì)約定的組件庫(kù)來(lái)源獲取,不各搞各的;任何對(duì)組件的本地修改都要記錄并進(jìn)版本管理;分享工程時(shí)分享工程包,不分享整個(gè)工作空間。這幾條看起來(lái)簡(jiǎn)單,但真正執(zhí)行下去,團(tuán)隊(duì)里環(huán)境問(wèn)題的扯皮能減少一大半。工具本身不復(fù)雜,復(fù)雜的是人和環(huán)境的一致性,把約定定下來(lái),問(wèn)題就少了一大半。寫到這里,關(guān)于劍池CDK的工作空間和組件這兩個(gè)概念,我基本把該說(shuō)的都說(shuō)了。如果你之前一直把工作空間當(dāng)成普通文件夾、把組件當(dāng)成普通代碼庫(kù),希望這幾段能幫你重新建立起準(zhǔn)確的心智模型。工具用得順不順,很多時(shí)候不取決于你代碼寫得多好,而取決于你有沒(méi)有真正理解它在背后替你管著什么。