GoGPT Best VPN GoSearch

OnWorks 网站图标

makepp_tutorial_compilation - 云端在线

通过 Ubuntu Online、Fedora Online、Windows 在线模拟器或 MAC OS 在线模拟器在 OnWorks 免费托管提供商中运行 makepp_tutorial_compilation

这是 makepp_tutorial_compilation 命令,可以使用我们的多个免费在线工作站之一(例如 Ubuntu Online、Fedora Online、Windows 在线模拟器或 MAC OS 在线模拟器)在 OnWorks 免费托管提供商中运行

程序:

您的姓名


makepp_tutorial_compilation -- Unix 编译命令

商品描述


如果您很好地掌握了编译命令的作用,请跳过本手册页。

我发现令人痛苦的是,很少有人在编程课上学到的是如何
一旦他们编写了程序就开始编译程序。新手要么依赖单一
记住命令,或者使用 make 中的内置规则。我很惊讶
非常具有计算机素养的人学会了在没有优化的情况下进行编译,因为
他们根本不知道这有多重要。编译的基本知识
命令的工作可能会使你的程序运行速度提高两倍或更多,所以它至少是值得的
5分钟。本页描述了编译 C 语言所需了解的几乎所有内容
或几乎任何 Unix 变体上的 C++ 程序。

这些示例主要针对 C,因为 C++ 编译是相同的,只是名称不同
编译器的不同。假设您正在将源代码编译到名为
“xyz.c”并且您想要构建一个名为“xyz”的程序。必须发生什么?

您可能知道可以使用如下命令一步构建程序:

cc -g xyz.c -o xyz

这会起作用,但它隐藏了一个两步过程,如果您是
编写 makefile。 (其实步骤不止两步,但你只需要
了解其中两个。)对于一个以上模块的程序,这两个步骤通常是
明确分开。

汇编
第一步是将 C 或 C++ 源代码转换为名为
一个目标文件。目标文件通常具有“.o”扩展名。 (对于一些最近
项目中,“.lo”也用于稍微不同类型的目标文件。)

在 Unix 上生成目标文件的命令如下所示:

cc -g -c xyz.c -o xyz.o

“cc”是C编译器。有时会使用替代的 C 编译器;一个很常见的是
称为“海湾合作委员会”。常见的 C++ 编译器是 GNU 编译器,通常称为“g++”。几乎
Unix 上的所有 C 和 C++ 编译器对于命令的其余部分都具有相同的语法(至少
对于基本操作),所以唯一的区别是第一个单词。

稍后我们将解释“-g”选项的作用。

“-c”选项告诉 C 编译器生成一个“.o”文件作为输出。 (如果你不
指定“-c”,然后它会自动执行第二个编译步骤。)

“-o xyz.o”选项告诉编译器目标文件的名称是什么。你可以
省略此项,只要目标文件的名称与源文件的名称相同即可
除“.o”扩展名之外的文件。

在大多数情况下,选项和文件名的顺序并不重要。一
重要的例外是输出文件必须紧跟在“-o”之后。

链接
构建程序的第二步称为 链接。目标文件无法运行
直接地;它是一种中间形式,必须是 链接 到其他组件,以便
制作一个程序。其他组件可能包括:

· 图书馆。 A 图书馆粗略地说,是对象模块的集合,这些模块是
必要时包括在内。例如,如果您的程序调用“printf”函数,那么
“printf”函数的定义必须包含在系统 C 库中。
有些库会自动链接到您的程序中(例如,包含
“printf”),所以你永远不需要担心它们。

· 从程序中的其他源文件派生的目标文件。如果你写你的
程序,以便它实际上有几个源文件,通常您会编译每个
源文件到一个单独的目标文件,然后将它们链接在一起。

这个 链接 是负责获取目标文件集合的程序
库并将它们链接在一起以生成可执行文件。可执行文件是
你实际运行的程序。

链接程序的命令如下所示:

cc -g xyz.o -o xyz

这可能看起来很奇怪,但我们通常运行相同的程序(“cc”)来执行链接。什么
表面上发生的情况是“cc”程序立即将控制权传递给
添加数字后的不同程序(链接器,有时称为加载器,或“ld”)
将复杂的信息传递到命令行。例如,“cc”告诉“ld”在哪里
系统库包含“printf”等函数的定义。直到你
开始编写共享库时,通常不需要直接处理“ld”。

如果不指定“-o xyz”,那么输出文件将被称为“a.out”,这看起来
对我来说这是一个完全无用且令人困惑的约定。所以总是指定“-o”
链接步骤。

如果你的程序有多个目标文件,你应该指定所有目标文件
链接命令。

需要 分开 这些因素包括原料奶的可用性以及达到必要粉末质量水平所需的工艺。 步骤
为什么不直接使用简单的一步命令,如下所示:

cc -g xyz.c -o xyz

而不是更复杂的两阶段编译

cc -g -c xyz.c -o xyz.o
cc -g xyz.o -o xyz

如果在内部将第一个转换为第二个?仅当以下情况时,差异才重要:
您的程序中有多个模块。假设我们有一个附加模块,
“abc.c”。现在我们的编译看起来像这样:

# 一级命令。
cc -g xyz.c abc.c -o xyz

or

# 两阶段命令。
cc -g -c xyz.c -o xyz.o
cc -g -c abc.c -o abc.o
cc -g xyz.o abc.o -o xyz

当然,第一种方法在内部转换为第二种方法。这意味着
每次运行命令时,“xyz.c”和“abc.c”都会重新编译。但如果你
仅更改了“xyz.c”,无需重新编译“abc.c”,因此两者的第二行-
不需要执行阶段命令。这会对编译产生巨大的影响
时间,特别是如果您有很多模块。因此,几乎所有 makefile 都保留
两个编译步骤是分开的。

这几乎是基础知识,但还有一些您真正应该了解的小细节
知道关于。

调试 优化
通常程序员编译程序要么是为了调试,要么是为了速度。汇编
因为速度被称为 优化;通过优化编译可以使您的代码运行到
速度提高 5 倍或更多,具体取决于您的代码、处理器和编译器。

有了如此巨大的收益,您为什么不想优化呢?最多
重要的答案是优化使调试器的使用变得更加困难
(有时不可能)。 (如果您对调试器一无所知,那么是时候学习了。
你花半个小时或一个小时学习基础知识将会得到很多倍的回报
以便稍后调试时节省时间。我建议从 GUI 调试器开始
例如“kdbg”、“ddd”或“gdb”在 emacs 中运行(请参阅 gdb 上的信息页面了解
有关如何执行此操作的说明)。)优化重新排序并组合语句,删除
不必要的临时变量,并且通常会重新排列您的代码,以便它非常
在调试器中很难遵循。通常的过程是编写代码,编译它
没有优化,调试一下,然后开启优化。

为了使调试器工作,编译器不仅必须配合
优化,还可以将有关符号名称的信息放入对象中
文件,以便调试器知道它们的名称。这就是“-g”编译的内容
选项。

如果您已完成调试,并且想要优化代码,只需将“-g”替换为
“-O”。对于许多编译器,您可以通过附加来指定增加的优化级别
“-O”后的数字。您还可以指定其他选项来增加
在某些情况下的速度(可能会增加内存使用量)。看
有关详细信息,请参阅编译器的手册页。例如,这是一个优化编译命令
我经常与“gcc”编译器一起使用:

gcc -O6 -malign-double -c xyz.c -o xyz.o

您可能必须尝试不同的优化选项才能获得绝对最佳效果
表现。对于不同的代码片段,您可能需要不同的选项。一般来说
简单来说,像“-O6”这样的简单优化标志适用于许多编译器,并且通常
产生了相当好的结果。

警告:在极少数情况下,您的程序实际上并不会执行完全相同的操作
它是经过优化编译的。这可能是由于 (1) 您做出的假设无效
在您的代码中,如果不进行优化是无害的,但会导致问题,因为
当你优化时,编译器会自由地重新排列事物;或(2)可悲的是,
编译器也有错误,包括优化器中的错误。对于像这样的稳定​​编译器
“gcc”在像 Pentium 这样的通用平台上,优化错误很少成为问题(截至
2000 年——几年前就出现过问题)。

如果您在编译命令中未指定“-g”或“-O”,则生成的对象
文件既不适合调试也不适合快速运行。由于某种原因,这是
默认。因此,请始终指定“-g”或“-O”。

在某些系统上,您必须在编译和链接步骤中提供“-g”;在别人身上
(例如Linux),仅需要在编译步骤中提供。在某些系统上,“-O”
实际上在链接阶段做了一些不同的事情,而在其他阶段则没有效果。
无论如何,为这两个命令提供“-g”或“-O”总是无害的。

</p>
大多数编译器能够捕获许多常见的编程错误(例如,
忘记从应该返回值的函数中返回值)。通常,
您需要打开警告。如何执行此操作取决于您的编译器(请参阅 man
页),但是使用“gcc”编译器,我通常使用如下所示的内容:

gcc -g -Wall -c xyz.c -o xyz.o

(有时我还会在“-Wall”之后添加“-Wno-uninitialized”,因为出现警告
通常在优化时会出现错误。)

这些警告为我节省了很多时间的调试时间。

其他 有用 汇编 选项
通常,必要的包含文件存储在当前目录以外的某个目录中
目录或系统包含目录(/ usr / include)。这种情况经常发生在
您正在使用附带包含文件的库来定义函数或类。

例如,假设您正在编写一个使用 Qt 库的应用程序。你已经
安装了 Qt 库的本地副本 /home/用户/joe/qt,这意味着
include文件存放在目录中 /home/用户/joe/qt/include。在你的代码中,你
希望能够做这样的事情:

#包括

而不是

#include“/home/users/joe/qt/include/qwidget.h”

您可以使用以下命令告诉编译器在不同目录中查找包含文件
“-I”编译选项:

g++ -I/home/users/joe/qt/include -g -c mywidget.cpp -o mywidget.o

“-I”和目录名之间通常没有空格。

当C++编译器寻找文件时 qwidget.h,它将查找
/home/用户/joe/qt/include 在查看系统包含目录之前。你可以
根据需要指定任意多个“-I”选项。

运用
您通常必须告诉链接器链接到特定的外部库,如果您
正在调用不属于标准 C 库的任何函数。 “-l”(小写
L) 选项表示链接到特定库:

cc -g xyz.o -o xyz -lm

“-lm”表示与系统数学库链接,如果您正在使用,则需要该库
函数类似于“sqrt”。

谨防: 如果您指定多个“-l”选项,则该顺序可能会在某些方面产生影响
系统。如果当您知道已包含以下内容时却收到未定义的变量
定义它们的库,您可以尝试将该库移动到命令的末尾
行,甚至在命令行末尾再次包含它。

有时您需要的库没有存储在系统的默认位置
图书馆。 “-labc”搜索名为的文件 libabc.a or libabc.so or libabc.sa ,在
系统库目录(/ usr / lib目录 通常还有其他一些地方,具体取决于什么
你正在运行的 Unix 类型)。 “-L”选项指定要搜索的附加目录
对于图书馆。再次使用上面的示例,假设您已经安装了 Qt 库
in /home/用户/joe/qt,这意味着库文件位于 /home/用户/joe/qt/lib.
您的程序的链接步骤可能如下所示:

g++ -g test_mywidget.o mywidget.o -o test_mywidget -L/home/users/joe/qt/lib -lqt

(在某些系统上,如果您在 Qt 中链接,您还需要添加其他库(例如,
“-L/usr/X11R6/lib -lX11 -lXext”)。您需要做什么取决于您的系统。)

请注意,“-L”和目录名之间没有空格。通常“-L”选项
出现在它应该影响的任何“-l”选项之前。

你怎么知道你需要哪些库?总的来说,这是一个很难的问题,而且各不相同
取决于您运行的 Unix 类型。功能或功能的文档
您正在使用的类应该说明您需要链接哪些库。如果您正在使用
来自外部包的函数或类,通常需要链接一个库
和;该库通常是一个名为“libabc.a”或“libabc.so”或“libabc.sa”的文件
如果您需要添加“-labc”选项。

other 扑朔迷离
您可能已经注意到,可以指定通常适用于的选项
链接步骤的编译,以及通常适用于链接的选项
编译步骤。例如,以下命令是有效的:

cc -g -L/usr/X11R6/lib -c xyz.c -o xyz.o
cc -g -I/某处/包括 xyz.o -o xyz

不相关的选项将被忽略;上面的命令与此完全等效:

cc -g -c xyz.c -o xyz.o
cc -g xyz.o -o xyz

使用 onworks.net 服务在线使用 makepp_tutorial_compilation


免费服务器和工作站

下载 Windows 和 Linux 应用程序

Linux 命令

Ad




×
广告
❤️在这里购物、预订或购买——免费,有助于保持服务免费。