Vacío Perfecto

Un poco acerca de nada

Cocoapods y los nuevos Mac

| Comments

Si llevas algún tiempo desarrollando en iOS habrás oido hablar de Cocoapods. Si aún no, conviene que te tomes una pausa y te pongas a leer sobre este sistema de distribución de componentes. Si conoces el mundo ruby, podemos decir que cocoapods es un sistema similar al gems de ruby. Y el haber elegido esta similitud no es casual porque cocapods está escrita, igual que gems, en ruby y de hecho hay que utilizar gems para instalarlo. El proceso no puede ser más sencillo:

Gandalf:~ rbarbera$ sudo gems install cocoapods

Y ahí empiezan nuestros problemas cuando intentamos utilizar uno de los nuevos Mac, o más concretamente, un Mac en el que se ha instalado OS X 10.7 partiendo de cero. En la web de cocoapods se puede ver que la versión de ruby necesaria es la 1.9.3 que no es la que viene instalada en OS X. Es decir, tenemos que empezar por instalar dicha versión.

rvm

El método recomendado para instalar un entorno de ruby es emplear el rvm (Ruby enVironment Manager). En principio la cosa es sencilla, tres lineas de comando y a rodar.

Gandalf:~ rbarbera$ bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)
Gandalf:~ rbarbera$ source ~/.bash_profile
Gandalf:~ rbarbera$ rvm install 1.9.3

El problema es que esta útima linea provoca un error. El culpable es el compiladore de c. Hasta la versión 4.1 de XCode, el IDE de Apple utilizaba como compilador de c, el mundialmente conocido gcc. Sin embargo, a partir de esa versión, Apple comenzó a utilizar un nuevo compilador, el clang basado en LLVM. Durante unas cuantas versiones de XCode Apple inlcuia ambos compiladores en su IDE y por lo tanto ambos estaban disponibles en la linea de comandos, necesaria para compilar los fuentes descargados. Pero en las versiones más recientes, Apple no incluye gcc, pues todo su sistema de desarrollo a pasado a utilizar el compilador más moderno, clang.

Una búsqueda en Stackoverflow nos da muchas entradas y la mayoría de ellas te obligan a instalar el gcc para facilitar la instalación. Sin embargo en unos equipos dedicados fundamentalmente al desarrollo en iOS, no me gustaba la idea de reinstalar un compilador extra. Puesto que clang entiende todos los switches y opciones de gcc, lo único que debería hacer es indicarle al proceso de configuración que utilice dicho compilador.

Primer intento: xcrun clang

Dicho y hecho. Mi primera opción es utilizar xcrun clang para emplear la versión del compilador distribuida con XCode

Gandalf:~ rbarbera$ rvm install 1.9.3 --with-gcc="xcrun clang"
Installing Ruby from source to: /Users/rbarbera/.rvm/rubies/ruby-1.9.3-p392, this may take a while depending on your cpu(s)...
ruby-1.9.3-p392 - #downloading ruby-1.9.3-p392, this may take a while depending on your connection...
######################################################################## 100,0%
ruby-1.9.3-p392 - #extracting ruby-1.9.3-p392 to /Users/rbarbera/.rvm/src/ruby-1.9.3-p392
ruby-1.9.3-p392 - #extracted to /Users/rbarbera/.rvm/src/ruby-1.9.3-p392
ruby-1.9.3-p392 - #configuring
Error running './configure --disable-install-doc --prefix=/Users/rbarbera/.rvm/rubies/ruby-1.9.3-p392 --with-gcc=xcrun clang --with-opt-dir=/Users/rbarbera/.rvm/usr --disable-shared', please read /Users/rbarbera/.rvm/log/ruby-1.9.3-p392/configure.log

Vaya, investigando en el log parece que a ./configure no le gusta que interpongamos a xcrun para la busqueda del compilador. Tenemos dos opciones: la primera es descargar las Command Line Tools desde dentro de XCode

Instalando CLT

La segunda, un poco más verbose es pedirle a xcrun el path de clang dentro de XCode

Gandalf:~ rbarbera$ xcrun -f clang
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang

Ese path es la ubicación del compilador de c que utiliza tu distribución de XCode cada vez que necesita compiar algo y es la misma que se ejecuta cuando invocas xcrun clang

Segundo intento: compilamos con clang

En mi caso, instalé las CTL y con toda la confianza del mundo, intenté compilar de nuevo ruby

Gandalf:~ rbarbera$ rvm install 1.9.3 --with-gcc=clang
Installing Ruby from source to: /Users/rbarbera/.rvm/rubies/ruby-1.9.3-p392, this may take a while depending on your cpu(s)...
ruby-1.9.3-p392 - #downloading ruby-1.9.3-p392, this may take a while depending on your connection...
ruby-1.9.3-p392 - #extracted to /Users/rbarbera/.rvm/src/ruby-1.9.3-p392 (already extracted)
ruby-1.9.3-p392 - #configuring
ruby-1.9.3-p392 - #compiling
Error running 'make', please read /Users/rbarbera/.rvm/log/ruby-1.9.3-p392/make.log
There has been an error while running make. Halting the installation.

¿Como? ¿un error de compilación en una versión de ruby estable? Vamos a ver que dice el make.log y nos encontramos con que hay una asignación de un long a int y el compilador nos lanza un warning avisando del posible truncado al pasar de 64 a 32 bits.

compiling st.c
st.c:520:35: error: implicit conversion loses integer precision: 'st_index_t' (aka 'unsigned long') to 'int' [-Werror,-Wshorten-64-to-32]
    i = table->num_entries++;
      ~ ~~~~~~~~~~~~~~~~~~^~

Por defecto el sistema de compilación de ruby trata todos los avisos como errores y ahí se detiene la compilación. Al parecer gcc es más permisivo con esas cosas y no le importa la posible pérdida de datos. Una busqueda en Stackoverflow de nuevo nos lleva en la dirección incorrecta: desinstalar XCode, instalar gcc, editar los fuentes directamente y cambiar el long por int (así, a pelo, sin analizar nada más).

Tercer intento: Evitamos que clang sea tan exquisito

Por suerte existe una solución más sencilla, seguir utilizando nuestro clang y pasarle el flag adecuado para que no genere error en ese warning en concreto.

Gandalf:~ rbarbera$ rvm install 1.9.3 --with-gcc=clang -C CFLAGS=-Wno-error=shorten-64-to-32
Installing Ruby from source to: /Users/rbarbera/.rvm/rubies/ruby-1.9.3-p392, this may take a while depending on your cpu(s)...
ruby-1.9.3-p392 - #downloading ruby-1.9.3-p392, this may take a while depending on your connection...
ruby-1.9.3-p392 - #extracted to /Users/rbarbera/.rvm/src/ruby-1.9.3-p392 (already extracted)
ruby-1.9.3-p392 - #configuring
ruby-1.9.3-p392 - #compiling
ruby-1.9.3-p392 - #installing 
Retrieving rubygems-1.8.25
######################################################################## 100,0%
Extracting rubygems-1.8.25 ...
Removing old Rubygems files...
Installing rubygems-1.8.25 for ruby-1.9.3-p392 ...
Installation of rubygems completed successfully.
Saving wrappers to '/Users/rbarbera/.rvm/bin'.
ruby-1.9.3-p392 - #adjusting #shebangs for (gem irb erb ri rdoc testrb rake).
ruby-1.9.3-p392 - #importing default gemsets, this may take time ...
Install of ruby-1.9.3-p392 - #complete 

Por fin tenemos un ruby 1.9.3 instalado en OS X 10.7 sin gcc, utilizando el compilador LLVM incluido con xcode. Ahora podemos configurar esta versión de ruby como entorno por defecto y comprobar que efectivamente vamos a utilizar ruby 1.9.3 como entorno de trabajo por defecto desde este momento

Gandalf:~ rbarbera$ rvm use 1.9.3 --default
Using /Users/rbarbera/.rvm/gems/ruby-1.9.3-p392
Gandalf:~ rbarbera$ ruby -v
ruby 1.9.3p392 (2013-02-22 revision 39386) [x86_64-darwin11.4.2]

Y ahora es sencillo instalar cocoapods

Gandalf:~ rbarbera$ sudo gem install cocoapods
Password:
Fetching: i18n-0.6.4.gem (100%)
Fetching: multi_json-1.6.1.gem (100%)
[...]
Installing RDoc documentation for cocoapods-0.16.4...

¿Ha merecido la pena el tiempo perdido? Bueno, yo creo que poder utilizar cocoapods en un Mac actual, sin tener que instalar otros compiladores, o subsistemas como homebrew si que ha merecido el tiempo invertido en investigar una solución limpia.

Gandalf:ruby-1.9.3-p392 rbarbera$ pod search dialog
Setting up CocoaPods master repo
Cloning spec repo `master' from `https://github.com/CocoaPods/Specs.git' (branch `master')

Cocoapods 0.17.0.rc5 is available.

Setup completed (read-only access)


-> CODialog (0.0.1)
   CODialog is a completely configurable, almost pixel perfect replacement for UIAlertView.
   - Homepage: https://github.com/eaigner/CODialog
   - Source:   https://github.com/eaigner/CODialog.git
   - Versions: 0.0.1 [master repo]


   -> QuickDialog (0.7)
   Quick and easy dialog screens for iOS.
   - Homepage: http://escoz.com/quickdialog
   - Source:   https://github.com/escoz/QuickDialog.git
   - Versions: 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1 [master repo]

Comments