-fobjc-arc flag passed to tools which don't understand it
amolloy opened this issue · comments
CocoaPods appears to add the -fobjc-arc flag to all compiled sources when requires_arc is true (which is the default now in 0.34), regardless of whether the tool that compiles that source file understands the flag or not. In particular, yacc (bison) will fail, and there are probably others.
Steps:
- Add a pod which includes a yacc source file and has requires_arc set to true to your podfile.
- Run pod install
- Build in Xcode
Expected results:
- CocoaPods only applies the -fobjc-arc flag to Objective-C source files (*.m, *.mm) and the project builds without error.
Actual results:
- CocoaPods applies the -fobjc-arc flag to every compiled source file, regardless of file type. This does not cause issues for files compiled using clang, regardless of the actual language, but fails with files compiled with some other tools including yacc/bison.
@amolloy Can you attach an example podspec which causes this problem.
Here is an example offending podspec:
Pod::Spec.new do |s|
s.name = "Moment"
s.version = "0.0.1"
s.summary = "Natural language date parser using Lex/Yacc/C."
s.homepage = "https://github.com/kmussel/Moment"
s.license = 'MIT'
s.author = 'kmussel'
s.source = { :git => "https://github.com/kmussel/Moment.git", :commit => "39f21fee0cef410c6d89c9fa94ff5638527ef7bc" }
s.source_files = 'TimeParser.{c,h}', 'parseIt.ym', 'tokeIt.l'
end
parseIt.ym will fail to compile because bison rejects the -fobjc-arc flag. Interestingly, lex appears to just ignore the flag and handles tokeIt.l with no warnings or errors.
I can confirm this one, we should only apply the -fobjc-arc
flag only to Objective-C sources. Removing these flags allows this pod to compile.
Yacc Moment/parseIt.ym
cd /Users/kylef/Desktop/testa/Pods
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/yacc -fobjc-arc -DOS_OBJECT_USE_OBJC=0 -d -b /Users/kylef/Library/Developer/Xcode/DerivedData/testa-cvtzssloqiqzlxebiovfijmnuzdr/Build/Intermediates/Pods.build/Debug-iphonesimulator/Pods-Moment.build/DerivedSources/y /Users/kylef/Desktop/testa/Pods/Moment/parseIt.ym
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/bison: invalid option -- f
Try `/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/bison --help' for more information.
Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/yacc failed with exit code 1
@amolloy, as a temporary work around. You should be able to set requires_arc
to false for this spec.
Thanks, I've done that so I'm good for now.
This seems to also be true for subspecs that don't use arc, causing it to add both the -fno-objc-arc flag and the -fobjc-arc one:
PodSpec:
{
"name": "Kiwi",
"version": "2.2.3",
"summary": "A Behavior Driven Development library for iOS and OS X.",
"homepage": "https://github.com/allending/Kiwi",
"authors": {
"Allen Ding": "alding@gmail.com",
"Luke Redpath": "luke@lukeredpath.co.uk",
"Marin Usalj": "mneorr@gmail.com",
"Stepan Hruda": "stepan.hruda@gmail.com"
},
"license": {
"type": "MIT",
"file": "License.txt"
},
"source": {
"git": "https://github.com/allending/Kiwi.git",
"tag": "2.2.3"
},
"ios": {
"xcconfig": {
"FRAMEWORK_SEARCH_PATHS": "$(inherited) \"$(SDKROOT)/Developer/Library/Frameworks\" \"$(DEVELOPER_LIBRARY_DIR)/Frameworks\""
}
},
"osx": {
"xcconfig": {
"FRAMEWORK_SEARCH_PATHS": "$(inherited) \"$(DEVELOPER_LIBRARY_DIR)/Frameworks\""
}
},
"platforms": {
"ios": "5.0",
"osx": "10.7"
},
"default_subspec": "SenTestingKit",
"subspecs": [
{
"name": "SenTestingKit",
"frameworks": "SenTestingKit",
"dependencies": {
"Kiwi/ARC": [
],
"Kiwi/NonARC": [
]
},
"source_files": "SenTestingKit/**/*.{h,m}",
"prefix_header_contents": "#import <SenTestingKit/SenTestingKit.h>\n"
},
{
"name": "XCTest",
"frameworks": "XCTest",
"dependencies": {
"Kiwi/ARC": [
],
"Kiwi/NonARC": [
]
},
"prefix_header_contents": "#import <XCTest/XCTest.h>\n"
},
{
"name": "ARC",
"source_files": "Classes/**/*.{h,m}",
"requires_arc": true
},
{
"name": "NonARC",
"source_files": "NonARC/**/*.{h,m}",
"compiler_flags": "-fno-objc-arc"
}
]
}
I think this is an issue with the "NonARC" subspec, it should specify requires_arc: false
, as it'll default to true
regardless of the contents of compiler_flags
.
For anyone interested in fixing this
It will require a little bit of refactoring. Currently compiler_flags_for_consumer
is called for each spec_consumer
which results in every "regular file" inside the consumer to have the same build flags. It's being called by add_files_to_build_phases
to get the compiler flags which are passed to Xcodeproj when adding the file references to the target. All of this logic lyes in lib/cocoapods/installer/target_installer/pod_target_installer.rb
.
target.add_file_references(regular_file_refs, flags)
I'd expect we would need to filter out the Objective-C like (This includes Objective-C++ etc) files which support ARC and add these file_references separate of the ones for non-arc supporting file types.
Here's the relevant two methods:
def add_files_to_build_phases
library.file_accessors.each do |file_accessor|
consumer = file_accessor.spec_consumer
flags = compiler_flags_for_consumer(consumer)
all_source_files = file_accessor.source_files
regular_source_files = all_source_files.reject { |sf| sf.extname == '.d' }
regular_file_refs = regular_source_files.map { |sf| project.reference_for_path(sf) }
target.add_file_references(regular_file_refs, flags)
other_file_refs = (all_source_files - regular_source_files).map { |sf| project.reference_for_path(sf) }
target.add_file_references(other_file_refs, nil)
end
end
def compiler_flags_for_consumer(consumer)
flags = consumer.compiler_flags.dup
if consumer.requires_arc
flags << '-fobjc-arc'
platform_name = consumer.platform_name
spec_deployment_target = consumer.spec.deployment_target(platform_name)
if spec_deployment_target.nil? || Version.new(spec_deployment_target) < ENABLE_OBJECT_USE_OBJC_FROM[platform_name]
flags << '-DOS_OBJECT_USE_OBJC=0'
end
end
if target_definition.inhibits_warnings_for_pod?(consumer.spec.root.name)
flags << '-w -Xanalyzer -analyzer-disable-checker -Xanalyzer deadcode'
end
flags * ' '
end
There is also #2262 which could probably be done a the same time, which means it's file which do not use ARC get the -fno-objc-arc
flag instead of files which support arc getting the '-fobjc-arc'
flag.
/cc @kattrali
@k0nserv did we fix this?
We had the discussion about what we should do to allow this and the conclusion was to make requires_arc
accept a file pattern instead. At least that the last I've heard of it, however I am unsure of the current status as I have been out of the loop the last month.
Regarding this issue the changes I made should solve it since the -fobjc-arc
is not passed anymore however now the opposite is going to be a problem, e.g requires_arc
set to false
Bump ...
Any idea when this might be fixed? :-) It's causing builds to fail for a number of important specs that use things like yacc, etc and the C libraries.
Is -fobjc-arc
still passed? #2769 makes it so that -fobjc-no-arc
is passed and the project default becomes CLANG_ENABLE_OBJC_ARC
.
@k0nserv I tried https://github.com/Bertrand/handlebars-objc from the linked issues and it lints for me (after fixing an unrelated issue with public_headers
in the spec).
CocoaPods never sets CLANG_ENABLE_OBJC_ARC
to NO
, only appends compiler flags (at least from what I've tried). So if you have source files that are non-arc (one example is the repository @neonichu mentioned), Pods will be unable to build without modifying build settings manually in Xcode and setting that property + removing all compiler flags for non-ObjC files.
Checked, this is still valid in 0.36.x, to repro:
git clone git@github.com:uranusjr/macdown.git
cd macdown
git submodule init
git submodule update
pod install