如何确保 `iostream` 可用于链接器?
How can I make sure `iostream` is available to the linker?
我在名为 helloworld.cpp
的文件中有以下 C++ 代码:
#include<iostream>
int main()
{
std::cout << "Hello, World!\n";
}
我想手动编译这个,这样我才能真正理解编译步骤是如何与 gcc
一起工作的,即:
- 预处理
- 编译
- 大会
- 正在链接
此 article 提供了一些有关如何分解编译步骤的有用信息。所以我想出了以下内容:
预处理
cpp helloworld.cpp > helloworld.i
编译
g++ -S helloworld.i
程序集as -o helloworld.o helloworld.s
正在链接
ld -o helloworld helloworld.o
除最后一步外,一切似乎都正常,如文章所述:
ld -o hello hello.o ...libraries...
The libraries argument above is a long list of libraries that you need to find out. I omitted the exact arguments because the list is really long and complicated, and depends on which libraries g++
is using on your system. If you are interested to find out, you can run the command g++ -Q -v -o hello hello.cpp
and take a look at the last line where g++
invokes collect2
所以我尝试了 运行 g++ -Q -v -o helloworld helloworld.cpp
,但结果非常冗长。
我仍然不确定如何完成 ld
,以便在我调用它时 iostream
可用于链接器。如何确保 iostream
可用于链接器?
I'm still unsure how to complete ld such that iostream can be available to the linker when I invoke it.
你应该永远不要使用ld
到link任何user-level程序,只有当你link正在做一些深奥的事情时,例如 OS 内核或引导加载程序。
相反,(对于 user-level 程序)始终 使用适当的编译器驱动程序(g++
此处)。
虽然您 可以 了解编译器驱动程序最终如何在内部调用 ld
(例如使用 strace -fe execve -s 1024 g++ ...
),但请注意该命令可能会从版本版本,并取决于大量标志(-pie
与 -no-pie
、-shared
、-static
等),并且您有机会 继续 几个月后使用正确的 ld
命令是零。
根据评论和发布的答案,我意识到我从中复制这些命令的博客使事情变得比我真正需要的更复杂。完全可以单独使用 g++
命令来隔离编译过程的每个步骤。这是我想出的 Makefile:
all: preprocess compile assemble link
# helloworld.i contains preprocessed source code
preprocess:
@echo "\nPREPROCESSING\n"; g++ -E -o helloworld.i helloworld.cpp
# compile preprocessed source code to assembly language.
# hello.s will contain assembly code
compile:
@echo "\nCOMPILATION\n"; g++ -S helloworld.i
# convert assembly to machine code
assemble:
@echo "\nASSEMBLY\n"; g++ -c helloworld.s
# links object code with the library code to produce an executable
# libraries need to be specified here
link:
@echo "\nLINKING\n"; g++ helloworld.o -o test
clean:
@find -type f ! -name "*.cpp" ! -name "*.h" ! -name "Makefile" -delete
现在我可以通过跟踪预处理器、编译器、汇编器或链接器是否产生错误的方式来编译我的 C++ 程序。
我在名为 helloworld.cpp
的文件中有以下 C++ 代码:
#include<iostream>
int main()
{
std::cout << "Hello, World!\n";
}
我想手动编译这个,这样我才能真正理解编译步骤是如何与 gcc
一起工作的,即:
- 预处理
- 编译
- 大会
- 正在链接
此 article 提供了一些有关如何分解编译步骤的有用信息。所以我想出了以下内容:
预处理
cpp helloworld.cpp > helloworld.i
编译
g++ -S helloworld.i
程序集
as -o helloworld.o helloworld.s
正在链接
ld -o helloworld helloworld.o
除最后一步外,一切似乎都正常,如文章所述:
ld -o hello hello.o ...libraries...
The libraries argument above is a long list of libraries that you need to find out. I omitted the exact arguments because the list is really long and complicated, and depends on which libraries
g++
is using on your system. If you are interested to find out, you can run the commandg++ -Q -v -o hello hello.cpp
and take a look at the last line whereg++
invokescollect2
所以我尝试了 运行 g++ -Q -v -o helloworld helloworld.cpp
,但结果非常冗长。
我仍然不确定如何完成 ld
,以便在我调用它时 iostream
可用于链接器。如何确保 iostream
可用于链接器?
I'm still unsure how to complete ld such that iostream can be available to the linker when I invoke it.
你应该永远不要使用ld
到link任何user-level程序,只有当你link正在做一些深奥的事情时,例如 OS 内核或引导加载程序。
相反,(对于 user-level 程序)始终 使用适当的编译器驱动程序(g++
此处)。
虽然您 可以 了解编译器驱动程序最终如何在内部调用 ld
(例如使用 strace -fe execve -s 1024 g++ ...
),但请注意该命令可能会从版本版本,并取决于大量标志(-pie
与 -no-pie
、-shared
、-static
等),并且您有机会 继续 几个月后使用正确的 ld
命令是零。
根据评论和发布的答案,我意识到我从中复制这些命令的博客使事情变得比我真正需要的更复杂。完全可以单独使用 g++
命令来隔离编译过程的每个步骤。这是我想出的 Makefile:
all: preprocess compile assemble link
# helloworld.i contains preprocessed source code
preprocess:
@echo "\nPREPROCESSING\n"; g++ -E -o helloworld.i helloworld.cpp
# compile preprocessed source code to assembly language.
# hello.s will contain assembly code
compile:
@echo "\nCOMPILATION\n"; g++ -S helloworld.i
# convert assembly to machine code
assemble:
@echo "\nASSEMBLY\n"; g++ -c helloworld.s
# links object code with the library code to produce an executable
# libraries need to be specified here
link:
@echo "\nLINKING\n"; g++ helloworld.o -o test
clean:
@find -type f ! -name "*.cpp" ! -name "*.h" ! -name "Makefile" -delete
现在我可以通过跟踪预处理器、编译器、汇编器或链接器是否产生错误的方式来编译我的 C++ 程序。