C / C ++. Comment utiliser les ressources d'application intégrées lorsque vous travaillez dans GCC sous Linux

Je voulais en quelque sorte utiliser automatiquement les ressources embarquées Linux. En général, la tâche est la suivante:


  1. Il existe un programme de projet Eclipse en C ++.
  2. Système d'exploitation: Linux Ubuntu. Compilateur: G ++
  3. Le projet utilise des données de fichiers externes: chaînes de localisation, requêtes SQL, images, sons, etc.
  4. Toutes les ressources doivent être incorporées dans le fichier exécutable, car le programme est prévu pour être distribué comme portable.
  5. De plus, je souhaite que le processus soit le plus automatisé possible, car paresse.

Pour commencer, une recherche sur les forums a fourni plusieurs façons possibles de résoudre le problème. Parmi celles jugées les plus universelles, l'idée m'a semblé utiliser le --format=binary « --format=binary » du lieur « ld ». Les messages du forum ont promis à une équipe du formulaire:

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

liera le fichier «my.res» à l'application et créera deux caractères - _binary_my_res_start et _binary_my_res_end , indiquant respectivement le début et la fin des données mêmes qui étaient dans le fichier lié. Par conséquent, l'accès aux données à partir de C ++ pourrait se faire comme ceci:
 extern const uint8_t my_res_start[] asm("_binary_my_res_start"); extern const uint8_t my_res_end[] asm("_binary_my_res_end"); 

Mais ça y était. Nous écrivons tout comme il se doit et le compilateur n'est pas content. Le symbole «_binary_my_res_start» , vous voyez, est introuvable. Eh bien, rien, nm pour nous aider. Nous écrivons la commande suivante:

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

Et nous obtenons:

 _binary__home_unknown_workspace_MyProgramm_res_my_res_sql_end _binary__home_unknown_workspace_MyProgramm_res_my_res_sql_start 

Il s'avère que le nom du symbole inclut le chemin complet vers celui-ci, ce qui, à l'avenir, pourrait nécessiter une réécriture constante du fichier d'en-tête contenant des liens vers des ressources. Le problème est résolu si le script suivant est ajouté à l'événement PostBuild dans les paramètres du projet 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' 

Comment ajouter le script «update_resource.sh», qui se trouve à la racine du projet, à l'événement PostBuild dans les paramètres du projet Eclipse.


Bon. Maintenant, le fichier d'en-tête sera comme neuf à chaque fois, et vous pouvez accéder aux données par les noms des variables qui ne changeront pas à moins que vous renommiez le fichier de ressources lui-même. De plus, ce script calcule la taille de chaque ressource. Non seulement prendre le pointeur au début du pointeur à la fin était un gros problème, mais, néanmoins, c'est plus pratique.

Mais ce n'est pas tout pour l'instant. Après tout, l'ajout de chaque nouvelle ressource à un projet se transformera en une AD en forme. Et ce problème peut également être résolu à l'aide d'un script, uniquement au stade de la liaison:

 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 

Comment remplacer l'appel de l'éditeur de liens standard par un script personnalisé dans les paramètres du projet Eclipse.


  • L' endroit en rouge est marqué dans l'image, où au lieu de la commande standard d'appeler l'éditeur de liens, le chemin vers le script "link.sh" est situé à la racine du projet.
  • Le vert dans l'image est un endroit dans lequel un autre éditeur de liens est ajouté aux paramètres habituels de l'éditeur de liens, qui indique au script l'emplacement du répertoire avec les ressources.
  • De plus , il est important de ne pas oublier d'envelopper les paramètres restants avec des guillemets doubles afin qu'ils ne se brisent pas accidentellement avec des espaces dans le mauvais ordre dans lequel le script les attend.


Super. Désormais, tous les fichiers qui se trouvent dans le sous-répertoire "res" tomberont eux-mêmes dans les ressources lors de chaque assemblage.

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


All Articles