C Comment gérer la relation #include entre plusieurs fichiers source et créer le fichier Make correct

J’ai de nouveau réédité ma question et cette fois, c’est définitif.

note: le programme fonctionne (merci pour toute l’aide). Mais il rest une certaine confusion sur le fonctionnement réel de la dépendance / des liens. Plus précisément, j’aimerais connaître le processus que le makefile comstack et exécute. (Par exemple, le compilateur commence par regarder main.c, à partir de la ligne 1, qui est main.h, puis dans main.h, à partir de la ligne 1, qui pointe vers function1.h, etc.).

Ma question principale est cependant la suivante: est-il vrai que le compilateur / makefile fonctionne de manière inversée, c’est-à-dire que lorsque le compilateur atteint le dernier arrêt (plus de lien), il a commencé à rassembler le contenu de manière récursive et à le placer dans le fichier object. Et que se passe-t-il si nous avons plusieurs fichiers objects et que la connexion est réticulée? Chaque fichier object doit-il être indépendant l’un de l’autre?

Voici mon résultat final. Je sais que cela fait beaucoup de parties, mais j’ai fait de mon mieux pour les mettre de manière organisée et avec une description ajoutée.

FINALE MAKEFILE / DEPENDENCY

Disposition du fichier

module principal: main.c modules supplémentaires: builder1.c, builder2.c builder1_function.c builder2_function.c fichiers d’en-tête: main.h control.h builder1.h builder2.h builder1_function.h builder2_fonction.h builder1_shared.h builder2_shared.h

1) main.c utilise une fonction primaire de builder1.c et builder2.c

2) builder1_function, builder2_function stockent les fonctions enfant utilisées par la fonction principale dans builder1.c et builder2.c

3) builder1 utilise un ensemble de nouvelles structures, builder2 utilise un autre ensemble de nouvelles structures. Ces structures sont déclarées dans builder1_shared.h et builder2_shared.h.

4) les prototypes de fonctions sont déclarés dans builder1.h builder2.h main.h

5) main.c, builder1.c, builder2.c partagent certaines constantes et utilisent toutes les bibliothèques standard. Ces constantes sont déclarées dans control.h

6) control.h: déclarer les constantes à l’échelle du système

DÉPENDANCE EN-TÊTE

main.c: *include* main.h and *define* system-wide constants (declared in control.h) main.h: *include* all std libs, *include* control.h, *include* builder1.h, *include* builder2.h builder1.c: *include* builder1.h, uses system-wide constants, child functions of builder1, and new structures of builder1, stdlib build1.h: *include* builder1_funcion.h *include* builder1_share.h *include* primary function prototype builder1_function.c: *include* builder1_function.h builder1_function.h: *include* builder1_shared.h *include* child function prototype builder_shared.h: *include* main.h, declare new structure for buidler1 builder2.c: *include* builder2.h, uses system-wide constants, child functions of builder2, and new structures of builder2, stdlib build2.h: *include* builder2_funcion.h *include* builder2_share.h *include* primary function prototype builder2_function.c: *include* builder2_function.h builder2_function.h: *include* builder2_shared.h *include* child function prototype builder_shared.h: *include* main.h, declare new structure for buidler2 

MAKEFILE

 main: main.o builder1.o builder1_function.o builder2.o builder2_function.o gcc -o main main.c builder1.c builder1_function.c builder2.c builder2_function.c -g builder1.o: builder1.c gcc -c builder1.c builder1_function.o: builder1_function.c gcc -c builder1_function.c builder2.o: builder2.c gcc -c builder2.c builder2_function.o: builder2_function.c gcc -c builder2_function.c 

    Les en-têtes fournissent des informations à plusieurs fichiers sources. Si un fichier source ne fournit aucun service à d’autres fichiers, il n’a pas besoin d’en-tête. Cela signifie que main.h n’est peut-être pas nécessaire, mais functions.h est nécessaire. Un en-tête doit contenir le code minimum nécessaire pour permettre aux consommateurs d’utiliser les fonctions (et les variables) définies dans le code source. Tous les autres en-têtes doivent être inclus directement dans le code source (les en-têtes doivent donc être petits, autonomes et idempotents).

    Notez que le fichier source principal correspondant à un en-tête ( main.c pour main.h ou functions.h pour functions.c ) doit inclure l’en-tête en tant que premier fichier inclus. Cela garantit que l’en-tête est autonome; il ne comstackra pas s’il ne l’est pas. Chaque consommateur de services provenant d’un autre fichier source doit inclure l’en-tête correspondant. Chaque fonction non statique (et la variable globale si vous en avez) doit être déclarée dans un en-tête précis; cet en-tête doit être utilisé partout où la fonction (ou la variable globale) est nécessaire.

    Compte tenu de votre problème, il semble que functions.c devrait inclure main.h (et main.h est donc nécessaire).

    Dans votre makefile, vous devriez probablement utiliser:

     OBJECTS = main.o functions.o all: main main: ${OBJECTS} ${CC} -o $@ ${OBJECTS} ${CFLAGS} ${LDFLAGS} ${LDLIBS} main.o: main.h functions.h functions.o: functions.h main.h 

    Voir également:

    • Que sont les variables extern en C?
    • Devrais-je utiliser #include dans les en-têtes?

    #include est une commande de pré-traitement qui n’inclut que du texte – rien de plus complexe ni de plus magique que cela.

    Alors:

    • Si un fichier .c a du code qui utilise une structure, il doit inclure le fichier d’en-tête qui définit cette structure.

    • Si un fichier .c implémente ou appelle une fonction, il doit inclure le fichier d’en-tête décrivant le prototype de cette fonction (il s’agit généralement du fichier d’en-tête qui correspond au fichier .c qui implémente la fonction).

    • si un fichier .c utilise certains types d’appels ou systèmes système, il doit inclure le fichier d’en-tête système correspondant.

    Une fois que vous avez utilisé le concept de #include , vous serez en mesure de structurer vos modules et vos fichiers d’en-tête de manière efficace et élégante, pour une lecture et une maintenance faciles.