Çok fazla soru işareti var, onları açıklayıcı bi şekilde halledelim.
Alıntı (İbrahim:1470486328):
> İşletim sistemlerinde çalıştırılabilir dosyalar olan uygulamalar (Windows'ta .exe dosyaları mesela) nasıl bu şekilde işletim sisteminde çalıştırılabilir hale getiriliyor? Yani ben C, C++, Pascal vs. derlemeli dillerde kod yazıp derlediğimde arka planda nasıl bir işlem oluyor?
Öncelikle, çeşitli işletim sistemlerinin kendine özgü "executable/çalıştırılabilir" dosya formatı vardır. Örneğin Windows'ta bu PE (https://en.wikipedia.org/wiki/Portable_Executable), Linux'ta (ve Unix benzeri çoğu sistemde) ELF (https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) ve Mac OSX'te de Mach-O (https://en.wikipedia.org/wiki/Mach-O) olmakta.
Derleyicinin işini nasıl yaptığı biraz karışık ve aslında standart kesin bir yolu da yok. Ama genel itibariyle şunları söyleyebiliriz:
Derleyiciler genelde 'front-end' ve 'back-end' modülünden oluşmakta. Front-end kodu okuyup syntatic (yazım) ve semantic (anlam) açıdan doğruladıktan sonra back-end'in kendine özgü düşük seviyeli kod formatına (LLVM IR (http://llvm.org/docs/LangRef.html) gibi) çevirir. Back-end bu kodu alıp üzerinde gerekli optimizasyon vb. işlemler uygulayıp "sembolik makine dili / assembly language (https://en.wikipedia.org/wiki/Assembly_language)" ne çevirir. Ardından sembolik yani okunabilir text şeklindeki bu kod da tam anlamıyla CPU'nun okuyabileceği "binary code / machine instructions" a dönüştürülür. Burada çeşitli dillerin çeşitli derleyicilerinin bazı şeyleri farklı yaptığını bilmekte fayda var.
Misal, C/C++ dili derlenirken her dosya tek tek okunup hepsi için birer "object file" (.obj) oluşturulur. Bu dosyalar binary makine kodlarıyla birlikte diğer dosyalarda bulunan semboller için referanslar barındırır. Örneğin çağrılacak bir fonksiyon başka dosyada bulunuyorsa o fonksiyonun kodları değil de fonksiyonun ismini içerir (ki bu da onun referansı olmakta). Linker (bağlayıcı) ise bütün obj dosyalarını birleştirir: referanslar gerçek adreslerle değiştirilir; makine kodları, statik veriler gibi bir çok şey istenen çalıştırılabilir dosya formatına göre düzenlenip ortaya çalışan bir program çıkarılır.
D diline baktığımızdaysa derleyici kaynak kodun tamamının tek seferde üzerinden geçerek sembolleri çeşitli özellikleriyle birlikte aklında tutarak her dosya için obj oluşturma ve bunları birleştirmek için gereksiz harcanan vakit ve elektriği sağ olsun önlüyor. Emin olmamakla birlikte derleyicinin bütün programı tek obj dosyasına derlediğini tahmin ediyorum. Hatta DMD'nin assembly kodu yada obj dosyası bile oluşturmakla uğraşmayıp bellekte işini bitiriverdiğini okumuştum [citation needed].
Aslında Java ve C# gibi hemen her modern dil de bu tarz iki-geçişli derleme yöntemini kullanmakta. Yani sembollerin fonksiyon içleri vs. kodlar okunmadan mantıksal ağacını oluşturarak ikinci geçişte referanslar anında çözümlenerek (linker'ın uğraştığı olay) kodun derlemesi yapılıyor.
Java ve C# daki ciddi farklılık ise back-end'in kodu "doğal makine dili / native machine language / assembly language" e çevirmek yerine Dalvik / ART (Java), CLR (C#) gibi interpreter'in (yorumlayıcı) anlayabileceği byte-code (https://en.wikipedia.org/wiki/Bytecode) denen kodlara dönüştürmesi. Böylece farklı işlemcili sistemlerde bile tekrar derleme olmadan aynı dosyanın çalıştırılabilmesi mümkün hale geliyor - gerekli interpreter sistemde kurulu olmak şartıyla.
C#'ı Java'dan ayıran bir özellik söz konusu o da Java'da byte-code'lar sürekli yorumlanarak çalışırken C# 'JIT Compiler' (Just In Time) denen bir sistemle byte-code'ları yorumlarken bi yandan da üzerinde çalıştığı makine koduna dönüştürmesi. Bu da kodların gayet hızlı çalışmasını mümkün kılıyor.
Alıntı (İbrahim:1470486328):
> Aslında asıl öğrenmek istediğim durum şu: Android'de yazılan uygulamalar Dalvik veya ART üzerinde çalışıyor. Aslında Android 4.4'den beri Dalvik emülatörünü bırakıp ART kullanmaya başladı ve bildiğim kadarıyla da bu ART direk kodları donanımla bağdaştırıyor. Yani Linux, Windows. Mac OS gibi işletim sistemlerinde bildiğimiz derleme gibi oluyor bildiğim kadarıyla. Sanırım ART'ye derleyici demek doğru olabilir bu durumda. bkz: https://source.android.com/devices/tech/dalvik/.
ART, Dalvik'ten farklı olarak Android'de kurulan uygulamayı üzerinde bulunduğu cihazın işlemcisine göre makine diline çeviriyor böylece hem Java'nın portability'sinden (taşınabilirlik) ödün verilmemiş oluyor (telefonların ne kadar çeşitli işlemcilere sahip olduğunu düşünürsek bu oldukça önemli) hem de ciddi anlamda performans artışı sağlanıyor. Ama bu hemen her şeyin mümkün olduğu C/C++/D gibi native dillere göre hala çok yavaş kalmakta.
Alıntı (İbrahim:1470486328):
> Benim anlamadığım olay ise biz C kodu yazdığımızda bir C derleyicisi ile ya da bir C++ kodunu C++ derleyicisi ile derleyerek Windows, Linux, Mac OS gibi bir sistemde direk program olarak çalıştırıyoruz. Lakin Android işletim sistemine baktığımızda derleyiciler yazdığımız Android uygulamasını ART kullanmadan çalıştıramıyor. Halbuki Linux, Windows gibi sistemlerde sadece o dile ait bir derleyici olması yetiyor. Sormak istediğim asıl soruysa ben C, C++, Pascal, Rust veya D ile yazdığım kodu bu dillere ait bir derleyiciyle derleyip ART olup olmamasına bakmadan direk olarak sistem üzerinde çalıştırabilir miyim?
Android tasarımı gereği tamamen Java'yı temel alacak şekilde geliştirildiği için bütün build tool ve compiler ayarları öntanımlı olarak Java tabanlı apk oluşturmaya çalışır. Her ne kadar kodları C++'la yazıp native derleseniz de aslında builder'ın yaptığı C++'la yazılan kodu Java kodlarından çağırıp başlatacak şekilde apk'ya gömmektir. Yani çakmak gazını C++ oluşturuyor ama kıvılcımı veren çakmak taşı Java oluyor.
Her şeye rağmen Android Linux tabanlı bir sistem olduğundan tabi ki %100 native ELF formatındaki executable dosya da aslında çalıştırılabilir (http://stackoverflow.com/q/9868309/3624513). Ancak buna pek gerek duyacağını sanmıyorum.
Alıntı (İbrahim:1470486328):
> Yani merak ediyorum da niçin Windows, Linux gibi sistemlerde kodları makine koduna derleyip direk olarak çalıştırabiliyoruz da Android gibi işletim sistemlerinde ART gibi araçlara maruz kalıyoruz? Halbuki Linux da, Windows da, Android de, iOS de birer işletim sistemi. Qt C++ kullandığı halde Android'e bir C++ kodu yazıp derleyip APK halinde getirip sonra da apk decompiler araçlarla bu Qt - C++ ile yazılan apk'yı çözdüğümde içerisinde Java kodları oluyor, C++ değil. Buradan da anlaşılan o ki ister Qt C++'da yaz, ister Xamarin C# ile yaz, ister React Native Javascript ile yaz, oluşan apk dosyası çözüldüğünde kodların Java olarak karşımıza çıkması ART vb. sistemlere maruz kaldığını gösteriyor.
Önceki paragrafta da dediğim gibi Android'de saf executable çalıştırmak mümkün ama Android, uygulamaların Java üzerinden çalışacağı varsayılarak tasarlanmış bir sistem. Başka bi deyişle Android uygulama kurucusu uygulamadan Java koduyla giriş yapmasını bekliyor, ondan sonra JNI kullanarak native kodları çağırmak sana kalmış.
C++ vs. dillerde kod yazıp da kodların Java çıkması gibi bi saçmalık söz konusu değil. Ne kadar diğer dillerde de yazılsa apk uygulamayı başlatmaya yarayan minimum Java koduna sahip olmak zorundadır. Yani apk çözüldüğünde çıkan kodlar C++'la yazılan kodun Java'ya çevrilmiş hali değil, sadece C++ kodunu başlatmak için köprü görevi gören kodlardır.
Xamarin/C# (https://www.xamarin.com/platform) (ve tahminimce Javascript) iOS'ta çalışabilmek için native makine koduna derleniyor (bkz: Ahead Of Time (http://www.mono-project.com/docs/advanced/aot/) compilation) ama bu runtime-reflection gibi bazı özelliklerin kullanılmasını engelliyor. Android'de ise tıpkı bilgisayardaki gibi JIT Compiler C# byte-code'larını çalıştırmakta - bunu da muhtemelen JIT Compiler'ı apk'ya gömerek yaptıklarını düşünüyorum.
Alıntı (İbrahim:1470486328):
> Demem o ki Linux, Windows, Mac OS gibi sistemlerde nasıl C++ kodunu bir derleyici ile derleyip direk olarak çalıştırıyorsak Android'de de bu şekilde direk olarak makine koduna dönüştürebilir miyiz?
Uzun lafın kısası, C++ zaten direk makine koduna dönüştürülüyor, gel gör ki Android'in canı Java sevdiği için C/C++/D/Pascal/Assembly dilinden derlenen makine kodları Java kodlarının içine gömülerek çalıştırılıyor.
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]