c++ visual-studio visual-c++ visual-studio-2013 protocol-buffers

c++ - Errores al vincular a protobuf 3 en MS Visual C



visual-studio visual-c++ (1)

No coincide la forma en que la biblioteca de tiempo de ejecución de VStudio C (y C ++) ( VCRTLib - marque [SO]: Cómo sortear la dependencia de los encabezados CRT de Windows Universal en vcruntime.h (respuesta de @ CristiFati) ) es utilizada por su proyecto y por el proyecto libprotobuf . Déjame detallar:

Digamos que hay un código C. El propósito de ese código es ser ejecutado. De lo que se puede lograr:

  • Directamente: incluir ese código en un proyecto de tipo de aplicación VC , que generará un .exe
  • Indirectamente: incluir el código en un proyecto de tipo biblioteca VC , que generará una biblioteca que solo podrá ejecutarse cuando se llame desde otro .exe (que llama a esa biblioteca). La biblioteca puede ser:
    • estático : todo el código C se compilará y almacenará en un archivo .lib . Necesitará ese archivo cuando use la biblioteca en otro proyecto (ya sea una aplicación o una biblioteca), en el momento del enlace . Tenga en cuenta que todo el código necesario de su .lib se "copiará" en el otro proyecto
    • dinámico : ahora tendrá 2 archivos: un archivo .dll que contendrá el código compilado (y vinculado) y un archivo .lib 1 que contendrá "punteros" (si lo desea) al código en el archivo .dll . Cuando use la biblioteca en otro proyecto, también necesitará el archivo .lib en el momento del enlace , pero ahora no contendrá el código, por lo que no se copiará en la otra biblioteca (la otra biblioteca será más pequeña), pero en tiempo de ejecución, la otra biblioteca necesitará el archivo .dll

Puede verificar [SO]: Error LNK2005 en el formulario CLR de Windows (respuesta de @ CristiFati) para obtener detalles sobre cómo el código C se transforma en formato ejecutable. Además, Google está lleno de artículos sobre las diferencias entre las bibliotecas estáticas y dinámicas, cuándo usar una u otra, se puede encontrar un ejemplo en [SO]: Cuándo usar bibliotecas dinámicas vs.

Como adivinó, la biblioteca de tiempo de ejecución CRT o C (que contiene el sistema subyacente que hace que el código C pueda ejecutarse; un ejemplo son las funciones de administración de memoria: malloc , gratis ) no hace una excepción: es el equivalente de la libc.a de Nix ( static o archive) vs. libc.so (objeto dinámico o compartido), pero en VStudio es un poco más complicado:

  • La CRT estática reside en libcmt.lib
  • El CRT dinámico reside en msvcrt.lib que "apunta" a msvcr ###. Dll 2 ( msvcr120.dll para VStudio 2013 )

Notas :

  • Una " d " al final del nombre de la biblioteca ( msvcr d .lib ) significa que está compilada con símbolos de depuración
  • La biblioteca de tiempo de ejecución de C ++ está bajo la situación exacta; los nombres tienen un p adicional: libc p mt.lib , msvc p rt.lib , msvc p 120.dll
  • Para más detalles, consulte [MS.Docs]: Características de la Biblioteca CRT

Ahora, las partes VCRTLib no están incluidas en el proyecto como cualquier otra lib ( Propiedades del proyecto -> Enlace -> Entrada -> Dependencias adicionales ), sino porque su naturaleza (estática o dinámica) se requiere en tiempo de compilación, se configuran desde: [ MS.Docs]: / MD, / MT, / LD (Use Run-Time Library) , donde hay 4 opciones disponibles:

  1. Multihilo ( / MT )
  2. Depuración de subprocesos múltiples ( / MTd )
  3. DLL multiproceso ( / MD )
  4. DLL de depuración de subprocesos múltiples ( / MDd )

Obviamente, los que contienen "Debug" son cuando se construye para la configuración de Debug mientras que los otros para Release ; El punto clave es que los que tienen DLL están usando la versión dinámica de tiempo de ejecución, mientras que los otros tienen la versión estática .

Volviendo a su error : el vinculador se queja de que main.obj (parte de su proyecto) tiene MDd_DynamicDebug (enlace contra la versión de depuración dinámica ), mientras que common.obj (parte del proyecto libprotobuf ) tiene MTd_StaticDebug (enlace contra la versión de depuración estática ), por lo tanto, se vincula con 2 tiempos de ejecución en el mismo ejecutable (o .dll ), lo que no es posible.

Para solucionarlo, debe asegurarse de que tanto libprotobuf como su proyecto principal tengan el mismo valor para VCRTLib .
Por supuesto, es más simple cambiar la configuración de su proyecto principal para que coincida con la de libprotobuf , pero se recomienda usar la versión dinámica de tiempo de ejecución (las cosas pueden complicarse en proyectos más grandes que tienen .dll s involucrados) incluso si esto requiere recompilar libprotobuf (bueno , si cambiar esa opción genera errores que hacen que libprotobuf sea muy difícil de construir, y su proyecto seguirá siendo así de simple, puede usar el VCRTLib estático).

Nota : No debe confundir el tipo VCRTLib (estático / dinámico) con la forma en que se está creando libprotobuf (estático en este momento, pero estoy seguro de que también se puede construir como dinámico).

@ EDIT0 :

Agregar información adicional en la nota anterior, como lo solicitaron algunos comentarios, y podría ser útil para otros usuarios.

Hay 2 aspectos acerca de una biblioteca (incluyendo libprotobuf ), que no están relacionados :

  1. Tipo de biblioteca (la forma en que se está creando): dinámico / estático
  2. Tipo de VCRTLib (la forma en que usa VCRTLib ): nuevamente, dinámico / estático

Entonces, hay 4 combinaciones perfectamente válidas:

  1. Biblioteca dinámica usando VCRTLib dinámico
  2. Biblioteca dinámica usando VCRTLib estático
  3. Biblioteca estática usando VCRTLib dinámico
  4. Biblioteca estática usando VCRTLib estático

Para libprotobuf , cada uno de los aspectos está controlado por una opción booleana cmake :

  1. Tipo de biblioteca: protobuf_BUILD_SHARED_LIBS
  2. Tipo de VCRTLib : protobuf_MSVC_STATIC_RUNTIME

Las 2 banderas se pueden establecer por:

  • cmake-gui
  • cmake cmdline (pasándolos como argumentos, por ejemplo: -Dprotobuf_BUILD_SHARED_LIBS=OFF -Dprotobuf_MSVC_STATIC_RUNTIME=OFF )

Las 4 combinaciones anteriores son, por lo tanto, posibles (al menos en v 3.5 ), pero # 2. está deshabilitado de forma predeterminada (especificando -Dprotobuf_BUILD_SHARED_LIBS=ON -Dprotobuf_MSVC_STATIC_RUNTIME=ON construirá un .dll que se vinculará al VCRTLib dinámico ), para evitar posibles problemas de tiempo de ejecución, y habilitarlo requiere intervención manual.

Para obtener más detalles sobre las instrucciones de compilación (a través de cmake ), consulte: [GitHub]: protocolbuffers / protobuf - (master) protobuf / cmake / README.md .


1 : El archivo .lib solo se creará si la biblioteca exporta símbolos , ya que de lo contrario no tendría sentido (no se necesita nada en el momento del enlace, y se creará el archivo .dll , pero prácticamente no se puede usar)

2 : Para las versiones más recientes de VStudio (a partir de 2015 ), la parte msvcr (t) ha sido reemplazada por vcruntime (o al menos este es el punto de entrada, ya que se dividió en partes lógicas más pequeñas)

Encontrado en Visual Studio 2013 , pero es reproducible con cualquier versión.

Cloné la biblioteca de búfer de protocolo de github, ejecuté CMake-gui (dejé todo por defecto, por lo que es la versión estática), solo construí libprotobuf (otro proyecto falló por alguna razón, error cmd.exe, podría tener algo que ver con pruebas, pero libprotobuf funciona bien).

Mi proyecto utiliza encabezados generados con el archivo .proto que se encuentra en el github de la especificación de mosaicos vectoriales de mapbox.

Cuando enlace, primero tengo este error

Error 1 error C4996: ''std::_Copy_impl'': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ ''Checked Iterators'' s:/program files (x86)/microsoft visual studio 12.0/vc/include/xutility

Intenté deshabilitarlo con -D_SCL_SECURE_NO_WARNINGS en argumentos de línea de comando adicionales, pero luego tengo otros errores:

Error 1 error LNK2038: mismatch detected for ''RuntimeLibrary'': value ''MTd_StaticDebug'' doesn''t match value ''MDd_DynamicDebug'' in main.obj S:/eiogit3/misc-projs/mapload/mapload/libprotobufd.lib(common.obj)