2009-08-07 20 views
5

Me gustaría utilizar make para conseguir una fabricación modular en combinación con continuous integration, prueba de la unidad automática y construye multiplataforma. Configuraciones similares son comunes en Java y .NET, pero me está costando armar esto para make y C/C++. ¿Cómo puede lograrse?makefile perfecto

Mis requisitos:

  • acumulación rápida; no recursivo make (pregunta desbordamiento de pila What is your experience with non-recursive make?)
  • sistema modular (es decir, dependencias mínimas, makefile en el subdirectorio con los componentes)
  • multiplataforma (típicamente PC para la unidad de pruebas, objetivo incorporado para sistema de integración/release)
  • completa comprobación de dependencia
  • capacidad para realizar pruebas de unidad (automático) (ingeniería Agile)
  • gancho en el sistema de integración continua
  • fácil de usar

He comenzado con non-rec make. Todavía me parece un gran lugar para comenzar.

Limitaciones hasta ahora:

  • hay integración de la unidad de prueba
  • de incompatibilidad de las ventanas compiladores ARM base con las rutas de Cygwin
  • incompatibilidad de makefile con Windows \ caminos
  • hacia adelante dependencias

Mi estructura se parece a:

project_root 
     /algorithm 
       /src 
        /algo1.c 
        /algo2.c 
       /unit_test 
        /algo1_test.c 
        /algo2_test.c 
       /out 
        algo1_test.exe 
        algo1_test.xml 
        algo2_test.exe 
        algo2_test.xml 
      headers.h 
     /embunit 
     /harnass 
    makefile 
    Rules.top 

Me gustaría mantener las cosas simples; aquí las pruebas unitarias (algo1_test.exe) dependen tanto del componente 'algoritmo' (ok) como del marco de prueba de la unidad (que puede o no conocerse en el momento de compilar esto). Sin embargo, mover las reglas de compilación a la marca superior no me atrae, ya que esto distribuiría el conocimiento local de los componentes en todo el sistema.

En cuanto a las rutas de Cygwin: Estoy trabajando en hacer la compilación utilizando rutas relativas. Esto resuelve el problema /cygdrive/c (como los compiladores generalmente pueden manejar/rutas) sin incluir C: (que no le gusta). ¿Alguna otra idea?

+0

Tenga en cuenta que puede usar '/' como separador de ruta en Windows por lo general muy bien. Casi todas las funciones de API que utilizan rutas las traducen a '' 'de todos modos. – Joey

+0

De hecho. Sin embargo, es la letra de la unidad lo que causa problemas. Make no maneja el: bien (como define un objetivo). Y que/cygdrive/c/no es reconocido por las aplicaciones de Windows. Si traduzco/cygdrive/c a c:/entonces el archivo de dependencia no reconoce el archivo de dependencia generado por el compilador. – Adriaan

Respuesta

3

CMake junto con las herramientas relacionadas CTest y CDash parecen responder a sus necesidades. Vale la pena echarle un vistazo.

Bill Hoffman (Un cable CMake desarrollador) se refiere al papel Recursive Make Considered Harmful en un post en la lista de correo CMake:

...como cmake está creando los makefiles para usted, se evitan muchas de las desventajas de de recursive make, por ejemplo, no debería tener que depurar los makefiles o incluso pensar en cómo funcionan. Hay otros ejemplos de las cosas en ese documento que también corrige usted.

Ver también this answer para "Recursive Make - friend or foe?" aquí en stackoverflow.

- Recursive Make - friend or foe?

+0

Gracias; Le daré una nueva mirada a esta combinación. +1 por tu esfuerzo. – Adriaan

+0

No es la respuesta que estaba buscando, pero aún así la acepté, ya que de hecho podría ser mejor evitar el problema que resolverlo en los archivos make. – Adriaan

0

autorización aquí es lo que hago:

Yo uso una Makefile en la raíz y patrones de comodines para recoger todas las archivos en un directorio. Tenga en cuenta que asumo que foo/*. C conformará foo.so por ejemplo. Esto hace que mantener el Makefile sea mínimo, ya que al agregar un archivo al directorio automáticamente se agrega a la compilación.

Dado que es lo que está utilizando estoy asumiendo (lo hago para mis proyectos) que se utiliza un compilador que utiliza la sintaxis de línea de comandos compatible con gcc (cc). Entonces MSC está fuera de servicio; pero no se frustre, hago la mayor parte de mi desarrollo (desafortunadamente) en Windows y uso MinGW con MSys; Funciona de maravilla. Produce binarios nativos, pero se creó con un entorno de compilación compatible con Posix.

La comprobación de la dependencia se realiza con el interruptor algo estándar -MD. Luego incluyo todos los archivos * .d en el archivo Makefile. Construyo los patrones a partir de los archivos fuente recopilados automáticamente.

Finalmente las pruebas unitarias se implementan con el objetivo "estándar" check. El objetivo de verificación es como el objetivo de todos, excepto que depende de la prueba de la unidad y lo ejecuta una vez que todo está construido. Lo hago de esta manera para que pueda construir el proyecto o construir las pruebas unitarias (y el resto del proyecto) de manera separable. Cuando no estoy desarrollando el proyecto, quiero simplemente construirlo y terminarlo.

Aquí es un ejemplo de cómo lo hago: https://github.com/rioki/c9y/blob/master/Makefile También tiene los objetivos install, uninstall y dist.

Como puede ver, todo es sencillo, no hay llamadas recursivas y todo es relativamente simple. Usé automake y autoconf y nunca volveré a hacerlo; también otras herramientas de compilación están fuera de cuestión, si necesito instalar foojam o barmake para construir algo, normalmente abandono ese proyecto inmediatamente.