Giriş
Bu yazı serisinde sizlere nasıl appimage dosyası yapılacağı anlatılacakdır.
İlk bölümde çalıştırılabilir dosyaların sistemden bağımsız çalıştırılması üzerinde durulacaktır. Bu bölümü net bir şekilde anlayabilmeniz için orta düzeyde gnu/linux bilgisine sahip olmalısınız.
Static ve dynamic binary kavramı
Static olarak derlenmiş bir kod herhangi bir ek kütüphaneye ihtiyaç duymadan çalışabilir. Bir dosyanın static olup olmadığını anlamak için ldd komutu ile o dosyaya bakmamız gerekir.
$ ldd /bin/bash linux-vdso.so.1 (0x00007ffc8f136000) libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007ff10adcd000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ff10adc7000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff10ac02000) /lib64/ld-linux-x86-64.so.2 (0x00007ff10af6c000)
Burada görüldüğü gibi dosyamız dynamic olarak derlendiği için bağımlılıkları listelenmektedir. Eğer dosyamız static olarak derlenseydi aşağıdaki gibi bir çıktı elde etmemiz gerekirdi.
$ ldd test.bin not a dynamic executable
libc ve interpreter kavramı
Dynamic olarak derlenmiş bütün dosyalar temelde libc.so.6 ve ld-linux-x86-64.so.2 bağımlılıklarına ihtiyaç duyar. Bu dosyalardan libc.so.6 temel C kütüphanesidir. Bu kütüphane sayesinde program temel işlevlerini yerine getirebilir hale gelir. ld-linux-x86-64.so.2 ise interpreter olup dosyanın ne şekilde çalıştırılacağını belirler. Bir dosyanın hangi interpreter ile çalıştığını bulmak için file komutundan yararlanabiliriz. linux-vdso.so.1 ise kernel tarafından sağlanır ve herhangi bir dosya şeklinde bulunmaz.
$ file /bin/bash /bin/bash: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, stripped
LD_LIBRARY_PATH kavramı
Bir çalıştırılabilir dosyanın bağımlılığı genellikle sistemde kurulu bulunmalıdır. Fakat bazı durumlarda sistem dizinlerinden farklı bir yerde bulunması gerekebilir. Bu gibi durumlarda LD_LIBRARY_PATH çevresel değişkeni tanımlanarak kütüphanenin aranacağı ek dizinin konumu belirtilir.
$ ldd test.bin linux-vdso.so.1 (0x00007ffc1c5c5000) libtest.so => not found libc.so.6 => /lib64/libc.so.6 (0x00007feaab862000) /lib64/ld-linux-x86-64.so.2 (0x00007feaaba76000)
Yukarıdaki örnekte libtest.so dosyası sistemde bulunamadığı için ldd çıktımızda uyarı ile karşılaştık. Şimdi de çevresel değişkenimizi tanımlayarak aynı işlemi tekrar deneyelim.
$ export LD_LIBRARY_PATH=/home/user/test/libs/ $ ldd test.bin linux-vdso.so.1 (0x00007ffe22bbc000) libtest.so => /home/user/test/libs/libtest.so (0x00007f4c97790000) libc.so.6 => /lib64/libc.so.6 (0x00007f4c97583000) /lib64/ld-linux-x86-64.so.2 (0x00007f4c9779c000)
Gördüğünüz gibi kütüphaneyi tanımladığımız dizinde buldu.
Bu şekilde bir dosyanın bütün bağımlılıklarını bir dizine kopyalarsak o dosyayı sistemden bağımsız şekilde çalıştırmamız mümkün olur.
$ ldd /bin/bash linux-vdso.so.1 (0x00007fff2c359000) libreadline.so.8 => /lib64/libreadline.so.8 (0x00007fce1e004000) libtinfo.so.6 => /lib64/libtinfo.so.6 (0x00007fce1dfc5000) libc.so.6 => /lib64/libc.so.6 (0x00007fce1ddcc000) libtinfow.so.6 => /lib64/libtinfow.so.6 (0x00007fce1dd8c000) /lib64/ld-linux-x86-64.so.2 (0x00007fce1e154000) # Şimdi tüm dosyaları libs adındaki bir dizine kopyalayalım. $ mkdir libs $ ldd /bin/bash | cut -f3 -d" " | grep "^/" | sed "s/.*/install & libs\//g" | sh # Bağımlılıkları toplu olarak kopyalamak için yukarıdaki komutu kullanabilirsiniz. $ ls libs libc.so.6 libreadline.so.8 libtinfo.so.6 libtinfow.so.6 # Şimdi çevresel değişkenimizi tanımlayalım. export LD_LIBRARY_PATH=/home/user/test/libs/ $ ldd /bin/bash linux-vdso.so.1 (0x00007ffdeddc6000) libreadline.so.8 => /home/user/test/libs/libreadline.so.8 (0x00007fd9ce7ea000) libtinfo.so.6 => /home/user/test/libs/libtinfo.so.6 (0x00007fd9ce7ab000) libc.so.6 => /home/user/test/libs/libc.so.6 (0x00007fd9ce5b2000) libtinfow.so.6 => /home/user/test/libs/libtinfow.so.6 (0x00007fd9ce572000) /lib64/ld-linux-x86-64.so.2 (0x00007fd9ce926000)
Yukarıdaki örnekte bütün bağımlılıkları sistemdeki konumundan çekip ayrı bir dizine kopyaladık ve bu dizinden kullanmasını sağladık. Burada dikkat ettiyseniz interpreter kopyalamadık. Bunun sebebi interpreter dosyayı çalıştırdığımızda dosya tarafından çağırılır. Bu durumun üstesinden gelmek için interpreter ve çalıştırılacak dosyayı da kopyalayalım ve aşağıdaki gibi çalıştıralım.
$ install /bin/bash ./ $ install /lib64/ld-linux-x86-64.so.2 ./ $ ./ld-linux-x86-64.so.2 --library-path "/home/user/test/libs/" ./bash --version GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu) ...
Artık programımızı herhangi bir sistemde bütün bağımlılıkları ile birlikte çalıştırmamız mümkün hale geldi.
Yazımızın devamına buradan ulaşabilirsiniz.