- tmux-rs प्रोजेक्ट लगभग 6 महीनों में C में लिखे गए tmux के पूरे कोड को Rust में पोर्ट करने का काम है
- शुरुआत में C2Rust टूल का इस्तेमाल करके ऑटोमैटिक कन्वर्ज़न की कोशिश की गई, लेकिन आउटपुट की maintainability कम होने के कारण अंततः मैन्युअल कन्वर्ज़न किया गया
- बिल्ड प्रोसेस और Rust-C इंटरऑपरेशन में कई बग और संरचनात्मक समस्याएँ सामने आईं
- goto स्टेटमेंट, macro data structures, yacc parser जैसे C-विशिष्ट पैटर्न को Rust में ले जाने के दौरान खास समस्याएँ और उनके समाधान मिले
- प्रोजेक्ट अभी unsafe Rust पर आधारित है, लेकिन precompile और run के ज़रिए Rust में पूरी तरह माइग्रेट करने का लक्ष्य है
प्रोजेक्ट अवलोकन
- tmux-rs, tmux के पूरे कोडबेस (लगभग 67,000 लाइनों का C कोड) को Rust (लगभग 81,000 लाइनें, comments और blank lines को छोड़कर) में पोर्ट करने वाला प्रोजेक्ट है
- डेवलपर ने इस काम को हॉबी प्रोजेक्ट के रूप में किया और C से Rust में माइग्रेशन के दौरान काफी trial and error और सीखने का अनुभव प्राप्त किया
C2Rust का उपयोग और उसकी सीमाएँ
- मूल रूप से C2Rust नामक ऑटोमैटिक कन्वर्ज़न टूल का इस्तेमाल करके tmux के C कोड को Rust में पोर्ट करने की कोशिश की गई थी
- ऑटोमैटिक कन्वर्टेड कोड की readability कम थी, वह मूल C कोड की तुलना में 3 गुना से अधिक बड़ा हो गया था, और कई अनावश्यक type conversions, constant names के loss आदि के कारण maintainability काफी खराब हो गई
- मैन्युअल refactoring के दौरान अंततः C2Rust के आउटपुट को छोड़ दिया गया और C कोड को रेफ़रेंस बनाकर सीधे Rust में पोर्ट करने के तरीके पर स्विच किया गया
- हालांकि, शुरुआती चरण में C2Rust का इस्तेमाल करके बिल्ड और रन संभव होना प्रोजेक्ट की वैधता और व्यवहार्यता की पुष्टि करने में बहुत मददगार रहा
बिल्ड प्रोसेस डिज़ाइन
- tmux, autotools बिल्ड सिस्टम पर आधारित है और Rust कोड तथा मौजूदा C कोड को static library के रूप में जोड़ा गया
- शुरुआत में Rust library को C binary से लिंक किया गया था, लेकिन जब अधिकांश कोड Rust में पोर्ट हो गया तो संरचना बदलकर Rust binary से C library को लिंक किया गया (
cc crate का उपयोग)
- बिल्ड ऑटोमेशन के लिए build.sh स्क्रिप्ट और
build.rs स्क्रिप्ट लिखी गईं, ताकि ट्रांसलेशन के दौरान भी क्रमिक रूप से बिल्ड जांच संभव हो सके
- header declarations की कमी, function signatures का mismatch जैसी बिल्ड प्रोसेस में बार-बार आने वाली समस्याओं को function स्तर पर चरणबद्ध तरीके से हल किया गया
ट्रांसलेशन के दौरान सामने आए बग के उदाहरण
बग 1: implicit declaration और pointer return
- Rust में कन्वर्ट किए गए function में pointer return type C कोड में implicit declaration के रूप में होने के कारण return value के ऊपरी 4 bytes कटकर गलत तरीके से पास हो रहे थे
- इसका समाधान C पक्ष में सही function prototype जोड़ना था, ताकि compiler सही व्यवहार कर सके
बग 2: struct field type mismatch
- client struct में field type (pointer बनाम integer) की गलत व्याख्या के कारण memory offset calculation बिगड़ गई, जिससे डेटा की गलत व्याख्या और segfault हुआ
- इसे C और Rust दोनों में struct definition को बिल्कुल एक जैसा करके हल किया गया
C-विशिष्ट पैटर्न को Rust में पोर्ट करना
Raw pointer का उपयोग
- C pointers को सीधे Rust references में मैप करना null को स्वीकार करने और initialization guarantee जैसी Rust की safety rules का उल्लंघन कर सकता है
- इसलिए अधिकांश pointer structures को raw pointer (
*mut, *const) के रूप में पोर्ट किया गया और उन्हें केवल unsafe हिस्सों में इस्तेमाल किया गया
goto स्टेटमेंट का हैंडलिंग
- C2Rust, goto के control flow को algorithm के रूप में कन्वर्ट करता है, लेकिन ज़्यादातर मामलों में Rust के labeled block + break और labeled loop + continue से इसे पर्याप्त रूप से लागू किया जा सकता है
macro data structures का पोर्ट
- tmux, intrusive red-black tree और linked list को C macros के रूप में implement करता है
- Rust में Generic trait और custom iterator का उपयोग करके समान interface लागू किया गया (एक ही trait की duplicate implementation की समस्या को dummy type से हल किया गया)
yacc parser conversion
- tmux, configuration file parser के लिए yacc(lex) का उपयोग करता है
- Rust में समान संरचना वाले lalrpop crate का उपयोग करके grammar और actions को लगभग ज्यों का त्यों पोर्ट किया गया, और C lexer के साथ इंटरऑपरेशन के लिए adapter भी लिखा गया
- इस प्रक्रिया में lalrpop की raw pointer support सीमाएँ (जैसे
NonNull<T> का उपयोग) भी सामने आईं
डेवलपमेंट एनवायरनमेंट और टूल्स
- मुख्य रूप से neovim में custom macros का उपयोग करके दोहराए जाने वाले कन्वर्ज़न कार्य किए गए
- उदाहरण:
ptr == NULL → ptr.is_null() / ptr->field → (*ptr).field जैसी mappings हाथ से की गईं
- ऑटोमेशन टूल (Cursor) भी आज़माया गया, लेकिन खोया हुआ या गलत कोड अधिक होने के कारण code review का बोझ बढ़ गया
- उंगलियों की थकान कम करने में कुछ मदद मिली, लेकिन productivity के लिहाज़ से इसकी उपयोगिता सीमित रही
निष्कर्ष और आगे की दिशा
- पूरा कोड सफलतापूर्वक Rust में पोर्ट हो चुका है / version 0.0.1 जारी किया गया है
- C2Rust की तुलना में मैन्युअल कोड कुछ हद तक बेहतर है, लेकिन यह अब भी unsafe Rust पर आधारित है और इसमें कई बग मौजूद हैं
- अंतिम लक्ष्य safe Rust कोड में बदलाव और tmux की सभी सुविधाओं का पूर्ण Rust पोर्ट पूरा करना है
- Rust और tmux में रुचि रखने वाले डेवलपर्स के साथ सहयोग और फ़ीडबैक की उम्मीद GitHub Discussions के माध्यम से की गई है
4 टिप्पणियां
ओह.. लेकिन क्या Rust ज़्यादा हल्का है?
ओ... अच्छा लग रहा है?
tmuxplugins मेंresurectकभी-कभी काफ़ी memory खा लेता है और थोड़ा अजीब तरह से काम भी करता है, इसलिए मैंने उसे हटा दिया था। अबtmux-rsके साथ यह बेहतर होगा या नहीं, यह जानने की जिज्ञासा है।https://rosettalens.com/s/ko/tmux-rs-intro
Hacker News राय
यह सचमुच एक शानदार project log पढ़ने का अनुभव था, और मैं इसके लिए अपनी प्रशंसा व्यक्त करना चाहता हूँ। लेखक की लगातार मेहनत और जिद के लिए गहरा सम्मान है। "बागवानी जैसी, लेकिन segfault ज़्यादा" वाली पंक्ति बहुत गहराई से जुड़ी लगी। ऐसे गंभीर hobby projects से ही अक्सर सबसे ज़्यादा सीख मिलती है।
c2rust वाला हिस्सा खास तौर पर दिलचस्प लगा। मैंने पहले भी language-to-language automatic code converters से इसी तरह के नतीजे देखे हैं। ऐसे tools किसी project को जल्दी bootstrap करने और feasibility साबित करने में बेहद उपयोगी होते हैं, लेकिन आखिरकार वे अक्सर target language के हिसाब से अप्राकृतिक और कुछ खाली-से लगने वाले code पर पहुंचते हैं। इसलिए, चाहे वह तकलीफ़देह रहा हो, manual porting पर जाना सही फैसला लगा। C code की intent को safe और Rust-like code में अपने-आप बदलने की automation की एक सीमा है।
"मज़ेदार bugs" सेक्शन में #2 वाला struct layout mismatch पढ़कर पुराने foreign function interface (FFI) वाले डरावने अनुभव याद आ गए। मैंने भी एक बार C++ और C# के बीच struct packing mismatch के कारण एक हफ्ता बर्बाद किया था, जब subtle data corruption पकड़ने की कोशिश कर रहा था। यह उन bugs में से है जो मानसिक रूप से पागल कर देते हैं। इन्हें ढूंढ़ने के लिए जबरदस्त debugging patience चाहिए। लेखक के लिए ज़ोरदार तालियां।
कुल मिलाकर, यह project core infrastructure code को modernize करने की वास्तविक कठिनाई और प्रक्रिया का बहुत अच्छा case study लगता है। अगला बड़ा लक्ष्य unsafe से safe Rust की ओर जाना है, यह जानकर सचमुच जिज्ञासा हो रही है कि इसकी strategy क्या होगी।
मेरा मानना है कि raw pointer, goto और दूसरे जटिल control flow को idiomatic और safe Rust में बदलना, बिना पूरे codebase को तोड़े, शायद शुरुआती porting से भी ज़्यादा कठिन हो सकता है। क्या वे lifetimes और borrow checker को module-by-module धीरे-धीरे लाने की योजना बना रहे हैं? intrusive data structures को कैसे संभालेंगे, यह भी दिलचस्प है। अगर उन्हें standard library के
BTreeMapजैसी चीज़ों से बदला जाए, तो performance impact हो सकता है; शायद मूल intrusive design का उद्देश्य ही वही रहा हो।खैर, यह अद्भुत काम है। प्रक्रिया को इतने विस्तार से साझा करने के लिए धन्यवाद। मैं GitHub पर project को follow करता रहूंगा।
यह खबर मुझे अपनी ओर खींच रही है।
मैं कुछ सालों से Rust-आधारित tmux session manager rmuxinator (कुछ-कुछ tmuxinator clone जैसा) पर काम कर रहा हूँ। ज़्यादातर चीज़ें ठीक चलती हैं, लेकिन ज़िंदगी व्यस्त रही, इसलिए प्रगति धीमी थी, और इन दिनों मैं फिर से bug fixes पर लौट आया हूँ। हाल में जो feature जोड़ा है, वह rmuxinator को library की तरह इस्तेमाल करने की क्षमता है। मैं tmux-rs को fork करके rmuxinator को dependency के रूप में जोड़ना चाहता हूँ, और देखना चाहता हूँ कि per-project config file से session शुरू करने का तरीका व्यवहार में काम करता है या नहीं। मैं यह नहीं कह रहा कि rmuxinator को upstream में शामिल किया जाए, लेकिन ऐसा session templating feature अगर terminal multiplexer में built-in होता, तो वह सचमुच उपयोगी होता।
उल्टा यह भी सोचता हूँ कि rmuxinator अगर tmux-rs को library की तरह इस्तेमाल करे और shell commands generate किए बिना पूरा session management संभाले, तो शायद और भी बेहतर हो (हालांकि अभी नहीं जानता कि tmux-rs यह support करता है या नहीं)।
जो bug fixes अभी कर रहा हूँ, वे खत्म होते ही ऊपर के ideas में से कम-से-कम एक ज़रूर आज़माऊँगा।
जो भी हो, richardscollin, शानदार काम।
"मैंने tmux को Rust में फिर से क्यों लिखा? कोई खास अच्छी वजह नहीं, बस एक hobby project है। बागवानी जैसी है, लेकिन segfault ज़्यादा हैं।" यह रवैया मुझे बहुत पसंद आया।
कुछ नया बनाते समय हर चीज़ के पीछे कोई बड़ा उद्देश्य या उपयोगिता होना ज़रूरी नहीं है। hobby projects में भी अप्रत्याशित खोजें हो सकती हैं। लेखक की इतनी विस्तृत लिखाई वाकई प्रभावित करती है।
वैसे, मेरे बगीचे में segfault भरे पड़े हैं। मेरे आंगन के लिए नया project code करना शायद ज़्यादा सुरक्षित है।
पूरी तरह सहमत। हर project का मकसद दुनिया बदलना होना ज़रूरी नहीं।
मैंने हाल ही में fzf को Rust में फिर से implement किया था: rs-fzf-clone
इसकी कोई खास वजह नहीं थी; मौजूदा fzf वैसे ही बहुत अच्छा काम करता है। मेरा मुख्य उद्देश्य Rust channels और fuzzy search algorithms को हाथ से समझना था। यह बहुत मज़ेदार learning experience था, और भले ही मूल fzf बेहतर है, वह इस संदर्भ में खास मायने नहीं रखता। असली बात कुछ नया आज़माना और experiment करना था।
"बागवानी दार्शनिक बनने का सबसे अच्छा बहाना है।"
जब कोई यह संकेत देता है कि Rust किसी तरह C से स्वाभाविक रूप से श्रेष्ठ है, तो मेरी पहली प्रतिक्रिया अक्सर सहज संशय की होती है। लेकिन मैं बार-बार भूल जाता हूँ कि लोग ऐसे projects सिर्फ़ मज़े के लिए भी करते हैं।
"हमें कुछ नया बनाने के लिए हमेशा किसी कारण की ज़रूरत नहीं होती" — यह पंक्ति बहुत अच्छी लगी।
हालांकि, tmux खुद कोई नई चीज़ नहीं है।
इससे यह सोचने पर मजबूर होना पड़ता है कि क्या मौजूदा software को सिर्फ़ एक भाषा से दूसरी भाषा में फिर से लिखने के लिए भी कोई कारण होना चाहिए।
"बागवानी जैसी, लेकिन segfault ज़्यादा" यह बहुत मज़ेदार पंक्ति है। मैं अभी Rust से परिचित नहीं हूँ, इसलिए यह जानने की उत्सुकता है कि किन ठोस स्थितियों में unsafe की ज़रूरत पड़ती है।
इस project का रवैया, और ज़्यादातर comments का सकारात्मक माहौल, दोनों बहुत प्रभावशाली लगे।
किसी mature application को दूसरी language में फिर से लिखना हमेशा अच्छा विचार नहीं माना जाता, लेकिन उसे वास्तव में करने की प्रक्रिया में बहुत कुछ सीखने को मिलता है। नतीजे से ज़्यादा प्रक्रिया महत्वपूर्ण है।
यहाँ मिली दिलचस्पी और AI की प्रगति को देखते हुए, यह Rust beginners के लिए एक बेहद आकर्षक hobby project बन सकता है। आसान bugs ठीक करना, नए features जोड़ना या optimization करना — ये सब शानदार अनुभव हो सकते हैं।
एक idea के तौर पर, मैं यह feature देखना चाहूँगा जिसमें Gemini CLI (या आपकी पसंद का कोई LLM) scratch buffer की तरह काम करे और tmux session की अलग-अलग windows/panes के साथ interact करे।
मेरे मामले में, मैं कई servers पर synchronized panes में commands चलाता हूँ और failures वगैरह को हाथ से संभालता हूँ। अगर AI को command execution सौंपा जा सके, और वह real time में output का analysis करके commands को dynamically regenerate करे, तो वह किसी dynamically generated custom shell script जैसा महसूस होगा।
उदाहरण के लिए, मैं रोज़ gvim इस्तेमाल करता हूँ, लेकिन अगर मुझे editor बनाना हो, तो मैं उसे gvim जैसा बनाने के बजाय अपनी पसंद के features वाला कोई नया और रचनात्मक tool बनाना चाहूँगा। अगर इतना समय लगाना ही है, तो मेरे हिसाब से कुछ विशिष्ट और रचनात्मक बनाना ज़्यादा सार्थक है।
मैंने अभी tmux को Fil-C में एक घंटे से कम समय में port करके देखा (libevent port और tests pass कराने सहित)। यह बहुत अच्छी तरह काम करता है और पूरी memory safety देता है।
मुझे ऐसे projects पसंद हैं। मेरा भी Rust में गहराई से उतरने का मन है।
वैसे, मैं zellij (Rust-आधारित terminal multiplexer) का ज़िक्र करना चाहूँगा।
मैं सिर्फ़ एक user हूँ, लेकिन मुझे Rust-आधारित solutions खोजते रहना और उनकी ओर migrate करना अच्छा लगता है।
संयोग से मैं अभी-अभी यह वीडियो "Oxidise Your Command Line" देख रहा था।
https://www.youtube.com/watch?v=rWMQ-g2QDsI
इसमें कुछ बातें शायद Rust developers के अलावा दूसरों के काम की न हों, लेकिन command-line environment से परिचित किसी भी व्यक्ति के लिए इसमें कई उपयोगी tips हैं।
मुझे लगता है कि c2rust में लेखक द्वारा बताए गए information loss, जैसे constant names को बनाए रखना, कम करने के लिए काफी सुधार किए जा सकते हैं। क्योंकि शुरुआती conversion का बोझ बड़ा होता है।
जब वह समय आएगा कि बड़े language models पूरे C code को एक घंटे में, सही तरीके से, अपने-आप Safe Rust में बदल सकें, तब ऐसे projects बहुत भविष्यदर्शी उदाहरण लगेंगे।
हालांकि, लेखक ने भी कहा कि आख़िरी चरण में Cursor से कोशिश करने पर (2025 के मध्य तक) conversion efficiency काफ़ी गिर गई, इसलिए व्यावहारिक प्रदर्शन अभी उस स्तर से काफ़ी दूर लगता है।
codemod.com जैसी जगहों पर इस दिशा में पहले से "codemods" की अवधारणा पर काम हो रहा है।
codemods AST (abstract syntax tree) का उपयोग करके तेज़, बड़े पैमाने पर code transformation और refactoring संभव बनाते हैं।
codemods API refactoring परिचय
"बड़े language models जटिल C code को एक घंटे में पूरी तरह Safe Rust में बदल सकते हैं" — यह बात इतनी ठोस तरह से कही गई कि ध्यान खींचती है।
उम्मीद है कि आगे code और साफ़-सुथरा होता जाएगा। मैंने zellij को कई बार आज़माया है, लेकिन कई साल के development के बाद भी उसमें tmux की कुछ सुविधाएँ अब भी नहीं हैं, जिनकी मुझे आदत है।
खास तौर पर status bar को hide/show न कर पाना सबसे परेशान करने वाली बात है।
zellij-org/zellij issue #694 देखें
जिन key bindings का मैं अक्सर उपयोग करता हूँ, वे session manager plugin की default bindings से टकरा जाती हैं, जिससे directory selection जैसे मुख्य features रुक जाते हैं।
नतीजतन, session creation भी plugin के बजाय command line से ही करनी पड़ती है।