库
基础
- -lz -lrt -lm -lc都是什么库
1 | libz 压缩库(Z) |
- 搜寻到指定的库文件
查询库文件 libhdf5.so 是否能在搜索路径中找到。
1 | gcc -lhdf5 --verbose |
apt-get
基础
- 查看apt-get有哪些软件
1 | apt-cache search all |
看下跟这个字母有关的软件都有哪些
1 | apt-cache search all | grep XXXX |
MakeFile
基础
http://blog.csdn.net/liang13664759/article/details/1771246/
- 概述
“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译
比如:Delphi的make,Visual C++的nmake,Linux下GNU的make
程序的编译和链接
首先要把源文件编译成中间代码文件,在Windows下也就是 .obj 文件,UNIX下是 .o 文件,即 Object File,这个动作叫做编译(compile)。
然后再把大量的Object File合成执行文件,这个动作叫作链接(link)。
中间目标文件打个包,在Windows下这种包叫“库文件”(Library File),也就是 .lib 文件,在UNIX下,是Archive File,也就是 .a 文件
总结一下
源文件首先会生成中间目标文件,再由中间目标文件生成执行文件。 在编译时,编译器只检测程序语法,和函数、变量是否被声明。 如果函数未被声明,编译器会给出一个警告,但可以生成Object File。而在链接程序时,链接器会在所有的Object File中找寻函数的实现,如果找不到,那到就会报链接错误码(Linker Error) 在VC下,这种错误一般是:Link 2001错误,意思说是说,链接器未能找到函数的实现。你需要指定函数的Object File.
- Makefile的规则
1 | target ... : prerequisites ... |
target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。
prerequisites就是,要生成那个target所需要的文件或是目标。
command也就是make需要执行的命令。(任意的Shell命令)
示例:
1 | # 在该目录下直接输入命令“make”就可以生成执行文件edit |
- make是如何工作的
1 | 1、make会在当前目录下找名字叫“Makefile”或“makefile”的文件。 |
- makefile中使用变量
1 | 声明一个变量,叫objects |
- 让make自动推导
GNU的make很强大,它可以自动推导文件以及文件依赖关系后面的命令
只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果make找到一个whatever.o,那么whatever.c,就会是whatever.o的依赖文件。并且 cc -c whatever.c 也会被推导出来
1 | objects = main.o kbd.o |
- 另类风格的makefile
1 | objects = main.o kbd.o |
这种风格的,一是文件的依赖关系看不清楚,二是如果文件一多,要加入几个新的.o文件,那就理不清楚了
- 清空目标文件的规则
1 | .PHONY : clean |
不成文的规矩是——“clean从来都是放在文件的最后”。
==在Makefile中的命令,必须要以[Tab]键开始==
- 引用其它的Makefile
在Makefile使用include关键字可以把别的Makefile包含进来,这很像C语言的#include,被包含的文件会原模原样的放在当前文件的包含位置。include的语法是:
include
filename可以是当前操作系统Shell的文件模式(可以保含路径和通配符)
1 | 1、如果make执行时,有“-I”或“--include-dir”参数,那么make就会在这个参数所指定的目录下去寻找。 |
-include
其表示,无论include过程中出现什么错误,都不要报错继续执行
- 文件搜寻
特殊变量“VPATH”就会在当当前目录找不到的情况下,到所指定的目录中去找寻文件
VPATH = src:../headers
上面的的定义指定两个目录,“src”和“../headers”,make会按照这个顺序进行搜索。目录由“冒号”分隔。
另一个设置文件搜索路径的方法是使用make的“vpath”关键字(注意,它是全小写的),这不是变量,这是一个make的关键字
1 | 1、vpath <pattern> <directories> |
- 伪目标
因为,我们并不生成“clean”这个文件。“伪目标”并不是一个文件,只是一个标签,由于“伪目标”不是文件,所以make无法生成它的依赖关系和决定它是否要执行。我们只有通过显示地指明这个“目标”才能让其生效
伪目标一般没有依赖的文件。但是,我们也可以为伪目标指定所依赖的文件。伪目标同样可以作为“默认目标”,只要将其放在第一个。一个示例就是,如果你的Makefile需要一口气生成若干个可执行文件,但你只想简单地敲一个make完事,并且,所有的目标文件都写在一个Makefile中,那么你可以使用“伪目标”这个特性:
1 | all : prog1 prog2 prog3 |
- 静态模式
语法:
1 | <targets ...>: <target-pattern>: <prereq-patterns ...> |
例子:
1 | objects = foo.o bar.o |
上面的例子中,指明了我们的目标从$object中获取,“%.o”表明要所有以“.o”结尾的目标,也就是“foo.o bar.o”,也就是变量$object集合的模式,而依赖模式“%.c”则取模式“%.o”的“%”,也就是“foo bar”,并为其加下“.c”的后缀,于是,我们的依赖目标就是“foo.c bar.c”。而命令中的“$<”和“$@”则是自动化变量,“$<”表示所有的依赖目标集(也就是“foo.c bar.c”),“$@”表示目标集(也就是“foo.o bar.o”)。于是,上面的规则展开后等价于下面的规则:
1 | foo.o : foo.c |
- 自动生成依赖性
比如,如果我们的main.c中有一句“#include “defs.h””,那么我们的依赖关系应该是:
main.o : main.c defs.h
大多数的C/C++编译器都支持一个“-M”的选项,即自动找寻源文件中包含的头文件,并生成一个依赖关系。例如,如果我们执行下面的命令:
cc -M main.c
其输出是:
main.o : main.c defs.h
如果你使用GNU的C/C++编译器,你得用“-MM”参数,不然,“-M”参数会把一些标准库的头文件也包含进来
GNU组织建议把编译器为每一个源文件的自动生成的依赖关系放到一个文件中,为每一个“name.c”的文件都生成一个“name.d”的Makefile文件,[.d]文件中就存放对应[.c]文件的依赖关系。
我们可以写出[.c]文件和[.d]文件的依赖关系,并让make自动更新或自成[.d]文件,并把其包含在我们的主Makefile中,这样,我们就可以自动化地生成每个文件的依赖关系了。
1 | %.d: %.c |
总而言之,这个模式要做的事就是在编译器生成的依赖关系中加入[.d]文件的依赖,即把依赖关系:
main.o : main.c defs.h
转成:
main.o main.d : main.c defs.h
可以使用Makefile的“include”命令,来引入别的Makefile文件(前面讲过),例如:
sources = foo.c bar.c
include $(sources:.c=.d)
上述语句中的“$(sources:.c=.d)”中的“.c=.d”的意思是做一个替换,把变量$(sources)所有[.c]的字串都替换成[.d]
- 命令
- 如果你要让上一条命令的结果应用在下一条命令时,你应该使用分号分隔这两条命令
示例一:
1 | exec: |
示例二:
1 | exec: |
当我们执行“make exec”时,第一个例子中的cd没有作用,pwd会打印出当前的Makefile目录,而第二个例子中,cd就起作用了,pwd会打印出“/home/hchen”。
忽略命令的出错,我们可以在Makefile的命令行前加一个减号“-”(在Tab键之后),标记为不管命令出不出错都认为是成功的
- 定义命令包
以“define”开始,以“endef”结束,如:
1 | define run-yacc |
这里,“run-yacc”是这个命令包的名字,其不要和Makefile中的变量重名。
1 | foo.c : foo.y |
我们可以看见,要使用这个命令包,我们就好像使用变量一样。
- 使用变量
变量在声明时需要给予初值,而在使用时,需要给在变量名前加上“$”符号,但最好用小括号“()”或是大括号“{}”把变量给包括起来。如果你要使用真实的“$”字符,那么你需要用“$$”来表示。
变量会在使用它的地方精确地展开,就像C/C++中的宏一样
- 变量中的变量
第一种方式,也就是简单的使用“=”号,在“=”左侧是变量,右侧是变量的值;右侧中的变量不一定非要是已定义好的值,其也可以使用后面定义的值。如:
1 | foo = $(bar) |
另一种用变量来定义变量的方法。这种方法使用的是“:=”操作符,如:
1 | x := foo |
其等价于:
1 | y := foo bar |
值得一提的是,这种方法,前面的变量不能使用后面的变量,只能使用前面已定义好了的变量。如果是这样:
1 | y := $(x) bar |
那么,y的值是“bar”,而不是“foo bar”。
注释符“#”的这种特性值得我们注意,如果我们这样定义一个变量:
dir := /foo/bar # directory to put the frobs in
dir这个变量的值是“/foo/bar”,后面还跟了4个空格,如果我们这样使用这样变量来指定别的目录——“$(dir)/file”那么就完蛋了
还有一个比较有用的操作符是“?=”,先看示例:
FOO ?= bar
其含义是,如果FOO没有被定义过,那么变量FOO的值就是“bar”,如果FOO先前被定义过,那么这条语将什么也不做,其等价于:
1 | ifeq ($(origin FOO), undefined) |
- 变量高级用法
第一种是变量值的替换
其格式是“$(var:a=b)”或是“${var:a=b}”,其意思是,把变量“var”中所有以“a”字串“结尾”的“a”替换成“b”字串。这里的“结尾”意思是“空格”或是“结束符”。
还是看一个示例吧:
1 | foo := a.o b.o c.o |
这个示例中,我们先定义了一个“$(foo)”变量,而第二行的意思是把“$(foo)”中所有以“.o”字串“结尾”全部替换成“.c”,所以我们的“$(bar)”的值就是“a.c b.c c.c”。
另外一种变量替换的技术是以“静态模式”(参见前面章节)定义的,如:
1 | foo := a.o b.o c.o |
这依赖于被替换字串中的有相同的模式,模式中必须包含一个“%”字符,这个例子同样让$(bar)变量的值为“a.c b.c c.c”。
第二种高级用法是——“把变量的值再当成变量”。先看一个例子:
1 | x = y |
在这个例子中,$(x)的值是“y”,所以$($(x))就是$(y),于是$(a)的值就是“z”。(注意,是“x=y”,而不是“x=$(y)”)
可以使用多个变量来组成一个变量的名字,然后再取其值:
1 | first_second = Hello |
这里的“$a_$b”组成了“first_second”,于是,$(all)的值就是“Hello”。
- 环境变量
如果我们在环境变量中设置了“CFLAGS”环境变量,那么我们就可以在所有的Makefile中使用这个变量了。
如果Makefile中定义了CFLAGS,那么则会使用Makefile中的这个变量,如果没有定义则使用系统环境变量的值
当make嵌套调用时,定义在文件中的变量,如果要向下层Makefile传递,则需要使用exprot关键字来声明。
- 目标变量
它可以和“全局变量”同名,因为它的作用范围只在这条规则以及连带规则中,所以其值也只在作用范围内有效。而不会影响规则链以外的全局变量的值。
1 | prog : CFLAGS = -g |
在这个示例中,不管全局的$(CFLAGS)的值是什么,在prog目标,以及其所引发的所有规则中(prog.o foo.o bar.o的规则),$(CFLAGS)的值都是“-g”
- 模式变量
make的“模式”一般是至少含有一个“%”的,所以,我们可以以如下方式给所有以[.o]结尾的目标定义目标变量:
%.o : CFLAGS = -O
同样,模式变量的语法和“目标变量”一样:
- 条件判断
1 | libs_for_gcc = -lgnu |
ifeq (
第二个条件关键字是“ifneq”
第三个条件关键字是“ifdef”。语法是:
ifdef
第四个条件关键字是“ifndef”
- 使用函数
make所支持的函数也不算很多,不过已经足够我们的操作了。函数调用后,函数的返回值可以当做变量来使用。
Makefile中的函数
- abspath函数
用法:$(abspath _names)
该函数主要用于将_names中的各路径转换成绝对路径,并将转换后的结果返回。
1 | ROOT := $(abspath /usr/../lib) |
- addprefix函数
用法:$(addprefix _prefix, _names)
该函数主要用于给名字列表_names中的每一个名字增加前缀_prefix,并将增加了前缀的名字列表返回。
1 | without_dir = main.c bar.c foo.c |
- addsuffix函数
用法:$(addsuffix _suffix, _names)
该函数主要用于给名字列表_names中的每一个名字增加后缀_suffix,并将增加了后缀_suffix的名字列表返回
- filter函数
用法:$(filter _pattern, _text)
该函数用于从一个名字列表_text中根据模式_pattern得到满足需要的名字列表返回。测试代码如下
1 | sources = foo.c bar.c baz.s ugh.h |
- eval函数
用法:$(eval _text)
eval函数的存在使得Makefile具有动态语言的特征。eval函数使得make将再一次解析_text语句。测试如下所示
1 | sources = foo.c bar.c baz.s ugh.h |
- filter-out函数
用法:$(filter-out _pattern, _text)
该函数用于从名字列表_text中根据模式_pattern滤除一部分名字,并将滤除后的列表返回
- notdir函数
用法:$(notdir _names)
该函数用于从路径_names中抽取文件名,并将文件名返回。
- strip函数
用法:$(strip _string)
用于清除名字列表中的多余空格
- wildcard函数
用法:$(wildcard _pattern)
该函数是通配符函数,通过它可以得到当前工作目录中满足_pattern模式的文件或目录名列表,测试代码如下
1 | SRCS = $(wildcard *.c) |
- patsubst :替换通配符
$(patsubst %.c,%.o,$(dir) )
patsubst把$(dir)中的变量符合后缀是.c的全部替换成.o
xgettext
生成国际化po文件
QT
Linux(Ubuntu)系统下安装Qt library和Qt Creator全过程记录
http://blog.csdn.net/shitsnail/article/details/78841919
- 开发环境
首先介绍一下我的开发环境:
Ubuntu 16.04 64位;
- 准备工作
Ubuntu系统中,为了保证Qt的正常运行,必须安装一些必要的工具,包括g++编译器,以及一些必要的库。可使用以下命令安装:
1 | sudo apt-get install g++ |
- 下载源码
要去Qt官网下载相应的源码和文件。我下载的时间是2017年2月底,此时,Qt Library的版本已经更新到了5.8.0,而Qt Creator的版本已经更新到了2.5.2。不过,鉴于网上部分网友的建议,说5.0之后的Qt库,用的人还比较少,一旦遇到问题,不太好解决,因此建议仍然使用5.0之前的库。所以,我就选择了5.0之前的最后一个版本的库,也就是4.8.6。至于Qt Library以及Qt Creator的具体下载地址如下:
qt library:http://download.qt.io/archive/qt/4.8/4.8.6/qt-everywhere-opensource-src-4.8.6.tar.gz
qt creator:http://download.qt.io/archive/qtcreator/2.5/qt-creator-linux-x86_64-opensource-2.5.2.bin
- 安装Qt Library
Qt Library的源码下载完毕之后,随意解压到一个临时目录,然后进入该目录进行配置和编译,具体步骤如下:
解压
1 | tar xzvf qt-everywhere-opensource-src-4.8.6.tar.gz |
配置
1 | cd qt-everywhere-opensource-src-4.8.6 |
然后终端会出现让你选择商业版还是开源版,输入字母o选择开源版。然后会有协议让你接受,输入yes就OK了。系统就会开始对整个项目进行配置,稍等片刻就好。
编译
配置完毕之后,终端会提示如下信息,
Qt is now configured for building. Just run ‘make’.
Once everything is built, you must run ‘make install’.
Qt will be installed into /usr/local/Trolltech/Qt-4.8.6
To reconfigure, run ‘make confclean’ and ‘configure’.
1 | sudo make |
此时,按照要求输入make便会开始编译生成Qt库,同时编译所有演示程序。这个过程比较漫长,耐心等待便可。
生成
Qt编译完成后,需要输入make install来安装,注意make install需要root权限,所以要加sudo。
1 | sudo make install |
安装过程比较快,安装完毕后,首先要进入Qt安装目录测试一下Qt是否安装成功,Qt默认安装在/usr/local/Trolltech/Qt-4.8.6目录里面,所以直接找到该目录,进入qmake所在的bin文件夹,然后输入./qmake -v指令,如果出现正确的版本信息,则表示安装成功了。
leon@Ubuntu:~$ cd /usr/local/Trolltech/Qt-4.8.1/bin
leon@Ubuntu:/usr/local/Trolltech/Qt-4.8.6/bin$ ./qmake -v
QMake version 2.01a
Using Qt version 4.8.6 in /usr/local/Trolltech/Qt-4.8.6/lib
- 安装Qt Creator
相比Qt Library,Qt Creator的安装要简单的多,我们下载的bin文件是可执行文件,安装时会出现像在Windows下的界面,安装路径默认就可以了。使用终端cd到你刚刚存放Qt Creator的临时目录,修改bin文件的权限使其具有可执行的权限:
1 | chmod a+x qt-creator-linux-x86_64-opensource-2.5.2.bin |
然后输入以下命令安装bin文件:
1 | ./qt-creator-linux-x86_64-opensource-2.5.2.bin |
就会出现仿windows系统的安装界面。如下图所示,一步步按照要求确认就可以完成安装流程了。
等待操作完成即可。
- 环境变量
最后要设置一下环境变量。设置环境变量的目的是为了在任何目录下都可以使用Qt。
1 | sudo gedit /etc/profile |
然后会弹出一个编辑窗口,在末尾添加以下代码,
1 | export QTDIR=/usr/local/Trolltech/Qt-4.8.6 |
保存后退出,然后重启电脑。
重启电脑后,打开终端在任意目录下输入qmake,如果能出现正确信息,则表明环境变量已经配置成功。
- 开始体验
到此为止,Qt已经安装完毕,在终端里输入Qt Creator命令,或者在dash主页中搜索Qt Creator并启动它来运行一个demo测试一下吧。
QT交叉编译环境搭建
- 下载源码和安装包
下载源码和安装包:http://pan.baidu.com/s/1ntyujRN
qt-everywhere-opensource-src-4.8.6.tar.gz | QT4.8.6 库文件
qt-creator-linux-x86_64-opensource-2.5.2.bin.tar.gz | PC 端 QT 开发 IDE
- 安装 QT-Creator
解压压缩包
1 | $ sudo tar -zxpf qt-creator-linux-x86_64-opensource-2.5.2.bin.tar.gz |
赋予执行权限
1 | $ sudo chmod +x qt-creator-linux-x86_64-opensource-2.5.2.bin |
开始安装,持续点击【Next】到安装结束
1 | $ sudo ./ qt-creator-linux-x86_64-opensource-2.5.2.bin |
- 交叉编译环境搭建
1 | $sudo apt-get update |
查看交叉编译工具链的版本:
1 | $ ls /usr/bin/arm-linux-gnueabihf-gcc -al |
ubuntu12.04 安装的交叉编译工具链是: arm-linux-gnueabihf-g++
1 | apt-get install g++-arm-linux-gnueabihf |
Qt编译 error: ‘std::tr1’ has not been declared
http://blog.csdn.net/baidu_33850454/article/details/79147161
在../common/gcc-base.conf (包含在文件../common/gcc-base-unix.conf 中)文件中找到,并修改为如下所示。
在../common/g++-base.conf (包含在文件../common/g++-unix.conf 中)文件中找到,并修改为如下所示
参考:QT交叉编译开发环境搭建CN.pdf
导入一个make构建的项目到Qt Creator里编译调试,比如Nginx
https://my.oschina.net/eechen/blog/166969
- 在Qt Creator中使用make构建,运行,调试通用C/C++项目
- 文件-新建文件或项目-导入项目-导入现有项目
这样导入的项目用的是make构建,需要自己写好Makefile文件后才能构建,支持自动完成,支持调试和内存分析.
- Qt Creator会自动识别系统中安装的gcc、g++、gdb、make、cmake、valgrind,也可以自己到菜单”工具”->”选项”里进行一些自定义配置
vim/emacs负责代码显示;ctags负责代码解析;gdb负责调试;gcc负责编译。
- 把自动完成快捷键”Ctrl+空格”改为”Alt+/”或者”Shift+Return”(Return表示Enter键)
tools工具–>options选项–>environment环境–>keyboard键盘–>Keyboard Shortcuts键盘快捷键–>输入“ctrl+space”–>选中结果,点击下方的”x”删除原来的”Ctrl+Space”,输入新的“Alt+/”,确定退出。
Qt Creator创建C++源代码工程
http://blog.sina.com.cn/s/blog_bdb9d4e40102x6qb.html
这里说明的是Qt Creator + Loki lib的源代码工程
- 库下载
http://sourceforge.NET/projects/loki-lib/
下载后解压,解压路径不能有空格。
- 创建C++工程
- 指定头文件路径
- 指定宏定义
Linux/Ubuntu上使用Qt Creator创建非Qt项目
- 安装CMake和Qt Creator
CMake和Qt Creator是Linux下开发C++程序的神器,Ubuntu 15.04已经集成了最新版的Qt Creator (3.1.1)。
1 | sudo apt-get install cmake qtcreator |
- 创建非Qt项目
“New Project”–>”Non-Qt Project”–>”Plain C++ Application”–>”choose”–>填好名字和路径,”Next”–>”Build System”选择“CMake” 并”Next”–>一路Next直到出现“Run CMake”–>Arguments输入“-DCMAKE_BUILD_TYPE=Debug”(输入它才可以调试) 并“Run CMake”–>最后Finish
问题汇总
make
- 编译时提示 conflicting types for 错误的解决办法
编译时错误提示:
1 | error: conflicting types for xxx |
原因与解决办法:
- 函数使用的位置位于声明之前,或未声明函数原型就使用函数;
这种情况往往出现在函数实现文件中,未在头部声明或声明的位置位于函数使用的位置之后;
解决办法:
将函数声明放到文件靠前位置;
- 函数声明的原型中参数或返回类型与函数实现时使用的类型不一致;
解决办法:
在确定调用与实现一致的情况下,将实现部分的函数头拷贝到声明处,即可解决;
- 头文件中的循环引用导致错误;
在a.h中引用了b.h后,又在b.h中引用了a.h,且其中一个头文件中定义了该函数的原型,在编译期对函数原型产生全局化的临时链接变量时,就出现了多个相同 原型声明,导致编译器报错。
解决办法:
在h文件头部加入防循环引用的宏定义,如 a.h 中加入:
1 | #ifndef _A_H_ |