本节以经典的 C++ Hello World 程序介绍一下使用 MinGW (Linux 上是 GNU 工具集)环境下编译程序的过程,并示范一下简单 Makefile 的使用。如果对 MinGW 编译环境比较熟悉,可以直接进入下一节, 本节是针对不太熟悉 MinGW 环境的新手讲解的。
本教程以后主要在 MinGW 环境编译 Qt 项目代码,因为国内还是 Windows 用的多,讲 Linux 也没多少人会用。本教程中的代码只要没有特殊说明,都是可以跨平台编译的,在 Linux 系统里主要是文件路径有差异,可执行程序和库的后缀名不一样,其他的没啥区别。
一般编写的程序代码文件要放到全英文(可以有数字和划线-_)的路径里面新建工程。这里是简单程序,比如就放在 D:\QtProjects\ch02 , 新建一个文件夹
helloworld。
注意项目和代码文件的全路径里不要包含任何中文字符、特殊字符和空格,这些字符对程序编译不方便,并且会导致开发工具找不到文件。
现在进入
D:\QtProjects\ch02\helloworld 文件夹,新建一个 helloworld.cpp ,里面输入如下代码:
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
cout<<"Hello world!"<<endl;
return 0;
}
打开 MinGW 命令行环境方式是: 开始菜单 --> Qt 5.4.0 --> 5.4 --> MinGW 4.9 (32-bit) --> Qt 5.4 for Desktop (MinGW 4.9 32 bit), 打开该命令行工具,就能使用 MinGW 和 Qt 库进行编译程序。如果是 Linux 系统按照“1.4.3 Qt开发环境脚本”一节的打开自制命令行即可。编译上面简单程序的命令为:
我们在 D:\QtProjects\ch02 文件夹里新建一个 hellorect 文件夹,进入 hellorect 文件夹,新建一个 rect.h,输入代码:
class Rect
{
private:
double m_dblWidth;
double m_dblHeight;
public:
Rect(double dblWidth, double dblHeight);
double GetWidth(){ return m_dblWidth; }
double GetHeight(){ return m_dblHeight; }
//Functions
double CalcDiagonal();
double CalcArea();
};
#include <cmath>
#include "rect.h"
using namespace std;
Rect::Rect(double dblWidth, double dblHeight)
{
m_dblWidth = abs(dblWidth);
m_dblHeight = abs(dblHeight);
}
double Rect::CalcDiagonal()
{
return sqrt(m_dblWidth*m_dblWidth + m_dblHeight*m_dblHeight);
}
double Rect::CalcArea()
{
return m_dblWidth * m_dblHeight;
}
#include <iostream>
#include "rect.h"
using namespace std;
int main(int argc, char **argv)
{
Rect arect(3.0, 4.0);
cout<<"Diagonal Length is "<<arect.CalcDiagonal()<<endl;
cout<<"Area is "<<arect.CalcArea()<<endl;
return 0;
}
上述代码定义了一个非常简单的类 Rect,然后计算了对角线长度 CalcDiagonal 和面积 CalcArea, 在 MinGW 命令行进入 hellorect 文件夹,编译两个 cpp 文件的命令如下:
简单程序可以自己一句句敲 g++ 命令,如果项目复杂起来,代码太多了,自己敲命令编译就很麻烦, 而且一个 .cpp
文件修改后就得重新生成目标文件 *.o,因此实际开发项目时都是借助 make 工具 (MinGW 的是 mingw32-make),编写好
Makefile 之后,只需要在项目文件夹执行一句 make 命令,
其他生成目标文件、链接目标文件和库以及自动根据源代码改动重新生成等,这些事情全交给 make , 而程序员就不用操心构建程序的具体过程。
Makefile 文件可以自己编写,其实绝大多数的集成开发环境都可以根据项目文件自动生成相应的
Makefile,所以实际中很多都是集成开发环境自动完成的。这里示范一个简单的 Makefile, 体会一下生成器 make 是如何工作的。
在上面 hellorect 文件夹里新建一个文件,命名为 Makefile,不要带扩展名。 使用记事本或 Notepad2 工具打开该
Makefile 文件,里面输入如下脚本:
CC = gcc
CXX = g++
LINKER = g++
LFLAGS = -lm -static
OBJECTS = rect.o hellorect.o
DSTTARGET = hellorect
# Default rule
all: $(DSTTARGET)
$(DSTTARGET): $(OBJECTS)
$(LINKER) $(LFLAGS) -o $@ $(OBJECTS)
hellorect.o: hellorect.cpp
$(CXX) -c -o $@ $<
rect.o: rect.cpp
$(CXX) -c -o $@ $<
clean:
rm $(OBJECTS) hellorect.exe
这里解释一下上面脚本意思(# 打头的是注释,忽略掉):
中间带有等于号的都是定义变量,引用变量的方式就是 $(变量名) , 脚本里 CC 是 C 语言编译器,CXX 是 C++ 编译器,LINKER
是链接器, LFLAGS 是链接器的参数。OBJECTS 是编译得到的目标文件,DSTTARGET 是可执行的目标程序。
接下来是 Makefile 的生成规则,Makefile 的基本规则是:
$(LINKER) $(LFLAGS) -o $@ $(OBJECTS)
hellorect.o: hellorect.cpp
$(CXX) -c -o $@ $<
rect.o: rect.cpp
$(CXX) -c -o $@ $<
clean:
rm $(OBJECTS) hellorect.exe