如何组织以前由GCC Make编译的C源文件,并将它们构建成Xcodebundle?我有一个重复的Symbol _main错误



如何从源代码构建.bundle?

这听起来可能是一个简单的问题,但它已经困扰了我一周。。。

这是我的问题:

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

然而,我的问题比这更复杂:我需要将.c和.h构建成一个捆绑包来重用它;我在Unity开发,Unity只能在Mac操作系统上接收.bundle文件。

这是我的目标:

以适当的方式组织源代码文件夹,这样我就可以在Xcode 4中将它们构建成一个捆绑包。

以下是我陷入困境的地方:

在构建项目时,我得到了以下错误:

中的重复符号(_M)/用户/zeningqu/Library/Developer/Xcode/DerivedData/ccn-cfygrtkrshubpnonflwimtyniq/Build/Inmediates/ccn.Build/Debug/ccn.bbuild/Objects normal/i386/ccndsmoketest.o和/用户/zeningqu/Library/Developer/Xcode/DerivedData/ccn-cfygrtkrshubpnonflwimtyniq/Build/Inmediates/ccn.Build/Debug/ccn.bbuild/Objects normal/i386/ccnd_main.o用于体系结构i386

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

以下是我尝试过的:

  1. 我试着删除所有那些utility.c文件,但没有成功。错误仍然存在。我删除和删除,直到一些文件找不到他们正在调用的函数的定义。所以我不得不停在那里。

  2. 虽然我不能构建一个捆绑包,但我可以构建一个C/C++静态库(带有.a扩展名)。在我得到.a文件后,我试图将其放入另一个Xcode项目中,并试图将其构建成一个捆绑包。我可以用这种方式构建一个捆绑包,但后来我在访问捆绑包的内容时遇到了问题如果静态库隐藏在捆绑包中,我如何调用该库中定义的函数我读过苹果的文档,上面写着:

注意:一些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项目中并将其构建到捆绑包中有意义吗?如果它是有意义的,那么在它被构建到bundle中之后,我如何调用.a中定义的函数
  3. 用其他东西替换所有main()条目是否合适

好吧,我想我至少找到了一个问题的解决方案。

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

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

如果您自己的代码报告了重复的主错误,您可以停止阅读此处。但如果你和我一样,有一堆gcc编译的源代码,急需一个捆绑包,但又不知道该怎么办,我可能会提供帮助

好吧,这就是我所做的:

  1. 我设置了一个空的工作空间。

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

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

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

  5. 生成静态库项目。(现在我有一个可以链接的库)

  6. 我建立了另一个项目,有一个捆绑包目标。

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

  8. 在bundle project->edit scheme->Build中,将静态库项目添加到scheme中,并将其向上移动到列表中,使其在我的bundle项目之前构建。

  9. 然后将我的库项目的.h文件作为引用添加到我的捆绑包项目中。

  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库,但当我找到上面写的解决方案时,我没有尝试该类

最后,如果你有更好的解决方案,请不要犹豫,让我知道!

我试图按照接受的答案中的步骤进行操作,但没有成功。最后,我意识到第10步需要稍作修改:

  • 在(.bundle)项目下创建一个dummy.cdummy.c可以完全为空
  • 删除要在Link Binary With Libraries中链接的库的设置
  • 而是使用-Wl,-force_load,$(CONFIGURATION_BUILD_DIR)/libYourLib.a-all_loadOther Linker Flags

PS:也可以使用子项目代替工作空间。并且使用CCD_ 7代替CCD_。

最新更新