C++,“老式”方式

发布于 2024-08-18 08:41:00 字数 608 浏览 8 评论 0原文

我在学校学习 C++ 来创建小型命令行程序。

然而,我只使用 IDE 构建了我的项目,包括 VS08 和 QtCreator。

我了解构建项目背后的过程:将源代码编译为目标代码,然后将它们链接到特定于平台的可执行文件(.exe.app 等)。我还知道大多数项目也使用 make 来简化编译和链接多个源文件和头文件的过程。

问题是,虽然 IDE 在幕后完成了所有这些工作,让生活变得非常轻松,但我并不真正知道到底发生了什么,并且觉得我需要习惯于构建“旧的”项目时尚的方式”:从命令行,显式使用工具链。

我知道 Makefile 是什么,但不知道如何编写它们。
我知道 gcc 的作用,但不知道如何使用它。
我知道链接器的作用,但不知道如何使用它。

我正在寻找的是一个解释,或者是一个教程的链接,该教程解释了 C++ 项目的工作流程,从第一次编写代码到运行生成的可执行文件。

我真的很想知道构建 C++ 的内容、方式和原因。

(如果有什么区别的话,我运行的是 Mac OS X,带有 gcc 4.0.1 和 make 3.81)

谢谢!

I have been learning C++ in school to create small command-line programs.

However, I have only built my projects with IDEs, including VS08 and QtCreator.

I understand the process behind building a project: compile source to object code, then link them into an executable that is platform specific (.exe, .app, etc). I also know most projects also use make to streamline the process of compiling and linking multiple source and header files.

The thing is, although IDEs do all this under the hood, making life very easy, I don't really know what is really happening, and feel that I need to get accustomed to building projects the "old fashioned way": from the command line, using the tool chain explicitly.

I know what Makefiles are, but not how to write them.
I know what gcc does, but not how to use it.
I know what the linker does, but not how to use it.

What I am looking for, is either an explanation, or link to a tutorial that explains, the workflow for a C++ project, from first writing the code up to running the produced executable.

I would really like to know the what, how, and why of building C++.

(If it makes any difference, I am running Mac OS X, with gcc 4.0.1 and make 3.81)

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

岁月苍老的讽刺 2024-08-25 08:41:01

编译

假设您想编写一个简单的“hello world”应用程序。您有 3 个文件,hello.cpp hello-writer.cpphello-writer.h,内容为

// hello-writer.h
void WriteHello(void);

// hello-writer.cpp
#include "hello-writer.h"
#include <stdio>
void WriteHello(void){
    std::cout<<"Hello World"<<std::endl;
}

// hello.cpp
#include "hello-writer.h"
int main(int argc, char ** argv){
    WriteHello();
}

*.cpp 文件为使用命令

g++ -c hello.cpp -o hello.o
g++ -c hello-writer.cpp -o hello-writer.o

-c 标志通过 g++ 转换为目标文件,暂时跳过链接。要将所有模块链接在一起,需要运行

g++ hello.o hello-writer.o -o hello

创建程序 hello。如果您需要链接任何外部库,请将它们添加到此行,例如数学库的 -lm 。实际的库文件看起来像 libm.alibm.so,添加链接器标志时忽略文件名的后缀和“lib”部分。

Makefile

要自动化构建过程,您可以使用 makefile,它由一系列规则组成,列出要创建的内容以及创建它所需的文件。例如hello.o依赖于hello.cpphello-writer.h,它的规则是

hello.o:hello.cpp hello-writer.h
     g++ -c hello.cpp -o hello.o # This line must begin with a tab.

如果你想阅读make手册,它告诉您如何使用变量和自动规则来简化事情。您应该只需编写

hello.o:hello.cpp hello-writer.h

即可自动创建规则。 hello 示例的完整 makefile 是

all:hello
hello:hello.o hello-writer.o
    g++ hello.o hello-writer.o -o hello
hello.o:hello.cpp hello-writer.h
    g++ -c hello.cpp -o hello.o
hello-writer.o:hello-writer.cpp hello-writer.h
    g++ -c hello-writer.cpp -o hello-writer.o

记住缩进行必须以制表符开头。并不是所有的规则都需要一个实际的文件,all 目标只是说 create hello。这通常是 makefile 中的第一条规则,第一条规则是在运行 make 时自动创建的。

完成所有这些设置后,您应该能够进入命令行并运行

$ make
$ ./hello
Hello World

更高级的 Makefile 内容

您还可以在 makefile 中定义一些有用的变量,其中包括

  • CXX:c++ 编译器
  • CXXFLAGS:
    附加标志传递给
    编译器(例如包含目录
    与 -I)
  • LDFLAGS: 附加标志
    传递给链接器
  • LDLIBS:库
    链接
  • CC:c 编译器(也用于
    链接)
  • CPPFLAGS:预处理器标志

使用 = 定义变量,使用 += 添加到变量。

将 .cpp 文件转换为 .o 文件的默认规则是,

$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c 
lt; -o $@

其中 $< 是第一个依赖项,$@ 是输出文件。通过将变量括在 $() 中来扩展变量,该规则将以 hello.o:hello.cpp 模式运行,

类似地,默认链接器规则是

$(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS)

$^ 是所有先决条件。该规则将以 hello:hello.o hello-writer.o 模式运行。请注意,这使用了 c 编译器,如果您不想覆盖此规则并使用 c++,请使用

LDLIBS+=-lstdc++

makefile 中的行将库 -lstdc++ 添加到 LDLIBS

最后,如果您没有列出 .o 文件的依赖关系,make 可以自己找到它们,因此最小的 makefile 可能是

LDFLAGS=-lstdc++
all:hello
hello:hello.o hello-writer.o

注意,这会忽略两个文件对 hello- 的依赖关系writer.h,因此如果头文件被修改,程序将不会被重建。如果您有兴趣,请检查 gcc 文档中的 -MD 标志,了解如何自动生成此依赖项。

最终 makefile

合理的最终 makefile 是

// Makefile
CC=gcc
CXX=g++
CXXFLAGS+=-Wall -Wextra -Werror
CXXFLAGS+=-Ipath/to/headers
LDLIBS+=-lstdc++ # You could instead use CC = $(CXX) for the same effect 
                 # (watch out for c code though!)

all:hello                                   # default target
hello:hello.o hello-world.o                 # linker
hello.o:hello.cpp hello-world.h             # compile a module
hello-world.o:hello-world.cpp hello-world.h # compile another module
    $(CXX) $(CXXFLAGS) -c 
lt; -o $@          # command to run (same as the default rule)
                                            # expands to g++ -Wall ... -c hello-world.cpp -o hello-world.o

Compiling

Let's say you want to write a simple 'hello world' application. You have 3 files, hello.cpp hello-writer.cpp and hello-writer.h, the contents being

// hello-writer.h
void WriteHello(void);

// hello-writer.cpp
#include "hello-writer.h"
#include <stdio>
void WriteHello(void){
    std::cout<<"Hello World"<<std::endl;
}

// hello.cpp
#include "hello-writer.h"
int main(int argc, char ** argv){
    WriteHello();
}

The *.cpp files are converted to object files by g++, using the commands

g++ -c hello.cpp -o hello.o
g++ -c hello-writer.cpp -o hello-writer.o

The -c flag skips the linking for the moment. To link all the modules together requires running

g++ hello.o hello-writer.o -o hello

creating the program hello. If you need to link in any external libraries you add them to this line, eg -lm for the math library. The actual library files would look something like libm.a or libm.so, you ignore the suffix and the 'lib' part of the filename when adding the linker flag.

Makefile

To automate the build process you use a makefile, which consists of a series of rules, listing a thing to create and the files needed to create it. For instance, hello.o depends on hello.cpp and hello-writer.h, its rule is

hello.o:hello.cpp hello-writer.h
     g++ -c hello.cpp -o hello.o # This line must begin with a tab.

If you want to read the make manual, it tells you how to use variables and automatic rules to simplify things. You should be able to just write

hello.o:hello.cpp hello-writer.h

and the rule will be created automagically. The full makefile for the hello example is

all:hello
hello:hello.o hello-writer.o
    g++ hello.o hello-writer.o -o hello
hello.o:hello.cpp hello-writer.h
    g++ -c hello.cpp -o hello.o
hello-writer.o:hello-writer.cpp hello-writer.h
    g++ -c hello-writer.cpp -o hello-writer.o

Remember that indented lines must start with tabs. Not that not all rules need an actual file, the all target just says create hello. It is common for this to be the first rule in the makefile, the first being automatically created when you run make.

With all this set up you should then be able to go to a command line and run

$ make
$ ./hello
Hello World

More advanced Makefile stuff

There are also some useful variables that you can define in your makefile, which include

  • CXX: c++ compiler
  • CXXFLAGS:
    Additional flags to pass to the
    compiler (E.g include directories
    with -I)
  • LDFLAGS: Additional flags to
    pass to the linker
  • LDLIBS: Libraries
    to link
  • CC: c compiler (also used to
    link)
  • CPPFLAGS: preprocessor flags

Define variables using =, add to variables using +=.

The default rule to convert a .cpp file to a .o file is

$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c 
lt; -o $@

where $< is the first dependancy and $@ is the output file. Variables are expanded by enclosing them in $(), this rule will be run with the pattern hello.o:hello.cpp

Similarly the default linker rule is

$(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS)

where $^ is all of the prerequisites. This rule will be run with the pattern hello:hello.o hello-writer.o. Note that this uses the c compiler, if you don't want to override this rule and are using c++ add the library -lstdc++ to LDLIBS with the line

LDLIBS+=-lstdc++

in the makefile.

Finally, if you don't list the dependancies of a .o file make can find them itself, so a minimal makefile might be

LDFLAGS=-lstdc++
all:hello
hello:hello.o hello-writer.o

Note that this ignores the dependancy of the two files on hello-writer.h, so if the header is modified the program won't be rebuilt. If you're interested, check the -MD flag in the gcc docs for how you can automatically generate this dependancy.

Final makefile

A reasonable final makefile would be

// Makefile
CC=gcc
CXX=g++
CXXFLAGS+=-Wall -Wextra -Werror
CXXFLAGS+=-Ipath/to/headers
LDLIBS+=-lstdc++ # You could instead use CC = $(CXX) for the same effect 
                 # (watch out for c code though!)

all:hello                                   # default target
hello:hello.o hello-world.o                 # linker
hello.o:hello.cpp hello-world.h             # compile a module
hello-world.o:hello-world.cpp hello-world.h # compile another module
    $(CXX) $(CXXFLAGS) -c 
lt; -o $@          # command to run (same as the default rule)
                                            # expands to g++ -Wall ... -c hello-world.cpp -o hello-world.o
你穿错了嫁妆 2024-08-25 08:41:01

一个简单的示例通常有助于展示基本过程,因此:

示例 gcc 用法来编译 C++ 文件:

$ g++ -c file1.cpp                 # compile object files
[...]
$ g++ -c file2.cpp
[...]
$ g++ -o program file1.o file2.o   # link program
[...]
$ ./program                        # run program

要使用 make 进行此构建,可以使用以下 Makefile:

# main target, with dependencies, followed by build command (indented with <tab>)
program: file1.o file2.o
    g++ -o program file1.o file2.o

# rules for object files, with dependencies and build commands
file1.o: file1.cpp file1.h
    g++ -c file1.cpp

file2.o: file2.cpp file2.h file1.h
    g++ -c file2.cpp

示例 Makefile 用法:

$ make                              # build it
[...]
$ ./program                         # run it

对于所有详细信息你可以查看 Gnu make 手册GCC 文档

A simple example is often useful to show the basic procedure, so:

Sample gcc usage to compile C++ files:

$ g++ -c file1.cpp                 # compile object files
[...]
$ g++ -c file2.cpp
[...]
$ g++ -o program file1.o file2.o   # link program
[...]
$ ./program                        # run program

To use make to do this build, the following Makefile could be used:

# main target, with dependencies, followed by build command (indented with <tab>)
program: file1.o file2.o
    g++ -o program file1.o file2.o

# rules for object files, with dependencies and build commands
file1.o: file1.cpp file1.h
    g++ -c file1.cpp

file2.o: file2.cpp file2.h file1.h
    g++ -c file2.cpp

Sample Makefile usage:

$ make                              # build it
[...]
$ ./program                         # run it

For all the details you can look at the Gnu make manual and GCC's documentation.

深海夜未眠 2024-08-25 08:41:01

我知道 Makefile 是什么,但不知道如何编写它们。

make 语法很糟糕,但 GNU make 文档 却不是坏的。主要语法是:

<target> : <dependency> <dependency> <dep...>
<tab>    <command>
<tab>    <command>

它定义了从给定依赖项构建目标的命令。

阅读文档和示例可能是大多数人学习 makefile 的方式,因为 make 有多种风格,各有细微差别。下载一些项目(选择一些已知可以在您的系统上运行的项目,这样您就可以实际尝试一下),查看构建系统,并了解它们是如何工作的。

您还应该尝试构建一个简单的版本(为您的第一个版本删除一堆较难的功能);我认为这是一个可以让您更好地了解情况的案例。

我知道 gcc 是做什么的,但不知道如何使用它。

同样,man g++、信息页面和其他文档很有用,但是直接调用它(而不是通过构建系统)时的主要用途是:

g++ file.cpp -o name            # to compile and link
g++ file.cpp other.cpp -o name  # to compile multiple files and link as "name"

您还可以编写自己的 shell 脚本(下面是我的 ~/bin/c++ 简化版),以合并 $CXXFLAGS,这样您就不会忘记:

#!/bin/sh
g++ $CXXFLAGS "$@"

您也可以包含任何其他选项。现在,您可以在 .bashrc 或类似文件中设置该环境变量($CXXFLAGS,C++ 标志的标准变量),或者在特定会话中重新定义它,以便在没有 makefile 的情况下工作(make 也可以做得很好)。

还可以使用 -v 标志来查看有关 g++ 功能的详细信息,包括...

我知道链接器的作用,但不知道如何使用它。

链接器负责获取目标文件并链接它们,我相信您知道,但是 g++ -v 会向您显示它使用的确切命令。比较 gcc -v file.cpp(gcc 可以使用 C++ 文件)和 g++ -v file.cpp 以查看链接器命令的差异例如,这通常会导致第一个失败。 Make 还显示默认运行的命令。

最好不要直接使用链接器,因为使用 gcc 或 g++ 并在需要时为它们提供特定的链接器选项要简单得多。

I know what Makefiles are, but not how to write them.

The make syntax is horrible, but the GNU make docs aren't bad. The main syntax is:

<target> : <dependency> <dependency> <dep...>
<tab>    <command>
<tab>    <command>

Which defines commands to build the target from the given dependencies.

Reading docs and examples is probably how most people learn makefiles, as there are many flavors of make with their own slight differences. Download some projects (pick something known to work on your system, so you can actually try it out), look at the build system, and see how they work.

You should also try building a simple make (strip out a bunch of the harder features for your first version); I think this is one case where that will give you a much better grasp on the situation.

I know what gcc does, but not how to use it.

Again, man g++, info pages, and other documentation is useful, but the main use when you call it directly (instead of through a build system) will be:

g++ file.cpp -o name            # to compile and link
g++ file.cpp other.cpp -o name  # to compile multiple files and link as "name"

You can also write your own shell script (below is my ~/bin/c++ simplified) to incorporate $CXXFLAGS so you won't forget:

#!/bin/sh
g++ $CXXFLAGS "$@"

You can include any other option as well. Now you can set that environment variable ($CXXFLAGS, the standard variable for C++ flags) in your .bashrc or similar, or redefine it in a particular session, for working without a makefile (which make does do just fine, too).

Also use the -v flag to see details on what g++ does, including...

I know what the linker does, but not how to use it.

The linker is what takes the object files and links them, as I'm sure you know, but g++ -v will show you the exact command it uses. Compare gcc -v file.cpp (gcc can work with C++ files) and g++ -v file.cpp to see the difference in linker commands that often causes the first to fail, for example. Make also shows the commands as it runs them by default.

You are better off not using the linker directly, because it is much simpler to use either gcc or g++ and give them specific linker options if required.

韬韬不绝 2024-08-25 08:41:01

只是为了把它扔在那里,可以在这里找到完整的 gcc 文档: http: //www.delorie.com/gnu/docs/gcc/gcc_toc.html

Just to throw this out there, the complete gcc documentation can be found here: http://www.delorie.com/gnu/docs/gcc/gcc_toc.html

半边脸i 2024-08-25 08:41:01

编译器获取一个 cpp 并转换为一个目标文件,其中包含本机代码和有关该本机代码的一些信息

链接器获取目标文件并使用目标文件中的额外信息布局可执行文件......它找到对的所有引用相同的东西并将它们链接起来,并使图像对于操作系统了解如何将所有代码加载到内存中很有用。

查看目标文件格式以更好地了解编译器生成的内容

http://en.wikipedia.org /wiki/Object_file (不同的编译器使用不同的格式)

也请查看(对于 gcc)

http://pages.cs.wisc.edu/~beechung/ref/gcc-intro.html 在命令行中输入的内容

compiler takes a cpp and turns into an object file which contains native code and some information about that native code

a linker takes the object files and lays out an excutable using the extra information in the object file.... it finds all the references to the same things and links them up, and makes and image useful for the operating system to know how to load all the code into memory.

check out object file formats to get a better understanding of what the compiler produces

http://en.wikipedia.org/wiki/Object_file (different compilers use different formats)

also check out (for gcc)

http://pages.cs.wisc.edu/~beechung/ref/gcc-intro.html on what you type at the command line

萤火眠眠 2024-08-25 08:41:01

您还可以查看 Autoproject,它设置 automake 和 autoconf 文件,这使人们可以更轻松地在不同平台上编译您的包: http://packages.debian.org/unstable/devel/autoproject

You might also look into Autoproject, which sets up automake and autoconf files, which makes it easier for people to compile your packages on different platforms: http://packages.debian.org/unstable/devel/autoproject

娇俏 2024-08-25 08:41:01

我喜欢这个关于使用 gcc 构建 hello world 程序的古怪介绍,基于 Linux,但命令-line 的东西应该可以在 OS/X 上正常工作。特别是,它会引导您犯一些常见错误并查看错误消息。

神圣编译器,罗宾,这该死的东西成功了!

I like this quirky intro to building a hello world program with gcc, Linux-based but the command-line stuff should work fine on OS/X. In particular, it walks you through making some common mistakes and seeing the error messages.

Holy Compilers, Robin, the darn thing worked!

樱花坊 2024-08-25 08:41:01

这帮助我学习了 autoconf,automake,...:

http://www.bioinf.uni-freiburg.de/~mmann/HowTo/automake.html

这是一个很好的教程,从简单的 helloworld 到带有库等的更高级结构。

This is what has helped me to learn the autoconf, automake, ...:

http://www.bioinf.uni-freiburg.de/~mmann/HowTo/automake.html

It is a nice tutorial progresses from a simple helloworld to more advanced structures with libraries etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文