Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variables in build settings are not resolved #505

Closed
mgrebenets opened this issue Sep 22, 2017 · 12 comments · Fixed by #507
Closed

Variables in build settings are not resolved #505

mgrebenets opened this issue Sep 22, 2017 · 12 comments · Fixed by #507

Comments

@mgrebenets
Copy link

Variables defined in xcconfig files and then used in build settings are not properly resolved.

Here's a sample project:
https://github.com/mgrebenets/XcodeprojBuildSettingsDemo

For example, PROVISIONING_PROFILE_SPECIFIER build setting is configured like so:
image

Both variables are defined in xcconfig files and are correctly resolved by Xcode:
image

The variables are also properly resolved by xcodebuild -showBuildSettings, for example:

xcodebuild -showBuildSettings -project  XcodeprojBuildSettingsDemo.xcodeproj` -configuration Release

# Output:
#  PROVISIONING_PROFILE_SPECIFIER = au.com.company.app

xcodebuild -showBuildSettings -project  XcodeprojBuildSettingsDemo.xcodeproj` -configuration Debug

# Output:
# PROVISIONING_PROFILE_SPECIFIER = match Development dev-au.com.company.app.prod

Using xcodeproj gem, however, fails to resolve the build settings:

path = 'path/to/XcodeprojBuildSettingsDemo/XcodeprojBuildSettingsDemo.xcodeproj'
p = Xcodeproj::Project.open(path)
t = p.targets.first
bc = t.build_configurations[1]
bs = bc.resolve_build_setting('PROVISIONING_PROFILE_SPECIFIER')
puts bs

# Output:
# $(COM_RELEASE_PROVISIONING_PROFILE_SPECIFIER_PROD)
@mgrebenets
Copy link
Author

This has been picked up as fastlane gym issue: fastlane/fastlane#10315

@UnsafePointer
Copy link
Contributor

Can you try passing the root target? https://github.com/CocoaPods/Xcodeproj/blob/master/lib/xcodeproj/project/object/build_configuration.rb#L85, in this case it would be something like:

t = p.targets.first
bc = t.build_configurations[1]
bs = bc.resolve_build_setting('PROVISIONING_PROFILE_SPECIFIER', t)

@mgrebenets
Copy link
Author

Actually, looks like for some of the times when I tried I forgot to use bundle exec... :/

Anyways, when I try with xcodeproj version 1.51.0 it tells me that resolve_build_setting takes only 1 argument, which is fine cause in that version is does take only 1.
So I switch to latest master and this time it works, the output is COM_BUNDLE_ID_BASE for both with and without the root target.

It doesn't seem to be resolving it right if I understand it correctly.
I'd expect the output to be au.com.company.app.

@UnsafePointer
Copy link
Contributor

I'm happy to take a look at this later today. Thank you for trying out master.

@UnsafePointer
Copy link
Contributor

I had a look at this and the problem is that you're using #include statements in your xcconfig files. Currently Config#to_hash doesn't support include statements. As a workaround you could get rid of those and duplicate some of the contents of Base.xcconfig.

@segiddins any hints on how to support include statements here?

@segiddins
Copy link
Member

It'd probably require parsing the included file, and merging in the current file's settings on top of it

@mgrebenets
Copy link
Author

In terms of workarounds that'd definitely one way to solve it temporarily.
I've tried and it works, at it's something I'd have to do to get CI into green again.

In the long term we'd need to get back to using #include statements with xcconfigs, so I'll be watching this one :)

Another thing that I noticed, that variable substitution logic in xcodeproj only seems to work for $(VAR) syntax, and fails to resolve $VAR syntax.
Probably it's related to the regex used to match variables in the settings, it seems it's expecting parens to be mandatory.

Do you think I should open a separate issue for $(VAR) vs $VAR or track it as part of this one?

@segiddins
Copy link
Member

Do you think I should open a separate issue for $(VAR) vs $VAR or track it as part of this one?

Separate issue

It'd probably require parsing the included file, and merging in the current file's settings on top of it

I meant that as the way this would likely be implemented in Xcodeproj

@truebit
Copy link

truebit commented Nov 3, 2017

after updated to 1.5.3, arguments like $(PRODUCT_NAME:rfc1034identifier) still not been converted.

And if I change it to $(PRODUCT_NAME}, it would display as TARGET_NAME, actually, it should be $(TARGET_NAME). so if arguments with recursion, still not work.

@OmarPedraza
Copy link

As @truebit points out, arguments with recursion don't work yet in version 1.5.9.

Any estimation for fixing this?

@segiddins
Copy link
Member

Please open up another issue, and contributions are welcome to add that functionality!

@azmenak
Copy link

azmenak commented Feb 11, 2020

For anyone still coming across this issue, wrote a quick method which solves our somewhat limited use case of having arguments like $(PRODUCT_NAME:lower) not being converted.

# Augments config.resolve_build_setting from xcproject
# to continue expanding build settings and evaluate modifiers
def resolve_recursive_build_setting(config, setting)
  resolution = config.resolve_build_setting(setting)

  # finds values with one of
  # $VALUE
  # $(VALLUE)
  # $(VALUE:modifier)
  # ${VALUE}
  # ${VALUE:modifier}
  resolution.gsub(/\$[\(\{]?.+[\)\}]?/) do |raw_value|
    # strip $() characters
    unresolved = raw_value.gsub(/[\$\(\)\{\}]/, '')

    # Get the modifiers after the ':' characters
    name, *modifiers = unresolved.split(':')

    # Expand variable name
    subresolution = resolve_recursive_build_setting(config, name)

    # Apply modifiers
    # NOTE: not all cases accounted for
    #
    # See http://codeworkshop.net/posts/xcode-build-setting-transformations
    # for various modifier options
    modifiers.each do |modifier|
      case modifier
      when 'lower'
        subresolution.downcase!
      when 'upper'
        subresolution.upcase!
      else
        # Fastlane message
        UI.error("Unknown modifier: `#{modifier}` in `#{raw_value}")
      end
    end

    subresolution
  end
end

Can replaced uses of config.resolve_build_setting

resolve_recursive_build_setting(config, 'PRODUCT_BUNDLE_IDENTIFIER')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants