Qt学习(5)——Hello Word
这里以经典的C++ Hello Word程序介绍一下使用MinGW(Linux上是GNU工具集)环境编译程序的过程,并且示范一下简单Makefile的使用。
1、简单的Hello Word
一般将编写的程序代码文件要放到不含中文、特殊字符和空格的路径里面建立工程。否则会对程序编译不方便。
现在进入E:QtProjectsch2helloworld文件夹,新建一个helloworld.cpp(本人使用Notepad++ 6.8.7),编写如下代码:
// helloworld.cpp
#include<iostream>
using namespace std;
int main ( )
{
cout << " Hello World " << endl;
return 0;
}
打开MinGW命令行环境:开始菜单—>Qt5.5.0—>5.5—>MinGW 4.9(32bit)—>Qt 5.5 for Desktop(MinGW 4.9.2 32bit),打开该命令行工具,就能使用MinGW和Qt库进行编译程序。
cd /d E:QtProjectsch2helloworld
g++ helloworld.cpp -o helloworld
上面第一句命令是进入 helloworld 文件夹,第二句命令是使用 g++ 编译 helloworld.cpp , -o 代表输出文件名为 helloworld (默认扩展名 .exe)。 执行该目标程序的命令为:helloworld
这时候进入 D:QtProjectsch02helloworld 文件夹,可以看到目标程序 helloworld.exe ,大小是48 KB, 这是使用动态链接库的程序,体积比较小,如果双击它,会出现提示“没有找到 libgcc_s_dw2-1.dll (GCC 异常处理库),因此这个应用程序未能启动。重新安装应用程序可能会修复此问题”, 这是因为之前 MinGW 命令行配置好了 PATH 环境变量,MinGW 命令行环境有该 dll 文件, 而操作系统的 PATH 环境变量没有该 dll 。另外该 helloworld.exe 还依赖 libstdc++-6.dll (C++标准库), 动态链接的程序就是这样,需要相应的 dll 才能正常执行。可以找到这两个 dll 复制到 helloworld 文件夹里, 或者使用如下静态编译命令:
新的静态链接版本程序 hellostatic.exe 是 1427 KB,比较大,双击运行不会报错,打印完字符串后会一闪而过, 普通的 CMD 命令行里可以直接运行该程序显示结果。 MinGW 编译程序的大概过程就是先用 g++ 编译器生成目标文件 *.o , 然后 g++ 自动调用了 ld 工具链接 *.o 和库文件,生成了 .exe 文件。 g++ 默认情况下生成的都是 Release 版可执行程序, 如果希望在可执行程序里加入 Debug 调试信息以供 gdb 调试,那需要在 g++ 编译时加一个 -g 选项,比如
//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();
};
然后新建一个rect.cpp,编写如下代码:
//rect.cpp
#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;
}
再建一个hellorect.cpp,编写如下代码:
//hellorect.cpp
#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++ -c rect.cpp -o rect.o
g++ -c hellorect.cpp -o hellorect.o
g++ -c的意思为编译生成目标代码文件*.o , 而不进行链接。链接*.o文件和链接库生成可执行程序的命令为:
g++ rect.o hellorect.o -lm -static -o hellorect
g++ 会自动调用链接器链接 .o 文件和系统里的链接库,-lm 是链接数学库,-static 是生成静态链接的程序,-o 是指定生成的输出文件名。然后执行 hellorect 就可以看到结果:
3、给Hello Rect编写简单的Makefile
简单程序可以自己一句句敲 g++ 命令,如果项目复杂起来,代码太多了,自己敲命令编译就很麻烦,而且一个 .cpp 文件修改后就得重新生成目标文件 *.o,因此实际开发项目时都是借助 make 工具 (MinGW 的是 mingw32-make),编写好Makefile 之后,只需要在项目文件夹执行一句 make 命令,其他生成目标文件、链接目标文件和库以及自动根据源代码改动重新生成等,这些事情全交给 make ,而程序员就不用操心构建程序的具体过程。
Makefile 文件可以自己编写,其实绝大多数的集成开发环境都可以根据项目文件自动生成相应的Makefile,所以实际中很多都是集成开发环境自动完成的。这里示范一个简单的 Makefile,体会一下生成器 make 是如何工作的。
上面 hellorect文件夹里新建一个文件,命名为 Makefile,不要带扩展名。使用记事本或 Notepad2 工具打开该 Makefile 文件,里面输入如下脚本:
# Makefile for building: hellorect
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 的基本规则是:
示例的 Makefile 中
是默认生成规则,依赖文件 $(DSTTARGET) ,它的下一行没有命令。 而如何生成 $(DSTTARGET) 呢,继续往下找
生成 $(DSTTARGET) 需要 $(OBJECTS),有了目标文件之后执行命令
$(LINKER) $(LFLAGS) -o $@ $(OBJECTS)
即调用链接器 $(LINKER),根据链接器参数 $(LFLAGS) 和 $(OBJECTS),生成 $@ 。 $@ 就是上一行冒号左边的要生成的目标。注意系统命令 $(LINKER) 之前一定要有制表符 tab 字符, 不能用 4 个空格代替,否则 make 时会出现没有分隔符(separator)的错误。 接下来的四句:
hellorect.o: hellorect.cpp
$(CXX) -c -o $@ $<
rect.o: rect.cpp
$(CXX) -c -o $@ $<
是使用编译器生成目标文件 hellorect.o 和 rect.o ,$@ 是上一行冒号左边的目标,$< 是上一行冒号右边第一个依赖文件。 hellorect.o 和 rect.o就是链接器需要的 $(OBJECTS) 。 最后的两句是清除规则:
clean:
rm $(OBJECTS) hellorect.exe
rm 是删除命令,如果 Windows 系统里没有 rm 命令,请安装一个 msysgit 工具( http://msysgit.github.io/), 然后系统环境变量里面会有 msysgit 工具路径,里面有 rm 工具。clean 做的事情就是删除项目生成的 .o 和 .exe 文件。(注:Linux 系统里可执行程序没有 .exe 后缀,需要去掉 .exe 后缀。)
编辑好 Makefile 文件之后,那么如何使用 make 工具呢?如果要生成项目,就在项目文件夹 hellorect 里执行:
如果要清理项目就执行:
MinGW 里面是用 mingw32-make 生成程序。(注:Linux 系统里直接用 make 。) 在 MinGW 环境的命令示范如下: