qt程序 linux bin,将 C++ Qt 程序移植至 Linux 系统

前言

前段时间,我一直在使用 Visual Studio 编写一个 C++ Qt 游戏小程序:https://github.com/lgasyou/SimpleSimulator。突然有一天,我想看看它的可移植性到底如何,于是我把它转化成 .pro 并移至了 Ubuntu 14.04 系统中,之后就开始了漫长的配置之旅。

Qt 的安装

1. 选择对应版本

可以前往 Qt 的官方网站根据CPU架构类型和版本号的不同选择 qt-opensource-linux-CPU架构类型-任意版本号.run 下载,例如需在 32 位系统下下载版本号为 5.8.0 时的 Qt 则选择 qt-opensource-linux-x86-5.8.0.run。

2. 更改文件的属性使得其具有可执行性:

刚刚下载的程序并不具有可执行性,还需要改变它的属性。

在终端中切换目录至文件路径,之后执行 chmod +x qt-opensource-linux-CPU架构类型-任意版本号.run。

3. 执行程序

在终端中输入./qt-opensource-linux-CPU架构类型-任意版本号.run,例如qt-opensource-linux-x86-5.8.0.run 或是直接双击执行程序。

4. 检查 Qt Creator 是否勾选。

4754078379be0a4f10658dafac1bf9d0.png

5. 进入 Qt Creator

安装完成,可以使用菜单栏的搜索功能搜索并进入 Qt Creator(Community)。如果需要可以选择将其固定至菜单栏之上。之后便进入了下一个环节。

Qt 环境的配置

1. 安装 gcc 或 g++ 编译器

安装完成,我创立了一个 HelloWorld 程序,并开始编译。但是很不幸运,编译器返回了 “error while building deploying project” 的错误。我在网上找了很久,但是解决方法都与我的情况基本无关。直到好几天后,我突然发现我的 Compiler 配置里面竟然没有 C++ 的编译器!于是我又安装了 g++: sudo apt-get install g++。终于,可以开始编译了!但是没有10秒钟,我又遇到了第二个问题。

另附:该页的打开方式为:Qt Creator 的菜单栏 -> Tools -> Options -> Build & Run -> Compilers。安装后会自动识别并显示在 Auto-detected 一栏。

51c85b5462781d6a35f3e5354035046d.png

2. 编译器错误 ICE: in gen_type_die_with_usage

这次,编译器又返回了 ICE: in gen_type_die_with_usage, at dwarf2out.c:19484 的错误。我上网一查,这次竟然是编译器的 bug。是 g++ 版本的问题,需要更新。

3. 更新 g++

根据这里的帖子,需要输入以下的命令来获取最新的g++:

sudo add-apt-repository ppa:ubuntu-toolchain-r/test

sudo apt-get update

(注:在这里,我执行完这两个语句后依然提醒:

E: Unable to locate package g++-5

E: Couldn’t find any package by regex ‘g++-5’,

E: Unable to locate package gcc-5

E: Couldn’t find any package by regex ‘gcc-5’,

但是再次执行就成功了,所以如果一次没成功不妨多试几次,要是还是不行就再查找其他解决方案也不迟)

sudo apt-get install gcc-5 g++-5

还没完,还需要将新的 g++-5 链接至 Qt 所调用的 link 文件(这个东西就和快捷方式差不多):

sudo ln -s /usr/local/bin/gcc /usr/bin/gcc

sudo ln -s /usr/local/bin/g++ /usr/bin/g++

可以通过 g++ --version查看版本判断是否成功

再次编译,结果遗憾的是,编译器又再次返回了 usr/bin/ld: cannot find -lGL 的错误。再次上网查找,最终找到了通用的缺失 -lxxx 的解决方法:http://eminzhang.blog.51cto.com/5292425/1285705。对于我的环境而言而言,这个是系统缺失 libGL.so 的问题,也就是缺失 OpenGL 导致的问题。于是有:

(注:可能需要安装 apt-file 程序并更新它的数据:)

sudo apt-get install apt-file

apt-file update

apt-cache search libgl-dev (注:寻找哪个包中包含该库)

sudo apt-get install libgl1-mesa-dev(注:这是我的系统上返回的第一项)

最终配置大致为:

41d960256e468b8302a379f81a3259ca.png

再次编译,几十秒内没有报错。

C++ 在 MSVC 与 GNU G++上的不同之处

很遗憾,它不肯善罢甘休,很快,我又遇到了多个 Error。

1. enum 的前置声明

之前有:

namespace Gameconstants {

enum BuildingTypes;

}

这种用法标准的 C++ 是不支持的。我猜想是微软扩充的结果。

对此有两种解决方法:

// 直接包含头文件

#include"gameconstants.h"

/* 使用 enum BuildingTypes */

或者,在 C++11 或之后版本:

// C++11 规定,枚举的前置声明需要指定成员类型,例如本例中指定为int。

// 同时,若是 enum class 类型,则可以不指定,使用默认类型 int。

namespace Gameconstants {

enum BuildingTypes : int;

}

2. size_t 与 std::size_t

以往,我都是直接使用 size_t 的:

size_t member;

但是在跨平台时,我又发现实际上 size_t 是定义在 std 命名空间中的。根据查找,size_t 是定义于 vcruntime.h 的。很明显,这也是微软扩充的结果。所以,通用的写法应该是:

std::size_t member;

3. auto 推断函数返回值

我在 baseindustry.h 中有:

const auto &machines() const { return this->machines_; }

但是,根据编译器提示这个是 C++14 之后才支持的,由于不想再次更新 g++,替换为

const std::vector &machines() const { return this->machines_; }

4. 函数返回数组问题

public:

auto occupiedMap() const { return this->occupiedMap_; }

private:

bool occupiedMap_[100][100];

在 VS 上编译成功,在 g++ 上失败。我本想使用 typedef 代替:

typedef bool Array[100][100];

Array occupiedMap() const { return this->occupiedMap_; }

但编译仍然失败,最终经过查找,由于数组不支持复制,所以 C++ 不允许返回数组。经过 《C++ Primer》 的启发,我将它改为了尾置返回类型:

// 返回了数组的指针

auto occupiedMap() const -> const bool(*)[100] {

return occupiedMap_;

}

相比而言,确实清晰明了。

最后的最后,程序终于成功运行。

其他问题

1. 初始化顺序, warning: will be initialized after [-Wreorder]

当时由于某个类成员变动频繁,类的构造函数中的成员顺序与声明时不同,所以出现了这个错误。

// 会返回 warning: memberOne will be initialized after [-Wreorder]

class A {

public:

A() : memberOne(), memberTwo()

{ }

private:

Type memberTwo;

Type memberOne;

}

应改为:

// 没有报警

class B {

public:

B() : memberOne(), memberTwo()

{ }

private:

Type memberOne;

Type memberTwo;

}

2. 替换 INT_MAX 和 INT_MIN

在原版的代码中,我是这样写的

#include

/* ... */

namespace GameConstants {

const int integerMaximum = INT_MAX;

const int integerMinimum = INT_MIN;

}

但在当时,不知道为何,编译时报错:INT_MAX 与 INT_MIN 未定义。没办法,我将他们替换成了:

const int integerMinimum = (1 << (sizeof(int) * 8 - 1));

const int integerMaximum = (int)((unsigned)integerMinimum - 1);

这是与平台无关的最大最小值。使用了位运算,具体实现请参考计算机组成原理。

另附:刚刚在 Linux 系统的 stdlib.h 中看到了 INT_MAX 与 INT_MIN 这两个宏定义。也就是说它们是 C 标准定义的。

感想

能够成功运行,着实不易。虽然过程很艰难,不过通过这个过程也学到了不少干货,很值。

接下来我的重点仍然在开头提到的游戏:https://github.com/lgasyou/SimpleSimulator。以上提到的改变均能在 Commits 中可以看到。欢迎讨论。

如果本文有错误的地方,欢迎大家指正。谢谢大家。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值