use*_*076 0 programming gcc c++ linker static-linking
我有理由不想依赖特定的构建系统。我并不是要否定任何人的最爱,但我真的只想坚持编译器附带的内容。在这种情况下,GCC。Automake 有一定的兼容性问题,尤其是在 Windows 上。<3 GNU make 是如此有限以至于它经常需要用 shell 脚本来补充。Shell 脚本可以有多种形式,长话短说,可能会激怒很多人,这就是我想要做的——
主要的切入点是上帝。无论是 C 还是 C++ 源文件,它都是应用程序的中心。我不仅希望主入口点是第一个被执行的东西,我还希望它是第一个被编译的东西。让我解释 -
曾经有一段时间,专有库和闭源库很常见。多亏了苹果转向 Unix 和微软在脚下开枪,那个时代结束了。任何需要动态链接的库都可以作为应用程序的支持文件包含在内。出于这个原因,单独的 .SOs(可能还有 .DLLs ;])的构建指令都很好而且很花哨,因为它们是单独的可执行文件。任何其他库都应该静态链接。现在,让我们谈谈静态链接——
静态链接是一个真正的婊子。这就是 makefile 的用途。如果整个项目是用一种语言编写的(例如 C 或 C++),您可以将库作为头文件#include。那很好。但是现在,让我们考虑另一种情况——
假设你和我一样,无法找出 C 对字符串的困难借口,所以你决定使用 C++。但是您想使用 C 库,例如 MiniBasic。上帝帮助我们。如果 C 库的设计不符合 C++ 的语法,那你就完蛋了。这就是 makefile 出现的时候,因为您需要使用 C 编译器编译 C 源文件,并使用 C++ 编译器编译 C++ 源文件。我不想使用makefile。
我希望有一种方法可以利用 GCC 的预处理器宏来告诉它如下内容:
嗨,海合会。你好吗?如果您忘记了,您现在正在查看的这个源文件是用 C++ 编写的。你当然应该用 G++ 编译它。这个文件需要另一个文件,但它是用 C 编写的。它被称为“locats.c”。我想让你用 GCC 把那个编译成一个目标文件,我想让你用 G++ 把这个编译成主目标文件,然后我想让你把它们链接成一个可执行文件。
我怎么能用预处理器行话写这样的东西?海湾合作委员会甚至这样做吗?
主要的切入点是上帝。无论是 C 还是 C++ 源文件,它都是应用程序的中心。
就像氮是松树的中心一样。它是一切开始的地方,但 C 或 C++ 并没有让您将应用程序的“中心”放在main().
许多 C 和 C++ 程序都建立在事件循环或I/O 泵上。这些是此类程序的“中心”。你甚至不用把这些循环相同的模块作为main()。
我不仅希望主入口点是第一个被执行的东西,我还希望它是第一个被编译的东西。
将main() 最后放在 C 或 C++ 源文件中实际上是最容易的。
C 和 C++ 不像某些语言,可以在声明之前使用符号。把main()你必须先手段前瞻性声明一切。
曾经有一段时间,专有库和闭源库很常见。多亏了苹果转向 Unix 和微软在脚下开枪,那个时代结束了。
“告诉‘我在做梦’! ”
OS X 和 iOS充满了专有代码,微软不会很快消失。
无论如何,Microsoft 当前的困难与您的问题有什么关系?您说您可能想要制作 DLL,并且您提到 Automake 无法有效处理 Windows。这告诉我微软在你的世界中也仍然重要。
静态链接是一个真正的婊子。
真的吗?我一直发现它比链接到动态库更容易。这是一种更古老、更简单的技术,出错的地方更少。
静态链接将外部依赖项合并到可执行文件中,因此可执行文件是独立的、自包含的。从您的其余问题来看,这应该会吸引您。
你可以 #include 库作为标题
不...您是#include 库标题,而不是库。
这不仅仅是迂腐。术语很重要。它是有意义的。
如果你可以#include图书馆,#include </usr/lib/libfoo.a>会工作。
在许多编程语言中,这就是外部模块/库引用的工作方式。也就是说,您直接引用外部代码。
C 和 C++ 不属于以这种方式工作的语言。
如果 C 库的设计不符合 C++ 的语法,那你就完蛋了。
不,您只需要学习使用 C++。具体在这里,extern "C"。
我怎么能用预处理器行话写这样的东西?
对于#include另一个 C 或 C++ 文件是完全合法的:
#include <some/library/main.cpp>
#include <some/other/library/main.c>
#include <some/other/library/secondary_module.c>
#include <iostream>
int main()
{
call_the_library();
do_other_stuff();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我们不在extern "C"这里使用,因为这会将其他库中的 C 和 C++ 代码直接提取到我们的 C++ 文件中,因此 C 模块也需要是合法的 C++。C 和 C++ 之间有许多令人讨厌的小差异,但是如果您要混合使用这两种语言,则无论如何都必须知道如何处理它们。
这样做的另一个棘手部分是,#includes如果是链接器命令,则 的顺序比库引用的顺序更敏感。当您以这种方式绕过链接器时,您最终必须手动完成一些链接器原本会自动为您完成的工作。
为了证明这一点,我采用了MiniBasic(您自己的示例)并将其script.c驱动程序转换为一个独立的 C++ 程序,该程序#include <basic.c>不是#include <basic.h>. ( patch ) 现在只是为了证明它确实是一个 C++ 程序,我将所有printf()调用更改为cout流插入。
我不得不做一些其他的改变,对于那些打算混合 C 和 C++ 的人来说,所有这些都在正常的一天工作中完成:
MiniBasic 代码利用了 C 允许从void*任何其他指针类型自动转换的意愿。C++ 让你变得明确。
较新的编译器不再允许"Hello, world!\n"在char*上下文中使用 C 字符串常量(例如)。该标准说允许编译器将它们放入只读内存中,因此您需要使用const char*.
就是这样。只需几分钟即可解决 GCC 投诉。
我必须对basic.c链接的script.c补丁文件中的更改进行一些类似的更改。我没有费心发布差异,因为它们更相似。
另一种方法是研究SQLite Amalgamation,与SQLite 源代码树相比。SQLite 不会将#include所有其他文件都使用到一个主文件中;它们实际上是连接在一起的,但#include在 C 或 C++ 中也是如此。
| 归档时间: |
|
| 查看次数: |
2015 次 |
| 最近记录: |