¿Debo agregar la fuente de las bibliotecas en lugar de vincularlas?

14

Soy relativamente nuevo en C ++, por lo que no estoy seguro de cómo manejar mejor las pequeñas dependencias (por ejemplo, un lenguaje de script o un analizador JSON / YAML / XML).

¿Debo crear proyectos separados y vincularlos como una biblioteca estática, o hay desventajas de simplemente poner los archivos .h / .cpp en mi proyecto principal?

Esto último parece mucho más fácil porque he pasado varias horas tratando con bibliotecas incompatibles (configuración de compilador diferente al construir la biblioteca), pero no quiero comenzar a aprender C ++ de la manera incorrecta.

Si es preferible mantenerlos como bibliotecas separadas, ¿cómo podría mantener sincronizados los indicadores de compilación para que los archivos .lib / .a se vinculen con éxito a mi aplicación?

(Actualmente estoy trabajando con MSVC 2015, pero el objetivo es compilar en Mac OS X e iOS usando XCode / clang, de modo que tenga que lidiar con al menos 3 tipos diferentes de bibliotecas (Win x86, Mac x64, ARM) )

Michael Stum
fuente
55
Mira a ABIss y te mirarán a ti
Basilevs
1
Tenga en cuenta que algunas bibliotecas están destinadas a ser utilizadas de esta manera. El patrón de uso preferido de la biblioteca SQLite es colocar el archivo fuente y el encabezado amalgamados en el árbol fuente de una aplicación C o C ++ para compilarlo en el ejecutable.
Mark Benningfield

Respuestas:

6

TLDR;

En caso de que añadir la fuente?
¿Debería X agregar la fuente? DEPENDE

Aquí viene el por qué ...

En el pasado, el tiempo de compilación era un problema que incluso los proyectos más pequeños tenían. Compilar sus fuentes y nunca preocuparse por el almacenamiento en caché de los resultados del compilador fue definitivamente atractivo para algunos. Ese es un punto para las bibliotecas irrelevantes para usted.

Otro importante es el versionado. ¿Realmente necesitas versionar cada biblioteca por separado? Ejecutar pruebas contra cada uno? ¿Distribuirlo entre muchos miembros del equipo? Las bibliotecas son excelentes si lo hace, y conveniente para moverse, pero de nuevo, parece que tampoco le importa.

El punto final aquí es que es una sobrecarga adicional, y soltar los archivos de origen es más fácil en su caso, lo que le da un punto muy fuerte para soltar los orígenes en lugar de usar bibliotecas. Como ha notado, una vez que realiza un cambio en la configuración del compilador, debe perseguir todas las dependencias de lo contrario.

Sé todo esto por experiencia:

Para proyectos Swift, definitivamente uso frameworks (bibliotecas) y enlaces contra ellos, ya que es fácil de configurar usando Xcode. También realmente necesito el control de versiones, las pruebas y el desacoplamiento allí, por eso.

Para los proyectos Mono (C #), para Unity, comencé con el enfoque moderno de dividir el proyecto en bibliotecas, compilé y probé cada uno, lo cual fue genial ... pero una vez que dejé las bibliotecas en Unity, sucedieron todo tipo de problemas , desde la versión pirateada de los usos de Mono Unity, hasta simplemente el comportamiento a veces diferente que exhibe el código al cambiar de plataforma. No tener un solo IDE aquí para administrar todas las bibliotecas fue un verdadero dolor, por lo que poner toda la fuente dentro de Unity fue una gran victoria para la productividad.

Finalmente, lo más relevante para ti, un proyecto de juego C ++ en el que trabajé. Un motor de juego, un cliente de red en tiempo real, un cliente HTTP de red, AI y una tienda de persistencia fueron escritos para este juego, solo en el lado del cliente. ¿Por qué opté? Bibliotecas CLion +. Aunque estaba usando bibliotecas, no parecía que lo estuviera. Todas las fuentes estaban en el proyecto CLion IDE, y al componer CMakeLists, pude activar todas las compilaciones y vincularlas de un solo golpe.

Como conclusión , diría que usar bibliotecas es una solución preparada para el futuro, pero también una optimización prematura si no es necesaria. Por lo que pude determinar de su situación, cambiar de MSVC a Xcode será un dolor si va a tener un objetivo de compilación múltiple. Por lo tanto, simplemente dejarlo caer y mantener tanto el aislamiento como sea posible para cuando el momento en el que podría necesitar bibliotecas de uso.

PD: Tengo un dilema similar en estos días con Docker. ¿Debo componer? ¿Debo correr solo localmente? .. etc. También Elixir, ya que le permite crear aplicaciones dentro de la misma aplicación. ¿Debería hacer eso? ¿O separar la aplicación en los llamados microservicios? ... etc. No hay bala de plata, siempre mídete, como YMMV.

Mazyod
fuente
2

Vincular con bibliotecas C ++ requiere mucha molestia, y requiere mucho conocimiento y esfuerzo para hacerlo correctamente. Puede ser intimidante para los estudiantes de C ++.


Muchas veces, los autores / mantenedores de una biblioteca específica de C ++ tendrán esto en mente y recomendarán de una forma u otra.

En otras palabras, si los autores / mantenedores pretenden que la biblioteca sea incluida por encabezados (* .h y .hpp solamente), o por fuente ( .h *, o .c ), lo habría dicho claramente en el archivo Léame o documentación.


Las bibliotecas diseñadas y mantenidas para ser multiplataforma (y compatibles con múltiples proveedores y entornos de compiladores de C ++) a menudo tendrán un sistema de archivo MAKE o un sistema de configuración de compilación (como CMake). Estos sistemas se utilizan para generar cuñas de encabezado que suavizan las diferencias de plataforma y para generar scripts que invocarán el compilador y el vinculador en los archivos de origen utilizando las opciones de línea de comandos adecuadas y en la secuencia correcta. Dependiendo de la plataforma y la configuración, estos sistemas de compilación pueden incluir o excluir ciertos encabezados o archivos de origen, o pueden definir o no definir ciertos símbolos de preprocesador.


Ir en contra de la recomendación de los autores / mantenedores es posible, pero eso siempre requiere un gran esfuerzo de portabilidad. La cantidad de trabajo requerida para ese esfuerzo de transferencia puede ser comparable a la transferencia a un entorno C ++ diferente.


Debido a que Visual C ++ usa su propio sistema de compilación basado en un archivo de descripción del proyecto (en parte basado en XML), es bastante diferente del sistema de compilación basado en scripts que se usa en Linux. El enfoque utilizado por CMake es que CMake tome la configuración y luego emita toda la estructura del proyecto Visual C ++, con las opciones de configuración integradas en los archivos * .vcxproj.

Si surgen problemas durante la vinculación de C ++ con Visual C ++, la configuración de compilación en los archivos * .vcxproj se puede modificar utilizando la GUI de Visual Studio (utilizando el cuadro de diálogo de páginas de propiedades del proyecto). Esto supone que comprende a fondo los significados y las consecuencias de una docena de configuraciones importantes de compilación y enlace de C ++.

Ahora viene la parte más estúpida del uso de Visual C ++: si está utilizando una docena de bibliotecas de terceros diferentes, cambiar la configuración de compilación para todas ellas significa ir a cada archivo * .vcxproj y repetir el mismo cambio en la GUI para una docena veces. Una molestia, pero se puede hacer, si sabes cómo hacerlo correctamente.

La mayoría de los estudiantes de Visual C ++ aprenden estas configuraciones de la manera más difícil, observando los errores del compilador y el enlazador de Visual C ++, identificados por su código de error. Por ejemplo, uno puede buscar LNK2005, con el significado superficial de "El símbolo del símbolo se definió más de una vez", pero con el entendimiento de que la definición duplicada no surge de un error de programación descuidado, sino que podría haber sucedido debido a algunos conflictos o aplicaciones incorrectas de las opciones de compilación y enlace.


Para proporcionar una respuesta más específica y útil a su situación, será necesario conocer los nombres de las bibliotecas que pretende utilizar, así como los errores de vinculación u otras dificultades que encuentre. Puede encontrar respuestas existentes a esas preguntas en los paneles de discusión de la biblioteca respectiva. Estas preguntas tienden a etiquetarse con "problemas de vinculación", "ventanas" y "visual C ++".

Es posible una guía de principiante a experto sobre este tema, pero será específica del proyecto. Las diferentes preferencias elegidas por diferentes proyectos requerirán una reescritura completa de la guía.

rwong
fuente
Si usa CMake para emitir .vcxproj, en lugar de modificar el .vcxproj, puede modificar la configuración de CMake
Caleth
1

Yo diría que sí, siempre y cuando sea más fácil. Hay bastantes beneficios:

  1. Resultará en un código mejor y más rápido, especialmente si activa la Optimización del tiempo de enlace.

  2. A su IDE le gustará más, por ejemplo, (con suerte) le permitirá saltar a la implementación (.cpp) del código de la biblioteca, en lugar de solo la interfaz (.h), lo cual es extremadamente útil cuando se trabaja con código mal documentado (es decir, la mayoría del código).

  3. A menudo le permite agregar la dependencia como un submódulo git, que es una forma un poco hacky pero en realidad bastante buena para tener dependencias (para C ++ de todos modos, que prácticamente no tiene sistemas de compilación sanos). Hace que sea muy fácil actualizar la biblioteca y probar diferentes versiones.

  4. No tiene que preocuparse de que se compile una dependencia con MSVC ++ 2013, mientras usa 2017, por ejemplo. O compartido frente a MSVCRT estático.

  5. Puede construir fácilmente en modo de depuración y acceder a la biblioteca.

La única razón por la que creo que no querría hacer esto es si la biblioteca es grande y tiene un sistema de compilación complejo que no desea replicar en el suyo, por ejemplo, Boost o LLVM. Pero para las bibliotecas simples no hay inconveniente realmente.

Como ejemplo, uso libusb en algunos proyectos y necesito admitir Windows. libusb usa autotools, que es una broma de un sistema de compilación y, de todos modos, no funciona realmente en Windows. Proporcionan binarios precompilados, pero están construidos con MSVC ++ 2013 y no funcionarán con 2017. La solución más sencilla fue, con mucho, agregar todos los archivos .c y .h relevantes a mi proyecto.

Timmmm
fuente
2
1) realmente? Una biblioteca estática es solo una colección de archivos de objetos, como si los acabara de compilar.
Baldrickk
Puede crear un archivo de .oarchivos compilados -fltopero que en realidad no son una biblioteca estática; para Clang son archivos de código de bits LLVM. Y obviamente no funcionará si usa bibliotecas estáticas que alguien más proporciona.
Timmmm
ok, vamos a actualizar esta discusión - Estoy deseando aprender algunas cosas más :)
Baldrickk