C / C ++. Cara menggunakan sumber daya aplikasi tertanam saat bekerja di GCC di Linux

Saya ingin entah bagaimana menggunakan sumber daya tertanam Linux, apalagi, secara otomatis. Secara umum, tugasnya adalah ini:


  1. Ada program proyek Eclipse di C ++.
  2. OS: Linux Ubuntu. Kompiler: G ++
  3. Proyek ini menggunakan data dari file eksternal: string pelokalan, kueri SQL, gambar, suara, dll.
  4. Semua sumber daya harus tertanam dalam file yang dapat dieksekusi, karena program ini direncanakan untuk didistribusikan sebagai perangkat portabel.
  5. Selain itu, saya ingin prosesnya seotomatis mungkin, karena malas.

Untuk mulai dengan, pencarian di forum menyediakan beberapa cara yang mungkin untuk menyelesaikan masalah. Di antara yang ditemukan sebagai yang paling universal, menurut saya, saya menggunakan --format=binary " --format=binary " " ld ". Posting forum menjanjikan tim formulir:

 g++ -Wl,--format=binary -Wl,my.res -Wl,--format=default 

akan menautkan file "my.res" ke aplikasi dan membuat dua karakter - _binary_my_res_start dan _binary_my_res_end , yang mengindikasikan, masing-masing, awal dan akhir dari data yang sama yang ada di file yang ditautkan. Oleh karena itu, mengakses data dari C ++ dapat dilakukan seperti ini:
 extern const uint8_t my_res_start[] asm("_binary_my_res_start"); extern const uint8_t my_res_end[] asm("_binary_my_res_end"); 

Tapi itu dia. Kami menulis semuanya sebagaimana mestinya, dan kompiler tidak senang. Simbol «_binary_my_res_start» , Anda lihat, tidak dapat ditemukan. Yah, tidak ada, nm untuk membantu kami. Kami menulis perintah berikut:

 nm MyProgramm |grep -w -o -P -e '_binary_[\w\d_]+' 

Dan kita mendapatkan:

 _binary__home_unknown_workspace_MyProgramm_res_my_res_sql_end _binary__home_unknown_workspace_MyProgramm_res_my_res_sql_start 

Ternyata nama simbol tersebut mencakup seluruh jalur ke sana, yang, di masa depan, dapat mengarah pada kebutuhan untuk menulis ulang konstan file header yang berisi tautan ke sumber daya. Masalahnya terpecahkan jika skrip berikut ditambahkan ke acara PostBuild di pengaturan proyek Eclipse:

 #!/bin/bash OUTPUT=$1/resources.h printf '#ifndef __RESOURCES_H__\n' > "$OUTPUT" printf '#define __RESOURCES_H__\n\n' >> "$OUTPUT" printf '#include <inttypes.h>\n\n' >> "$OUTPUT" SYMBOLS=$(nm NewsParser |grep -w -o -P -e '_binary_[\w\d_]+') >> "$OUTPUT" VAR_SIZES_LIST='' for SYMBOL in $SYMBOLS do VAR_NAME=$(echo $SYMBOL | grep -o -P -e 'res_[\w\d_]+'|cut -c 5-) if [[ -z $(echo $SYMBOL|grep _size) ]] then printf '\textern const uint8_t '$VAR_NAME'[]\tasm("'$SYMBOL'");\n\n' >> "$OUTPUT" else START_VAR=$(echo $VAR_NAME|rev|cut -c 5-|rev)'start' END_VAR=$(echo $VAR_NAME|rev|cut -c 5-|rev)'end' VAR_SIZES_LIST=$VAR_SIZES_LIST$(printf '\\tconst uint64_t '$VAR_NAME'\\t=\\t'$END_VAR' - '$START_VAR';\\n\\n') fi done printf "$VAR_SIZES_LIST" >> "$OUTPUT" printf '#endif\n' >> "$OUTPUT" printf 'File '$OUTPUT' is generated.\n' 

Cara menambahkan skrip “update_resource.sh”, yang merupakan root dari proyek, ke acara PostBuild di pengaturan proyek Eclipse.


Bagus Sekarang file header akan seperti baru setiap kali, dan Anda dapat mengakses data dengan nama variabel yang tidak akan berubah kecuali jika Anda mengubah nama file sumber itu sendiri. Selain itu, skrip ini menghitung ukuran untuk setiap sumber daya. Tidak hanya membawa pointer ke awal dari pointer ke akhir adalah masalah besar, tetapi, bagaimanapun, itu lebih nyaman.

Tapi ini, untuk saat ini, belum semuanya. Lagi pula, menambahkan setiap sumber daya baru ke proyek akan berubah menjadi AD berbentuk. Dan masalah ini juga dapat diselesaikan dengan bantuan skrip, hanya pada tahap penautan:

 FLAGS=$1 OUTPUT_FLAG=$2 OUTPUT_PREFIX=$3 OUTPUT=$4 INPUTS=$5 RESOURCE_PATH=$6 RESOURCES='' for res_file in $(ls $RESOURCE_PATH/*) do RESOURCES=$RESOURCES' '-Wl,$res_file echo ' '$res_file'   ' done g++ $FLAGS $OUTPUT_FLAG $OUTPUT_PREFIX$OUTPUT $INPUTS -Wl,--format=binary $RESOURCES -Wl,--format=default 

Cara mengganti panggilan tautan standar dengan skrip khusus di pengaturan proyek Eclipse.


  • Tempat berwarna merah ditandai pada gambar, di mana alih-alih perintah standar untuk memanggil penghubung, jalur ke skrip “link.sh” terletak di akar proyek.
  • Hijau dalam gambar adalah tempat di mana linker lain ditambahkan ke parameter linker biasa, yang memberi tahu script lokasi direktori dengan sumber daya.
  • Selain itu , penting untuk tidak lupa membungkus parameter yang tersisa dengan tanda kutip ganda sehingga mereka tidak sengaja memecah dengan spasi dalam urutan yang salah di mana skrip menunggu mereka.


Bagus Sekarang semua file yang ada di subdirektori "res" akan dengan sendirinya jatuh ke sumber daya selama setiap perakitan.

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


All Articles