如何组织以前由 GCC Make 编译的 C 源文件并将它们构建到 Xcode 包中?我有一个重复的符号 _main 错误 [英] How to organize C source file previously compiled by GCC Make and build them into an Xcode bundle? I have a Duplicate Symbol _main Error

查看:15
本文介绍了如何组织以前由 GCC Make 编译的 C 源文件并将它们构建到 Xcode 包中?我有一个重复的符号 _main 错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何从源代码构建 .bundle?

这听起来像是一个简单的问题,但它已经困扰了我一个星期......

这是我的问题:

我有一堆 .c 和 .h 文件,它们组织在一个文件夹及其子文件夹中.源代码是用 gcc make 编写和编译的,并由许多其他 make 工具测试.源代码有一些实用程序和命令行工具,并且它有更多的代码作为这些实用程序和工具的库.我想重用这些文件作为库.(通过库我不是指静态库或其他东西,我只是说某些子文件夹中的一些 .c 和 .h 文件提供了可以被其他一些 .c 文件调用的函数.我希望能够调用这些函数,也)

但我的问题比这更复杂:我需要将这些 .c 和 .h 构建到一个包中以重用它.我不是用 C 编写我的应用程序;我在 Unity 中开发,Unity 只能在 Mac OS 上接收 .bundle 文件.

这是我的目标:

以适当的方式组织源代码文件夹,以便我可以将它们构建到 Xcode 4 中的包中.

这是我卡住的地方:

在构建项目时出现以下错误:

<块引用>

重复的符号 _main in/Users/zeningqu/Library/Developer/Xcode/DerivedData/ccn-cfygrtkrshubpofnfxalwimtyniq/Build/Intermediates/ccn.build/Debug/ccn.build/Objects-normal/i386/ccndsmoketest.o和/Users/zeningqu/Library/Developer/Xcode/DerivedData/ccn-cfygrtkrshubpofnfxalwimtyniq/Build/Intermediates/ccn.build/Debug/ccn.build/Objects-normal/i386/ccnd_main.o对于架构 i386

我可以解决这个错误,因为我可以在源代码中找到很多主要条目.其中大多数是测试实用程序.

这是我尝试过的:

  1. 我尝试删除所有这些实用程序 .c 文件,但没有成功.错误仍然存​​在.我删除并删除,直到某些文件找不到它们正在调用的函数的定义.所以我不得不停在那里.

  2. 虽然我无法构建一个包,但我能够构建一个 C/C++ 静态库(带有 .a 扩展名).获得 .a 文件后,我尝试将其放入另一个 Xcode 项目并尝试将其构建成一个包.我可以以这种方式构建一个捆绑包,但是我在访问捆绑包的内容时遇到了问题.如果 .a 静态库隐藏在包中,我如何调用该库中定义的函数?我阅读了有关 Apple 的文档,其中说:

<块引用>

注意:一些 Xcode 目标(例如 shell 工具和静态库)可以不会导致创建捆绑包或包.这是正常的和无需专门为这些目标创建捆绑包类型.为这些目标生成的二进制文件旨在按原样使用.

(引自:https://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFBundles/AboutBundles/AboutBundles.html#//apple_ref/doc/uid/10000123i-CH100-SW1)

这是我的想法:

  1. 我想过用 main_sth 之类的东西替换所有 main.但是源代码不是我写的,所以我不想修改它.(我觉得这不是一种正确的做事方式……)
  2. 我了解到Xcode内置了gcc编译器.所以我猜如果gcc可以做到,那么Xcode也可以吗?这只是一个疯狂的猜测 - 我不熟悉 Xcode 和 gcc.

这是我的问题的摘要:

  1. 有没有办法正确组织一堆以前由 gcc make 编译和生成的代码,以便将它们构建到 Xcode 包中?
  2. 将 .a 库放在 Xcode 项目中并将其构建到包中是否有意义?如果有意义,.a 中定义的函数在构建成 bundle 后如何调用?
  3. 只用其他东西替换所有 main() 条目是否合适?

解决方案

好吧,我想我已经找到了至少一种解决问题的方法.

重复的主要错误是由我的源代码中的一堆主要条目引起的.当代码由 gcc make 编译时,我猜作者定义了一种编译顺序,这样重复的 main 就不会成为问题.(如果你知道怎么做,请告诉我.我几乎不知道make tools.)但是当我只是将整个源代码文件夹添加到我的Xcode项目中时,Xcode当然会在链接过程中抱怨......

由于我不愿意修改源代码(因为源代码库不是我开发的),所以我决定用另一种策略来绕过这个问题.

如果您自己的代码报告了重复的主要错误,您可以在此处停止阅读.但如果你像我一样,有一堆 gcc 编译的源代码,急需一个包但不知道该怎么做,我也许可以提供帮助.

好的,这就是我所做的:

  1. 我设置了一个空工作区.

  2. 我构建了一个 C/C++ 静态库项目.

  3. 将我的整个源代码文件夹导入到静态库项目中.

  4. 为静态库项目设置一些头文件搜索路径.

  5. 构建静态库项目.(现在我有一个可以链接的 .a 库)

  6. 我设置了另一个项目,带有一个捆绑目标.

  7. 在 bundle 项目 -> Build Phases -> Link Binary with Libraries,添加我刚刚构建的 .a 库.

  8. 在 bundle 项目 -> edit scheme -> Build 中,将静态库项目添加到 scheme 并将其上移,以便在我的 bundle 项目之前构建它.

  9. 然后将我的库项目的 .h 文件添加到我的 bundle 项目中作为参考.

  10. 之后,在我的 bundle 项目中添加一个 .c 文件,该文件基本上用作包装器.我选择了一个我想在 Unity 中调用的函数,在新的 .c 文件中编写了一个包装函数,并且能够构建包.

  11. 经过多次反复试验,我能够将包导入 Unity 并能够从 Unity 调用测试功能.

我对此感到非常兴奋!虽然它还没有完成,但我认为这给了我希望,我相信我现在可以使用源代码了!而这个方案最大的好处就是我不用修改别人开发的库代码.每当他们更新代码时,我只需更新我的 .a 库即可!

虽然我列出了 11 个步骤,但我仍然觉得我错过了很多细节.所以这里是我的参考:

  1. 我按照本教程将源代码构建到静态库中:http://www.ccnx.org/?post_type=incsub_wiki&p=1315

  2. 我按照这个博客链接静态库与我的捆绑代码并扭曲构建阶段和搜索标题:http://blog.carbonfive.com/2011/04/04/using-open-source-static-libraries-in-xcode-4/

  3. 我按照这个文档将我的包作为插件导入 Unity3D Pro:http://unity3d.com/support/documentation/Manual/Plugins.html

我强烈推荐第二个参考,因为它解决了我的问题!

虽然问题差不多解决了,但还是有几点我没搞清楚:

  1. 我不知道是否需要包装函数.我明天会试试这个,然后回来更新.

-- 我回来更新:包装函数不是必需的.只要确保你的包项目中有所有的头文件,你就可以使用头文件中定义的所有数据结构和调用函数.

  1. 虽然我阅读了一些关于它的文档,但我没有使用过 NSBundle 类.以前我正在考虑使用该类来访问封装在我的包中的 .a 库,但是当我找到上面写的解决方案时,我没有尝试该类.

最后,如果您有更好的解决方案,请随时告诉我!

How to build a .bundle from source code?

This might sound like a simple problem but it has been hurdling me for a week...

Here is my problem:

I have a bunch of .c and .h files that are organized in a folder and its sub folders. The source code was written and compiled with gcc make and tested by many other make tools. The source code has some utilities and command line tools and it has more code that serve as library for those utilities and tools. It is the files that serve as libraries that I want to reuse. (By library I don't mean static library or something, I just mean that some .c and .h files in certain subfolders provide functions that can be called by some other .c files. I want to be able to call those functions, too)

Yet my problem is more complex than that: I need to build those .c and .h into a bundle to reuse it. I am not writing my application in C; I am developing in Unity and Unity can only take in .bundle files on Mac OS.

Here is my goal:

Organize the source code folder in a proper way so that I can build them into a bundle in Xcode 4.

Here is where I got stuck:

When building the project I got the following error:

Duplicate symbol _main in /Users/zeningqu/Library/Developer/Xcode/DerivedData/ccn-cfygrtkrshubpofnfxalwimtyniq/Build/Intermediates/ccn.build/Debug/ccn.build/Objects-normal/i386/ccndsmoketest.o and /Users/zeningqu/Library/Developer/Xcode/DerivedData/ccn-cfygrtkrshubpofnfxalwimtyniq/Build/Intermediates/ccn.build/Debug/ccn.build/Objects-normal/i386/ccnd_main.o for architecture i386

I can relate to this error because I can find lots of main entries in the source code. Most of them are test utilities.

Here is what I tried:

  1. I tried removing all those utility .c files but with no luck. The error is still there. I delete and delete until some files cannot find the definition of the function they are calling. So I had to stop there.

  2. Though I wasn't able to build a bundle I was able to build a C/C++ static library (with an .a extension). After I got the .a file I tried to put it into another Xcode project and tried to build it into a bundle. I could build a bundle in that way, but then I had problem accessing the content of the bundle. How do I call functions defined in a .a static library if that library is hidden in a bundle? I read about Apple's documentation which says:

Note: Some Xcode targets (such as shell tools and static libraries) do not result in the creation of a bundle or package. This is normal and there is no need to create bundles specifically for these target types. The resulting binaries generated for those targets are intended to be used as is.

(quoted from: https://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFBundles/AboutBundles/AboutBundles.html#//apple_ref/doc/uid/10000123i-CH100-SW1)

Here is what I thought about:

  1. I thought about replacing all main with something like main_sth. But the source code was not written by me so I didn't want to modify it. (It just doesn't feel like a proper way of doing things to me...)
  2. I learnt that Xcode has gcc compiler built in. So I guess if gcc can make it, so can Xcode? It's just a wild guess - I am not familiar with Xcode and gcc.

Here is a summary of my questions:

  1. Is there a way to properly organize a pile of code previously compiled and made by gcc make so that they can be built into an Xcode bundle?
  2. Is it meaningful to put a .a library in an Xcode project and build it into a bundle? If it is meaningful, how do I call functions defined in .a after it is built into a bundle?
  3. Is it proper to just replace all main() entries with something else?

解决方案

Alright I think I have figured out at least one solution to the problem.

The duplicate main error was caused by a bunch of main entries in my source code. When the code was compiled by gcc make, I guess the author defined a sort of compilation order so that duplicate mains won't be an issue. (If you know how to do this, please let me know. I barely know make tools.) But when I just add the entire source code folder into my Xcode project, of course Xcode would complain during linking...

As I was unwilling to modify the source code (because the source code library is not developed by me), I decided to use another strategy to walk around this problem.

If your duplicate main error was reported from your own code, you can stop reading here. But if you are like me, with a bunch of gcc compiled source code and badly need a bundle yet don't know what to do, I may be able to help.

Okay here is what I did:

  1. I set up an empty workspace.

  2. I built a C/C++ static library project.

  3. Import my entire source code folder into the static library project.

  4. Set some header search path for the static library project.

  5. Build the static library project. (Now I have a .a library which I could link against)

  6. I set up another project, with a bundle target.

  7. At the bundle project -> Build Phases -> Link Binary with Libraries, add the .a library that I just built.

  8. At the bundle project -> edit scheme -> Build, add the static library project to the scheme and move it up the list so that it is built prior to my bundle project.

  9. Then add .h files of my library project to my bundle project as references.

  10. After that, add a .c file in my bundle project that basically functions as a wrapper. I picked a function that I want to call in Unity, wrote a wrapper function in the new .c file, and was able to build the bundle.

  11. After several trial and error, I was able to import the bundle into Unity and was able to call the test function from Unity.

I was really excited about this! Though it's not completed yet I think this gives me hope and I am confident I can use the source code now! And the best thing about this solution is that I don't have to modify the library code developed by others. Whenever they update their code, I just update my .a library and that's it!

Though I have listed 11 steps I still feel that there are lots of details that I missed. So here are my references:

  1. I followed this tutorial to build my source code into a static library: http://www.ccnx.org/?post_type=incsub_wiki&p=1315

  2. I followed this blog to link static library against my bundle code and twist build phases and search headers: http://blog.carbonfive.com/2011/04/04/using-open-source-static-libraries-in-xcode-4/

  3. I followed this doc to import my bundle to Unity3D Pro as a plugin: http://unity3d.com/support/documentation/Manual/Plugins.html

I strongly recommend the second reference because that's what solved my problem!

Though the problem is almost solved there are still a few things that I haven't figured out:

  1. I don't know if a wrapper function is at all necessary. I will try this out tomorrow and come back to update.

-- I am coming back to update: the wrapper function is NOT necessary. Just make sure you have all the headers in your bundle project and you will be able to use all the data structures and call functions defined in your headers.

  1. I haven't used NSBundle class though I read a few docs about it. Previously I was thinking about using that class to access my .a library encapsulated in my bundle, but as I found the solution I wrote above, I didn't try the class out.

Lastly, if you have better solution, please don't hesitate to let me know!

这篇关于如何组织以前由 GCC Make 编译的 C 源文件并将它们构建到 Xcode 包中?我有一个重复的符号 _main 错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆