Open adrigm opened 11 years ago
Por mi parte me gustaria que usaramos Boost, porque nunca lo he usado y estaria bueno aprender alguna tecnología nueva, pero no sé si complica demasiado las cosas, vemos que opinan los demás, igualmente @adrigm tu decides!! jaja
El problema de Boost es que es pesado de narices para un proyecto tan simple, encima filesystem no es de las que tenga solo headers sino que también tiene binarios.
yo opto por no usar la librería Boost, más que nada porque puede dificultar la lectura de algo que se hace puramente con una intención didáctica, además se añadir más tamaño al proyecto.
Por mi usemos argv[0]. Que sistemas operativos no ponen la ruta ahí?
Voto por usar argv[0].
Aquí hay una buena colección de formas nativas en cada sistema: http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe
Pero prefiriría huir de esto si es posible.
Yo en mi experiencia de multiplataforma he encontrado dos métodos: 1. Usar las APIs del sistema en proyectos pequeños. En Linux tienes readlink(); usando como path /proc/self/exe y en Windows tienes GetModuleFileName();, puedes usar eso o, 2. usar un script en plataformas UNIX, ya que estas son la únicas que cargan los recursos así, en Windows da igual. El script sería similar a este: http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Deploying%20Your%20Application#Building_and_Packaging_Dynamically
Estos son mis 2 centavos como dirían los ingleses.
Podríamos usar una interfaz y que en cada sistema operativo se utilize la mas común, cuanto mas código multiplataforma se use mejor, pero llegara un punto en el que no sea posible.
tendriamos una interfaz ResourceReader
y luego las distintas implementaciones para cada SO
PD: se nota mucho q vengo del mundo Java, no?
argv[0]
esta mal. Digamos que el binario esta en /usr/bin/genbetadev/juego
pero nosotros lo llamamos desde la terminal con juego
... argv[0]
va a ser igual a juego
lo que, obviamente, esta completamente mal.
La manera "correcta" de hacerlo en C++ sería con boost::filesystem
aunque como ya habeis dicho es algo pesado para incluir en un proyecto como este, aunque bueno, eso se puede discutir.
getcwd
es una función que funciona en todos los sitemas POSIX (y Windows: http://msdn.microsoft.com/en-us/library/windows/desktop/aa364934(v=vs.85).aspx) y aparentemente es la manera correcta de obtenerlo.
http://pic.dhe.ibm.com/infocenter/zos/v1r12/index.jsp?topic=%2Fcom.ibm.zos.r12.bpxbd00%2Frtgtc.htm
Por cierto, hay un draft para crear un std::filesystem
Aunque siquiera esta implementado en C++11.
getcwd devuelve el directorio desde el que fue llamado el ejecutable. Así puesejecutar test desde el mismo directorio y desde, por ejemplo, la raíz es diferente. Hay una posibilidad que es uniendo getcwd y argv[0], pero yo soy más partidario del script para Unix-like o las llamadas nativas.
Una idea que no sé si es factible, pero por si acaso aquí la dejo. ¿Sería posible, al iniciar el programa, hacer un CD al directorio donde reside el ejecutable y a partir de ahí resolverlo todo con rutas relativas?
Buscando un poco he encontrado:
Windows:
int bytes = GetModuleFileName(NULL, pBuf, len);
if(bytes == 0)
return -1;
else
return bytes;
Linux:
char szTmp[32];
sprintf(szTmp, "/proc/%d/exe", getpid());
int bytes = MIN(readlink(szTmp, pBuf, len), len - 1);
if(bytes >= 0)
pBuf[bytes] = '\0';
return bytes;
El código está sacado de: http://stackoverflow.com/questions/143174/how-do-i-get-the-directory-that-a-program-is-running-from
Hm, y en *nix no podemos hacer "whereis juego" ? Eso debería devolver el directorio donde se encuentra el Binario.
Cómo exactamente usarías el whereis? No tiene sentido usar una aplicación de línea de comando para averiguar el directorio, invocada desde el propio ejecutable
Según la documentación de Boost, para obtener el directorio actual del proceso llama current_path http://www.boost.org/doc/libs/1_32_0/libs/filesystem/doc/operations.htm#current_path, en el que usa getcwd
en Linux y GetCurrentDirectory
en Windows (Dice que son sus equivalentes en cada SO, por lo que podemos estimar que los usa) como mencionó @dysoco anteriormente, por lo que podriamos hacerlo de este modo,
@LeonardoJegigzem creo que lo que tu dices no es lo que se busca. Esa función de boost te da el directorio actual, pero lo que buscamos es el directorio del ejecutable (que puede ser distinto)
En esta respuesta de SO dan una solución multiplataforma, que básicamente es lo que ha dicho @DavidBM http://stackoverflow.com/questions/933850/how-to-find-the-location-of-the-executable-in-c
Quizás nos deberíamos plantear usar Boost Filesystem para el manejo del sistema de ficheros, nos ahorraríamos reinventar un sistema multiplataforma bien probado.
Para mi integrarlo no es problema, pero crearíamos dependencia de dos nuevas bibliotecas Boost::Filesystem y Boost::System (Filesystem depende de ella).
Aquí la cuestión sería si como SFML que cada uno copie las librerías o integrarlas en el proyecto. Yo soy de los que siempre compila Boost a pelo tanto en Windows como en Linux, pero quizás para los usuarios noveles deberíamos distribuir los binarios aunque sea de windows ya que en linux tenemos versiones de Boost en los repositorios. En OSX no sé si existe una forma sencillo de instalar binarios sin compilar el código fuente tu mismo.
Boost en OSX se instala con Homebrew fácilmente:
brew install boost
Y si no tienes homebrew en OSX... ¡mal hecho! ;) http://brew.sh
@adrigm a mi usar Boost no me parece mala idea. Es una librería que se usa mucho, así que es una gran oportunidad para aprender. Además si vamos con cuidado y no abusamos puedes mantener las dependencias con Boost bajo control (e.g. a veces puedes añadir algo simplemente con referenciar un header)
Tienes mi voto :+1:
Filesystem no es de las de solo headers como lo son la mayoría de Boost es de las pocas que tiene biblioteca, ademas depende de System que también tiene.
Es decir que hay que incluir los headers necesarios (hay que mirar cuantas dependencias hay en total) y a parte la parte compilada de System y Filesystem.
Por mi la usamos, ya he trabajado con Boost y es una delicia. Incluso se me ocurre que en el futuro (mucho más adelante) si queremos meter un lenguaje de scripts podemos hacer uso de Boost Python.
Lo se lo se, digo que hay otras dependencias que son menos "duras". Que Filesystem tenga dependencias de librerías es lógico, ya que tiene que linkar con las librerías de cada diferente SOs.
Este debería ser un problema conocido para el que se haya enfrentado a proyectos multiplataformas.
En el gestor de recursos y en general en cualquier lugar que se trabaje con ficheros normalmente los buscaremos con rutas relativas al ejecutable ("Data/images/player.png"), donde Data está en el mismo directorio que el ejecutable.
El problema es que C++ las rutas relativas las calcula desde el directorio donde se está ejecutando, si tu en linux haces algo como:
Las rutas relativas te las va a calcular desde el directorio actual y no desde el directorio del ejecutable. Por lo que necesitamos utilizar rutas absolutas para que no falle.
La forma que se suele usar de resolver esto es obteniendo la ruta del ejecutable con argv[0]. No todos los sistema usan argv[0] para almacenar la ruta del ejecutable, pero si es lo más generalizado y en los sistemas a los que vamos a dar soporte sí lo hacen. Así que creo que sería la opción más acertada.
Otra opción es usar algo externo como Boost Filesystem que es un todo terreno para esto, pero prefiero, de momento, no meter grandes bibliotecas externas.