Open kastiglione opened 8 years ago
Can you please share a podspec & its source files so we can reproduce the issue? Thanks!
The issue here is that we generate an app target in 1.0 which imports a Pod to catch more errors during the linting process. The generated code is ObjC, though, which Pods like yours with C++ headers break, as you already discovered.
I see two possible fixes:
I think we can go with the first approach as headers probably won't hit any of the C vs. C++ incompatibilities and the second approach would likely be brittle.
First one sounds reasonable. Another possibility is generating as .m, compiling, and if that fails, re-generate as .mm, compile again, and if that works it's known to be C++. It would be slower linting for projects that use C++ in the headers, but would avoid any linkage issues for libraries that don't extern "C".
@kastiglione running pod spec lint
succeeds for me with FBAllocationTracker master
@segiddins The podspec has since been updated. It was version 0.1 that was failing.
Hm so since those all still use .h
extensions, I can't think of a good way of detecting this
Unfortunately, there's also no real standard for C++ header extensions, it goes all the way from .h
over .hh
to even having no extension. :sob:
Maybe we could switch to generating ObjC++ if library
contains c++
— this doesn't necessarily mean that a Pod's header exposes C++, but at least we would limit this to Pods which are (partially) written in C++.
That's not a bad place to start.
@neonichu but then that kinda screws of pods like Realm that use c++ but purposefully don't expose any to the user? idk, it just kinda sucks either way :P
Couldn't just the linter generate a dummy .mm
file also? Xcode takes care of the rest.
But that could (potentially) break imports of raw C headers
@neonichu I have same trouble. But I can make the lint project be succeeded! Do this (Use --no-clean --use-libraries):
pod lib lint --sources='http://gitlab.baidao.com/ios/ytx-pod-specs.git,master' --verbose --use-libraries --no-clean
open the temporary lint project like
open /var/folders/w2/khz8t6h10q51lx_hvw8ds9wr0000gn/T/CocoaPods/Lint/App.xcworkspace
Rename "main.m" to "main.mm" in xcode.
Modify "main.mm" like this: (Do not use @import
)
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <YTXChart/YTXChart.h>
int main() {}
Run the command which is executed in 'pod lib lint'
xcodebuild clean build -workspace App.xcworkspace -scheme App -configuration Release CODE_SIGN_IDENTITY=- -sdk iphonesimulator -destination id=F76ED5E4-9AB6-4BC1-8BD1-87676A2B08CC
Finally, BUILD SUCCEEDED
Touch /Users/apple/Library/Developer/Xcode/DerivedData/App-beckcjxzcqwvwhbhxsbzztinnxlo/Build/Products/Release-iphonesimulator/App.app
cd /var/folders/w2/khz8t6h10q51lx_hvw8ds9wr0000gn/T/CocoaPods/Lint
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/opt/local/bin:/opt/local/sbin:/Users/apple/bin:/usr/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Users/apple/android-sdk/platform-tools:/Users/apple/android-sdk/tools:/Users/apple/apache-ant-1.9.2/bin:/Users/apple/oclint/bin:/Users/apple/.gem/ruby/2.0.0/bin"
/usr/bin/touch -c /Users/apple/Library/Developer/Xcode/DerivedData/App-beckcjxzcqwvwhbhxsbzztinnxlo/Build/Products/Release-iphonesimulator/App.app
** BUILD SUCCEEDED **
So could you add a new parameter like '--use-c++' ? The new parameter will create a new temporary lint project. There is a "Main.mm" in this project.
This is my podspec:
Pod::Spec.new do |s|
s.name = "YTXChart"
s.version = "0.15.1"
s.summary = "YTXChart for pod"
# This description is used to generate tags and improve search results.
# * Think: What does it do? Why did you write it? What is the focus?
# * Try to keep it short, snappy and to the point.
# * Write the description between the DESC delimiters below.
# * Finally, don't worry about the indent, CocoaPods strips it!
s.description = "银天下Chart, 依赖AFNetworking"
s.homepage = "http://gitlab.baidao.com/ios/YTXChart.git"
# s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2"
s.license = 'MIT'
s.author = { "caojun-mac" => "78612846@qq.com" }
s.source = { :git => "http://gitlab.baidao.com/ios/YTXChart.git", :tag => s.version }
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
s.platform = :ios, '7.0'
s.requires_arc = true
s.source_files = "Pod/Classes/painter/*.{h,m,mm}", "Pod/Classes/painterview/*.{h,m,mm}", "Pod/Classes/chart/*.{h,m,mm}", "Pod/Classes/core/*.{h,mm}", "Pod/Classes/core/**/*.{h,m,mm,inl}"
# s.resource_bundles = {
# 'YTXChart' => ['Pod/Assets/*.png']
# }
s.frameworks = 'Foundation', 'UIKit'
s.libraries = 'sqlite3', 'c++'
s.dependency 'YTXServerId'
s.dependency 'AFNetworking', '~> 2.0'
end
PS: This repo lint succeeded at 0.39.0 and build succeeded in xcode GUI by using 'cmd+B'.
Hi @mdsb100
I have followed your steps and I come at the BUILD SUCCEEDED,
But I don't understood when I use the '--use-c++' parameters and finish my repo lint.
Can you explain a little more about this steps. Big Thanks.
@ezefranca I just suggest the contributor to add '--use-c++' parameter for creating a lint project like my steps.
'.mm' would include static c++ library like 'std'. 'main.mm' is the entrance, so it must be a '.mm'.
We can add a static c++ library in XCode, but it does not work. Unless you rename the main.m to main.mm.
'@import' check this import-vs-import-ios-7
I do not know why the c++ project can not be a Module. May be this:
You don't actually need to use the @import keyword. If you opt-in to using modules, all #import and #include directives are mapped to use @import automatically. That means that you don't have to change your source code (or the source code of libraries that you download from elsewhere). Supposedly using modules improves the build performance too, especially if you haven't been using PCHs well or if your project has many small source files.
You can test simple c++ project and use '@import'.
@segiddins When you plan to fix it?
@mdsb100 we haven't really come up with a good fix yet, so that's a prerequisite to implementing one, sorry
@segiddins Can you give a thought to my solution which is my previous comment in this issue. I have to switch to cocoapods@0.39.0 to lint and publish my c++/oc pod library.
We don't want to add new command line options for linting unless strictly necessary
+1
Is there any workaround to this? At least a way to push to a private repo without passing the linting stage?
@mikewoodworth Currently you have to switch 0.39.0 to lint and publish
I'd advocate for a --use-c++
flag, until a better solution is found. As it stands cocopods 1.0.1 is effectively useless as soon as c++ is used anywhere. Together with #5441 (support for symlinks; which is on hold), it seems like one should advocate to stick with 0.39.0 :(
@mdsb100 niubility!
Is there new message?
We can not use cocoapod@0.39.0 for now. Because some third-party depended module must need cocoapod@1.0.0 to publish/lint!!!
We cant rewrite c++ to oc...
Please help me
@mdsb100 现在好像没这个问题了吧
@a83988029 cocoapod@1.1.1 不能发啊 你能发?
@mdsb100 我能啊
@mdsb100 pod repo push private-repo 依赖c++header的xxx.podspec --allow-warnings --verbose --use-libraries
你的库在不在github上 我去研究下
@mdsb100 不在github,我们用的公司内部的gitlab
1.1.1么 我表示还是不行啊
@mdsb100 是1.1.1,我这没问题
那你lint能过么?你们不lint的?
我不lint啊,push成功了不就行了么,push失败了也能看到错误在哪,一般不lint
Finally, I figure out solution.
If you repo call the name is 'YTXChart', And you should add a 'YTXChart.h'. This header file does not contain any c++ header . In a word, 'YTXChart.h' can be empty. You can create a 'YTXChartHeader.h' contains origin content, this header can contain c++.
Lint passed! Test in cocoapods@1.1.1
Change your code in your main project:
<YTXChart/Chart.h>
to
<YTXChart/YTXChartHeader.h>
最终,我找到了一个解决方案。 如果你的repo名字是'YTXChart',你需要有一个叫做'YTXChart.h'的头文件。这个头文件不包含任何c++的内容(包括import的其他头文件)。一句话, 'YTXChart.h' 可以是空的。你可以增加一个'YTXChartHeader.h'包含原来头文件里的内容,这个头文件可以含有c++。
Lint 通过! 测试版本 cocoapods@1.1.1
在你的主工程里面把代码改成:
<YTXChart/Chart.h>
to
<YTXChart/YTXChartHeader.h>
@mdsb100 为啥一定要lint 直接push有什么问题吗
当然要Lint,合规啊。我这边是lint不过push也不过的。
My workaround was to edit cocoapods source to use C++ then I could push.
(Don't worry this is a private repo)
@ntnmrndn any chance you can make this repo public/forkable? I think we're ready to go the same way. Perhaps we can all pool our efforts to maintain as a fork until they are ready to move on this?
@mikewoodworth I edited the file in place on my computer. I created a gist with the one file I changed (validator.rb) https://gist.github.com/ntnmrndn/5f91755c12812390b3ae8dec73c1154e
I don't think maintaining a fork is a good idea, since it would be incompatible with the main cocoa pods. We should however try to move forward on this issue.
To sum up the previous talks and current status, it seems
So far the only option I see is to add a field to the podspec.
This could looks like this:
# ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# CocoaPods is smart about how it includes source code. For source files
# giving a folder will include any swift, h, m, mm, c & cpp files.
# For header files it will include any header in the folder.
# Not including the public_header_files will make all headers public.
#
s.source_files = "Classes", "Classes/**/*.{h,m}"
s.exclude_files = "Classes/Exclude"
# s.public_header_files = "Classes/**/*.h"
# s.public_cpp_header_files = "Classes/**/*.h[pp]?}"
If s.public_cpp_header_files contains files, we include them (and just them) in a separate main.mm
file, while they are excluded from main.m
compilation.
This should preserve backward compatibility and fix our issue.
If I could get feedback on this option quickly, I might find the time to implement it. Any thoughts ?
@ntnmrndn I think that sounds fair. I think a few other maintainers should weigh in and then perhaps implement this.
That would be nice
In 1.2.1.beta.1 a new option --skip-import-validation
was added to match the behavior of 0.39.x. This means you can push Pods without performing linking (overall risky to do) but it should unblock most of the C++ pods that fail to link because the generated main.m
does not work properly.
Until a much better solution is added I believe the flag should help most to publish.
Is there no "setting" to say that headers in a specific folder are C++ headers?
Wouldn't that be a good solution? (I know nothing about implementing it)
EDIT: @ntnmrndn proposes that solution, it looks good to me 👍
使用了 --use-libraries 之后就可以了
Was able to solve the linting issue by changing app_target_helper.rb
for cocoapod version 1.4.0 to this gist. It replicates the logic given by @ntnmrndn above
I just spent many hours trying to fix this same thing. Why is this not mentioned anywhere on the CocoaPods website ?
Report
Using latest beta, there's an issue when linting a library that has C++ in its headers. The file
CocoaPods/Lint/App/main.m
is ObjC, and gets compilation errors when the library has C++ in its headers.What did you do?
pod spec lint --private MyLibrary.podspec
What did you expected to happen?
I expected it to lint successfully. It does with the latest release of cocoapods (0.39.0) but not the latest pre-release (1.0.0.beta.6)
What happened instead?
Build errors pointing to
CocoaPods/Lint/App/main.m
. For example:fatal error: 'unordered_map' file not found
or
error: unknown type name 'namespace'
Podfile
No
Podfile
is involved. This was linting a.podspec
.