tools from for xcode xcodebuild

from - xcodebuild install



¿Cómo fuerzo a Xcode para reconstruir el archivo Info.plist en mi proyecto cada vez que construyo el proyecto? (10)

Trabajando con Xcode 8.3.2

Inspirado por la respuesta de @LeeH de 2013, se me han ocurrido dos soluciones para reconstruir el Info.plist.

Solución 1: La más sencilla y elegante.

La solución más simple es forzar a Xcode a leer sus variables personalizadas tocando la lista de objetivos Info.plist .

Agregue una fase de compilación, vea la captura de pantalla a continuación (originalmente captura de pantalla para la Solución 2 ), y simplemente agregue esta línea:

touch $INFOPLIST_FILE

¡Eso es todo! Ahora Xcode debe forzar la recarga de sus variables personalizadas en el archivo Info.plist .

Esta solución es la misma que sugirió @lukelutman, pero usando la fase de compilación. El guión de pre-acción no me funcionó.

Solución 2: más compleja y pirata.

Otra solución es eliminar el Info.plist almacenado en caché en el directorio de compilación .

Escribí este super sencillo script de bash pequeño

#!/bin/bash info_plist="$CONFIGURATION_BUILD_DIR/$PRODUCT_NAME.app/Info.plist" echo "Removing Info.plist from build dir in order to force rebuild of it and reading of correct xcconfig variables, plist path $info_plist" rm "$info_plist"

Luego lo guardé y lo llamé desde las fases de construcción para el objetivo. Lo puse como la primera fase de construcción.

Fondo:

Tengo tres configuraciones diferentes: Config , Alpha , AppStore y estoy usando Universal Links, Notificaciones Push y otras cosas que requieren el uso de un archivo de titularidad. Pero no quería tener tres archivos de derechos, uno para cada configuración.

Mi proyecto ya se basa en gran medida en los archivos de configuración ( .xcconfig ). De hecho, configuré el archivo de derechos ( MyAppsProductName.entitlements ) usando variables de configuración personalizadas.

Pero quería leer el mismo tiempo de ejecución de las variables de configuración, pensé que podría hacerlo si se agregaran a mis objetivos Info.plist. Que funciono

Pero noté que cuando cambié los valores en mi archivo .xcconfig , entonces el archivo Info.plist no cambió el valor. Noté que si realizaba una compilación limpia, entonces los valores en la Info.plist obtuvieron actualizaciones de acuerdo con los valores dentro del archivo .xcconfig . De hecho, Xcode almacena en caché el archivo Info.plist .

Así que estas soluciones solucionan este problema. ¡Espero eso ayude! :)

Discusión

No tengo idea si la Solución 2 tiene alguna ventaja sobre la Solución 1 ... ¿Probablemente no? ¿Alguna entrada a alguien?

Al parecer, el archivo se almacena en caché, por lo que solo se crea cuando se modifica. Sin embargo, tengo variables de entorno configuradas para incrementar mi número de versión y las actualizo independientemente del plist (en realidad, en la configuración de construcción del proyecto) ¿Hay algún script que pueda usar como fase de compilación de un script que obligue a que se actualice Info.plist? ¿Alguna otra manera conveniente?


Asegúrese de que también actualice su vista de la lista.
Al ver el plist en Xcode, simplemente haga clic en el triángulo de revelación junto al elemento raíz en el plist ( Information Property List ). Y luego haz clic de nuevo para expandirlo.
Verás que los valores han sido actualizados. Estaba ejecutando un script similar y pensé que funcionaba solo de manera intermitente hasta que me di cuenta de que la vista completa simplemente no era refrescante.


En Xcode 4, puede usar una acción de construcción previa para tocar la lista de información.

Nota: Esto no es lo mismo que una fase de compilación del script de ejecución. Una acción de construcción previa ocurre antes de que Xcode verifique la lista de información, una fase de compilación del script de ejecución parece ocurrir después de que Xcode ya haya verificado la lista de información (por lo que solo funciona cada dos veces).

  1. Vaya a Editar esquema> Crear> Acciones previas
  2. Haga clic en el botón "+" y elija "Nueva acción del script de ejecución"
  3. Elija su objetivo en el menú desplegable "Proporcionar configuración de construcción desde"
  4. Agregue el touch "${SRCROOT}/${INFOPLIST_FILE}" en el cuadro de secuencia de comandos

Hay una opción en la pestaña "Crear" de la ventana Obtener información del objetivo, abajo en "Empaquetado" con la etiqueta "Archivo de información de preprocesamiento" que puede verificar. Creo que actualizará el archivo cada compilación.


Otro enfoque es crear un objetivo "agregado" que solo tiene una fase de compilación. Úsalo para tocar el archivo Info.plist. Haz que el objetivo sea una dependencia del objetivo que construye tu aplicación.

Debido a que es un destino separado y una dependencia del objetivo de su aplicación, se construirá antes de que incluso se comprueben los archivos Info.plist del objetivo de la aplicación. (Como se señaló en otra parte, las fases de compilación del objetivo de la aplicación en sí mismas se producen demasiado tarde, después de que la hora de modificación de los archivos Info.plist ya se haya verificado).


Para aquellos que han luchado para obtener un proyecto para realizar la creación de versiones automática, creé un proyecto macOS GitHub que demuestra cómo implementarlo de una manera muy fácil y directa, gracias a las ideas de @GayleDDS y Daniel Farrelly y su blog sobre versiones y Algunas implementaciones propias. Creo que puedes traducirlo a tus proyectos en otras plataformas sin problemas.

Aquí hay una pequeña guía de cómo puede replicarlo en sus proyectos (Xcode 8).

  1. Para disminuir las posibilidades de que se equivoque, asegúrese de haber agregado todos sus objetivos a su proyecto de antemano.
  2. Vaya al menú Archivo> Nuevo archivo ... y luego desplácese hacia abajo y elija Archivo de ajustes de configuración
  3. Asígnele el nombre BuildNumber y no olvide agregar este archivo de configuración a todos los destinos que desee mantener sincronizados; Para ello, haga clic en las casillas de verificación correspondientes antes de guardar este archivo.
  4. Debería ver un archivo llamado BuildNumber.xcconfig en su proyecto
  5. Agregue a este archivo el siguiente texto: CURRENT_PROJECT_VERSION = 1 . Si lo desea, puede comenzar con otro número. Este será su número de compilación que aumentará cada vez que construya. Sin embargo, por favor, no cambie el nombre de la variable .
  6. Si tiene más de un objetivo, agregue la siguiente secuencia de comandos al primer objetivo creado navegando a Proyecto> Destino> Construir fases
  7. Navegue al menú Editor> Agregar fase de compilación> Agregar fase de secuencia de comandos de ejecución
  8. Se debería haber agregado una fase de ejecución de script a su objetivo; así que arrástrelo hasta que esté debajo de Dependencias de destino (este detalle es importante).
  9. Ahora viene la parte interesante y explicaré el script casi línea por línea:

Comience por crear una ruta a PlistBuddy en la primera línea del script:

plistbuddy="/usr/libexec/PlistBuddy"

Agregue la línea 2 para leer el archivo de configuración y luego lea la variable CURRENT_PROJECT_VERSION que configuró en el paso 5.

OLD_VERSION=`cat "$SRCROOT/BuildNumber.xcconfig" | awk ''/CURRENT_PROJECT_VERSION/ { print $3 }''`

La línea 3-11 configura NEW_VERSION con el valor incrementado, luego guarda el archivo de configuración con el nuevo número de compilación; Las líneas restantes son para guardar la versión de marketing y el número de compilación en el plist:

NEW_VERSION=`cat "$SRCROOT/BuildNumber.xcconfig" | awk ''/CURRENT_PROJECT_VERSION/ { print $3 + 1 }''` sed -i '''' "s/CURRENT_PROJECT_VERSION = .*/CURRENT_PROJECT_VERSION = $NEW_VERSION/" "$SRCROOT/BuildNumber.xcconfig" CURRENT_PROJECT_VERSION=$NEW_VERSION BUILD_STR="Build $NEW_VERSION" COPYRIGHT_STR="© 2017 MyCompany.net" APP_VERSION_STR="1.3.5" $plistbuddy -c "Set :CFBundleShortVersionString $APP_VERSION_STR" "${SRCROOT}/$TARGETNAME/Info.plist" $plistbuddy -c "Set :CFBundleVersion $BUILD_STR" "${SRCROOT}/$EXECUTABLE_NAME/Info.plist" $plistbuddy -c "Set :NSHumanReadableCopyright $COPYRIGHT_STR" "$INFOPLIST_FILE"

También muestro en las líneas 8-11 cómo usar diferentes variables de entorno que Xcode configura para sus scripts. Puede agregar líneas adicionales para editar info.plist para otros objetivos y luego mantener la versión de su aplicación principal y sus ayudantes sincronizados. Vaya a GitHub , descargue el proyecto y juegue con él y luego adáptelo a sus necesidades. Feliz versionado automático con Xcode.


Podría intentar usar el comando touch para actualizar la marca de tiempo, que supongo que es lo que Xcode usa para determinar si se debe reconstruir, por ejemplo

$ touch Info.plist


Seleccione ''Editar esquema'', luego seleccione ''Crear'' desde el control de la izquierda.

Luego, agregue un paso de acciones previas, asegúrese de que el esquema en cuestión esté seleccionado en el menú desplegable ''Proporcionar configuraciones de compilación desde'' y luego agregue esto a la ventana de edición a continuación:

rm "${CONFIGURATION_BUILD_DIR}/${INFOPLIST_PATH}"

Esto eliminará la versión en caché de Info.plist , lo que Info.plist que XCode la reconstruya cada vez que presionas compilar.

Alternativamente, si deja que Xcode preprocese una plantilla de archivo Info.plist, simplemente toque la plantilla con

touch ${PROJECT_DIR}/${INFOPLIST_FILE}

trabaja tambien

Depuración de scripts de pre-acción

Los pasos de acciones previas no proporcionan ninguna información cuando ha cometido un error. Puede depurar el uso de sus variables de compilación agregando esta línea al script

echo "${CONFIGURATION_BUILD_DIR}/${INFOPLIST_PATH}" > ~/debug.txt

Luego verifique el contenido de ~/debug.txt para verificar que se haya ejecutado el script de acción previa y para ver si ha usado la ruta correcta.


Una forma de hacerlo sería tener una fase de compilación del script de ejecución para generar Info.plist desde un archivo Info.plist.template y luego rm Info.plist después de crear el paquete. Idea de un comentario que Dave DeLong publicó en su blog here .

Si el almacenamiento en caché es bastante grave (es decir, el almacenamiento en caché, incluso si no tiene la lista de información abierta en el historial de archivos), es posible que también desee rm la versión almacenada en caché en esta secuencia de comandos.


Yo también tengo la configuración automática de mis números de versión. He creado una fase de compilación de secuencia de comandos de ejecución . La clave es actualizar la copia del directorio de compilación de destino de Info.plist, no el directorio de compilación uno. También debe tener su secuencia de comandos de ejecución después de la fase de paquete de copia. Está bien editar el archivo del paquete directamente porque está antes de firmar el código. No quieres generar el archivo que está reinventando la rueda.

Aquí está mi guión:

# ---------------------------- IMPORTANT ---------------------------- # You must set GITHash to something like ''Set by build script'' in the file # file ''<Project Name>-Info.plist'' in the ''Supporting Files'' group # ------------------------------------------------------------------- # # Get the version number from the tag in git and the number of commits as the build number # appVersion=$(git describe --long | cut -f 1 -d "-") appBuild=$(git describe --long | cut -f 2 -d "-") gitHash=$(git describe --long | cut -f 3 -d "-") echo "From GIT Version = $appVersion Build = $appBuild" # # Set the version info in plist file # /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $appVersion" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}" /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $appBuild" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}" /usr/libexec/PlistBuddy -c "Set :GITHash $gitHash" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}" echo "Updated ${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"

Para su información , también configuro automáticamente la versión y compilo en la pestaña Acerca de con el siguiente código

NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; NSString *appDisplayName = infoDictionary[@"CFBundleDisplayName"]; NSString *majorVersion = infoDictionary[@"CFBundleShortVersionString"]; NSString *minorVersion = infoDictionary[@"CFBundleVersion"]; self.appDescription.text = [NSString stringWithFormat:@"Dirty Dog Software/n%@/nVersion: %@(%@)", appDisplayName, majorVersion, minorVersion];