xcode - que - script type= text/javascript src=
Xcode: Ejecutar un script antes de cada compilación que modifique el código fuente directamente (5)
A partir de Xcode 4, parece que si agrega los archivos generados a la sección de salida de la fase de compilación, respetará esa configuración y no generará ... has been modified since the precompiled header was built
los mensajes de error del ... has been modified since the precompiled header was built
.
Esta es una buena opción si su script solo genera un puñado de archivos cada vez.
Lo que hice:
Tengo un guion que
- Lee algunos archivos de configuración para generar fragmentos de código fuente
- Encuentra archivos fuente relevantes de Objective-C y
- Reemplace algunas partes del código fuente con el código generado en el paso 1.
y un Makefile que tiene un archivo de marca de tiempo especial como destino de marca y los archivos de configuración como orígenes de destino:
SRC = $(shell find ../config -iname "*.txt")
STAMP = $(PROJECT_TEMP_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME).stamp
$(STAMP): $(SRC)
python inject.py
touch $(STAMP)
Agregué este Makefile como una "Fase de compilación del script de ejecución" en la parte superior de la pila de fases de compilación para el objetivo del proyecto.
Que pasó:
La fase de compilación del script se ejecutó antes de compilar la fuente.
Sin embargo, como la secuencia de comandos modifica el código fuente durante su ejecución, tuve que compilar dos veces para obtener la versión más reciente del producto de compilación. Esto es lo que me imagino que está pasando:
- 1ª ejecución: Xcode recopila información de dependencia ---> sin cambios
- Primera ejecución: Xcode ejecuta "Run Script Build Phase" ---> la fuente se cambia detrás de la espalda de Xcode
- 1ª ejecución: Xcode finaliza la compilación, pensando que no hay que actualizar nada
- Segunda ejecución: Xcode recopila información de dependencia ---> la fuente ha cambiado, ¡necesita reconstrucción!
- Segunda ejecución: Xcode ejecuta Ejecutar secuencia de compilación de scripts "---> todo está actualizado
- Segunda ejecución: Xcode procede a la compilación.
Después de leer la documentación de Xcode en Build Phases , intenté agregar un archivo fuente que se sabe que se actualiza cada vez que se ejecuta el script como resultado de "Run Script Build Phases", pero nada cambió. Dado que la cantidad de archivos de configuración puede variar en mi proyecto, no quiero especificar cada archivo de entrada y salida.
Pregunta:
¿Cómo hago que Xcode tenga conocimiento de los cambios en el archivo fuente realizados durante la "Fase de compilación de ejecución de script"?
Editar:
- Se agregó que coloqué la fase de compilación del script antes de las otras fases de compilación.
Esta solución es probablemente obsoleta. Ver la respuesta más votada en su lugar.
Utilice "Objetivo externo":
- Seleccione "Proyecto"> "Nuevo objetivo ..." en el menú
- Seleccione "Mac OS X"> "Otro"> "Objetivo externo" y agréguelo a su proyecto
- Abra su configuración y complete la configuración de su script
- Abra la pestaña "General" de la configuración del objetivo principal y agregue el nuevo objetivo como dependencia directa
Ahora, el nuevo "Objetivo externo" se ejecuta antes de que el objetivo principal incluso comience a recopilar información de dependencia, por lo que cualquier cambio realizado durante la ejecución del script debe incluirse en la compilación.
Hay otra opción, ligeramente más simple, que no requiere un objetivo separado, pero solo es viable si su script tiende a modificar los mismos archivos de origen cada vez.
Primero, aquí hay una breve explicación para cualquiera que esté confundido acerca de por qué Xcode a veces requiere que compile dos veces (o haga una compilación limpia) para ver ciertos cambios reflejados en su aplicación de destino. Xcode compila un archivo fuente si falta el archivo objeto que produce, o si la fecha de última modificación del archivo objeto es anterior a la fecha de la última modificación del archivo fuente al comienzo de la primera fase de compilación . Si su proyecto ejecuta una secuencia de comandos que modifica un archivo de origen en una fase de compilación previa a la compilación, Xcode no notará que la fecha de última modificación del archivo de origen ha cambiado, por lo que no se molestará en volver a compilarlo. Solo cuando construyes el proyecto por segunda vez, Xcode notará el cambio de fecha y volverá a compilar el archivo.
Aquí hay una solución simple si su secuencia de comandos modifica los mismos archivos de origen cada vez. Simplemente agregue una fase de compilación de Run Script al final de su proceso de compilación de la siguiente manera:
touch Classes/FirstModifiedFile.m Classes/SecondModifiedFile.m
exit $?
La ejecución de estos archivos de origen al final del proceso de compilación garantiza que siempre tendrán una fecha de última modificación posterior a la de sus archivos de objeto, por lo que Xcode los recompilará cada vez.
Toda técnica mencionada hasta ahora es una exageración. Reproduciendo el comentario de steve kim para visibilidad:
En la pestaña de fases de compilación, simplemente arrastre el paso "Ejecutar script" a una ubicación más alta (por ejemplo, antes de "Compilar orígenes").
Probado en XCode 6
Yo también luché con esto durante mucho tiempo. La respuesta es usar la solución "Objetivo externo" de ento. Él es POR QUÉ ocurre este problema y cómo lo usamos en la práctica ...
Los pasos de compilación de Xcode4 no se ejecutan hasta DESPUÉS de que se haya compilado el plist. Esto es tonto, por supuesto, porque significa que cualquier paso previo a la compilación que modifique el plist no tendrá efecto. Pero si lo piensas, realmente tienen efecto ... en la compilación SIGUIENTE. Es por eso que algunas personas han hablado de "almacenar en caché" valores plist o "tengo que hacer 2 versiones para que funcione". Lo que sucede es que se crea el plist, luego se ejecuta el script. La próxima vez que construyas, Plist crea con tus archivos modificados, de ahí la segunda compilación.
La solución de ento es la única forma que he encontrado para hacer un verdadero paso previo a la construcción. Desafortunadamente, también encontré que no hace que el plist se actualice sin una compilación limpia y lo arreglé. Aquí es cómo tenemos valores de usuario basados en datos en el plist:
- Agregue un proyecto de sistema de compilación externo que apunte a un script de Python y pase algunos argumentos
- Agregar configuraciones de construcción definidas por el usuario a la construcción. Estos son los argumentos que pasas a python (más sobre por qué hacemos esto más adelante)
- La secuencia de comandos de python lee algunos archivos JSON de entrada y crea un archivo de encabezado de preprocesador de plist Y toca la lista principal de la aplicación
- El proyecto principal tiene "archivos de lista de preproceso" activados y apunta a este archivo de preprocesador
El uso de la tecla táctil en el archivo de la aplicación principal hace que el objetivo principal genere la lista cada vez. La razón por la que pasamos la configuración de compilación como parámetros es que nuestra compilación de línea de comandos puede anular la configuración:
- Agregue una variable definida por el usuario "foo" al proyecto prebuild.
- En tu prebuild puedes usar $ (foo) para pasar el valor a la secuencia de comandos de python.
- En la línea de comandos puede agregar foo = test para pasar un nuevo valor.
La secuencia de comandos de Python utiliza archivos de configuración base y permite que los archivos de configuración definidos por el usuario anulen los valores predeterminados. Usted hace un cambio e inmediatamente termina en la lista. Solo usamos esto para configuraciones que DEBEN estar en la lista. Para cualquier otra cosa, es una pérdida de esfuerzo ... generar un archivo json o algo similar en su lugar y cargarlo en tiempo de ejecución :)
Espero que esto ayude ... han sido un par de días difíciles para resolver esto.