הבלוג של ארתיום :: C++‎‏ http://artyom.cppcms.com/ בלוג על לינוקס, תוכנה חופשית, מוזיקה, סלסה, ומה לא! לחבר שני תחביבים http://artyom.cppcms.com/post/338 http://artyom.cppcms.com/post/338 <div style="direction:rtl"> <p>אני חובב אסטרונומיה. בתור חובב אסטרונומיה אני סובל ואחת הבעיות הגדולות של העולם המודרני - זיהום אור. יש המון גרמי שמיים חיוורים כמו גלסקסיות וערפיליות שפשוט לא ניתן לראות מהעיר. בשביל זה צריך לנסוע לנגב או לרמת הגולן ולבלות לילה בתצפית. זה מאוד כיף כמובן. אבל זה לא תמיד נגיש.</p> <p>אחד המעקפים לבעיה זה שימוש בצילום. מצלמה שיכולה לאגור פוטונים מגלקסיות מרוחקות ומאפשרת לחדור דרך שכבת זיהום אור כבדה ולהראות לנו גרמי שמיים עמומים. זה כמובן לא תחליף לצפייה ישירה אבל גם נותן יתרונות רבים אחרים. במובן, צילום אסטרונומי הוא נושא מורכב שדורש שימוש בתוכנות ייעודיות: איסוף תמונות רבות ככל הניתן, ועיבוד שלהם (הערמה) כדי לקבל תמונה יפה של איזו ערפיליות או גלקסיה.</p> <h2>אמרנו לינוקס?</h2> <p>אז מה המצב התוכנה בתחום זה מבחינת תוכנה חופשית ולינוקס? יש ויש. חלק הארי של הכלים הם חופשיים/קוד־פתוח. יש לא מעט תוכנה ללינוקס, אם כי הדברים הטובים ביותר רצים על חלונות. רוב הדרייברים של המצלמות דווקא סגורים. אבל לרוב יש גרסאות לינוקס, Raspberry PI ועוד.</p> <p>עכשיו, בצילום אסטרונומי יש נדבך חשוב שמעניין אותו במיוחד: Electronically Assisted Astronomy או EAA בקיצור. פירושו ביצוע כל הפעולות הנדרשות לצילום (כולל עיבוד, איסוף תמונות והערמה) בזמן אמת, כאשר עם כל תמונה חדשה של האובייקט, אתה מקבל את התמונה הסופית המשופרת יותר ויותר. המטרה של EAA בניגוד לצילום, לא להגיע לתמונה הטובה ביותר אפשרית, אלא להגיע לתמונה שמספיק טובה כדי לראות את האובייקט ולהנות ממנו.</p> <p>למעשה, במקום לצפות באובייקט דרך עינית, צופים בו דרך המסך. ובניגוד לצילום אסטרונומי שיכול להמשך שעות ארוכות, מסתפקים בזמן איסוף כולל קצת יחסית - מעשרות שניות עד דקות בודדות - כי המטרה לראות ולעבור לאובייקט מעניין הבא. מה מצב התוכנה פה? אם בצילום היה מאתגר בלינוקס, פה המצב קשה. יש מעט מאוד פתרונות ולא כולם עובדים ונוחים.</p> <p>הבעיה השניה, מבחינתי, זה ש־EAA דורשת לרוב להביא מחשב נייד לשטח כדי להפעיל את כל התוכנה המסובכת הזו. למעשה, אם תצפיתן שצופה ויזואלית יכול להביא איתו תיק אחד ובו טלסקופ, חצובה וכמה עיניות, צלם צריך להביא איתו לשטח: חצובה ממונעת, עשרות כבלים, מחשב, ספק כוח שיספיק למספר רב של שעות ועוד. הקמה וקיפול של הציוד לצילום יכולים לקחת בקלות בין חצי־שעה ולשעה בניגוד לצופים בעין - העושים הכל במספר דקות בודדות.</p> <p>אבל לרובינו יש כבר מחשב די חזק ונייד: טלפון או טאבלט! לו רק יכולתי לחבר את המצלמה ישירות לאליהם...</p> <h2>אז הרמתי את דגל</h2> <p>בניתי פתרון ל־EAA עבור לינוקס ואנדרואיד ושמו <a href="https://github.com/artyom-beilis/OpenLiveStacker">OpenLiveStacker</a>. והוא בנוי בצורה הבאה:</p> <ul> <li>הקוד כתוב ב־C++‎ עם שימוש ב־OpenCV לצורך עיבוד תמונה</li> <li>הממשק בנוי כ־web interface שמדבר ב־REST עם השרת - מה שמאפשר בניית ממשק בלינוקס ואנדרואיד באותה צורה וגם מקל על גישה מרחוק במקרה והתוכנה רצה על pi. כמובן שהשרת מבוסס CppCMS. מה שמאפשר חיבור קל ונוח בין הקוד שדורש ביצועים הגובהים לממשק משתמש.</li> <li>הדרייברים נטענים דינאמית: <ul> <li>אחד עבור מצלמה גנרית עם פרוטוקול UVC על בסיס libusb/libuvc- שתומך במצלמות רשת או במצלמות כמו SVBony sv105 - אבל הוא מוגבל לצורכים אסטרונומיים</li> <li>דרייבר של ASI ZWO - החברה המובילה בתחום, שעובד מול SDK שלהם. לצערי הדרייבר עצמו הוא קוד סגור, אבל יש להם גרסה לאנדרואיד.</li> <li>דרייבר גנרי שיודע לקרוא קבצים מהספרייה איך שהם מגיעים - מה שמאפשר חיבור לכל מצלמה אחרת דרך כלים קיימים כמו indi/ekos.</li> </ul> </li> <li>לצורך תמיכה באנדרואיד יש אפליקציה קטנה שעוטפת את השרת ומנהלת גישה ל־USB (כי באנדרואיד הכל צריך להיות מסובך)</li> <li>לצורך הקלה על התמצאות יש חיבור לתוכנה פופולרית מאוד בתחום אסטרונומיה: ASTAP שיש לה גם גרסה (קובץ ריצה) לאנדרואיד. הדבר המעניין בתוכנה הזו שהיא כתובה בפסקל! לא חשבתי שאתקל בדבר כזה בימינו.</li> </ul> <h2>מה למדתי?</h2> <ul> <li>בניית אפליקציות אנדרואיד זה די סיוט וזה לא בגלל השפה אלא בגלל שצריך ללמוד פחות או יותר הכל מ־0. מזל שרוב הקוד ניתן לכתוב ב־C++‎.</li> <li>כמעט כל דבר באנדרואיד עובד "קצת שונה". למשל: אין לך ‎/tmp, להריץ exe חיצוני זה סיפור שעלה לי בלילה לבן, להביא קבצים עם אפליקציה זה גם לא משהו טריוויאלי. בקיצור. זה לינוקס, אבל לא בדיוק.</li> <li>אני שונא לעבוד עם קוד סגור. אומנם ASI ZWO משחררים דרייברים לאנדרואיד, אבל הם גם הכניסו <a href="https://bbs.astronomy-imaging-camera.com/d/16038-asi-zwo-android-sdk-critical-bugs">באג מעצבן</a> שגורם ל־RTTI לא לעבוד! למעשה כל תכנת החיבור ל־SDK שלהם כתבתי ב־C+-‎ בגלל אי זמינות של RTTI. וזה לא היה משהו מסובך אם הייתי יכול לקמפל את הדרייבר מחדש הבעיה הייתה פשוט נעלמת.</li> </ul> <h2>שורה תחתונה</h2> <p>אבל מה שחשוב, שבשורה תחתונה, יש לי פתרון פשוט - לעבוד עם טאבלט שבקושי צורך חשמל, קל ונוח.</p> <p><img src="https://user-images.githubusercontent.com/14816918/229337011-72031279-8de8-4be0-b1a1-61d592525230.jpeg" width="450" height="400"></p> </div> התקדמות חשובה בתמיכה ב־OpenCL ב־pytorch. http://artyom.cppcms.com/post/337 http://artyom.cppcms.com/post/337 <div style="direction:rtl"> <h2>רקע</h2> <p>היום pytorch היא אחת התשתיות המובילות בעולם למידה עמוקה. יש לה יתרונות רבות, אבל מבחינת המפתח זה קוד איכותי ותיעוד טוב. הקוד כתוב בצורה מאוד מודרנית עם שימוש נכון ביכולות C++‎ מה שמאוד מקל על הפיתוח. אני עובד בתקופה האחרונה על פיתוח מנוע עבור pytorch מבוסס OpenCL כחלופה ל־cuda.</p> <p>כבר כתבתי <a href="http://blog.dlprimitives.org/post/2">בעבר</a> על חשיבות התמיכה ב־OpenCL.</p> <p>אבל בכל זאת אזכיר כמה נקודות מבחינת קהילת תוכנה חופשית וקוד פתוח:</p> <ol> <li>אנחנו זקוקים בתמיכה חוצת פלטפורמה בכרטיסי מסך מיצרנים שונים כמו AMD, Intel וכמובן nVidia.</li> <li>אנחנו זקוקים למימוש האלגוריתמים המרכזיים כקוד פתוח הזמין לכל (ולא כקופסה סגורה ש־nVidia נותנת)</li> <li>אנחנו רוצים לעבוד עם סטנדרטים פתוחים וזמינים כמו OpenCL ולא מימושים ספציפיים של יצרן (כמו cuda).</li> </ol> <p><a href="https://github.com/artyom-beilis/pytorch_dlprim">הפרוייקט ב־github‏</a></p> <h2>אז מה חדש? קלות אינטגרציה!</h2> <p>עם שחרור גרסה 1.13 של pytorch חל שיפור משמעותי ב־out-of-tree-backend. עכשיו הוספת מנוע אימון מבוסס OpenCL היא פשוטה מאוד ולמעשה שאלה של מספר דקות, אפילו בוונידוס העניין יחסית פשוט. המשמעות שאפשר להשתמש במנוע OpenCL בקלות רבה הן בלינוקס והן בווינדוס.</p> <p>מה עם הביצועים? אם משווים מול גרסת cuda/cudnn על אותו ה־gpu מדובר בין 50 ל־70 אחוז ביצועי cuda באימון ובין כ־60 ל־80 באבלואציה (תלוי ברשת כמובן).</p> <p>למרות שהמנוע עדיין ניסיוני וחסרים בו לא מעט פעולות הוא נבדק בהצלחה על עשרות רשתות כמו resnet, mobilenet ורבות אחרות.</p> <p>המנוע עצמו מבוסס על ספריית <a href="https://github.com/artyom-beilis/dlprimitives">dlprimitives‏</a> שאני מפתח במקביל והיא חלופה ל־cuDNN על בסיס OpenCL וגם מנוע חיזוי שעובד עם מודלים בפורמט ONNX - שזה נושא גדול בפני עצמו.</p> <h2>מה המשמעות של זה?</h2> <ul> <li><p>משתמשי AMD יכולים לאמן רשתות. הם לא מוגבלים למספר מצומצם של דגמים ש־rocm תומך בהם או לשימוש בלינוקס בלבד. התמיכה היא גורפת מ־APUים ישנים כמו Stoney Ridge ועד ל־RDNA 2 וגם זה עובד על "חלונות" למי שמעוניין.</p> <p> זו הייתה משימה כמעט ובלי אפשרית עד היום. עכשיו זה במרחק מספר פקודות</p></li> <li><p>תשתית אימון היא קוד פתוח לגמרי גם אם עובדים עם nVidia (טוב חוץ מהדרייבר שלהם)</p></li> <li>כל מה שצריך זה דרייברי של OpenCL. לא צריך את כל המפלצת של cuda (מי שיצא לו להתקין לשדרג לגלות בעיות תאימות יבין אותי מידי)</li> </ul> <h3>מחפש עזרה...</h3> <p>מישהו יודע איך אפשר לבנות ולפרסם whl לפלטפורמות שונות? רצוי איזה שירות ענן שיעשה זאת? כדי שזה יהיה ממש במרחק של pip install <code>:-)</code></p> </div> CppCMS עובר מ-LGPLv3 ל-MIT http://artyom.cppcms.com/post/320 http://artyom.cppcms.com/post/320 <div style="direction:rtl"> <p>היום עדכנתי רישיון של CppCMS ל-MIT. הגרסה הקרובה 1.2 תשוחרר עם רישיון מעודכן</p> <p>ההחלטה נובעת ממספר סיבות:</p> <ol> <li>רצון להגדיל נתח השוק של CppCMS ולהקל על כניסה של משתמשים חדשים</li> <li>להביא יותר מפתחים לפרויקט</li> </ol> </div> אחרי תקופה ארוכה שוחררה בטא של CppCMS 1.1.0 http://artyom.cppcms.com/post/319 http://artyom.cppcms.com/post/319 <div style="direction:rtl"> <p>אחרי תקופה ארוכה של המתנה שוחררה גרסת בטא 1.1.0 של CppCMS. גרסה זו <a href="http://cppcms.com/wikipp/en/page/cppcms_1_2_whats_new">מכילה המון שיפורים ושיוניים</a>. ביניהם:</p> <ul> <li>תכנון מחדש של application pool לתיקון מספר בעיות מובנות שהיו קיימות בו עד כה</li> <li>API חדש של פעולות non-blocking לשיפור משמעותי בביצועי אפליקציות אסינכרוניות</li> <li>סיכון ועיבוד בזמן העלאה של התוכן (למשל עיבוד או בדיקה של קבצים תוך כדי העלאה)</li> <li>תמיכה משופרת ב-RESTful API</li> <li>מערכת לניהול plugin ושיפורים מערכת תבניות (templates) בהם.</li> <li>אפשרות ניהול session ללא עוגיות (למקרה והמשתמש ממש צריך)</li> <li>שילוב ניהול ה-session מול טכנולוגיות אחרות כולל מימוש עבור PHP, Java Servlet, ASP.Net ו-Python Django</li> <li>שיפורי ביצועים רבים</li> <li>ועוד...</li> </ul> <p>התכנון הוא לבצע בדיקת בטא מהירה, לשחרר 1.2 כגרסה יציבה (גם ככה חלק ניכר מהמשתמשים כבר עובד בענף הפיתוח ב-git).</p> <p>לאחר מכן אני רוצה לעבור לפיתוח בחלקים יותר קטנים ללא השהיות גדולות בין הגרסאות. בהמשך <a href="http://cppcms.com/wikipp/en/page/cppcms_1x_tasks">מתכנון</a>:</p> <ul> <li>ל-1.4 תמיכה מלאה ב-HTTP/1.1, ב-HTTPS ומימוש של websockets</li> <li>ל-2.0 להעביר CppCMS ל-C++11 תוך ניקוי חלק מה-API שילקח מספריה סטנדרטית כמו <code>std::shared_ptr</code></li> </ul> <p>אתם מוזמנים להתנסות בגרסת בטא האחרונה!</p> </div> שילוב בין טכנולוגיות Web שונות ו-CppCMS http://artyom.cppcms.com/post/317 http://artyom.cppcms.com/post/317 <div style="direction:rtl"> <p>כשיש לך מערכת ווב גדולה ומפותחת ואתה צריך להעביר חלקים קריטיים ממנה לטכנולוגיה מהירה יותר (קרי CppCMS) אתה נתקל קודם כל בבעיה הבסיסית - איך לשתף מידע.</p> <p>נתונים גולמיים זה קל - יש מסדי נתונים, יש קבצים - אין פה משהו מסובך, אבל אתה צריך גם לשתף מידע על המשתמש ועל ה-session שלו בין הטכנולוגיות ופה כל אחד ממש את מה שהוא צריך בצורה אחרת. מצד שני זה מאוד חיוני לשתף מידע קריטי כמו זיהוי משתמש בצורה מאובטחת.</p> <p>לכן, יצרתי שכבת תיאמות שמאפשרת לגשת ל-Session של CppCMS מכל שפת תכנות אחרת.</p> <p>בשלב ראשון עדכנתי את המחלקות הקשירות לניהול ה-Session של CppCMS שיוכלו לפעול בצורה בלתי תלויה מהמערכת. <a href="http://sourceforge.net/p/cppcms/code/HEAD/tree/framework/trunk/cppcms/capi/session.h">יצרתי API נקי</a> מבוסס C בלבד כדי שלא יהיו בעיות כמו חריגות (exceptions) האופייניות ל-++C וגם כדי שאפשר היה לטעון את הפונקיות ישירות בעזרת dlopen.</p> <p>אחר כך יצרתי מספר מודולים עבור שפות שונות:</p> <ul> <li>PHP עם שימוש ב-Swig</li> <li>Java/Servlet עם שימוש ב-JNA</li> <li>Python עם שימוש ב-ctypes והתממשקות עם Django (אבל לא מוגבל ל-Django)</li> <li>Asp.Net עם שימוש ב-PInvoke</li> </ul> <p>כמובן זה לא מוגבל אליהם בלבד. אבל לכל שפה חדשה צריך לבנות מעטפת. שקלתי לעשות גם ל-Ruby on Rails אבל ויתרתי לבינתיים כי אין לי ניסיון עם Ruby בכלל, אז שמישהו יתרום בעת הצורך.</p> <p>חייב להגיד לכל טכנולויה היו בעיות משלה... למשל ב-Python היו התנהגויות מוזרות כשניסיתי לבנות מתודות באופן דינאמי, ב-Java/JNA הכל עבר חלק להבפליא. PInvoke שיגע אותי עם חוסר רצון שלו להמיר UTF-8 ל-string ובחזרה (אגב Mono כן עושה זאת בצורה שקופה אבל לא Net. של Windows מתעקש להשתמש בקידוד ANSI). יצירת מודולים עם Swig עבדה לא רע בכלל, אבל נדרשת עוד מעטפת כדי להתאים את הכל בסופו של דבר לשפה עצמה והתנהגותה.</p> <p>ואיך זה נראה</p> <p>PHP:</p> <pre><code>// pool initialization $pool=CppCMS_SessionPool::from_config('cppcms-config.js'); // per request session access $session=$pool-&gt;session(); $session-&gt;load(); $x=0; if($session-&gt;is_set('x')) { $x=$session['x']; } $x=intval($x)+1; $session['x']=$x; $session-&gt;save(); ... </code></pre> <p>Java/Servlet:</p> <pre><code>static SessionPool pool; public void init() throws ServletException { pool = SessionPool.openFromConfig("/path/to/cppcms-config.js"); } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Session session = pool.getSession(); session.load(request); String x="0"; if(session.isSet("x")) x=session.get("x"); x=Integer.toString(Integer.parseInt(x)+1); session.set("x",x); session.save(response); session.close(); ... } </code></pre> <p>Python/Django:</p> <pre><code># Create global pool pool=cppcms.SessionPool('/path/to/cppcms-config.js') # Actual view def home(request): s=pool.session() s.load(django_request=request) v='0' if 'x' in s: v= s['x'] s['x']=str(int(v)+1) response = HttpResponse() s.save(django_response=response) ... </code></pre> <p>C#/ASP.Net:</p> <pre><code>static SessionPool pool; static Example() { pool = SessionPool.FromConfig("cppcms-config.js"); } protected void Page_Load(object sender,EventArgs e) { using(Session s = pool.Session()) { s.Load(Request); string v="0"; if(s.IsSet("x")) v=s["x"]; v = (int.Parse(v) + 1).ToString(); s["x"]=v; s.Save(Response); } ... } </code></pre> <p>אפשר לראות את הקוד והדוגמאות המלאות <a href="http://sourceforge.net/p/cppcms/code/HEAD/tree/framework/trunk/contrib/integration/session/">כאן</a></p> <p>אני עדיין תוהה עם איזו עוד פלטפורמה כדי לעשות אינטגרציה. בסופו של דבר חשובה לי הפשוטות והנוחות של העבודה.</p> </div> כשעפים על מספר מעבדים http://artyom.cppcms.com/post/309 http://artyom.cppcms.com/post/309 <div style="direction:rtl"> <p>לפני כמה ימים <a href="http://thread.gmane.org/gmane.comp.lib.cppcms.user/1633">קיבלתי דיווח</a>, שתוכנה פשוטה שעובדת עם CppCMS עפה ב־FreeBSD כשיוצרים עומס. קיבלתי trace של המחסנית, שהיה נראה חשוד ומוזר. ניסיתי לשחזר... הכל היה תקין.</p> <p>אז הופנית ל<a href="http://sourceforge.net/tracker/?func=detail&amp;aid=3535893&amp;group_id=209965&amp;atid=1011835">דיווח על באג ישן</a> וסגור שנראה כשתי טיפות מים דומה לתעופה הזו. אז הבנתי שבכל זאת מדובר במשהו אמתי. פתחתי VirtualBox, הורדתי image של FreeBSD 9.0/64bit ותוך עשר דקות התחלתי לנסות שוב. ללא הועיל. ואז קיבלתי תוכנה שלדוגמה (טריביאלית לחלוטין) שבאמת עפה!</p> <p>מעמיסים עליה כמה אלפי פניות ומידי פעם אני מקבל תעופה בפניה לאובייקט <code>std::locale</code> - האובייקט שמחזיק מידע על לוקל המערכת ובפרט הקידוד שלה (כדי להוסיף ל־content-type).</p> <p>צללתי פנימה והתחלתי לחפור - זה היה נראה כמו באג שקשור ל־threading, ניסיתי גרסאות קומפיילר שונות ואופציות שונות - תעופה היה קבועה וברורה.</p> <p>עכשיו קצת רקע: אובייקט הלוקל הוא אובייקט מאוד יעיל שמנהל הכל עם reference-counting - כך שבפועל קיים אובייקט יחיד ששומר את המידע - אז התחלתי לעקוב אחריו וגיליתי שאם יוצרים עומס על המערכת, האובייקט לא נמחק - או נמחק מוקדם מידי ומיד אחריו באה התעופה.</p> <p>פה נדלקה לי מנורה אדומה - משהו לא בסדר ב־reference-counting, קרי הוא לא מתבצע בצורה אטומית. הכנתי תוכנית לבדיקה שהעתיקה את האובייקט מיליוני פעמים ממספר חוטים - הכל תקין.</p> <p>נכנסתי עוד יותר פנימה והתחלתי להדפיס את המונה (שהוצאתי בדרך לא דרך כי הוא private) ואכן - הוא ממש לא יציב, הולך וגדל עם הזמן - קרי, קיבלתי אמות - יש בעיה במונה!</p> <p>המשכתי לחפור עוד יותר לעומק והגעתי לקוד שמבצע את עדכון המונה ב־‎<code>libstdc++</code>‎:</p> <pre><code>if (__gthread_active_p()) __atomic_add(__mem, __val); else __atomic_add_single(__mem, __val); </code></pre> <p>כאשר המטרה של הקוד היא - אם אנחנו רצים מחוט אחד - אז אפשר לבצע חיבור פשוט וזול, אחרת מנהלים עדכון מונה בצורה אטומית - נכנסתי עם gdb בקוד לדוגמה וגיליתי:</p> <ul> <li>אם אני לא עושה קישור עם libpthread - הוא תמיד מריץ קוד עבור מערכת עם חוט יחיד.</li> <li>אחרת תמיד מבצע פעולה אטומית.</li> </ul> <p>מה הבעיה? הספרייה שלי קשורה ישירות ב־libpthread, אבל התכנה הראשית לא! בלינוקס זה לא מפריע אבל ב־FreeBSD זה לא עובד!</p> <p>אז הוספתי דגלון ‎<code>-lpthread</code>‎ לתכנה הראשית והבעיה נפתרה ב־100% - המונה הפך ליציב ומתאפס מתי שצריך.</p> <p>כנראה צריך ללכת לחברה ב־FreeBSD או ב־GCC ולפתוח באג: אם התכנה הראשית לא צריכה להפעיל חוטים באופן ישיר זה לא אומר שהספריות לא עובדות עם החוטים!</p> <p>זה גם הסביר לי מדוע אותו באג שנסגר בגלל שלא היה ניתן לשחזר אותו, לא השתחזר - כי הבעיה נפתרה כנראה במקרה ע"י קישור ל־libpthread.</p> <p>כך או אחרת, שמחתי שמצאתי את הבעיה, אפילו שהוא ממש לא הבעיה של ה־framework.</p> </div> כיצד לא לעשות יוניקוד http://artyom.cppcms.com/post/308 http://artyom.cppcms.com/post/308 <div style="direction:rtl"> <p>הסיפורו של הניסיון להדפיס "שלום" במספר שפות במסוף של חלונות.</p> <p><a href="http://blog.cppcms.com/post/105">http://blog.cppcms.com/post/105</a></p> </div> מפתח בארץ ה־IDE http://artyom.cppcms.com/post/296 http://artyom.cppcms.com/post/296 <div style="direction:rtl"> <p>לאחרונה, הייתי צריך לבחון סביבת פיתוח משולבת (IDE) בלינוקס, ולעשות להן השוואה: איזו סביבה היא יותר מתקדמת ונוחה בהקשר של פיתוח ב־C++‎. למרות שאני כותב הרבה קוד, ויצא לי בעבר להשתמש בלא מעט IDE, ביניהם גם Visual Studio וגם KDevelop 3, אני מעדיף לעבוד עם vim, סביבת הפיתוח האולטימטיבית. אבל <code>vim</code> בתור "סביבת פיתוח משולבת" זה לא בדיוק מוכר. יש אנשים שאוהבים IDE... כך שפשטתי שרוולים והתחלתי לבדוק.</p> <p>על הפרק עמדו מספר אופציות:</p> <ul> <li>KDevelop שהיה לי ניסיון איתו בגסראות 3</li> <li>Eclipse שרבים עובדים איתו</li> <li>Netbeans שרבים ממליצים עליו</li> </ul> <p>ומספר IDE נוספים: Anjuta, CodeBlocks ו־CodeLite.</p> <h2>התחלתי מ־KDevelop 4:</h2> <p>בעבר היה לי ניסיון לא רע עם KDevelop 3 והחלטתי לתת לסביבה הזו הזדמנות נוספת. לפני שאני מתחיל את הסיפור, אומר, אחרי כ־20 דקות עבודה התחלתי להרגיש שאני יותר פרודוקטיבי עם KDevelop מאשר עם vim!</p> <p>הסביבה עשתה צעד עצום מאז גרסה 3. השלמה אוטומטית כמעט מושלמת ומהירה, highlighting מעולה וגם tooltips מאוד נוחים שמאפשרים לגשת לכל מקום. שילוב נוח עם CMake, הגדרות פשוטות, התנהגות ברורה, אינטגרציה עם קובצי man ועוד.</p> <p>התחלתי לממש פיצ'ר מסוים עבור <a href="http://art-blog.no-ip.info/sql/cppdb/">cppdb‏</a> ולראשונה הרגשתי שאני מצליח לכתוב קוד מהר יותר ומדויק יותר בהשוואה ל־vim.</p> <p>הסביבה מאוד מהירה ומגיבה בצורה כמעט מידית.</p> <p>מבחינת יכולת הדיבוג, הדבר היחיד שלא הצלחתי למצוא זה כיצד אני מגדיד למשל <code>catch throw</code> - לעצור על זריקת החריגה, בסוף, הפעלתי את זה ישירות דרך מסוף ה־gdb.</p> <p>יחד עם כל היתרונות האלה, היא באה עם חסרון אחד גדול ובלתי נסלח: היא קורסת מידי פעם. תוך כדי העבודה היא עפה לי מספר פעמים. אומנם, לא איבדתי שום דבר, פתחתי אותה מחדש ותוך מספר שניות חזרתי לעבוד בדיוק מאותו מקום, עדיין, בעיניי זה משהו שלא אמור לקרות, נקודה. סימן קריאה!</p> <h2>המשכתי ל־Eclipse</h2> <p>אחרי מעט הגדרות הצלחתי לגרום לו לעבוד עם קובץ Makefile הנוצר ע"י CMake, הגדרתי פרויקט והתחלתי לעבוד.</p> <p>הסביבה עבדה בצורה יפה, לא הרגשתי אטיות מיוחדת, יחד עם זאת, היא לא הגיבה בצורה מספיק מהירה בעיניי. כשהקלדתי <code>foo.‎</code> - אחרי הקלדת הנקודה יש השהיה קטנה עד שהתפריט מופיע. אומנם היא מאוד קצרה, היא עושה הבדל מהותי במהירות הכתיבה שלי.</p> <p>בנוסף, בניגוד ל־KDevelop הוא לא ידע להשלים ערכים תוך כדי הקלדה בצורה לגמרי אוטומטית, למשל אני מתחיל לכתוב <code>my_variable</code> הוא לא מציע לי השלמה אחרי שכתבתי <code>my_va</code> - צריך ללחוץ ctrl-space, אבל בסה"כ הסביבה בהחלט לא רעה ופרודוקטיבית.</p> <p>התרשמתי לטובה מסימון השגיאות בקוד תוך כדי כתיבה, הוא הרגיש לי קצת יותר ברור בהשוואה ל־KDevelop, מבחינת הדיבוג המצב היה דומה לזה של KDevelop.</p> <p>בכל אופן, הרגשתי שזאת סביבה ברמה מאוד גבוהה, אבל קצת אטית.</p> <h2>ניסיתי סביבות "קלות" יותר</h2> <p>אז פתחתי CodeBlocks שרבים ממליצים עליו. ויתרתי עליו די מהר - מבחינתי חוסר אינטגרציה עם כלי בניה חיצוניים הוא "deal-breaker" ובכלל לא התרשמתי ממנה יותר מידי. ניסיתי קצת codelite - גם הוא היה יותר מידי lite לטעמי.</p> <p>לאחר מכן ניסיתי Anjuta, שגם אתה עבדתי בעבר. לא התרשמתי יותר מידי. בפרט, למשל חסרה אפשרות להשלמת הפונקציות של מצביעים חכמים ועוד.</p> <p>גם היא ירדה מהפרק די מהר.</p> <h2>נותרה לי סביבת Netbeans</h2> <p>שמעתי עליה הרבה דברים טובים והמלצות רבות. בעבר יצא לי לנסות אותה אבל ויתרתי עליה כמעט באופן מידי, אחרי שיא המשיכה "ליצור אינדקס" של הפרויקט במשך דקות ארוכות. אבל החלטתי לתת לה סיכוי במחשב החדש.</p> <p>בניגוד לסביבות אחרות שזמינות ישירות ומהמאגרים של Ubuntu, ‏Netbeans לא מופיעה שם, צריך להתקין אותה בנפרד. הורדתי את הגרסה היציבה האחרונה המותאמת לפיתוח C++‎ והתקנתי.</p> <p>פה הייתה לי הפתעה ממש טובה:</p> <ul> <li>אפילו שהיא צרכת הרבה יותר זיכרון מ־eclipse ו־KDevelop הסביבה עבדה מאוד מהר, השלמה אוטומטית כמעט מושלמת ומהירה.</li> <li>אינטגרציה מעולה עם subversion, למשל הצגת diff מאוד נוחה עם אפשרות עריכה ישירה.</li> <li>הגדרות פשוטות</li> <li>אינטגרציה עם CMake (שחסרה ל־eclipse)</li> <li>תפריטים נוחים והגיוניים (ב־eclipse הן היו ממש קטסטרופה)</li> </ul> <p>ועוד</p> <p>ובכלל, הרגשתי שזאת סביבה מאוד פרודוקטיבית, בנויה היטב ויעילה. מה שכן, היא ללא ספק בנויה למחשבים חזקים עם כמויות זיכרון גדולות.</p> <h2>סיכום</h2> <p>אחרי הרבה שנים של עבודה עם vim אני חושב שאתחיל לבחון את הגישה שלי ל־IDE מחדש. כרגע Netbeans היא הבחירה המובילה. הייתי מאוד רוצה לעבוד עם KDevelop אבל אני לא חושב שאוכל לעבוד אתו כל עוד הוא קורס.</p> <p>מבחינתי יציבות ואמינות יותר חשובה מכל פיצ'ר אחר, וכרגע KDevelop לא עונה על הדרישה הבסיסית הזו וחבל.</p> </div> שוחררה גרסת 1.48 של Boost שמכילה Boost.Locale http://artyom.cppcms.com/post/293 http://artyom.cppcms.com/post/293 <div style="direction:rtl"> <p>סוף סוף שוחררה גרסה 1.48 של Boost. אחד הדברים המשמעותיים בה היא שילוב של Boost.Locale - ספריית הלוקליזציה שאני פיתחתי.</p> <p>קישורים:</p> <ul> <li>אתר הפרויקט: <a href="http://www.boost.org">http://www.boost.org</a></li> <li>הודעת שחרור: <a href="http://www.boost.org/users/history/version_1_48_0.html">http://www.boost.org/users/history/version_1_48_0.html</a></li> <li>תיעוד Boost.Locale‏: <a href="http://www.boost.org/libs/locale/index.html">http://www.boost.org/libs/locale/index.html</a></li> </ul> <p>להזכירכם, Boost.Locale פותחה כחלק מפרויקט <a href="http://cppcms.sf.net">CppCMS‏</a></p> </div> כמה מטומטם ה־API יכול להיות http://artyom.cppcms.com/post/291 http://artyom.cppcms.com/post/291 <div style="direction:rtl"> <p>היום בניה לילית נתקעה... מכונה וירטואלית של חלונות לא ירדה.</p> <p>תוך כדי בירור נכנסתי למכונה וגיליתי חלונית עם הודעה בסגנון:</p> <pre><code>The library e:\mingw\lib\libsqlite3.dll is not valid windows library. Reinstalling application may solve the problem </code></pre> <p>אני מכיר את הבעיה שאם אתה מריץ תוכנה שחסר לה dll אז קופצת חלונית. אפשר להבין התנהגות כזו. רק שבמקרה הספציפי הזה: מדובר בטעינה דינאמית של dll עם LoadLibrary...</p> <p><strong>אני מצפה שפונקציה תחזיר שגיאה ולא תציג חלון!</strong> אחרי חיפוש קצר הגעתי לפונקציה <code>SetErrorMode</code>... שמאפשרת "לפתור" את הבעיה. אבל באמת... אם אין dll אז LoadLibrary יחזיר שגיאה אבל אם ה־dll לא ניתן לטעינה תקפיץ חלון?!?!</p> <p>מי האידיוט שתכנן את ה־API הזה... בחלום הרע שלי לא הייתי מצפה להתנהגות כזו!</p> <p><strong>בקיצור:</strong> אם אתם לא חייבים אל תפתחו לחלונות!</p> </div>