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

Build errors when linting projects that expose C++ in headers #5152

Open
1 task done
kastiglione opened this issue Apr 13, 2016 · 49 comments
Open
1 task done

Build errors when linting projects that expose C++ in headers #5152

kastiglione opened this issue Apr 13, 2016 · 49 comments
Labels
s7:workaround available A workaround for the issue is available t2:defect These are known bugs. The issue should also contain steps to reproduce. PRs welcome!

Comments

@kastiglione
Copy link

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.

@segiddins
Copy link
Member

Can you please share a podspec & its source files so we can reproduce the issue? Thanks!

@segiddins segiddins added the s1:awaiting input Waiting for input from the original author label Apr 13, 2016
@neonichu
Copy link
Member

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:

  • Just make the generated files ObjC++ unconditionally.
  • Somehow determine if C++ is used by any headers and switch to ObjC++ in that case.

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.

@kastiglione
Copy link
Author

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".

@neonichu neonichu added t2:defect These are known bugs. The issue should also contain steps to reproduce. PRs welcome! and removed s1:awaiting input Waiting for input from the original author labels Apr 14, 2016
@segiddins
Copy link
Member

@kastiglione running pod spec lint succeeds for me with FBAllocationTracker master

@kastiglione
Copy link
Author

@segiddins The podspec has since been updated. It was version 0.1 that was failing.

@segiddins
Copy link
Member

Hm so since those all still use .h extensions, I can't think of a good way of detecting this

@neonichu
Copy link
Member

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. 😭

@neonichu
Copy link
Member

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++.

@kastiglione
Copy link
Author

That's not a bad place to start.

@segiddins
Copy link
Member

@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

@jafara
Copy link

jafara commented Apr 14, 2016

Couldn't just the linter generate a dummy .mm file also? Xcode takes care of the rest.

@segiddins
Copy link
Member

But that could (potentially) break imports of raw C headers

@mdsb100
Copy link

mdsb100 commented Jun 12, 2016

@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'.

@ezefranca
Copy link

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.

@mdsb100
Copy link

mdsb100 commented Jun 30, 2016

@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'.

@mdsb100
Copy link

mdsb100 commented Jul 14, 2016

@segiddins
When you plan to fix it?

@segiddins
Copy link
Member

@mdsb100 we haven't really come up with a good fix yet, so that's a prerequisite to implementing one, sorry

@mdsb100
Copy link

mdsb100 commented Jul 15, 2016

@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.

@segiddins
Copy link
Member

We don't want to add new command line options for linting unless strictly necessary

@mikewoodworth
Copy link

+1

Is there any workaround to this? At least a way to push to a private repo without passing the linting stage?

@kastiglione kastiglione changed the title Build errors when listing projects that expose C++ in headers Build errors when linting projects that expose C++ in headers Jul 21, 2016
@mdsb100
Copy link

mdsb100 commented Jul 21, 2016

@mikewoodworth
Currently you have to switch 0.39.0 to lint and publish

@angerman
Copy link

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 :(

@a83988029
Copy link

@mdsb100 niubility!

itsthejb pushed a commit to itsthejb/CKToolbox that referenced this issue Aug 30, 2016
@mdsb100
Copy link

mdsb100 commented Dec 9, 2016

1.1.1么 我表示还是不行啊

@a83988029
Copy link

@mdsb100 是1.1.1,我这没问题

@mdsb100
Copy link

mdsb100 commented Dec 9, 2016

那你lint能过么?你们不lint的?

@a83988029
Copy link

我不lint啊,push成功了不就行了么,push失败了也能看到错误在哪,一般不lint

@mdsb100
Copy link

mdsb100 commented Dec 15, 2016

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>

@a83988029
Copy link

@mdsb100
为啥一定要lint
直接push有什么问题吗

@mdsb100
Copy link

mdsb100 commented Dec 15, 2016

当然要Lint,合规啊。我这边是lint不过push也不过的。

@ntnmrndn
Copy link

My workaround was to edit cocoapods source to use C++ then I could push.

(Don't worry this is a private repo)

@mikewoodworth
Copy link

@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?

@ntnmrndn
Copy link

@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.

@ntnmrndn
Copy link

ntnmrndn commented Dec 20, 2016

To sum up the previous talks and current status, it seems

  • We do not support c++ headers because we are compiling in objective-c instead of c++.
  • We do not have a good solution to differentiate C++ from C from Objective C headers
  • We do not want to add command line options
  • We do not want to compile in ObjectiveC++ by default because it might in turn break C compatibility
  • We do not want to do both Objective C and Objective C++ because it might break mixed C/C++

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 ?

@dnkoutso
Copy link
Contributor

@ntnmrndn I think that sounds fair. I think a few other maintainers should weigh in and then perhaps implement this.

@beloso
Copy link

beloso commented Mar 21, 2017

That would be nice

@dnkoutso
Copy link
Contributor

dnkoutso commented Mar 21, 2017

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.

See #6420

@beloso
Copy link

beloso commented Apr 10, 2017

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 👍

@GarryLance
Copy link

使用了 --use-libraries 之后就可以了

@priteshrnandgaonkar
Copy link

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

facebook-github-bot pushed a commit to facebook/yoga that referenced this issue Mar 23, 2018
Summary:
Podspec to push yoga 1.8.0 to cocoapods. There is an issue with cocoapods and it fails to lint those projects with C++ in its header, which is the case with yoga too.

Follow this thread CocoaPods/CocoaPods#5152. To make the lint pass, one would have to change `app_target_helper.rb` cocoapod source file in the local machine. Follow my [gist](https://gist.github.com/priteshrnandgaonkar/dcca9639a3bc0a3b9adecae3a2b3b0c4).

I am able to pass the lint, but not able to push the pod in cocoapods as I am not the admin. @[759512522:emilsj], please push it on Cocoapods or give me permission.

Podspec now also exposes public header explicitly.

Reviewed By: gkassabli

Differential Revision: D7375018

fbshipit-source-id: 4e82e1c0b6340c3f8d3b8a96ecadbcb711d4bcd8
@dnkoutso dnkoutso added the s7:workaround available A workaround for the issue is available label Aug 4, 2018
TimSylvester added a commit to mousebird-consulting-inc/WhirlyGlobe that referenced this issue Jun 7, 2021
…t` from working.

- Files in `*_header_files` must also be included in `source_files`
- Eigen needs to be included but doesn't use extensions and so can't be included in `source_files`.
Unfortunately it still fails because `pod` uses a `.m` file as the final target, so C++ stuff doesn't build.  See CocoaPods/CocoaPods#5152
Remove obsolete iOS GLES stuff, but leave GLU for tessellation
TimSylvester added a commit to mousebird-consulting-inc/WhirlyGlobe that referenced this issue Apr 13, 2022
…t` from working.

- Files in `*_header_files` must also be included in `source_files`
- Eigen needs to be included but doesn't use extensions and so can't be included in `source_files`.
Unfortunately it still fails because `pod` uses a `.m` file as the final target, so C++ stuff doesn't build.  See CocoaPods/CocoaPods#5152
Remove obsolete iOS GLES stuff, but leave GLU for tessellation


Former-commit-id: 9c74f1e
@Sakari369
Copy link

I just spent many hours trying to fix this same thing. Why is this not mentioned anywhere on the CocoaPods website ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
s7:workaround available A workaround for the issue is available t2:defect These are known bugs. The issue should also contain steps to reproduce. PRs welcome!
Projects
None yet
Development

No branches or pull requests