Cara menulis D pada ARM

Selamat siang, Habr!


Hari ini saya ingin berbagi pengalaman pengembangan saya untuk komputer mini di linux (RPI, BBB dan lainnya) dalam bahasa pemrograman D. Di bawah luka, instruksi lengkap tentang cara melakukan ini tanpa rasa sakit. Ya, atau hampir ... =)



Mengapa d?


Ketika di tempat kerja tugasnya adalah menulis sistem pemantauan untuk ARM, bahkan sebagai penggemar berat D, saya ragu apakah itu harus diambil sebagai alat utama. Secara umum, saya bukan orang yang aneh, dan saya telah berada di D untuk waktu yang lama, jadi saya pikir itu patut dicoba dan ... tidak semuanya begitu sederhana. Di satu sisi, tidak ada masalah khusus (kecuali satu yang tidak sepenuhnya jelas yang tersisa dengan kedatangan versi baru dari kompiler), di sisi lain, orang yang sedang mengembangkan ARM dapat terus-menerus berpikir bahwa toolkit tidak siap dari kata sama sekali. Terserah Anda.


Toolkit


Saya dapat menyarankan Visual Studio Code dengan plugin D Programming Language dari kawan. WebFreak (Jan Jurzitza). Di pengaturan, Anda dapat mengatur pengaturan Beta Stream untuk selalu memiliki versi terbaru dari serve-d . Plugin itu sendiri menginstal perangkat lunak yang diperlukan.


Struktur umum proyek


Secara umum, ternyata cukup membingungkan (dibandingkan dengan proyek yang biasa pada D), tetapi, menurut saya, itu cukup fleksibel dan nyaman.


 . ├── arm-lib/ |  ├── libcrypto.a |  ├── libssl.a |  └── libz.a ├── docker-ctx/ |  ├── Dockerfile |  └── entry.sh ├── source |  └── app.d ├── .gitignore ├── build-docker ├── ddb ├── dub.sdl ├── ldc └── makefile 

arm-lib - perpustakaan yang diperlukan agar aplikasi kita dapat berfungsi (dikompilasi di bawah lengan)
docker-ctx - konteks untuk merakit gambar buruh pelabuhan
entry.sh - akan melakukan beberapa tindakan tentang setiap peluncuran wadah nanti, tentang yang nanti
dub.sdl - file proyek dalam D, memungkinkan Anda untuk memasukkan perpustakaan pihak ketiga dan banyak lagi
build-docker - skrip pembuatan wadah (dasarnya 1 baris, tapi tetap saja)
ddb - buruh pelabuhan D pembangun - skrip peluncuran wadah (juga satu baris, tetapi sebenarnya lebih nyaman)
ldc - skrip yang memungkinkan Anda memanggil ldc dengan semua parameter yang diperlukan
makefile - berisi resep buatan untuk arm dan x86 dan tindakan tambahan
source/app.d - sumber proyek


Beberapa kata tentang arm-lib .
Ada file yang diperlukan agar vibe berfungsi. Menambahkan file biner ke repositori adalah bentuk yang buruk. Tetapi di sini, untuk menyederhanakan hidup Anda, lebih mudah untuk melakukan hal itu. Anda dapat menambahkannya di dalam wadah, tetapi kemudian untuk sepenuhnya membentuk resep perakitan wadah, Anda harus menyimpan folder arm-lib di dockert-ctx . Rasa dan warnanya ...


Algoritma perakitan umum


 ./ddb make 

  1. ddb memulai wadah, menjalankan skrip entry.sh
  2. entry.sh mengkonfigurasi dub sedikit sehingga menggunakan folder perpustakaan di dalam wadah, yang akan berlokasi di direktori saat ini, yang akan memungkinkan Anda untuk tidak memompa keluar dan mengumpulkan perpustakaan yang digunakan dalam proyek ketika Anda me-restart perakitan
  3. entry.sh akhirnya melewati kontrol ke perintah input ( make di kasus kami)
  4. make pada gilirannya membaca makefile
  5. semua flag untuk kompilasi silang dan direktori build disimpan di makefile , saluran panggilan dub dibentuk
  6. ketika dipanggil ke dub skrip ldc dari direktori saat ini diteruskan sebagai variabel kompilator dan lingkungan ditetapkan
  7. pustaka runtime ditetapkan sebagai dependensi make-up di makefile , yang, jika hilang, dikumpulkan oleh ldc-build-runtime
  8. variabel diteruskan ke skrip dub.sdl dan ke parameter dub.sdl

Isi dari file utama


Dockerfile


Karena kami akan menulis di bawah RPI3, kami memilih gambar dari sistem dasar debian:stretch-slim , di mana gcc-arm-linux-gnueabihf menggunakan versi glibc sama dengan distribusi raspbian resmi (ada masalah dengan fedora, di mana pengelola kompiler silang menggunakan versi glibc terlalu baru untuk glibc )


 FROM debian:stretch-slim RUN apt-get update && apt-get install -y \ make cmake bash p7zip-full tar wget gpg xz-utils \ gcc-arm-linux-gnueabihf ca-certificates \ && apt-get autoremove -y && apt-get clean ARG ldcver=1.11.0 RUN wget -O /root/ldc.tar.xz https://github.com/ldc-developers/ldc/releases/download/v$ldcver/ldc2-$ldcver-linux-x86_64.tar.xz \ && tar xf /root/ldc.tar.xz -C /root/ && rm /root/ldc.tar.xz ENV PATH "/root/ldc2-$ldcver-linux-x86_64/bin:$PATH" ADD entry.sh /entry.sh RUN chmod +x /entry.sh WORKDIR /workdir ENTRYPOINT [ "/entry.sh" ] 

ldc kompiler ldc dari github , di mana ia dikompilasi berdasarkan llvm saat ini.


entry.sh


 #!/bin/bash if [ ! -d ".dpack" ]; then mkdir .dpack fi ln -s $(pwd)/.dpack /root/.dub exec $@ 

Semuanya sederhana di sini: jika tidak ada folder .dpack , lalu buat, gunakan .dpack untuk membuat tautan simbolis ke /root/.dub .
Ini akan memungkinkan Anda untuk menyimpan paket yang diunduh oleh dub di folder proyek.


build-docker, ddb, ldc


Ini adalah tiga file baris tunggal sederhana. Dua di antaranya adalah opsional, tetapi nyaman, tetapi ditulis untuk linux (bash). Untuk windows, Anda harus membuat file serupa pada skrip lokal atau menjalankannya dengan tangan.


build-docker memulai build container (dipanggil sekali, hanya untuk linux):


 #!/bin/bash docker build -t dcross docker-ctx 

ddb meluncurkan wadah untuk perakitan dan melewati parameter (hanya linux):


 #!/bin/bash docker run -v `pwd`:/workdir -t --rm dcross $@ 

Harap dicatat bahwa nama wadah digunakan dcross (nama itu sendiri tidak masalah, tetapi harus cocok di kedua file) dan perintah pwd digunakan untuk Dockerfile direktori saat ini di /workdir (direktori tersebut ditentukan sebagai WORKDIR di Dockerfile ) (dalam kemenangan, tampaknya, Anda perlu menggunakan %CD% ).


ldc mulai ldc , anehnya, saat menggunakan variabel lingkungan (hanya linux, tapi itu dimulai dalam wadah, sehingga tidak perlu diubah untuk membangun di bawah menang):


 #!/bin/bash $LDC $LDC_FLAGS $@ 

dub.sdl


Sebagai contoh, ini akan sangat sederhana:


 name "chw" description "Cross Hello World" license "MIT" targetType "executable" targetPath "$TP" dependency "vibe-d" version="~>0.8.4" dependency "vibe-d:tls" version="~>0.8.4" subConfiguration "vibe-d:tls" "openssl-1.1" 

targetPath diambil dari variabel lingkungan karena dub tidak dapat menentukan bidang resep perakitan dengan platform (misalnya, lflags "-L.libs" platform="arm" akan menambahkan bendera ke linker hanya ketika membangun di bawah lengan).


makefile


Dan inilah yang paling menarik. Bahkan, make tidak digunakan untuk membangun seperti itu, ia memanggil dub untuk ini, dan dub sendiri memantau apa yang perlu dirakit ulang dan apa yang tidak. Tetapi dengan bantuan makefile semua variabel lingkungan yang diperlukan terbentuk, perintah tambahan dieksekusi dalam kasus yang lebih kompleks (membangun perpustakaan di C, mengemas file pembaruan, dll.).


Isi makefile lebih besar dari yang lain:


 #     arm arch = arm # target path -- ,      TP = build-$(arch) LDC_DFLAGS = -mtriple=armv7l-linux-gnueabihf -disable-inlining -mcpu=cortex-a8 #         EMPTY := SPACE :=$(EMPTY) $(EMPTY) LDC_BRT_DFLAGS = $(subst $(SPACE),;,$(LDC_DFLAGS)) ifeq ($(force), y) #        #  , .. dub      FORCE = --force else FORCE = endif ifeq ($(release), y) BUILD_TYPE = --build=release else BUILD_TYPE = endif DUB_FLAGS = build --parallel --compiler=./ldc $(FORCE) $(BUILD_TYPE) $(info DUB_FLAGS: $(DUB_FLAGS)) #     LDC = ldc2 LDC_BRT = ldc-build-runtime #    ldc,    runtime   ARM LDC_RT_DIR = .ldc-rt #  gcc      GCC = arm-linux-gnueabihf-gcc ifeq ($(arch), x86) LDC_FLAGS = else ifeq ($(arch), arm) LDC_FLAGS = $(LDC_DFLAGS) -LL./$(LDC_RT_DIR)/lib -LL./arm-lib -gcc=$(GCC) else $(error unknown arch) endif DUB = TP=$(TP) LDC=$(LDC) LDC_FLAGS="$(LDC_FLAGS)" dub $(DUB_FLAGS) #      .PHONY: all clean rtlibs stat #    all: rtlibs $(DUB) DRT_LIBS=$(addprefix $(LDC_RT_DIR)/lib/, libdruntime-ldc.a libdruntime-ldc-debug.a libphobos2-ldc.a libphobos2-ldc-debug.a) $(DRT_LIBS): CC=$(GCC) $(LDC_BRT) -j8 --dFlags="$(LDC_BRT_DFLAGS)" --buildDir=$(LDC_RT_DIR) \ --targetSystem="Linux;UNIX" BUILD_SHARED_LIBS=OFF # D runtime  ARM rtlibs: $(DRT_LIBS) #      stat: find source -name '*.d' | xargs wc -l clean: rm -rf $(TP) rm -rf .dub $(LDC_BRT) --buildDir=$(LDC_RT_DIR) --resetOnly 

makefile semacam itu memungkinkan Anda membangun sebuah proyek di bawah lengan dan x86 dengan hampir satu perintah:


 ./ddb make ./ddb make arch=x86 #     x86 make arch=x86 #   host    ldc 

File untuk arm masuk ke build-arm , untuk x86 di build-x86 .


app.d


Nah, untuk hidangan pembuka, untuk gambaran lengkap, kode app.d :


 import vibe.core.core : runApplication; import vibe.http.server; void handleRequest(scope HTTPServerRequest req, scope HTTPServerResponse res) { if (req.path == "/") res.writeBody("Hello, World!", "text/plain"); } void main() { auto settings = new HTTPServerSettings; settings.port = 8080; settings.bindAddresses = ["::1", "0.0.0.0"]; auto l = listenHTTP(settings, &handleRequest); scope (exit) l.stopListening(); runApplication(); } 

Semua orang sekarang membutuhkan web =)


Kesimpulan


Secara umum, semuanya tidak begitu rumit seperti yang terlihat pada pandangan pertama, hanya saja pendekatan universal belum siap. Secara pribadi, saya menghabiskan banyak waktu mencoba melakukan tanpa make . Dengan dia, segalanya menjadi lebih sederhana dan lebih bervariasi.


Tetapi Anda perlu memahami bahwa D tidak Go, di D itu kebiasaan untuk menggunakan perpustakaan eksternal dan Anda perlu berhati-hati dengan versi mereka.
Cara termudah untuk mendapatkan perpustakaan untuk lengan adalah menyalinnya dari perangkat yang berfungsi.


Referensi


Berikut ini adalah kode sumbernya. Dalam repositori ini, komunitas berbahasa Rusia secara bertahap mengumpulkan informasi, contoh, tautan.


Ada informasi tambahan di sini, seperti bagaimana membangun untuk YoctoLinux.


Umpan berita dalam VK

Source: https://habr.com/ru/post/id428982/


All Articles