Haz el bien y no mires a quién y todas esas… cómo compilar ActiveMQCpp en Wintendo…
Porque en el readme dice que no soporta Cygwin ni MinGW, solamente el compilador de MSVC.
Las librerías que necesitamos son.
- La primera advertencia es que hay tener cuidado con los Runtime de C >>, que tienen que ser todos el mismo. ¿Qué significa ésto?¿Dónde lo especifico?¿Dónde compilo siquiera?…
- También hay que tener el SDK de Windows porque ActiveMQ lo usa. Se baja acá (ISO) o acá (instalador Web, este último es más rápido). Siempre se usa la última versión ya que es backwards compatible.
- De las librerías APR (Apache Portable Runtime) ¡las quiero todas! i.e. APR, APR-util y APR-iconv
- CppUnit se descarga de acá y es un tarball, así es que mejor descomprimirlo en linux.
Todas éstas las estamos agregando como proyectos en la solución (no es necesariamente una buena idea)
En seguida nos preocuparemos de los include paths (los que en unix pasaríamos como -I al compilador), es decir cómo sabe el programa donde encontrar los headers de las librerías de las que depende. >>>
Para ésto vamos a Propiedades > Propiedades de configuración > C/C++ > General.
Ahora, probablemente, como tenemos todos las librerías abiertas en la solución ésto no sea necesario…
De hecho, llama la atención que en el proyecyo de ActiveMQCpp los valores en este campo sean a variables de entorno
¿será que éstas no están seteadas? En efecto, si vemos en Propiedades > Propiedades de configuración > Depuración > Entorno >> no hay nada. Así es que se las seteamos según esta sintaxis >>
pero ná-ni-ná.
Bueno, de hecho apr-util por ejemplo, no está compilando de por sí, sino que tenemos que darle el include path de apr y de apr-iconv para que compile. Por su parte, apr-iconv necesita tener a apr en el include path. Ahora todos éstos naenderthals compilan por separado ¿significa e?to que activemq-cpp compile también? Course not, ni siquiera pasándole directamente arp-util y arp-inconv al include path…
Sigamos con el linker.
El equivalente a los -l en Linux aquí estaría en Propiedades > Propiedades de configuración > Bibliotecario > General > Dependencias adicionales le pasamos apr-1, apriconv-1 y aprutil-1… no pasa nada. ¿Será que como cada librería se compiló en su propio directorio no sabe dónde buscarlas?
En efecto abajo en Propiedades > Propiedades de configuración > Bibliotecario > General > Directorios de biblioteca adicionales podemos darle los search paths (equivalente a -L en linux). Pero sigue sin compilar.
De hecho el header que no encuentra es en específico
Cannot open include file: 'apr_pools.h': No such file or directory
que fue un problema que también tuve compilando en debian… pero que se había arreglado con el linker de hecho.
En este caso pareciera aún ser problema de las variables de entorno
Proyecto : warning PRJ0018 : No se encontraron las siguientes variables de entorno: $(CPPUNIT_DIST) $(PLATFORM_SDK) $(APR_DIST)
Ya me aburrí. Creo que en todo caso abrir cada librería necesaria como un proyecto dentro de la solución no es lo correcto.
En teoría lo que debiera hacer es abrir cada proyecto como una solución sola y generar su .lib, luego éstos importarlos en mi solución con el linker (-l) y referenciar sus respectivos include path (-L). Éso debiera ser todo.
Para compilar ActiveMQCpp, necesito entonces compilar antes
- CppUnit>>. El link lo único que dice es que hay que abrir el archivo INSTALL-WIN32.txt que viene dentro del proyecto src/CppUnitLibraries.dsw. Ahí lo que dice es que hay que abrir el menú Generar > Generación por lotes (Batch build), luego lo seleccionamos todo y presionamos Generar.
Hay algunos de los proyectos que no compilan (4 de 12), seguramente falte un flag con la versión de Wintendo, porque se tiraWINVER not defined. Defaulting to 0x0600 (Windows Vista)
pero lib/cppunit.lib sí está bien, así es que probablemente podamos obviar ésto. Ojo que también está lib/cppunitd.lib (con símbolos de Debug).
- APR. Si bien tiene un Makefile.win, probablemente éste instale APR como dll y yo la necesito estática. Así es que intentaremos hacerlo desde el proyecto apr.dsw que viene en el zip. Nuevamente vamos a Generar > Generación por lotes y compilamos todo. Ok… compilan 36 de 48. ¿Cuál es el que nos sirve? Probablemente
apr, configuración: Release Win32
o a lo sumo el Debug Win32.
Eso sí en el README y en docs/win32_builds.html insisten en que hay que usar el define -D APR_DECLARE_STATIC. Ahora, no entiendo si éste es par el compilador de APR o para el linker de mi solución. Parece que es más o menos lo segundo:To use it as a static library, simply define APR_DECLARE_STATIC before you include any apr header files in your source, and link to apr.lib instead.
y también
In order to prepare to use one of the static libraries above, your application must be compiled with the define shown above, so that the correct linkage is created.
- APR-Util. Repetiremos el procedimiento anterior. Lo curioso es que los proyecyos de APR (a secas) vienen referenciados desde APR-Util, entonces da unos errores al abrir. ¿Será que hay que compilarlos juntos? En efecto, no compila de por sí.
Lo que pasa es que ambos deben estar en directorios paralelos >> (tan ituitivo que es…) llamados \midir\apr y \midir\aprutil. ¿Necesitaremos también apr-iconv? Sí, en \midir\apr-iconv. Y ahí tengo el aprutil-1.lib.
Nótese que al igual que para APR, hay que usar un define APU_DECLARE_STATIC. - Windows SDK. Como vimos más arriba.
Entonces ahora le daremos los include path a la solución de ActiveMQCpp. Ésto se hace en Herramientas > Opciones > Proyectos y soluciones > Directorios de VC++, seleccionando Archivos de inclusión y añadiendo los directorios include de cada carpeta.
¿Y dónde linkeamos las librerías estáticas? Ésto se debe hacer por proyecto, en Propiedades > Propiedades de configuración > Bibliotecario > General. Ahí, en Dependencias adicionales ponemos las librerías estáticas separadas por espacio e incluyendo la extensión .lib, y en Directorios de bibliotecas adicionales ponemos los directorios donde encontrarlos (LibD para los APR, lib para CppUnit).
Y compila, efectivamente. Ésto a pesar que no le pasé los define para APR. Pesa al rededor de 140Mb, por lo ques es probable que todas las librerías estáticas estén efectivamente adentro.
Lo que sí no compila son los ejemplos y los tests. ¿Quizás necesiten tener el primero como dependencia? Sí lo tienen. Parece que lo que no encuentran son las librerías de debug.
Por ej. activemq-cpp-integration-tests pide cppunitd.lib. Éste de hecho está linkeado en Propiedades > Propiedades de configuración > Vinculador > Entrada > Dependencias adicionales (es distinto a lo de arriba por ser distintos tipos de proyecto). La ruta a éstos debiera estar en Propiedades > Propiedades de configuración > Vinculador > General > Directorios de bibliotecas adicionales, en donde efectivamente se está linkeando por con macros (mismo problema que arriba).
Para definir las famosas macros, se hace en una hoja de propiedades >>. Hay que ir a Ver > Administrador de propiedades, ahí click derecho en el proyecto y Agregar nueva hoja de propiedades del proyecto, en ésta se encuentra Propiedades comunes > Macros del usuario, y ahí podemos agregar las tres rutas que necesitamos.
Después, para los demás proyectos de la solución, en el mismo Administrador de propiedades habrá que darles click derecho y Agregar hoja de propiedades existente para seleccionar la sheet que acabamos de crear. Para cada uno de ellos. Charcha.
Funciona, pero los ejemplos y tests siguen sin compilar, esta vez porque lo que busca son los dlls, no los libs. ¿Tendré que pasarle en alguna parte los define que vimos antes? Nop, de hecho ActiveMQCpp ya los tiene en Propiedades > Propiedades de configuración > C/C++ > Preprocesador > Definiciones del preprocesador.
Finalmente, si quiero linkear la librería estáticamente desde otro proyecto, se cae en el linker con el siguiente tipo de error
libactivemq-cpp.lib(start.obj) : error LNK2001: unresolved external symbol __imp__WSACleanup@0 libactivemq-cpp.lib(xlate.obj) : error LNK2001: unresolved external symbol _apr_iconv_open@16
por el segundo error, creo que puede que me haya faltado linkear apriconv dentro de activemq-cpp. el primero podría ser del SDK de Windows…
Yep, los errores de apr se resuelven incluyendo apriconv-1.lib como librería estática dentro de activemq-cpp.
Al parecer los errores __imp__ ¿son de Winsock? Tratemos de linkear ws2_32.lib en activemq-cpp (suponiendo que se encuentre en unos de los search pathspor defecto). Sí, se fueron la mayoría de los errores con ésto, y de hecho esa librería pertence al SDK de windows, pero aún me quedan
libactivemq-cpp.lib(sendrecv.obj) : error LNK2001: unresolved external symbol _TransmitFile@28 libactivemq-cpp.lib(rand.obj) : error LNK2001: unresolved external symbol __imp__UuidCreate@4
veamos a qué corresponden.
Wait, no será más bien que falta la variable de entorno de MSVC – que es una de las recomendaciones del README
MSVC install is set in the PATH env variable.
de hecho el comano cl.exe no se reconoce. Aquí está cómo se hace >>, pero no tiene nada que ver.
Otra opción antes de seguir buscando a qué librerías pertenecen estos símbolos, es instalar el Redistribuíble de MS >>. Ésto porque en el README dicen que hay que instalarlo en las máquinas que correrán el programa, en el mismo párrafo en el que dicen que hay que compilar con el SDK.
No, ya, básicamente TransmitFile se encuentra en Mswsock.lib y UuidCreate en Rpcrt4.lib (se me perdieron los links al respecto). Ambas librerías pertenecen al SDK de Windows y deben ser linkeadas en ActiveMQCpp si queremos linkearlo estáticamente.
Con ésto compila.
Sin embargo, en tiempo de ejecución se cae porque no encuentra el dll de SIGAR sigar-x86-winnt.dll. Ésto se soluciona copiándolo/pegándolo en C:\WINDOWS\system32, lo cual no me convence nada. También se puede dejar en la misma carpeta que el exe resultante (\Debug o \Release), lo cual es un poco más limpio, pero no del todo. En todo caso, éso es arena de otro costal >>>