Estoy construyendo un marco dinámico desde la fuente para iOS con bitcode habilitado (usando cmake y xcodebuild). Utilizo lipo y install_name_tool para hacer un binario pesado y actualizar LC_ID_DYLIB, para que el binario se cargue correctamente. Cuando archive la aplicación, el marco está correctamente firmado y empaquetado con la aplicación. Esta es la salida de file:

MyFramework: Mach-O universal binary with 3 architectures: [arm_v7: Mach-O dynamically linked shared library arm_v7] [arm_v7s] [arm64]
MyFramework (for architecture armv7):   Mach-O dynamically linked shared library arm_v7
MyFramework (for architecture armv7s):  Mach-O dynamically linked shared library arm_v7s
MyFramework (for architecture arm64):   Mach-O 64-bit dynamically linked shared library arm64

Al observar la salida de otool -l para LC_ID_DYLIB se muestra esto:

Load command 4
          cmd LC_ID_DYLIB
      cmdsize 64
         name @rpath/MyFramework.framework/MyFramework (offset 24)
   time stamp 1 Thu Jan  1 01:00:01 1970
      current version 1.0.0
compatibility version 1.0.0

Todo parece correcto. Si subo este archivo a la App Store, se carga y procesa correctamente. Después de ejecutarlo desde la App Store, se bloquea inmediatamente después del inicio, debido a la carga de marcos dinámicos. Se sabe que las aplicaciones se vuelven a compilar desde Bitcode en App Store, así que simulé eso exportando como Ad-Hoc y dejando habilitada la opción "Reconstruir desde Bitcode" como se sugiere en Nota técnica TN2432. Al inspeccionar el .ipa (que también se bloqueó después del inicio) y el marco en cuestión, este es el resultado de otool -l:

Load command 3
          cmd LC_ID_DYLIB
      cmdsize 128
         name /Users/legoless/Downloads/ios/build/build-iphoneos/lib/Release/MyFramework_ios.framework/MyFramework_ios (offset 24)
   time stamp 1 Thu Jan  1 01:00:01 1970
      current version 1.0.0
compatibility version 1.0.0

Entonces, obviamente, el LC_ID_DYLIB de esta biblioteca es incorrecto y esta es la ruta absoluta a la ubicación donde se construyó originalmente el marco, antes de hacer un binario gordo. Esto se reemplaza en el paso Reconstruir desde Bitcode , pero no tengo idea de por qué o incluso dónde se almacena esta ruta en el archivo Mach-O existente. Usé las herramientas otool y objdump para tratar de encontrar la referencia en el binario Mach-O, sin suerte.

En la práctica, otro marco depende de este y este es el comando de carga para el marco de destino:

Load command 14
          cmd LC_LOAD_DYLIB
      cmdsize 64
         name @rpath/MyFramework.framework/MyFramework (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 1.0.0
compatibility version 1.0.0

Nuevamente, después de Rebuild with Bitcode, la referencia también se cambia aquí:

Load command 13
          cmd LC_LOAD_DYLIB
      cmdsize 128
         name /Users/legoless/Downloads/ios/build/build-iphoneos/lib/Release/MyFramework_ios.framework/MyFramework_ios (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 1.0.0
compatibility version 1.0.0

Esto solo sucede para el marco en cuestión, pero no para otros marcos, donde @rpath se deja como estaba.

Mi pregunta aún permanece:

¿Dónde se almacena esta referencia de ruta absoluta? ¿Y cómo eliminarlo para que Rebuild from Bitcode ya no lo afecte?

¡Gracias!

4
Legoless 13 dic. 2016 a las 13:47

2 respuestas

La mejor respuesta

Al hacer una investigación detallada sobre este problema, se demostró que el archivo .xar que contiene el código de bits dentro del archivo Mach-O almacena bastante información, incluidas las banderas del vinculador. Esta información se almacena en la Tabla de contenido del archivo y se utiliza para recompilar / volver a vincular las bibliotecas en la recompilación de código de bits.

En mi caso, estaba construyendo el marco con cmake , que agregó esta información a los indicadores del vinculador . Configurar INSTALL_NAME_DIR y BUILD_WITH_INSTALL_RPATH y usar @rpath solucionó el problema de manera efectiva, y install_name_tool ya no era necesario.

2
Legoless 14 ene. 2017 a las 05:59

Estaba experimentando exactamente el mismo problema. La respuesta aceptada me acercó, pero configurar el parámetro INSTALL_NAME_DIR por sí solo no lo solucionó, ya que no le permite establecer el valor completo pasado al vinculador como install_name (solo el directorio, como era de esperar ).

En su lugar, configuro XCODE_ATTRIBUTE_LD_DYLIB_INSTALL_NAME que sobrescribe el valor completo de una sola vez. Obviamente, esto solo funciona en el generador XCode en CMake, pero estaba bien para lo que quería. Para resumir, mi archivo CMake para este marco ahora contiene:

set_target_properties(${LIBRARY_NAME} PROPERTIES XCODE_ATTRIBUTE_LD_DYLIB_INSTALL_NAME "@rpath/${LIBRARY_NAME}.framework/${LIBRARY_NAME}")
set_target_properties(${LIBRARY_NAME} PROPERTIES BUILD_WITH_INSTALL_RPATH 1)
0
mfj 21 sep. 2017 a las 10:48