Foros

  • Mi problema es relativamente simple: estoy utilizando fmod en linux y viene como una librería que se carga dinámicamente (un .so que es lo que viene a ser una .dll, si no he entendido mal). El intríngulis viene porque cuando lo enlazo, se guarda exactamente la ruta a la librería que he utilizado para enlazar, pero esto me da un problema al ejecutar que demostraré con un ejemplo:

    Tengo esta estructura de directorios:

    • raíz, donde van a parar los ejecutables de la demo
      • data
      • src – el código fuente
        • fmod – fmod, sus .h, sus .so
        • otras librerías que no vienen a cuento

    El problema es que al enlazar, en la línea de comandos le pongo algo tal que

    g++ -w -O3 -g -o ../out $(SOURCES) ./fmod/libfmodex.so

    ¿Y qué pasa con eso? Pues que si luego ejecutas la demo (que recordemos está en el raíz), te sale que no puede cargar la librería porque no está exactamente en ./fmod/libfmodex.so

    La solución pasaría por editar de alguna manera que desconozco la tabla de enlaces del ejecutable y poder cambiarlo a ./libfmodex.so una vez enlazado. De esa manera, incluso podría cambiar el make para que al compilar, utilizara la copia de libfmodex.so que tiene que estar en la raíz. Pero no acabo de dar con el comando mágico…

    A ver si alguien ha hecho esto antes, es que en Mac sé que lo hice una vez, pero ahora no recuerdo cómo se llamaba el comando, ni sé muy bien si lo estoy buscando como toca.

  • Igual yo estoy muy perdido … pero según creo recordar si compilas contra una biblioteca dinámica está la va a buscar al LD_LIBRARY_PATH que tengas definido en tu sistema (generalmente /lib y /usr/lib).

    De todas maneras un enlace muy chulo sobre el tema http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html

    Saludos desde las Islas

  • Hola Sole,

    Vayamos por partes. En Linux, cuando se carga un binario (lease ejecutable o librería), que a su vez depende de otras librerías dinámicas .so (i.e. shared object), el enlazador dinámico (ld.so) busca las librerías correspondientes en un conjunto de rutas que incluyen:

    - las definidas a través de la variable de entorno LD_LIBRARY_PATH

    - las definidas en el propio binario (i.e. rpaths)

    - las definidas por defecto a nivel de sistema (e.g. /etc/ld.so.conf)

    En concreto, la búsqueda se realiza precisamente en este orden, y la primera librería encontrada que satisfaga la dependencia será la utilizada. Por lo que nos comentas, más que emplear el primer mecanismo, lo que deseas es definir la ruta donde se encuentra libfmodex.so en el propio binario.

    Para ello, ten en cuenta que lo que el binario contiene no es una lista con los enlaces a cada librería, sino una lista de rutas adicionales en las que buscar las dependencias. Esto es, esas rutas afectarán a la resolución de todas las dependencias, no solo a la búsqueda de esa librería individualmente.

    Dicho esto, esas rutas adicionales se pueden definir en tiempo de compilación pasando la opción “-rpath <dir>” o “-R <dir>” al enlazador (e.g. ld) tantas veces como sea necesario. Si quieres incorporar la opción para el enlazador en la llamada a g++, tendrás que indicarlo de este modo:

    g++ -w -O3 -g -o ../out $(SOURCES) -Lfmod -lfmodex -Wl,-R./src/fmod

    A continuación, para comprobar las rutas (i.e. rpaths) definidas en el ejecutable puedes utilizar el comando readelf tal que:

    readelf -d ../out | grep RPATH

    Por último, existe una utilidad que te permitirá alterar las rutas definidas en un ejecutable ya compilado, aunque no suele encontrarse instalada por defecto: chrpath. De todos modos, está disponible en los repositorios de Debian y Ubuntu, e imagino que lo mismo sucederá en otras distribuciones. Su uso es muy sencillo. Por ejemplo, para reemplazar las rutas de búsqueda en un binario, el comando a emplear sería:

    chrpath -r ./src/fmod ../out

    Y creo que eso es todo. Si tienes cualquier otra duda, no dudes en preguntar happy

  • Nada, he probado varias cosas y ninguna acaba de acertar. Que rabia!

    He llegado a compilar con alguna combinacion de -L, -Wl y blabla, pero he olvidado anotar que combinacion era. La he borrado porque aunque compilaba, el problema es que me habia enlazado la libreria apuntando a ../libfmodex.so que no es lo que quiero, claro esta.

    Todos los ejemplos que he visto hasta ahora van de enlazar rutas absolutas en las librerias (tal que /usr/local/pitimini). No piensan en las demos sad

    Mi pragmatica solucion:

    cp ../libfmodex.so ../libfmodex-4.24.11.so .
    g++ -O3 -o ../demo $(OBJECTS) ./libfmodex.so ./SOIL/libSOIL.a \\
    -pthread `sdl-config --cflags --libs` -lGL -lGLU
    rm ./libfmodex.so ./libfmodex-4.24.11.so

    Como libfmodex.so tiene que estar en el dir raiz, que es donde estara el exe al final, me la copio al dir de los sources para compilar, y luego la borro.

    Cutre? Si! Funciona? La unica que funciona! veryhappy

    Supongo que seria o eso, o usar el chrpath que comentas, pero es que no queria introducir una dependencia mas para compilar.

    ——-

    Y tambien he mirado el Makefile que proporcionan los ejemplos de fmod, y tiran un tanto hacia unas rutas peculiares tambien. Por ejemplo:

    g++ -O3 -o channelgroups main.c ../../api/lib/libfmodex.so -pthread

  • Ajá, así que lo que quieres es dejar tanto el binario como la librería en el raíz y ejecutarlos desde ahí. En tal caso, en vez de copiar la librería a la ubicación donde estás compilando, borrándola después, lo más fácil sería modificar tu llamada a G++ tal que:

    g++ -O3 -o ../demo $(OBJECTS) -L.. -lfmodex ./SOIL/libSOIL.a \\
    -pthread `sdl-config --cflags --libs` -lGL -lGLU -Wl,-R.

    Normalmente, las dependencias no se buscan en el directorio actual por seguridad, aunque algunas distribuciones lo establecen así. De todos modos, con pasarle al enlazador “-R.” como te indico, te curas en salud independientemente del sistema. De este modo, deberías poder ejecutar la demo sin problemas desde el raíz, aunque si intentas llamar al binario desde otra ubicación, entonces no encontrará la librería a menos que se encuentre instalada en uno de los directorios estándar del sistema… o que establezcas la variable de entorno LD_LIBRARY_PATH convenientemente.

    Aparte de eso, acabo de comprobar que tenías razón sobre el binario resultante cuando usas la ruta y el nombre completo de la librería para indicársela al compilador (en lugar de -l y -L). En tal caso, la dependencia se almacena explícitamente con la ruta dada y, aparentemente, ignora el resto de rutas para buscarla. Moraleja: usa -l y -L.

    Y para comprobar las dependencias del binario, y la resolución de las mismas desde el directorio actual, ya sabes:

    ldd demo

    P.D.: Si, a la hora de compilar, la librería en cuestión no se encuentra aún en el raíz (i.e. ..), sino que está en otro directorio, tan solo tienes que cambiar el path especificado mediante -L en la línea de compilación indicada más arriba.

  • Has dado en el blanco! Yo me habia hecho un lio con -L, -Wl,R y demas. Ahora ya compila, perfectamente.

    A mi para demos me gusta mas tener la libreria con el ejecutable, los dos juntitos. Eso de tener las librerias desperdigadas por /usr/lib me da un repelus considerable. Siempre pienso que si programas demos asi, estas llamando al fracaso cuanto antes posible, especialmente cuando presentas en una party. Ya me imagino la ventanita de turno anunciando que no se ha encontrado la dll/so/dylib correspondiente veryhappy

    Por cierto, la utilidad que comentaba para cambiar el path de una libreria en un ejecutable de MacOS se llama install_name_tool. Se usa, por ejemplo, asi:

    install_name_tool -change ../libfmodex.dylib ./libfmodex.dylib ../demo

    tal que: install_name_tool -change ruta_antigua nueva_ruta ejecutable

    Diria que viene con el SDK (el XCode y companyia). No recuerdo haberla instalado a mano, vamos.

    Bueno, me voy a entretener ahora probando BASS en lugar de fmod. Gracias de nuevo, senyor spock! happy

  • Como diría Andrew Martin: “uno se alegra de resultar útil” happy

  • Sole, si te interesa depender lo minimo de las librerias del sistema, igual te viene mejor meter el fmod y similares como enlace estatico (enlazando al .a) para que vaya todo en el ejecutable, y ademas te elimina automaticamente las funciones que no estes usando.

  • Si, a mi me encantaria poder hacer eso, pero resulta que se han puesto en plan proveer solamente .so’s en vez de .a’s tongue

    Echa un vistazo a sus .zips y ya veras, ya…