xcode info.plist build variable ${PRODUCT_NAME:rfc1034identifier} seems completely undocumented?
Asked Answered
B

5

37

I'm trying to find documentation that describe the syntax and possibilities suggested by the construction ${PRODUCT_NAME:rfc1034identifier}. Obviously this turns into some version of the product name, but where is the documentation that describes how? I just grepped the entire /Developer directory, and got nothing useful.

I'm not looking for the narrow definition of what happens to this particular variable, I want to know about all such modifiers like rfc1034identifier.

Bayonne answered 2/3, 2011 at 21:5 Comment(6)
This might be helpful for you: #2468676Freestanding
I'm really looking for a formal definition. It makes me feel very nervous to be using things as if they were magic.Bayonne
Are you sure the ":" is a modifier and not just another character in the macro name? Where is the list of legal characters?Strontianite
That's what I'm asking. Among other things.Bayonne
Filed a developer issue with Apple.Bayonne
Filed a bug with Apple, since the DTS person couldn't find and documentation either. bugreport.apple.com/cgi-bin/WebObjects/RadarWeb.woa/9/wo/…Bayonne
B
13

At long last, Apple produced some documentation on this. This is in the "Text Macros" section of the Xcode manual, as of this date.

Text macro format reference

A text macro can contain any valid unicode text. It can also contain other text macros.

Including other text macros To include another text macro, add three underscore (_) characters before and after the macro name:

___<MacroName>___

Modifying text macro expansion You can modify the final expansion of the text macro by adding one or more modifiers. Add a modifier to a text macro by placing a colon (:) at the end of the macro followed by the modifier. Add multiple modifiers by separating each one with a comma (,).

<MACRO>:<modifier>[,<modifier>]…

For example, the following macro will remove the path extension from the FILENAME macro:

FILENAME:deletingPathExtension

To turn the modified macro above into a valid C identifier, add the identifier macro:

FILENAME:deletingPathExtension,identifier

Modifiers

bundleIdentifier: Replaces any non-bundle identifier characters with a hyphen (-).

deletingLastPathComponent: Removes the last path component from the expansion string.

deletingPathExtension: Removes any path extension from the expansion string.

deletingTrailingDot: Removes any trailing dots (.).

identifier: Replaces any non-C identifier characters with an underscore (_).

lastPathComponent: Returns just the last path component of the expansion string.

pathExtension: Returns the path extension of the expansion string.

rfc1034Identifier: Replaces any non-rfc1034 identifier characters with a hyphen (-).

xml: Replaces special xml characters with the corresponding escape string. For example, less-than (<) is replaced with &lt;

TEXT MACROS

Text macros reference

COPYRIGHT A copyright string that uses the company name of the team for the project. If there is no company name, the string is blank.

The example shows a copyright string when the company is set to “Apple”.

Copyright © 2018 Apple. All rights reserved.

DATE The current date.

DEFAULTTOOLCHAINSWIFTVERSION The version of Swift used for the default toolchain.

FILEBASENAME The name of the current file without any extension.

FILEBASENAMEASIDENTIFIER The name of the current file encoded as a C identifier.

FILEHEADER The text placed at the top of every new text file.

FILENAME The full name of the current file.

FULLUSERNAME The full name of the current macOS user.

NSHUMANREADABLECOPYRIGHTPLIST The entry for the human readable copyright string in the Info.plist file of a macOS app target. The value of the macro must include the XML delimiters for the plist. For example, a valid value is:

'''
    <key>NSHumanReadableCopyright</key>

    <string>Copyright © 2018 Apple, Inc. All rights reserved.</string>


'''

Notice that the value includes a newline.

ORGANIZATIONNAME The name for your organization that appears in boilerplate text throughout your project folder. The organization name in your project isn’t the same as the organization name that you enter in App Store Connect.

PACKAGENAME The name of the package built by the current scheme.

PACKAGENAMEASIDENTIFIER A C-identifier encoded version of the package name built by the current scheme.

PRODUCTNAME The app name of the product built by the current scheme.

PROJECTNAME The name of the current project.

RUNNINGMACOSVERSION The version of macOS that is running Xcode.

TARGETNAME The name of the current target.

TIME The current time.

USERNAME The login name for the current macOS user.

UUID Returns a unique ID. The first time this macro is used, it generates the ID before returning it. You can use this macro to create multiple unique IDs by using a modifier. Each modifier returns an ID that is unique for that modifier. For example, the first time the UUID:firstPurpose modifier is used, the macro generates and returns a unique ID for that macro and modifier combination. Subsequent uses of the UUID:firstPurpose modifier return the same ID. Adding the UUID:secondPurpose modifier generates and returns a different ID that will be unique to UUID:secondPurpose, and different from the ID for UUID:firstPurpose.

WORKSPACENAME The name of the current workspace. If there is only one project open, then the name of the current project.

YEAR The current year as a four-digit number.

Bayonne answered 29/8, 2018 at 14:57 Comment(0)
Y
33

By using strings I also dug out the following things that look like they're related to :rfc1034identifier:

  • :quote - adds backslashes before whitespaces (and more), for use in shell scripts
  • :identifier - replaces whitespace, slashes (and more) with underscores
  • :rfc1034identifier - replaces whitespace, slashes (and more) with dashes
  • :dir - don't know, observed replace with ./ in some cases
  • :abs - don't know

Exact command:

strings /Developer/Library/PrivateFrameworks/DevToolsCore.framework/Versions/A/DevToolsCore|grep '^:'

There are more things that look like interesting modifiers (for example, :char-range=%@), but I couldn't get these to work. There's only one example of :char-range on the net, and it's from a crash log for Xcode.

Someone asked how do we know it's a modifier specification. Well, we know because it works on multiple variables in build settings. Plist preprocessor probably uses the same mechanisms to resolve build variables as does the build system.

Hack Saw, if you get a response via that bug report, don't forget to keep us informed :-)

Yon answered 7/6, 2011 at 10:8 Comment(3)
I certainly will. Thanks for your investigation!Bayonne
WHen using stand alone Xcode.app, the path is /Applications/Xcode.app/Contents/OtherFrameworks/DevToolsCore.framework/Versions/A/DevToolsCoreLeandraleandre
codeworkshop.net/posts/xcode-build-setting-transformations looks like it has some helpful explanations.Temptress
C
13

Looks like you can stack these as well. The useful case floating around out there is

com.yourcompany.${PRODUCT_NAME:rfc1034identifier:lower}

such that a product name of "Your App" becomes com.yourcompany.your-app.

Cuddy answered 27/11, 2013 at 7:13 Comment(1)
Thanks for the hint! I was looking for something to uppercase a variable and :upper apparently works as well (XCode 8.2.1).Excision
B
13

At long last, Apple produced some documentation on this. This is in the "Text Macros" section of the Xcode manual, as of this date.

Text macro format reference

A text macro can contain any valid unicode text. It can also contain other text macros.

Including other text macros To include another text macro, add three underscore (_) characters before and after the macro name:

___<MacroName>___

Modifying text macro expansion You can modify the final expansion of the text macro by adding one or more modifiers. Add a modifier to a text macro by placing a colon (:) at the end of the macro followed by the modifier. Add multiple modifiers by separating each one with a comma (,).

<MACRO>:<modifier>[,<modifier>]…

For example, the following macro will remove the path extension from the FILENAME macro:

FILENAME:deletingPathExtension

To turn the modified macro above into a valid C identifier, add the identifier macro:

FILENAME:deletingPathExtension,identifier

Modifiers

bundleIdentifier: Replaces any non-bundle identifier characters with a hyphen (-).

deletingLastPathComponent: Removes the last path component from the expansion string.

deletingPathExtension: Removes any path extension from the expansion string.

deletingTrailingDot: Removes any trailing dots (.).

identifier: Replaces any non-C identifier characters with an underscore (_).

lastPathComponent: Returns just the last path component of the expansion string.

pathExtension: Returns the path extension of the expansion string.

rfc1034Identifier: Replaces any non-rfc1034 identifier characters with a hyphen (-).

xml: Replaces special xml characters with the corresponding escape string. For example, less-than (<) is replaced with &lt;

TEXT MACROS

Text macros reference

COPYRIGHT A copyright string that uses the company name of the team for the project. If there is no company name, the string is blank.

The example shows a copyright string when the company is set to “Apple”.

Copyright © 2018 Apple. All rights reserved.

DATE The current date.

DEFAULTTOOLCHAINSWIFTVERSION The version of Swift used for the default toolchain.

FILEBASENAME The name of the current file without any extension.

FILEBASENAMEASIDENTIFIER The name of the current file encoded as a C identifier.

FILEHEADER The text placed at the top of every new text file.

FILENAME The full name of the current file.

FULLUSERNAME The full name of the current macOS user.

NSHUMANREADABLECOPYRIGHTPLIST The entry for the human readable copyright string in the Info.plist file of a macOS app target. The value of the macro must include the XML delimiters for the plist. For example, a valid value is:

'''
    <key>NSHumanReadableCopyright</key>

    <string>Copyright © 2018 Apple, Inc. All rights reserved.</string>


'''

Notice that the value includes a newline.

ORGANIZATIONNAME The name for your organization that appears in boilerplate text throughout your project folder. The organization name in your project isn’t the same as the organization name that you enter in App Store Connect.

PACKAGENAME The name of the package built by the current scheme.

PACKAGENAMEASIDENTIFIER A C-identifier encoded version of the package name built by the current scheme.

PRODUCTNAME The app name of the product built by the current scheme.

PROJECTNAME The name of the current project.

RUNNINGMACOSVERSION The version of macOS that is running Xcode.

TARGETNAME The name of the current target.

TIME The current time.

USERNAME The login name for the current macOS user.

UUID Returns a unique ID. The first time this macro is used, it generates the ID before returning it. You can use this macro to create multiple unique IDs by using a modifier. Each modifier returns an ID that is unique for that modifier. For example, the first time the UUID:firstPurpose modifier is used, the macro generates and returns a unique ID for that macro and modifier combination. Subsequent uses of the UUID:firstPurpose modifier return the same ID. Adding the UUID:secondPurpose modifier generates and returns a different ID that will be unique to UUID:secondPurpose, and different from the ID for UUID:firstPurpose.

WORKSPACENAME The name of the current workspace. If there is only one project open, then the name of the current project.

YEAR The current year as a four-digit number.

Bayonne answered 29/8, 2018 at 14:57 Comment(0)
P
4
$ strings /Developer/Library/PrivateFrameworks/DevToolsCore.framework/Versions/A/DevToolsCore

PRODUCTNAME
PRODUCTNAMEASIDENTIFIER
PRODUCTNAMEASRFC1034IDENTIFIER
PRODUCTNAMEASXML

It seems that there are :identifier, :rfc1034identifier and :xml modifiers. But I have no clue except this.

Pardue answered 3/3, 2011 at 2:35 Comment(3)
It seems sad that we'd have to resort to forensics to get clues. I think I will have to file a bug with apple.Bayonne
But, why do you want to know about such modifiers? I have never seen any modifiers except PRODUCT_NAME:rfc1034identifier and PRODUCT_NAME:identifier.Pardue
I want to know what they are defined to do. Undocumented "features" are fragile in my mind. Maybe they'll be supported, maybe they'll be stable, maybe not.Bayonne
C
3

After stumbling over this question and its existing answers, I have to say: Apples documentation did not improve on this topic over the recent years. We are currently at Xcode 13 and there is still no complete list of all modifiers available.

Therefore I did some spelunking and found the supported modifiers in DVTFoundation.framework which I will list below.

I've tested them all in Xcode 13.3 build settings and used the following two macros to illustrate their impact:

MY_MACRO = Some "text" with umlauts äöüçñ and special characters are ',/|\-_:;%&<>.!
MY_SOURCE = /Applications/Xcode.app/Contents/Frameworks/../SharedFrameworks/DVTFoundation.framework

Retrieval operators/modifiers

Retrieval modifiers are used to extract and/or transform all or parts of a macro/variable/setting.
They are applied using the following syntax: $(<VARIABLE>:<MODIFIER>)

  • quote: Escapes all characters which have a special meaning in shell scripts/commands like space, colon, semicolon and backslash.
RESULT_quote = $(MY_MACRO:quote)

Some\ \"text\"\ with\ umlauts\ äöüçñ\ and\ special\ characters\ are\ \',/|\\-_:;%&<>.!
  • upper: Transforms all characters to their uppercase equivalents.
RESULT_upper = $(MY_MACRO:upper)

SOME "TEXT" WITH UMLAUTS ÄÖÜÇÑ AND SPECIAL CHARACTERS ARE ',/|\-_:;%&<>.!
  • lower: Transforms all characters to their lowercase equivalents.
RESULT_lower = $(MY_MACRO:lower)

some "text" with umlauts äöüçñ and special characters are ',/|\-_:;%&<>.!
  • identifier: Replaces any non-C identifier characters with an underscore (_).
RESULT_identifier = $(MY_MACRO:identifier)

Some__text__with_umlauts_______and_special_characters_are________________
  • rfc1034identifier: Replaces any non-rfc1034 identifier characters with a hyphen (-)
RESULT_rfc1034identifier = $(MY_MACRO:rfc1034identifier)


Some--text--with-umlauts-------and-special-characters-are----------------------------
  • c99extidentifier: Replaces any non-C99 identifier characters with an underscore (_). Umlauts are allowed as C99 uses Unicode!
RESULT_c99extidentifier = $(MY_MACRO:c99extidentifier)

Some__text__with_umlauts_äöüçñ_and_special_characters_are___________________________
  • xml: According to Apple documentation it should replace special xml characters with the corresponding escape string. For example, less-than (<) is replaced with <. But in my examples this didn't work.
RESULT_xml = $(MY_MACRO:xml)

Some "text" with umlauts äöüçñ and special characters are ',/|\-_:;%&<>.!
  • dir: Extracts the directory part of a path
RESULT_dir = $(MY_SOURCE:dir)

/Applications/Xcode.app/Contents/Frameworks/../SharedFrameworks/
  • file: Extracts the filename part of a path
RESULT_file = $(MY_SOURCE:file)

DVTFoundation.framework
  • base: Extracts the filename base part of a path (=filename without suffix/extension)
RESULT_base = $(MY_SOURCE:base)

DVTFoundation
  • suffix: Extracts the filename extension/suffix a path or filename
RESULT_suffix = $(MY_SOURCE:suffix)

.framework
  • standardizepath: Standardizes the path (e.g. ../ and tilde (~) are resolved)
RESULT_standardizepath = $(MY_SOURCE:standardizepath)

/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework

Replacement operators/modifiers

Beside above extracting/transforming operators, there is support built into the build settings system to replace specific parts of a directory which are matched using a modifier.
They are applied using the following syntax: $(<VARIABLE>:<MODIFIER>=<VALUE>)

  • dir=<VALUE>: Replaces the directory part of a path with <VALUE> and returns the new path
RESULT2_dir = $(MY_SOURCE:dir=/Developer/SharedFrameworks)

/Developer/SharedFrameworks/DVTFoundation.framework
  • file=<VALUE>: Replaces the filename part of a path and returns the new path
RESULT2_file = $(MY_SOURCE:file=my_file.txt)

/Applications/Xcode.app/Contents/Frameworks/../SharedFrameworks/my_file.txt
  • base=<VALUE>: Replaces the filename base part of a path (=filename without suffix/extension) and returns the new path
RESULT2_base = $(MY_SOURCE:base=Dummy)

/Applications/Xcode.app/Contents/Frameworks/../SharedFrameworks/Dummy.framework
  • suffix=<VALUE>: Replaces the filename extension/suffix a path and returns the new path
RESULT2_suffix = $(MY_SOURCE:suffix=.txt)

/Applications/Xcode.app/Contents/Frameworks/../SharedFrameworks/DVTFoundation.txt

I hope this list will help more people looking at Xcodes build settings and wondering how they can be transformed.

Carolus answered 7/5, 2022 at 13:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.