c++ - tipos - que es una libreria estatica
¿Cómo se manejan las bibliotecas de terceros con sistemas de compilación completamente diferentes? (4)
¿Supongo que no está mencionando intencionalmente ninguna biblioteca específica?
De todos modos, debe preguntarse si realmente necesita este código de terceros en su sistema de compilación.
Las bibliotecas de terceros que utilizamos se compilan una vez (con sus respectivos scripts de compilación) y se comprueban los conmutadores de VC correctos, y luego se comprueba el archivo DLL o LIB en el control de origen de la aplicación que usa la lib.
Por lo tanto, la compilación de una biblioteca de terceros es algo que solo hacemos una vez por cada lanzamiento de terceros y no cargamos a nuestro sistema de compilación con las complejidades de crear las bibliotecas de terceros.
Supongo que existen argumentos válidos para cualquiera de los dos enfoques, y quizás pueda proporcionar algunos detalles en la pregunta de por qué necesita / desea tener las librerías de terceros dentro de su sistema de compilación.
El estándar C ++ (y C, aunque importa menos allí) establece que todas las unidades de traducción en un programa deben tener la misma definición; y eso incluye cosas como compiladores. Por ejemplo, en MSVC ++, se debe vincular a la versión correcta de la biblioteca de tiempo de ejecución de C ( /MT
versus /MD
versus /MTd
versus /MDd
) en todas las unidades de traducción.
Sin embargo, hay un par de dependencias de terceros que nos gustaría usar, y hay un par de cosas:
- Todos usan sistemas de compilación diferentes (hay un autoconf, hay un cmake, y hay uno que parece tener su propia cosa enrollada a mano ...)
- Los sistemas de compilación no exponen todos estos tipos de conmutadores en su configuración, y los que están codificados de forma rígida se configuran de manera diferente en diferentes sistemas. (Por ejemplo, una biblioteca fuerzas
/MD
y/MDd
, mientras que otra fuerza/MT
y/MTd
)
No estamos seguros de cuál es la mejor manera de manejar este tipo de cosas. Hemos discutido las siguientes opciones:
- Construya nuestro propio sistema de compilación alrededor de las dependencias de terceros.
- PRO: Sabemos que las cosas van a coincidir
- PRO: Sabemos que podemos hacer soporte multiplataforma de la manera correcta
- CON: No sabemos exactamente cómo funciona cada uno de los sistemas de construcción de terceros
- CON: Mucho y mucho trabajo.
- CON: Rompe si la dependencia de terceros cambia
- Intente utilizar sistemas de compilación de terceros e intente modificarlos para hacer lo que necesitamos.
- PRO: Parece ser menos trabajo
- CON: Podríamos romper el sistema de terceros
- CON: Rompe si la dependencia de terceros cambia
- CON: obliga a nuestra propia construcción a ser realmente complicada
Aunque no sabemos qué hacer; y no podemos creer que estamos solos en tener este tipo de problemas. ¿Deberíamos hacer una de las opciones anteriores o alguna tercera alternativa que no haya pensado?
No es estrictamente necesario que todas sus bibliotecas se vinculen al mismo tiempo de ejecución. Suponiendo que son archivos DLL, solo es un problema si pasan las estructuras de datos CRT a través del límite DLL. Crear un FILE*
en una DLL utilizando un tiempo de ejecución, y usarlo desde una DLL que está vinculada a otra ejecución es una receta para el desastre. Llamar a malloc
o new
desde una DLL utilizando un tiempo de ejecución, y free
/ delete
de otra causa muchos problemas divertidos.
Pero siempre que todas las cosas relacionadas con CRT se mantengan internas en la DLL, puede enlazar de manera segura a una DLL que usa otra CRT. Eso también significa que su compilación de depuración puede usar una biblioteca vinculada contra la versión CRT. Nuevamente, siempre y cuando no intentes mezclar estructuras de datos CRT en bibliotecas.
Tenga en cuenta también que la mayoría de los indicadores del compilador no afectan a la ABI, por lo que pueden ser diferentes entre bibliotecas (o archivos). Los que sí cambian el ABI son generalmente obvios, como si fueras al empaquetado o alineación de la pila.
Entonces lo que hacemos es básicamente esto:
- Siempre que sea posible, construimos la biblioteca nosotros mismos. En su mayor parte, esto significa que podemos, a través de medios bastante simples, controlar con qué tiempo de ejecución debe vincularse. Eso podría requerir una pequeña cantidad de ajustes del sistema de compilación, pero generalmente, solo es cuestión de especificar si se debe compilar una compilación de debug o de release, para lo que la mayoría de los sistemas de compilación tienen opciones. (Y si la biblioteca usa Visual Studio para su sistema de compilación, intentamos actualizarlo a 2010 cuando sea posible)
- Utilizamos el propio sistema de compilación de la biblioteca. Cualquier otra cosa es solo una receta para la miseria. Desea poder confiar en que el sistema de compilación realmente se mantiene sincronizado con el código fuente de la biblioteca, y la forma más sencilla de asegurarse de que es usar el sistema de compilación que se envía con el código fuente.
- Si no es práctico construir la biblioteca, simplemente la usamos tal como está, y luego tenemos que distribuir cualquier tiempo de ejecución con el que esté vinculado. Tratamos de evitar esto, pero es lo suficientemente seguro como para hacerlo cuando no hay otra opción disponible.
- cuando construimos una biblioteca, documentamos exactamente cómo se hizo en nuestra wiki interna. Esta es una gran ayuda si tenemos que actualizar a una versión más nueva de la biblioteca o reconstruirla.
Actualmente dependemos de tres tiempos de ejecución de VS diferentes (2005, 2008 y 2010), lo cual es una molestia, pero funciona . Y para uno o dos de ellos, siempre usamos la versión de lanzamiento, incluso en versiones de depuración de nuestro propio código.
Es un poco complicado mantener, pero funciona . Y realmente no puedo ver una mejor manera de hacerlo.
Por supuesto, debe minimizar la cantidad de dependencias de terceros que tiene, y cuando elige una biblioteca de terceros, su sistema de compilación definitivamente debería ser un factor a considerar. Algunos son mucho más dolorosos para trabajar que otros.
Pero al final, probablemente terminará teniendo que usar algunas bibliotecas que simplemente no tienen sistemas de construcción de buen comportamiento, o que serían tan difíciles de compilar que simplemente no vale la pena el esfuerzo, o donde puede hacerlo ". t crear una versión de depuración de la biblioteca. Y luego solo toma lo que puedas conseguir. Deje que use el tiempo de ejecución que quiera usar.
No hay una respuesta definitiva, depende de cómo se diseñe la interfaz de código de terceros. Si la interfaz es compacta, por ejemplo, tipos de datos compartidos no opacos, es mejor reconstruirlos usando su propia compilación y opciones. Tienes que analizar la interfaz y determinar cómo integrarlos. Por otro lado, si la interfaz es simple y se puede desacoplar fácilmente, pueden construirse como dll y solicitarse a pedido. Por supuesto, tendrá diferentes versiones de las bibliotecas de C cargadas en la aplicación y todas tendrán diferentes instancias de búferes de io, gestión de memoria, etc.
Si tiene el código fuente disponible, la mejor opción es invertir más tiempo en integrarlos en su propia compilación.
Tienes razón, no estás solo en tener este tipo de problemas.
Según nuestra experiencia, una combinación de dependencias (una forma elegante de decir que copian archivos manualmente, supongo) y la modificación del sistema de construcción de terceros es la más efectiva, especialmente si se construye para Windows.
Algunas cosas que hemos encontrado útiles: -
Documente los cambios que tuvo que aplicar (Usamos una página wiki) para la versión particular e incluimos los pasos / dependencias requeridos aquí (por ejemplo, el intérprete de Perl requerido para compilar OpenSSL) y ejecute todas las pruebas incluidas antes de usar la compilación.
Descubrimos que cambiar el nombre de las bibliotecas de salida para que se marquen de acuerdo con el ABI es realmente útil aquí en lugar de usar los nombres generados por la tercera parte.
por lo que la dependencia X de C ++ de terceros termina en nuestra estructura de directorios (comprometida con svn) como
X / [version_number] / include (archivos de encabezado para usar lib)
X / [version_number] / lib / Windows (construido manualmente, probado y renombrado libs)
p.ej
X-vc100.lib X-vc100-gd.lib
etc
(En realidad, copiamos nuestros nombres de los nombres de boost http://www.boost.org/doc/libs/1_49_0/more/getting_started/windows.html#library-naming ya que parecían totalmente sensibles)
Luego, el sistema de compilación puede seleccionar la dependencia de un tercero en particular (para VS utilizamos una hoja de propiedades heredada con todas las dependencias nombradas como macro de usuario, por lo que solo se puede agregar $ (x_inc) a los directorios de inclusión de un proyecto y $ (x_lib ) agregados a las bibliotecas: estas macros luego seleccionan la versión y abi requeridas para ese proyecto en particular.