2011-03-04 18 views
5

Estoy trabajando en un conjunto relativamente grande de bibliotecas de código C de código de serie, que luego serán paralelizadas en CUDA por mis colaboradores.¿Cómo puedo hacer que mi proyecto altamente modular sea fácil de compilar para los usuarios finales?

Para este proyecto mi código esencialmente se reduce a

#include "Initialize.cpp" 
#include "PerformMoves.cpp" 
#include "CollectResults.cpp" 

main() 
{ 
    //DECLARE General Vars 

    Initialize(); 

    for (unsigned int step=0; step < maxStep; step++) 
    { 
     PerformMoves(); 
    } 

    CollectResults(); 
} 

Ahora los pasos que realizo dentro de inicializar y PerformMoves serán muy diferentes dependiendo de qué tipo de simulación que estoy construyendo. La velocidad es el máximo rendimiento ya que mi código es una simulación de Monte Carlo que realizará millones de movimientos, cada uno de los cuales implica potencialmente miles de cálculos. Por lo tanto, quiero evitar cualquier condicionales innecesarios.

Por lo tanto, esencialmente quiero diferentes módulos "plug and play" C, p.

InitializeSimType1.cpp InitializeSimType2.cpp InitializeSimType3.cpp

PerformMovesType1.cpp PerformMovesType2.cpp PerformMovesType3.cpp

....

cada uno optimizado para una cierto tipo de procedimiento de simulación, sin la "pelusa" de grandes condicionales para manejar una variedad de cas es.

Actualmente tengo dos tipos diferentes de simulaciones, y sólo tienen estos en dos carpetas diferentes y compilar la siguiente manera:

g ++ Main.cc Initialize.cpp PerformMoves.cpp CollectResults.cpp -O MC_Prog

Me gustaría pasar a algún tipo de esquema de compilación condicional, donde tengo un archivo de configuración de tipo donde especifico opciones y toma los archivos cpp correctos y los compila.

Supongo que un makefile + config files es mi mejor opción, pero más allá de los objetivos básicos y la compilación muy lineal, soy bastante novato en el mundo de los makefiles complejos.

¿Cuáles son algunas buenas formas en que podría crear un sistema de compilación basado en listas, que permitiría a los usuarios con conocimientos básicos de C crear fácilmente un objetivo con los módulos que desean? Mis usuarios finales no tendrán una gran cantidad de conocimiento de archivos (o conocimientos de programación en general), por lo que un sistema complejo en su extremo está fuera de cuestión. Quiero que básicamente tengan un sistema transparente de archivos de configuración que les permita elegir un módulo Initialize, un módulo PerformMoves y un módulo CollectResults. Una vez que hayan modificado este archivo de configuración con sus selecciones, quiero que puedan hacer una compilación de un solo comando.

En otras palabras, quiero ser capaz de crear un README que dirige a los usuarios:

  1. de entrada estas entradas en este archivo de configuración (da el nombre del archivo de configuración, opciones para poner para cada entrada del archivo de configuración). ..
  2. Compilar utilizando este comando (da mando único)

Sé que esto es una pregunta bastante abstracto y complejo, pero sé que hay algunos expertos/c Makefile por ahí que me podía ofrecer una buena orientación.

+1

Bueno para uno Usted no debe usar tantas capitales en sus instrucciones. – Hello71

+0

En mi código actual, sigo la convención de nomenclatura de MSDN sugerida por Microsoft, que es (la última vez que lo comprobé) que tapa la primera letra de todas las palabras dentro de vars. El código anterior simplemente hice tapping muy rápido para dar una idea aproximada de lo que estaba tratando de hacer. Entiendo que hay muchas ideas diferentes sobre la carcasa variable, pero calculé que MSFT era una autoridad bastante buena, así que simplemente sigan con sus sugerencias. ¿Es una mala idea? –

+0

Siempre parece ser mejor utilizar guiones bajos para editar y dinking con código. MS es, después de todo, la compañía que creó la notación húngara. –

Respuesta

1

puedo pensar en un par de sistemas de construcción similares:

  1. Cuando se construye GCC se construye bibliotecas con rutinas de ayuda (por ejemplo libgcc.a). Quiere asegurarse de que solo las funciones necesarias se vinculen a su programa. Como la unidad de granularidad del enlazador es un solo .o, construye un archivo .c docenas de veces con diferentes opciones de -D_enable_xxx para activar cada función individualmente. Luego usa ar para generar el resultado .o en un .a con el que puede establecer un vínculo para obtener solo lo que necesita.
  2. El servidor de ventanas X tiene varias funciones que realizan operaciones en gran parte idénticas, excepto que las matemáticas en el bucle más interno son diferentes. Por ejemplo, podría xor o and o or bits juntos. No quiere un condicional en su bucle interno, por lo que construye el mismo archivo una y otra vez con diferentes opciones de -D_math_xor para producir docenas de .o cada una con una función que realiza la operación matemática específica envuelta en la función de bucle. Utiliza todos los .o (porque la operación es realmente seleccionada por el cliente X, no en tiempo de compilación) por lo que la técnica .a no es importante.

Parece que usted podría utilizar una mezcla de los para producir una biblioteca de .o, donde se pre-compilado con las opciones específicas de cada uno y luego reconstruir simplemente main.c una y otra llamando a diferentes funciones y enlazar en su libaray.

Sobre la base de sus comentarios a continuación, aquí están algunas otras ideas:

  1. Cuando se construye Binutils, GCC, glibc, etc desembalar la distribución de la fuente pero no construyen en el interior del árbol de fuentes . En cambio, usted mkdir obj-mytarget; cd obj-mytarget; ../path/to/gcc/configure --options...; make El script configure crea config.h y Makefile específicos para las opciones (y, por supuesto, las capacidades del sistema). Una gran ventaja de esta configuración es que todos los productos de compilación (desde .o hasta ejecutables) para ese conjunto de opciones son independientes y no interfieren con las compilaciones que usan otras opciones.
  2. La configuración clásica del kernel BSD se hace editando un archivo (idiomáticamente dado un nombre de mayúsculas como GENERIC que produce el núcleo predeterminado o LINT que activa todo para fines de análisis estáticos) y luego invocando config CONFNAME. config analiza el archivo de configuración simple y crea un árbol de directorio con el nombre del archivo. El árbol de directorios contiene un Makefile y varios archivos .h para controlar la compilación. Mismas ventajas básicas que el método anterior.
  3. avr-libc (una libc para microcontroladores AVR Atmel) automatiza los enfoques anteriores creando automáticamente directorios de destino para docenas de microcontroladores (con variaciones en el tamaño de la memoria, disponibilidad de periféricos, etc.) y compilando todos de las variaciones en un solo pasar. El resultado es que muchas bibliotecas proporcionan un entorno de compilación cruzada capaz de apuntar a cualquier AVR. Podría usar una idea similar para construir automáticamente cada permutación de su programa.
+0

Hola Ben , Gracias por los buenos consejos Veo que tanto GCC como X Window Server están usando algún tipo de compilación macro impulsada. Esto se está acercando a lo que quiero, pero no es exactamente lo que esperaba. Este tipo de Parece que el sistema sería bueno para compilar varios objetivos predefinidos que comparten componentes comunes (piense en entradas en un restaurante que comparten ingredientes). Mi objetivo sería tener en su lugar un archivo de configuración que proporcione esta información y una única marca objetivo para mi ejecutable central (piense en una barra de ensaladas donde puede recogerlo r elementos para obtener su entrada neta). –

+0

Para terminar mi reflexión, de esa manera el usuario puede modificar este archivo, decir 'CONFIG ', y luego escribir' make MC_Prog' y automáticamente seleccionará los componentes de instalación adecuados a través de los pares variable/valor en el archivo de configuración. De esta forma, los usuarios finales no tienen que preocuparse por ningún indicador complejo o un montón de objetivos, simplemente obtienen un archivo CONFIG fácil de entender y un solo objetivo principal (junto con los objetivos secundarios adecuados como limpio, etc.) . Supongo que lo que necesito es algún tipo de análisis de texto/lógica condicional dentro del archivo MAKE ... –

+0

o un sistema de script que analiza el archivo de configuración y autogenera/llama a un archivo MAKE apropiado. Estoy pensando que PUEDE ser mi mejor opción: tengo un script * .py que analiza los pares var/value en 'CONFIG' (ignorando las líneas de comentario) que escupe y llama a un makefile. De esta manera, simplemente modifican los valores en 'CONFIG' a una de las opciones dadas en los comentarios, luego ejecutan el script y el sistema de compilación hace su truco sin ninguna complejidad para ellos. ¿Le parece una buena solución? –

Cuestiones relacionadas