㈠ 如何編譯 dotnet/runtime 源代碼
編譯 dotnet/runtime 源代碼的步驟如下:
環境准備:
安裝Python 3:
解決下載問題:
生成和運行編譯命令:
指定編譯框架版本:
驗證編譯結果:
重點注意事項: 編譯過程中可能會遇到由於訪問國外伺服器網速較慢導致的下載問題,需要耐心解決。 確保按照官方文檔和實際需求正確配置編譯環境。 在編譯過程中遇到問題時,查閱相關文檔和社區資源,尋求解決方案。
㈡ 編譯型框架 SvelteJS
在2016年,Svelte框架由Rollup等工具的作者Rich Harris推出,旨在解決React等框架存在的問題,雖然它沒有像其他框架那樣大紅大紫,但從State of JS的統計來看,它一直保持著持久的熱度。本文將深入淺出地介紹Svelte,希望更多人在適合的場景下可以考慮使用它。
Svelte的誕生源於Rich對前端庫和框架的深入思考。他非常欣賞React等框架帶來的更聲明式、低心智負擔的開發方式,這使得前端工程師能夠更好地控制復雜度、提升開發效率和質量。然而,他也敏銳地洞察到了一些不那麼盡如人意之處。
Rich注意到,盡管React、Vue等框架引入了Virtual DOM的概念,從而能夠進行現有DOM與期望DOM的對比,並執行較重的DOM操作以保持兩者一致,但這其實更多是一種實現聲明式、狀態驅動UI開發的手段,並非不可或缺。Virtual DOM的主要問題在於有很多不必要的Diff操作。例如,假設我們有一個React App,點擊一次按鈕後,新舊Virtual DOM對比如下:雖然只有p節點下的文本需要更新,但React實際上會遍歷所有節點,造成不必要的額外開銷。盡管人們可能覺得純粹的JS運算不會有顯著的開銷,但在頁面內容和邏輯足夠復雜的情況下,這個問題會變得更加明顯。因此,React提供了useMemo、useCallback等Hooks來避免一些耗時操作的重復執行或不必要的重復渲染,但這些其實可以視為錯誤設計的副作用,讓開發者需要關注一些本應是實現原理層面的技巧,增加了額外的心智負擔。
那麼,是否有一種新的方式,可以在count變化時僅僅更新引用它的DOM文本節點?如果能夠做到這一點,那豈不是更加響應式?
Rich還質疑了運行時在前端框架中的必要性。React、Angular、Vue等框架都有運行時,用於處理用戶操作或數據請求引起組件狀態變化時的高效更新DOM節點。然而,運行時代碼會被打包到最終產物中。以典型的TodoMVC應用為例,我們來看幾種方案下的JS包體積:如果我們以JavaScript ES6為基準衡量其他方案因為運行時而帶來的額外包體積,那麼Vue大約是10倍,React約為18倍,Angular則接近27倍。誠然,這些優秀的框架為開發者提供了更為便捷和高效的開發方式,而且現在動輒上兆的中大型前端應用比比皆是,幾十K壓縮後的JS包並不是那麼關鍵。不過,退一步想,如果有一個新的方案可以提供與主流框架相媲美的特性,同時最終包體積接近原生JS,那豈不是更好?
基於以上兩點洞見,Rich開始從一個全新的角度理解和思考前端框架:前端框架應該是主要用來結構化想法而非代碼,它們使得應用的復雜度能夠受到合理的控制。如果我們有辦法在提供結構化想法的種種功能的同時,在編譯階段將應用源代碼轉換為接近原生JS實現的最終代碼,那麼就不再需要瀏覽器和源代碼之間的中間抽象層,我們的應用也會運行得更快。
雖然有了一個嶄新的思路,但落實在實現層面還會有眾多挑戰。接下來,我們將簡要介紹Svelte的具體實現。
Svelte採用了模板為先的組件封裝方案,每個組件都存儲在.svelte文件中,語法是HTML的超集。一個示例將前面的計數器App用Svelte重新實現,看起來非常像Vue,組件的JS、CSS、HTML都在同一文件中集中管理。因此,從開發者的角度來看,Svelte的編程方式十分熟悉、自然。選擇模板而非靈活的JSX的原因也體現在這個例子中,編譯器很容易發現結構化的視圖中p元素有一部分文本需要使用count,以及點擊按鈕時需要調用一個回調函數,其他部分都是確定的。因此,只需在count變化時刷新相應的DOM文本節點即可。為了在有一定約束的情況下提供足夠多的功能,Svelte也提供了一系列模板語法。
在介紹Svelte編譯器如何工作之前,我們不妨設想:如果讓我們自己使用原生JS實現上面的計數器App的話,會是什麼樣的呢?一個可供參考的實現如下(暫時忽略CSS)。
Svelte生成的JS結果如下,可以運行的完整示例見NaiveCompiledApp。可以看出,雖然細節上有些許不同,但是整體的代碼結構與我們前面人肉編譯的版本非常相像。令人驚嘆的是,Svelte也能在count變化時精準地更新對應的文本節點,十分高效。這里的回調函數中的$$invalidate可以理解成一種更具效率的數據變更處理機制,具體實現運用了位掩碼(bitmask)來標記臟數據的變數索引,然後安排一個microtask非同步進行批量更新。
此外,除了一些簡單的append、element、set_data等工具方法和SvelteComponent基類以外,最終構建的應用幾乎沒有使用任何額外的框架代碼,所有的框架工作都基本在編譯階段完成,這真所謂是「編譯器即框架」!
在編譯器內部,可以細分為解析模板、分析代碼、構建產物三個步驟。在編譯過程中,Svelte將.svelte文件編譯成一個JS文件和一個可選的CSS文件,這些產物可以在瀏覽器中直接運行。
在介紹完基本原理後,讓我們看下Svelte的具體表現。從生成最終代碼的體積來看,同樣以TodoMVC為例,Svelte代碼的最終體積是:JS包13K,Gzip壓縮後5.3K。以下是與其他框架對照的圖表。Svelte構建JS包的體積是Vue的1/6,React的1/9,Angular的1/12,已經非常接近於原生JS。可以說是非常精巧的。
從運行速度來看,JSFrameworkBenchmark的測試結果如下。從最後一行的加權結果來看,Svelte的性能非常接近原生JS,與同類型編譯型框架Solid以及以快著稱的類React框架Inferno相當,優於Vue、Angular,更是大幅領先React。
了解完基本原理後,我們將介紹幾個常用的進階特性,如顯式聲明響應性。在實際開發中,我們常常遇到一些場景:一個變數依賴了另一個或多個變數,且這種依賴關系非常確定。例如:
得益於編譯器即框架的優勢,Svelte使用$標簽來更為顯式地聲明這類依賴關系,建立更具效率的響應性:依賴的變數有變化則需要重新執行賦值操作。下面是一個示例。
實現這一特性的思路並不復雜:遇到有標簽$的賦值語句時,則在等號右側變數變化的時候執行$$invalidate將左側變數標記為臟數據,進而觸發後續的更新邏輯。進一步地,Svelte還支持使用$標簽來聲明任意變數的依賴關系。
㈢ linux Kbuild詳解系列(3) - Kbuild系統框架概覽
深入探索Kbuild系統框架概覽,揭示其背後機制,本系列博客從本章節開始,逐步揭秘Kbuild系統。Linux內核的Makefile主要用於編譯源碼,生成目標文件,實現內核的簡潔高效編譯。Make和Makefile是Linux下用於編譯工具和配置文件,執行make命令時,系統會自動尋找Makefile文件並按配置進行編譯。Linux內核源碼的編譯採用了擴展的make工具和Makefile,形成kbuild系統,專為內核編譯設計。
Linux內核的編譯文件形式多樣,包括vmlinux、vmlinux.bin、vmlinuz、zImage、bzImage等。Kbuild系統中的Makefile文件分布於各個目錄,對模塊進行分離編譯,降低耦合性,實現靈活的編譯方式。Makefile主要分為五部分:配置文件、模塊編譯、鏈接、模塊排列和鏈接順序。
內核模塊的編譯流程包括將模塊編譯進內核、生成vmlinux鏡像。配置文件控制模塊的編譯行為,通過make的自動推導原則,模塊自動編譯。鏈接順序決定了模塊執行的順序,優先順序相同的模塊按編譯順序依次執行。所有配置為-m的模塊將被編譯為可載入模塊.ko文件。
驅動模塊依賴多個文件時,通過指定依賴文件進行編譯。Makefile中定義的目錄層次關系處理原則是一個Makefile只負責處理本目錄的編譯關系。頂層Makefile中定義的變數如KERNELRELEASE、ARCH、INSTALL_PATH等在編譯內核時發揮關鍵作用。變數定義影響編譯選項、安裝目錄等。
編譯選項在不同版本中進行了調整,如ccflags-y、asflags-y和ldflags-y分別對應編譯、匯編和鏈接時的參數。subdir-ccflags-y和subdir-asflags-y針對本目錄及其子目錄有效。CFLAGS_\$@和AFLAGS_\$@允許為模塊提供單獨的編譯參數。
Kbuild系統中的變數在頂層Makefile中定義,全局有效,影響整個編譯流程。驅動開發者在編譯單一模塊時,頂層Makefile中的變數未被定義,只有調用頂層Makefile後,子目錄的Makefile中才可能被賦值。生成header文件為開發者提供內核介面,便於模塊集成。通過指定DIR目錄和架構,build工具生成對應的頭文件,供開發者使用。
理解Kbuild系統的執行流程是內核開發和維護的關鍵。通過官方文檔和源碼參考,開發者能更深入地掌握Kbuild系統的工作原理,優化內核編譯過程,提升開發效率。本系列博客旨在提供全面的指導,幫助開發者全面了解Kbuild系統框架,實現高效、穩定的內核開發。