Pregunta

Soy un novato en C

Escribo mucho código en lenguajes dinámicos (javascript, python, haskell, etc.), pero ahora estoy aprendiendo C para la escuela de posgrado y no tengo idea de lo que estoy haciendo.

El problema

Originalmente estaba compilando todo mi código fuente en un directorio usando un archivo MAKE, que funcionó bastante bien.Sin embargo, mi proyecto está creciendo y me gustaría dividir el código fuente en varios directorios (pruebas unitarias, utilidades, núcleo, etc.).Por ejemplo, mi árbol de directorios podría verse así:

.
|-- src
|   |-- foo.c
|   |-- foo.h
|   `-- main.c
`-- test
    `-- test_foo.c

test/test_foo.c usa ambos src/foo.c y src/foo.h.Usando archivos MAKE, ¿cuál es la mejor forma/estándar de construir esto?Preferiblemente, habría una regla para construir el proyecto y otra para construir las pruebas.

Nota

Sé que hay otras formas de hacer esto, incluida autoconf y otras soluciones automáticas.Sin embargo, me gustaría entender qué está sucediendo y poder escribir los archivos MAKE desde cero a pesar de su posible impracticabilidad.

Se agradecería cualquier orientación o consejo.¡Gracias!

[Editar]

Entonces las tres soluciones dadas hasta ahora son las siguientes:

  • Coloque los archivos de encabezado utilizados globalmente en paralelo include directorio
  • utilizar el camino en el #include saciedad como en #include "../src/foo.h"
  • utilizar el -I cambiar para informar al compilador de las ubicaciones de inclusión

Hasta ahora me gusta el -I solución de cambio porque no implica cambiar el código fuente cuando cambia la estructura del directorio.

¿Fue útil?

Solución

Para test_foo.c sólo hay que indicar al compilador donde los archivos de cabecera se pueden encontrar. P.ej.

gcc -I../src -c test_foo.c

A continuación, el compilador también buscará en este directorio para encontrar los archivos de cabecera. En test_foo.c se escribe a continuación:

#include "foo.h"

Editar : Para enlazar contra foo.c, en realidad contra foo.o, es necesario mencionar que en la lista de archivos objeto. Asumo que ya tiene los archivos de objetos, a continuación, hacer después de eso:

gcc test_foo.o ../src/foo.o -o test

Otros consejos

También rara vez utilizan las autotools de GNU. En su lugar, voy a poner un solo archivo MAKE hechos a mano en el directorio raíz.

Para obtener todas las cabeceras en el directorio de origen, usar algo como esto:

get_headers = $(wildcard $(1)/*.h)
headers := $(call get_headers,src)

A continuación, puede utilizar el siguiente para hacer que los objetos-archivos en el directorio de prueba dependerá de estos encabezados:

test/%.o : test/%.c $(headers)
    gcc -std=c99 -pedantic -Wall -Wextra -Werror $(flags) -Isrc -g -c -o $@ $<

Como se puede ver, no soy un fan de directivas incorporadas. También tenga en cuenta el interruptor -I.

Obtener una lista de archivos de objeto para un directorio es un poco más complicado:

get_objects = $(patsubst %.c,%.o,$(wildcard $(1)/*.c))
test_objects = $(call get_objects,test)

La siguiente regla haría que los objetos para sus pruebas:

test : $(test_objects)

La regla test no sólo debe hacer los archivos de objetos, pero los ejecutables. Cómo escribir la regla depende de la estructura de las pruebas:. Por ejemplo, se podría crear un archivo ejecutable para cada archivo .c o simplemente uno solo que pone a prueba todos los

Una forma común de hacer esto es para los archivos de cabecera utilizados por un solo archivo de C que se nombrará el mismo que el archivo C y en el mismo directorio y los archivos de cabecera utilizada por muchos archivos C (especialmente los utilizados por el todo proyecto) para estar en un include directorio que es paralelo al directorio de origen C.

Su archivo de prueba solo debe incluir los archivos de cabecera directamente utilizando rutas relativas, por ejemplo:

#include "../src/foo.h"
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top