---
title: Archivos de configuración de compilación de Xcode
author: Mattt
translator: Nicolás García
category: Xcode
excerpt: >-
Las mejores prácticas de desarrollo de software prescriben la estricta separación entre configuración y código. Aprenda cómo puede utilizar los archivos `xcconfig` para hacer sus proyectos más comprensibles, compactos y potentes.
status:
swift: 5.2
revisions:
2019-05-13: Initial Publication
2020-02-27: Updated for Xcode 11.4
---
Las mejores prácticas de desarrollo de software prescriben la estricta separación entre configuración y código. Sin embargo, los desarrolladores de las plataformas de Apple a menudo luchan con hacerlas cuadrar con el pesado flujo de trabajo de Xcode.
En un proyecto, comprender lo que cada configuración hace y cómo interactúan entre sí, es una habilidad que puede llevar años perfeccionar. Tampoco nos hace ningún favor el hecho de que gran parte de esta información esté enterrada en lo profundo de las GUIs (interfaces gráficas de usuario) de Xcode.
Diríjase a la pestaña "Build Settings" (Configuración de compilación) del editor y será recibido por cientos de configuraciones de compilación, distribuidas en capas de proyectos, targets y configuraciones --- ¡y esto es nada comparado a las otras seis pestañas!
Afortunadamente, hay una mejor manera de administrar toda esta configuración, la cual implica no tener que hacer clicks dentro de un laberinto de pestañas.
Esta semana, le mostraremos cómo puede utilizar los archivos de texto de extensión xcconfig
para externalizar la configuración de compilación de Xcode, haciendo que sus proyectos sean más compactos, potentes y comprensibles.
{% info %}
Consulte XcodeBuildSettings.com para acceder a una completa referencia de cada configuración de compilación, compatible con la última versión de Xcode.
{% endinfo %}
Los archivos de configuración de compilación Xcode, más comúnmente conocidos por su extensión xcconfig
, permiten que la configuración de compilación de su aplicación se declare y administre sin utilizar Xcode. Son archivos de texto simples, lo que significa que son mucho más amigables con los sistemas de control de versiones y que se pueden modificar con cualquier editor de texto.
Fundamentalmente, cada archivo de configuración consiste de una secuencia de asignaciones en formato clave-valor, con la siguiente sintaxis:
<#NOMBRE_DE_CONFIGURACION#> = <#valor#>
Por ejemplo, para especificar la versión de Swift de un proyecto, debe especificar la configuración de compilación SWIFT_VERSION
de esta manera:
SWIFT_VERSION = 5.0
{% info %}
Según el estándar POSIX, las variables de entorno deben tener nombres que consisten únicamente de letras mayúsculas, dígitos y guiones bajos (_
) - una convención que me gusta llamar SCREAMING_SNAKE_CASE
🐍🗯.
{% endinfo %}
A primera vista, los archivos xcconfig
tienen un sorprendente parecido con los archivos .env
, debido a su sintaxis simple y delimitada por líneas nuevas. Pero hay más en los archivos de configuración de compilación de Xcode de lo que pareciera. ¡A dar una mirada!
Para añadir, en lugar de reemplazar las definiciones existentes, utilice la variable $(inherited)
de la siguiente manera:
<#NOMBRE_DE_CONFIGURACION#> = $(inherited)<#valor adicional#>
Normalmente, usted haría esto para crear listas de valores, como por ejemplo, las rutas donde el compilador busca los frameworks para encontrar los archivos de encabezado incluidos (FRAMEWORK_SEARCH_PATHS
):
FRAMEWORK_SEARCH_PATHS = $(inherited) $(PROJECT_DIR)
Xcode asigna los valores heredados en el siguiente orden (de menor a mayor precedencia):
- Valores predeterminados de la plataforma
- Archivo
xcconfig
del proyecto Xcode - Configuración de compilación del archivo de proyecto Xcode
- Archivo
xcconfig
del Target - Configuración de compilación del Target
{% info %}
Los espacios se utilizan para delimitar elementos en listas de rutas y texto. Para especificar un elemento que contenga espacios en blanco, debe encerrarlo entre comillas ("
).
{% endinfo %}
Puede sustituir valores de otras configuraciones mediante el nombre con el cual fueron declaradas usando la siguiente sintaxis:
<#NOMBRE_DE_CONFIGURACION#> = $(<#OTRO_NOMBRE_DE_CONFIGURACION#>)
Las sustituciones se pueden usar para definir nuevas variables de acuerdo con los valores existentes o en línea para construir nuevos valores dinámicamente.
OBJROOT = $(SYMROOT)
CONFIGURATION_BUILD_DIR = $(BUILD_DIR)/$(CONFIGURATION)-$(PLATFORM_NAME)
Desde Xcode 11.4 en adelante, puede utilizar el operador de evaluación default
para especificar un valor por defecto a usar en caso de que la configuración de compilación referenciada se evalúe como vacía.
$(<#NOMBRE_DE_CONFIGURACION#>:default=<#valor#>)
Puede condicionar la configuración de compilación según sus SDK (sdk
), arquitectura (arch
) y/o la configuración (config
) utilizando la siguiente sintaxis:
<#NOMBRE_DE_CONFIGURACION#>[sdk=<#sdk#>] = <#valor para el SDK especificado#>
<#NOMBRE_DE_CONFIGURACION#>[arch=<#architecture#>] = <#valor para la arquitectura especificada#>
<#NOMBRE_DE_CONFIGURACION#>[config=<#configuration#>] = <#valor para la configuración especificada#>
Dada la posibilidad de elegir entre varias definiciones de una misma configuración de compilación, el compilador resolverá según la especificidad dada.
<#NOMBRE_DE_CONFIGURACION#>[sdk=<#sdk#>][arch=<#architecture#>] = <#valor para el SDK y arquitectura especificados#>
<#NOMBRE_DE_CONFIGURACION#>[sdk=*][arch=<#architecture#>] = <#valor para todos los otros SDK con la arquitectura especificada#>
Por ejemplo, puede especificar la siguiente configuración de compilación para acelerar las compilaciones locales compilando solo para la arquitectura activa:
ONLY_ACTIVE_ARCH[config=Debug][sdk=*][arch=*] = YES
Un archivo de configuración de compilación puede incluir configuraciones de otros archivos de configuración usando la misma sintaxis #include
como en la directiva equivalente en C
, sobre la cual se basa esta funcionalidad:
#include "<#ruta/de/Archivo.xcconfig#>"
Como veremos más adelante en el artículo, puede aprovechar esto para crear listas en cascada de configuraciones de compilación de maneras muy poderosas.
{% info %}
Normalmente, cuando el compilador encuentra una directiva #include
que no se puede resolver, indicará un error. Pero los archivos xcconfig
también admiten la directiva #include?
, la cual no indicará un error si el archivo no se puede encontrar.
No hay muchos casos en los que usted quisiera que la existencia o inexistencia de un archivo cambie el comportamiento en tiempo de compilación; después de todo, las compilaciones son mejores cuando son predecibles. Pero, usted podría usar esta opción en herramientas de desarrollo opcionales como Reveal, la cual requiere la siguiente configuración:
# Reveal.xcconfig
OTHER_LDFLAGS = $(inherited) -weak_framework RevealServer
FRAMEWORK_SEARCH_PATHS = $(inherited) /Applications/Reveal.app/Contents/SharedSupport/iOS-Libraries
{% endinfo %}
Para crear un archivo de configuración de compilación, vaya al menú "File > New File..." (⌘N), desplácese hacia abajo hasta la sección etiquetada "Other", y seleccione la plantilla del archivo de ajustes de configuración (Configuration Settings File). Luego, guárdelo en algún lugar del directorio de su proyecto, asegurándose de no agregarlo a ningún target.
Una vez que haya creado el archivo xcconfig
, puede asignarlo a una o más configuraciones de compilación mediante sus targets asociados.
{% info %}
Los archivos de configuración de compilación no deben ser incluidos en ninguno de los targets de su proyecto. Si encuentra archivos .xcconfig
en el archivo .ipa
de su aplicación, asegúrese de que no sean miembros de ningún target y que no aparecen en ninguna fase de compilación en "Copy Bundle Resources".
{% endinfo %}
Ahora que hemos cubierto los conceptos básicos del uso de archivos de configuración de compilación de Xcode, veamos un par de ejemplos de cómo puede usarlos para gestionar entornos de desarrollo, integración y producción.
El desarrollo de una aplicación para iOS generalmente implica hacer malabarismos con varias compilaciones internas en los simuladores y dispositivos de pruebas (así como la última versión de la App Store).
Puede facilitarse las cosas con archivos xcconfig
, asignando en cada configuración un ícono y nombre distintivos para la aplicación.
// Development.xcconfig
PRODUCT_NAME = $(inherited) α
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-Alpha
//////////////////////////////////////////////////
// Staging.xcconfig
PRODUCT_NAME = $(inherited) β
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-Beta
Si sus desarrolladores back-end actúan de acuerdo con la filosofía 12 Factor App mencionada anteriormente, tendrán entonces endpoints separados para entornos de desarrollo, integración y producción.
En iOS, quizás el enfoque más común para administrar estos entornos es usar sentencias de compilación condicional, con configuraciones de compilación tales como DEBUG
.
import Foundation
#if DEBUG
let apiBaseURL = URL(string: "https://api.staging.example.com")!
#else
let apiBaseURL = URL(string: "https://api.example.com")!
#endif
Esto hace el trabajo, pero entra en conflicto con el canon de la separación entre código y configuración.
Un enfoque alternativo es tomar estos valores específicos para el entorno y ponerlos donde pertenecen - en archivos xcconfig
.
// Development.xcconfig
API_BASE_URL = api.staging.example.com
//////////////////////////////////////////
// Production.xcconfig
API_BASE_URL = api.example.com
{% warning %}
Los archivos xcconfig
tratan la secuencia //
como un delimitador de comentarios, independientemente de si está o no entre comillas. Si intenta utilizar barras invertidas \/\/
, estas apareceran literalmente y deberán ser eliminadas del valor resultante. Esto es especialmente inconveniente al especificar constantes de tipo URL por cada entorno.
Si prefiere evitar este desafortunado comportamiento, siempre puede omitir el esquema de la URL y anteponer https://
directamente en el código. (Está usando https... ¿verdad?)
{% endwarning %}
Sin embargo, para extraer estos valores programáticamente, tendremos que dar un paso adicional:
Las configuraciones de compilación definidas por el archivo del proyecto Xcode, los archivos xcconfig
y las variables de entorno solo están disponibles en tiempo de compilación. Cuando ejecute la aplicación, ya compilada, nada de ese contexto circundante estará disponible. (¡Y gracias a Dios por eso!)
Pero, espere un segundo - ¿No recuerda haber visto algunas de esas configuraciones antes? ¿En una de esas otras pestañas? En "Info", ¿verdad?
Sucede que esa pestaña de información es en realidad solo una presentación elegante del archivo Info.plist
del target. Al momento de compilar, ese archivo Info.plist
es compilado de acuerdo con la configuración de compilación proporcionada y luego copiado en el bundle resultante de la aplicación. Por lo tanto, al añadir referencias a $(API_BASE_URL)
, puede acceder a los valores para esas configuraciones a través de la propiedad infoDictionary
de la API Bundle
de Foundation. ¡Genial!
Siguiendo este enfoque, podríamos hacer algo como lo siguiente:
import Foundation
enum Configuration {
enum Error: Swift.Error {
case missingKey, invalidValue
}
static func value<T>(for key: String) throws -> T where T: LosslessStringConvertible {
guard let object = Bundle.main.object(forInfoDictionaryKey:key) else {
throw Error.missingKey
}
switch object {
case let value as T:
return value
case let string as String:
guard let value = T(string) else { fallthrough }
return value
default:
throw Error.invalidValue
}
}
}
enum API {
static var baseURL: URL {
return try! URL(string: "https://" + Configuration.value(for: "API_BASE_URL"))!
}
}
Visto desde el lugar de llamada, encontramos que este enfoque armoniza maravillosamente con nuestras mejores prácticas - ¡Ninguna constante definida programáticamente a la vista!
let url = URL(string: path, relativeTo: API.baseURL)!
var request = URLRequest(url: url)
request.httpMethod = method
{% error %}
No utilice los archivos xcconfig
para almacenar secretos como claves de API u otras credenciales. Para más información, consulte nuestro artículo sobre gestión de secretos en iOS.
{% enderror %}
Los proyectos de Xcode son monolíticos, frágiles y opacos. Son una fuente de fricción para la colaboración entre los miembros de un equipo y, generalmente, complicados de trabajar.
Afortunadamente, los archivos xcconfig
ayudan mucho para abordar estos puntos débiles. Mover la configuración de Xcode a los archivos xcconfig
confiere una multitud de beneficios y ofrece una manera de distanciar su proyecto de las particularidades de Xcode, sin abandonar el "camino feliz" aprobado por Cupertino.