win7搭建pyqt4开发环境【轉】

【原文鏈接】
https://www.cnblogs.com/toSeek/p/6363036.html
【原文內容】
win7 64bit
python2.7  https://www.python.org/ftp/python/2.7.13/python-2.7.13.amd64.msi
pyqt4    https://downloads.sourceforge.net/project/pyqt/PyQt4/PyQt-4.11.4/PyQt4-4.11.4-gpl-Py2.7-Qt4.8.7-x64.exe?r=https%3A%2F%2Fsourceforge.net%2Fprojects%2Fpyqt%2Ffiles%2FPyQt4%2FPyQt-4.11.4%2F&ts=1484798634&use_mirror=ncu
eric6    https://downloads.sourceforge.net/project/eric-ide/eric6/stable/17.01/eric6-17.01.zip?r=http%3A%2F%2Feric-ide.python-projects.org%2Feric-download.html&ts=1484797072&use_mirror=nchc

python2.7和pyqt4直接运行安装即可;

解压eric6的安装包,使用python运行其中的install.py;

启动eric6:C:\Python27\Scripts\eric6.bat,默认应该就是简体中文;

第一次进入需要进行一些配置,在编辑器->api中把Python2 pyqt的api编译下,开启自动补全等;

在窗体中创建一个ui,双击会进入qt设计师进行可视化界面设计:

待界面设计完毕,保存,在ui文件上右键”编译窗体“,然后右键”生成对话框代码“;

新建一个main.py文件,调用并显示窗体:

# -*- coding: utf-8 -*-

from mainframe import *
from PyQt4.QtGui import QApplication

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mw = MainWindow()
    mw.show()
    sys.exit(app.exec_())

在main.py按f5开始调试(之后在任意地方按f4都可以从main.py开始调试,直到再按f5);

tips: eric6不是特别成熟,如果不是偏爱IDE的话还是建议用自己熟悉的编辑器(vim什么的);

不用eric6的情况下,手动编译ui文件:

C:\Python27\Lib\site-packages\PyQt4\pyuic4.bat -o ui_mainframe.py mainframe.ui

使用pyinstaller打包成exe文件

首先打开一个dos窗口,使用pip安装pyinstaller(使用的是豆瓣的源)

C:\Python27\Scripts\pip install -i https://pypi.doubanio.com/simple/ pyinstaller

在dos窗口cd到上述main.py所在目录,执行命令

c:\Python27\Scripts\pyinstaller.exe -F -w main.py

若无错误,会在当前目录生成dist和build文件夹,dist下的main.exe就是打包后的结果,可以拷贝到其他未安装python和pyqt环境的机器上测试执行;

pyinstaller的参数说明:

-F     打包成一个单文件
-c     打包成一个控制台程序(默认)
-w     打包成一个windows程序
-i     指定一个ico文件作图标

over

研发团队GIT开发流程新人学习指南【轉】

【原文鏈接】

研发团队GIT开发流程新人学习指南

【原文內容】

分支流程说明

简介

项目中长期存在的两个分支

  • master:主分支,负责记录上线版本的迭代,该分支代码与线上代码是完全一致的。
  • develop:开发分支,该分支记录相对稳定的版本,所有的feature分支和bugfix分支都从该分支创建。

其它分支为短期分支,其完成功能开发之后需要删除

  • feature/*:特性(功能)分支,用于开发新的功能,不同的功能创建不同的功能分支,功能分支开发完成并自测通过之后,需要合并到 develop 分支,之后删除该分支。
  • bugfix/*:bug修复分支,用于修复不紧急的bug,普通bug均需要创建bugfix分支开发,开发完成自测没问题后合并到 develop 分支后,删除该分支。
  • release/*:发布分支,用于代码上线准备,该分支从develop分支创建,创建之后由测试同学发布到测试环境进行测试,测试过程中发现bug需要开发人员在该release分支上进行bug修复,所有bug修复完后,在上线之前,需要合并该release分支到master分支和develop分支。
  • hotfix/*:紧急bug修复分支,该分支只有在紧急情况下使用,从master分支创建,用于紧急修复线上bug,修复完成后,需要合并该分支到master分支以便上线,同时需要再合并到develop分支。

必读文章

团队中的 Git 实践
Git 在团队中的最佳实践–如何正确使用Git Flow

分支命令规范

特性(功能)分支

功能分支的分支名称应该为能够准确描述该功能的英文简要表述

  1. feature/分支名称

例如,开发的功能为 新增商品到物料库,则可以创建名称为 feature/material-add的分支。

bug修复分支、紧急bug修复分支

bug修复分支的分支名称可以为Jira中bug代码或者是描述该bug的英文简称

  1. bugfix/分支名称
  2. hotfix/分支名称

比如,修复的bug在jira中代号为MATERIAL-1,则可以创建一个名为bugfix/MATERIAL-1的分支。

release分支

release分支为预发布分支,命名为本次发布的主要功能英文简称

  1. release/分支名称

比如,本次上线物料库新增的功能,则分支名称可以为release/material-add

常用操作命令简介

基本操作

基本命令这里就不多说了,基本跟以前一样,唯一的区别是注意分支是从哪里拉去的以及分支的命名规范。涉及到的命令主要包含以下,大家自己学习:

  • git commit
  • git add [–all]
  • git push
  • git pull
  • git branch [-d]
  • git merge
  • git cherry-pick
  • git checkout [-b] BRANCH_NAME
  • git stash

分支操作参考 Git常用操作-分支管理

使用git flow简化操作

git flow是git的一个插件,可以极大程度的简化执行git标准分支流程的操作,可以在gitflow-avh安装。

如果是windows下通过安装包安装的git,则该插件默认已经包含,可以直接使用。

初始化

使用git flow init初始化项目

  1. $ git flow init
  2. Which branch should be used for bringing forth production releases?
  3. – develop
  4. – feature-fulltext
  5. – feature-vender
  6. – master
  7. Branch name for production releases: [master]
  8. Which branch should be used for integration of the “next release”?
  9. – develop
  10. – feature-fulltext
  11. – feature-vender
  12. Branch name for “next release” development: [develop]
  13. How to name your supporting branch prefixes?
  14. Feature branches? [feature/]
  15. Bugfix branches? [bugfix/]
  16. Release branches? [release/]
  17. Hotfix branches? [hotfix/]
  18. Support branches? [support/]
  19. Version tag prefix? []
  20. Hooks and filters directory? [/Users/mylxsw/codes/work/e-business-3.0/.git/hooks]

功能分支

  1. git flow feature
  2. git flow feature start <name>
  3. git flow feature finish <name>
  4. git flow feature delete <name>
  5. git flow feature publish <name>
  6. git flow feature track <name>

功能分支使用例子:

  1. $ git flow feature start material-add
  2. Switched to a new branch ‘feature/material-add’
  3. Summary of actions:
  4. – A new branch ‘feature/material-add’ was created, based on ‘develop’
  5. – You are now on branch ‘feature/material-add’
  6. Now, start committing on your feature. When done, use:
  7. git flow feature finish material-add
  8. $ git status
  9. On branch feature/material-add
  10. nothing to commit, working directory clean
  11. $ git flow feature publish
  12. Total 0 (delta 0), reused 0 (delta 0)
  13. To http://dev.oss.yunsom.cn:801/yunsom/e-business-3.0.git
  14. * [new branch] feature/material-add -> feature/material-add
  15. Branch feature/material-add set up to track remote branch feature/material-add from origin.
  16. Already on ‘feature/material-add’
  17. Your branch is up-to-date with ‘origin/feature/material-add’.
  18. Summary of actions:
  19. – The remote branch ‘feature/material-add’ was created or updated
  20. – The local branch ‘feature/material-add’ was configured to track the remote branch
  21. – You are now on branch ‘feature/material-add’
  22. $ vim README.md
  23. $ git add –all
  24. $ git commit -m “modify readme file “
  25. [feature/material-add 7235bd4] modify readme file
  26. 1 file changed, 1 insertion(+), 2 deletions()
  27. $ git push
  28. Counting objects: 3, done.
  29. Delta compression using up to 4 threads.
  30. Compressing objects: 100% (3/3), done.
  31. Writing objects: 100% (3/3), 303 bytes | 0 bytes/s, done.
  32. Total 3 (delta 2), reused 0 (delta 0)
  33. To http://dev.oss.yunsom.cn:801/yunsom/e-business-3.0.git
  34. 0d4fb8f..7235bd4 feature/material-add -> feature/material-add
  35. $ git flow feature finish
  36. Switched to branch ‘develop’
  37. Your branch is up-to-date with ‘origin/develop’.
  38. Updating 0d4fb8f..7235bd4
  39. Fast-forward
  40. README.md | 3 +–
  41. 1 file changed, 1 insertion(+), 2 deletions()
  42. To http://dev.oss.yunsom.cn:801/yunsom/e-business-3.0.git
  43. [deleted] feature/material-add
  44. Deleted branch feature/material-add (was 7235bd4).
  45. Summary of actions:
  46. – The feature branch ‘feature/material-add’ was merged into ‘develop’
  47. – Feature branch ‘feature/material-add’ has been locally deleted; it has been remotely deleted from ‘origin’
  48. – You are now on branch ‘develop’
  49. $ git branch
  50. * develop
  51. feature-fulltext
  52. feature-vender
  53. master

预发布分支

  1. git flow release
  2. git flow release start <release> [<base>]
  3. git flow release finish <release>
  4. git flow release delete <release>

hotfix分支

  1. git flow hotfix
  2. git flow hotfix start <release> [<base>]
  3. git flow hotfix finish <release>
  4. git flow hotfix delete <release>

git-flow 备忘清单

参考git-flow 备忘清单

总结

如果上面内容太多记不住,也没有关系,作为开发人员,刚开始的时候只要知道以下几点就足够了,其它的可以在碰到的时候再深入学习:

  • 所有的新功能开发,bug修复(非紧急)都要从develop分支拉取新的分支进行开发,开发完成自测没有问题再合并到develop分支
  • release分支发布到测试环境,由开发人员创建release分支(需要测试人员提出需求)并发布到测试环境,如果测试过程中发现bug,需要开发人员track到该release分支修复bug,上线前需要测试人员提交merge requestmaster分支,准备上线,同时需要合并回develop分支。
  • 只有紧急情况下才允许从master上拉取hotfix分支,hotfix分支需要最终同时合并到developmaster分支(共两次merge操作)
  • 除了masterdevelop分支,其它分支在开发完成后都要删除

源码编译svn1.7.16【轉】

【摘自鏈接】

http://blog.csdn.net/xiaohuan_study/article/details/21623053

【原文內容】

1. 下载svn源码

源码地址:http://subversion.apache.org/download/

我们选择1.7.16版本,因为我windows PC环境下TortoiseSVN的内核是1.7版本的。

2. 下载apr, apr-utils

因为svn 对apr,apr-utils有依赖,所以需要下载源码:

svn co  http://svn.apache.org/repos/asf/apr/apr/branches/1.3.x    apr

svn co  http://svn.apache.org/repos/asf/apr/apr-util/branches/1.3.x   apr-util

上面两个库编译顺序有先后,编译方式是

$ cd apr; ./buildconf; ./configure …; make; make install
$ cd apr-util; ./buildconf; ./configure …; make; make install

其中在./configure的时候,可以通过–prefix指定安装目录

3. 下载sqlite

对sqlite有依赖,需要下载http://www.sqlite.org/sqlite-amalgamation-3.7.6.3.tar.gz,并吧解压出来的sqlite3.c放置到svn源码目录下的子目录sqlite-amalgamation中,如果没有,就建立个子目录。

3.编译svn

./configure –prefix=svn安装目录 –with-apr=指向apr安装目录 –with-apr-util=指向apr-util安装目录

make install

4. 测试

输入命令:svn –version

输入如下:

svn, version 1.7.16 (r1569520)
compiled Mar 20 2014, 16:01:57

 

DOXYGEN简明实用教程【轉】

【摘自鏈接】

http://www.cnblogs.com/wswqwps/archive/2009/03/04/1403376.html

【原文內容】

代码写多了难免需要做文档,给自己还是给别人看都需要如此,这次XBOX360制作,前期没怎么写注释,回头改Bug都要猜半天自己写的代码是什么意思。更别提别人写的东西,100行代码也没有一句注释,幸好不是我维护,否则要疯掉了。

花了一天功夫尝试了一下Doxygen的使用,还好不难,但是有些磕磕绊绊,它自己的文档也说不清楚,网上搜出来的教程也只是给出样子,遇到的问题还是靠自己尝试了几十次才搞定。

不管如何,常用的东西都可以弄出来了。贴在下面:

———————————————————————————–

1.所有注释都可以使用///开始(C++风格)。

2.类体前必须加上///描述,否则会产生警告【Compound 类名 is not documented】
描述中最好不要带有此类的类名,否则会产生两个链接(但指向同一个文件)影响美观。

3.public和protected会自动生成,但是private要在Expert的Build选项里勾中EXTRACT_PRIVATE,static成员也是如此。

4.函数注释方式
/// Constructor【函数描述】
/// @param [in] pos       The position of Camera in world coordinate         【参数描述1】
/// @param [in] lookat    The point Camera looks at in world coordinate    【参数描述2】
BaseCamera( const D3DXVECTOR3& pos, const D3DXVECTOR3& lookat );

5.变量注释方式
D3DXVECTOR3 m_Position;    /*!< Camera position point in world coordinate */   或
D3DXVECTOR3 m_Position;    ///< Camera position point in world coordinate
两种方式产生的结果不同。前者会单独产生一块Member Data Documentation注释,后者会在Pubilc/Protected/Private Attributes变量描述后紧跟注释。

6.@参数和\参数相同

7.产生描述顺序和注释顺序相同,一般风格为

/// 函数描述
/// @param     参数描述
/// @return     返回值描述
/// @retval     返回值1     返回值1描述
/// @retval     返回值2     返回值2描述
/// @remarks     注意事项
/// @note    注意事项,功能同@remarks,显示字样不同
/// @par    自定义图块,后面可跟示例代码之类
/// @code(必须使用@endcode结束)
/// 示例代码(无需缩进)
/// @endcode
/// @see     其他参考项【产生指向参考的链接】
函数代码声明

8.特殊符号
/// –        产生一个黑色圆点

9.定义在类体里面的enum
/// Camera types
enum CAMERA_TYPE
{
CAMERA_FIRST_VIEW,/*!< Camera that looks from the first view */
CAMERA_MODEL_VIEW,///< Camera that looks from the third view
};
两种风格相同。

以下开始的项都是全局非类内定义,在文件最开始(我尝试是在include之前) 必须加上【/// \file 文件名】,否则不会生成注释【没有File Member页】。

10. 定义在文件里面的宏
#define CAMERA_TYPE_NUMBER     ///< The number of camera types.       或
#define CAMERA_TYPE_NUMBER     /*!< The number of camera types. */
风格说明见5。

11. 非类内enum定义同10.        两种风格相同。见9。
12. 非类内typedef定义同10.     风格说明见5。

———————————————————–

vim以16进制打开和编辑文件【轉】

【原文鏈接】

【Linux】vim以16进制打开和编辑文件

【原文內容】

先用vim以二进制格式打开需要编辑或查看的文件,不采用-b参数有时会导致转换错误,详见分隔线后部分。

vim -b file-to-open.dat

然后用xxd把文件转换成十六进制格式

:%!xxd

转化后显示类似如下

现在就可以对待普通文本一样查看和编辑二进制文件了。

修改十六进制内容是不会导致右侧字符改变;其实右侧的文本只是给你参考的,修改了再将十六进制转换回二进制,这些修改都会忽略。

修改完成使用xxd把十六进制转换回二进制:

:%!xxd -r

只有十六进制的修改会生效。

对称加密和分组加密中的四种模式(ECB、CBC、CFB、OFB)【轉】

【原文鏈接】

http://www.cnblogs.com/happyhippy/archive/2006/12/23/601353.html

【原文內容】

. AES对称加密:


AES加密

分组

. 分组密码的填充

分组密码的填充

e.g.:

PKCS#5填充方式

. 流密码:

. 分组密码加密中的四种模式:

3.1 ECB模式

优点:

1.简单;

2.有利于并行计算;

3.误差不会被传送;

缺点:

1.不能隐藏明文的模式;

2.可能对明文进行主动攻击;


3.2 CBC
模式:

优点:

1.不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。

缺点:

1.不利于并行计算;

2.误差传递;

3.需要初始化向量IV

 

3.3 CFB模式:

优点:

1.隐藏了明文模式;

2.分组密码转化为流模式;

3.可以及时加密传送小于分组的数据;

缺点:

1.不利于并行计算;

2.误差传送:一个明文单元损坏影响多个单元;

3.唯一的IV;

 

3.4 OFB模式:

优点:

1.隐藏了明文模式;

2.分组密码转化为流模式;

3.可以及时加密传送小于分组的数据;

缺点:

1.不利于并行计算;

2.对明文的主动攻击是可能的;

3.误差传送:一个明文单元损坏影响多个单元;

happyhippy作者:Silent Void
出处:http://happyhippy.cnblogs.com/
转载须保留此声明,并注明在文章起始位置给出原文链接。

学习用 doxygen 生成源码文档【轉】

【原文鏈接】

https://www.ibm.com/developerworks/cn/aix/library/au-learningdoxygen/

【原文內容】

维护用 C/C++ 开发的遗留系统并添加新特性是一项艰难的任务。这涉及几方面的问题:理解现有的类层次结构和全局变量,不同的用户定义类型,以及函数调用图分析等等。本文在 C/C++ 项目的上下文中通过示例讨论 doxygen 的几个特性。但是,doxygen 非常灵活,也可用于用 Python、Java、PHP 和其他语言开发的软件项目。本文的主要目的是帮助您从 C/C++ 源代码提取出信息,但也简要描述了如何用 doxygen 定义的标记生成代码文档。

安装 doxygen

有两种获得 doxygen 的方法。可以下载预编译的可执行文件,也可以从 SVN 存储库下载源代码并自己编译。清单 1 演示的是后一种方法。

清单 1. 安装和构建 doxygen 源代码
1
2
3
4
5
6
7
bash-2.05$ svn co https://doxygen.svn.sourceforge.net/svnroot/doxygen/trunk doxygen-svn
bash-2.05$ cd doxygen-svn
bash-2.05$ ./configure –prefix=/home/user1/bin
bash-2.05$ make
bash-2.05$ make install

注意,配置脚本把编译的源代码存储在 /home/user1/bin 中(进行编译后,会在 PATH 变量中添加这个目录),因为并非每个 UNIX® 用户都有写 /usr 文件夹的权限。另外,需要用 svn 实用程序下载源代码。

使用 doxygen 生成文档

使用 doxygen 生成源代码的文档需要执行三个步骤。

生成配置文件

在 shell 提示上,输入命令 doxygen -g。这个命令在当前目录中生成一个可编辑的配置文件 Doxyfile。可以改变这个文件名,在这种情况下,应该调用 doxygen -g <user-specified file name>,见 清单 2

清单 2. 生成默认的配置文件
1
2
3
4
5
6
7
bash-2.05b$ doxygen -g
Configuration file 'Doxyfile' created.
Now edit the configuration file and enter
  doxygen Doxyfile
to generate the documentation for your project
bash-2.05b$ ls Doxyfile
Doxyfile

编辑配置文件

配置文件采用 <TAGNAME> = <VALUE> 这样的结构,与 Make 文件格式相似。下面是最重要的标记:

  • <OUTPUT_DIRECTORY>必须在这里提供一个目录名,例如 /home/user1/documentation,这个目录是放置生成的文档文件的位置。如果提供一个不存在的目录名,doxygen 会以这个名称创建具有适当用户权限的目录。
  • <INPUT>这个标记创建一个以空格分隔的所有目录的列表,这个列表包含需要生成文档的 C/C++ 源代码文件和头文件。例如,请考虑以下代码片段:
    1
    INPUT = /home/user1/project/kernel /home/user1/project/memory

    在这里,doxygen 会从这两个目录读取 C/C++ 源代码。如果项目只有一个源代码根目录,其中有多个子目录,那么只需指定根目录并把 <RECURSIVE> 标记设置为 Yes

  • <FILE_PATTERNS>在默认情况下,doxygen 会搜索具有典型 C/C++ 扩展名的文件,比如 .c、.cc、.cpp、.h.hpp。如果 <FILE_PATTERNS> 标记没有相关联的值,doxygen 就会这样做。如果源代码文件采用不同的命名约定,就应该相应地更新这个标记。例如,如果项目使用 .c86 作为 C 文件扩展名,就应该在 <FILE_PATTERNS> 标记中添加这个扩展名。
  • <RECURSIVE>如果源代码层次结构是嵌套的,而且需要为所有层次上的 C/C++ 文件生成文档,就把这个标记设置为 Yes。例如,请考虑源代码根目录层次结构 /home/user1/project/kernel,其中有 /home/user1/project/kernel/vmm 和 /home/user1/project/kernel/asm 等子目录。如果这个标记设置为 Yes,doxygen 就会递归地搜索整个层次结构并提取信息。
  • <EXTRACT_ALL>这个标记告诉 doxygen,即使各个类或函数没有文档,也要提取信息。必须把这个标记设置为 Yes
  • <EXTRACT_PRIVATE>把这个标记设置为 Yes。否则,文档不包含类的私有数据成员。
  • <EXTRACT_STATIC>把这个标记设置为 Yes。否则,文档不包含文件的静态成员(函数和变量)。

清单 3 给出一个 Doxyfile 示例。

清单 3. 包含用户提供的标记值的 doxyfile 示例
1
2
3
4
5
6
7
8
9
OUTPUT_DIRECTORY = /home/user1/docs
EXTRACT_ALL = yes
EXTRACT_PRIVATE = yes
EXTRACT_STATIC = yes
INPUT = /home/user1/project/kernel
#Do not add anything here unless you need to. Doxygen already covers all
#common formats like .c/.cc/.cxx/.c++/.cpp/.inl/.h/.hpp
FILE_PATTERNS =
RECURSIVE = yes

运行 doxygen

在 shell 提示下输入 doxygen Doxyfile(或者已为配置文件选择的其他文件名)运行 doxygen。在最终生成 Hypertext Markup Language(HTML)和 Latex 格式(默认)的文档之前,doxygen 会显示几个消息。在生成文档期间,在 <OUTPUT_DIRECTORY> 标记指定的文件夹中,会创建两个子文件夹 htmllatex清单 4 是一个 doxygen 运行日志示例。

清单 4. doxygen 的日志输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Searching for include files...
Searching for example files...
Searching for images...
Searching for dot files...
Searching for files to exclude
Reading input files...
Reading and parsing tag files
Preprocessing /home/user1/project/kernel/kernel.h
Read 12489207 bytes
Parsing input...
Parsing file /project/user1/project/kernel/epico.cxx
Freeing input...
Building group list...
..
Generating docs for compound MemoryManager::ProcessSpec
Generating docs for namespace std
Generating group index...
Generating example index...
Generating file member index...
Generating namespace member index...
Generating page index...
Generating graph info page...
Generating search index...
Generating style sheet...

文档输出格式

除了 HTML 之外,doxygen 还可以生成几种输出格式的文档。可以让 doxygen 生成以下格式的文档:

  • UNIX 手册页:<GENERATE_MAN> 标记设置为 Yes。在默认情况下,会在 <OUTPUT_DIRECTORY> 指定的目录中创建 man 子文件夹,生成的文档放在这个文件夹中。必须把这个文件夹添加到 MANPATH 环境变量中。
  • Rich Text Format(RTF):<GENERATE_RTF> 标记设置为 Yes。把 <RTF_OUTPUT> 标记设置为希望放置 .rtf 文件的目录;在默认情况下,文档放在 OUTPUT_DIRECTORY 中的 rtf 子文件夹中。要想支持跨文档浏览,应该把 <RTF_HYPERLINKS> 标记设置为 Yes。如果设置这个标记,生成的 .rtf 文件会包含跨文档链接。
  • Latex:在默认情况下,doxygen 生成 Latex 和 HTML 格式的文档。在默认的 Doxyfile 中,<GENERATE_LATEX> 标记设置为 Yes。另外,<LATEX_OUTPUT> 标记设置为 Latex,这意味着会在 OUTPUT_DIRECTORY 中创建 latex 子文件夹并在其中生成 Latex 文件。
  • Microsoft® Compiled HTML Help(CHM)格式:<GENERATE_HTMLHELP> 标记设置为 Yes。因为在 UNIX 平台上不支持这种格式,doxygen 只在保存 HTML 文件的文件夹中生成一个 index.hhp 文件。您必须通过 HTML 帮助编译器把这个文件转换为 .chm 文件。
  • Extensible Markup Language(XML)格式:<GENERATE_XML> 标记设置为 Yes。(注意,doxygen 开发团队还在开发 XML 输出)。

清单 5 提供的 Doxyfile 示例让 doxygen 生成所有格式的文档。

清单 5. 生成多种格式的文档的 Doxyfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#for HTML
GENERATE_HTML = YES
HTML_FILE_EXTENSION = .htm
#for CHM files
GENERATE_HTMLHELP = YES
#for Latex output
GENERATE_LATEX = YES
LATEX_OUTPUT = latex
#for RTF
GENERATE_RTF = YES
RTF_OUTPUT = rtf
RTF_HYPERLINKS = YES
#for MAN pages
GENERATE_MAN = YES
MAN_OUTPUT = man
#for XML
GENERATE_XML = YES

doxygen 中的特殊标记

doxygen 包含几个特殊标记。

C/C++ 代码的预处理

为了提取信息,doxygen 必须对 C/C++ 代码进行预处理。但是,在默认情况下,它只进行部分预处理 —— 计算条件编译语句(#if…#endif),但是不执行宏展开。请考虑 清单 6 中的代码。

清单 6. 使用宏的 C++ 代码示例
1
2
3
4
5
6
7
8
9
10
11
12
#include <cstring>
#include <rope>
#define USE_ROPE
#ifdef USE_ROPE
  #define STRING std::rope
#else
  #define STRING std::string
#endif
static STRING name;

通过源代码中定义的 <USE_ROPE>,doxygen 生成的文档如下:

1
2
3
4
5
6
Defines
    #define USE_ROPE
    #define STRING std::rope
Variables
    static STRING name

在这里可以看到 doxygen 执行了条件编译,但是没有对 STRING 执行宏展开。Doxyfile 中的 <ENABLE_PREPROCESSING> 标记在默认情况下设置为 Yes。为了执行宏展开,还应该把 <MACRO_EXPANSION> 标记设置为 Yes。这会使 doxygen 产生以下输出:

1
2
3
4
5
6
Defines
   #define USE_ROPE
    #define STRING std::string
Variables
    static std::rope name

如果把 <ENABLE_PREPROCESSING> 标记设置为 No,前面源代码的 doxygen 输出就是:

1
2
Variables
    static STRING name

注意,文档现在没有定义,而且不可能推导出 STRING 的类型。因此,总是应该把 <ENABLE_PREPROCESSING> 标记设置为 Yes

在文档中,可能希望只展开特定的宏。为此,除了把 <ENABLE_PREPROCESSING><MACRO_EXPANSION> 标记设置为 Yes 之外,还必须把 <EXPAND_ONLY_PREDEF> 标记设置为 Yes(这个标记在默认情况下设置为 No),并在 <PREDEFINED><EXPAND_AS_DEFINED> 标记中提供宏的细节。请考虑 清单 7 中的代码,这里只希望展开宏 CONTAINER

清单 7. 包含多个宏的 C++ 源代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifdef USE_ROPE
  #define STRING std::rope
#else
  #define STRING std::string
#endif
#if ALLOW_RANDOM_ACCESS == 1
  #define CONTAINER std::vector
#else
  #define CONTAINER std::list
#endif
static STRING name;
static CONTAINER gList;

清单 8 给出配置文件。

清单 8. 允许有选择地展开宏的 Doxyfile
1
2
3
4
5
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
EXPAND_AS_DEFINED = CONTAINER

下面的 doxygen 输出只展开了 CONTAINER

1
2
3
4
5
6
7
Defines
#define STRING   std::string
#define CONTAINER   std::list
Variables
static STRING name
static std::list gList

注意,只有 CONTAINER 宏被展开了。在 <MACRO_EXPANSION><EXPAND_ONLY_PREDEF> 都设置为 Yes 的情况下,<EXPAND_AS_DEFINED> 标记只选择展开等号操作符右边列出的宏。

对于预处理过程,要注意的最后一个标记是 <PREDEFINED>。就像用 -D 开关向 C++ 编译器传递预处理器定义一样,使用这个标记定义宏。请考虑 清单 9 中的 Doxyfile。

清单 9. 定义了宏展开标记的 Doxyfile
1
2
3
4
5
6
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
EXPAND_AS_DEFINED =
PREDEFINED = USE_ROPE= \
                             ALLOW_RANDOM_ACCESS=1

下面是 doxygen 生成的输出:

1
2
3
4
5
6
7
8
Defines
#define USE_CROPE
#define STRING   std::rope
#define CONTAINER   std::vector
Variables
static std::rope name
static std::vector gList

在使用 <PREDEFINED> 标记时,宏应该定义为 <macro name>=<value> 形式。如果不提供值,比如简单的 #define,那么只使用 <macro name>=<spaces> 即可。多个宏定义以空格或反斜杠(\)分隔。

从文档生成过程中排除特定文件或目录

在 Doxyfile 中的 <EXCLUDE> 标记中,添加不应该为其生成文档的文件或目录(以空格分隔)。因此,如果提供了源代码层次结构的根,并要跳过某些子目录,这将非常有用。例如,如果层次结构的根是 src_root,希望在文档生成过程中跳过 examples/ 和 test/memoryleaks 文件夹,Doxyfile 应该像 清单 10 这样。

清单 10. 使用 EXCLUDE 标记的 Doxyfile
1
2
3
INPUT = /home/user1/src_root
EXCLUDE = /home/user1/src_root/examples /home/user1/src_root/test/memoryleaks

生成图形和图表

在默认情况下,Doxyfile 把 <CLASS_DIAGRAMS> 标记设置为 Yes。这个标记用来生成类层次结构图。要想生成更好的视图,可以从 Graphviz 下载站点 下载 dot 工具。Doxyfile 中的以下标记用来生成图表:

  • <CLASS_DIAGRAMS>在 Doxyfile 中这个标记默认设置为 Yes。如果这个标记设置为 No,就不生成继承层次结构图。
  • <HAVE_DOT>如果这个标记设置为 Yes,doxygen 就使用 dot 工具生成更强大的图形,比如帮助理解类成员及其数据结构的协作图。注意,如果这个标记设置为 Yes<CLASS_DIAGRAMS> 标记就无效了。
  • <CLASS_GRAPH>如果 <HAVE_DOT> 标记和这个标记同时设置为 Yes,就使用 dot 生成继承层次结构图,而且其外观比只使用 <CLASS_DIAGRAMS> 时更丰富。
  • <COLLABORATION_GRAPH>如果 <HAVE_DOT> 标记和这个标记同时设置为 Yes,doxygen 会生成协作图(还有继承图),显示各个类成员(即包含)及其继承层次结构。

清单 11 提供一个使用一些数据结构的示例。注意,在配置文件中 <HAVE_DOT><CLASS_GRAPH><COLLABORATION_GRAPH> 标记都设置为 Yes

清单 11. C++ 类和结构示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct D {
  int d;
};
class A {
  int a;
};
class B : public A {
  int b;
};
class C : public B {
  int c;
  D d;
};

图 1 给出 doxygen 的输出。

图 1. 使用 dot 工具生成的类继承图和协作图

类继承图

代码文档样式

到目前为止,我们都是使用 doxygen 从原本没有文档的代码中提取信息。但是,doxygen 也鼓励使用文档样式和语法,这有助于生成更详细的文档。本节讨论 doxygen 鼓励在 C/C++ 代码中使用的一些常用标记。更多信息参见 参考资料

每个代码元素有两种描述:简短的和详细的。简短描述通常是单行的。函数和类方法还有第三种描述体内描述(in-body description),这种描述把在函数体中找到的所有注释块集中在一起。比较常用的一些 doxygen 标记和注释样式如下:

  • 简短描述:使用单行的 C++ 注释,或使用 <\brief> 标记。
  • 详细描述:使用 JavaDoc 式的注释 /** … test … */(注意开头的两个星号 [*])或 Qt 式的注释 /*! … text … */
  • 体内描述:类、结构、联合体和名称空间等 C++ 元素都有自己的标记,比如 <\class><\struct><\union><\namespace>

为了为全局函数、变量和枚举类型生成文档,必须先对对应的文件使用 <\file> 标记。清单 12 给出的示例包含用于四种元素的标记:函数标记(<\fn>)、函数参数标记(<\param>)、变量名标记(<\var>)、用于 #define 的标记(<\def>)以及用来表示与一个代码片段相关的问题的标记(<\warning>)。

清单 12. 典型的 doxygen 标记及其使用方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*! \file globaldecls.h
      \brief Place to look for global variables, enums, functions
           and macro definitions
  */
/** \var const int fileSize
      \brief Default size of the file on disk
  */
const int fileSize = 1048576;
/** \def SHIFT(value, length)
      \brief Left shift value by length in bits
  */
#define SHIFT(value, length) ((value) << (length))
/** \fn bool check_for_io_errors(FILE* fp)
      \brief Checks if a file is corrupted or not
      \param fp Pointer to an already opened file
      \warning Not thread safe!
  */
bool check_for_io_errors(FILE* fp);

下面是生成的文档:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Defines
#define SHIFT(value, length)   ((value) << (length)) 
             Left shift value by length in bits.
Functions
bool check_for_io_errors (FILE *fp) 
        Checks if a file is corrupted or not.
Variables
const int fileSize = 1048576;
Function Documentation
bool check_for_io_errors (FILE* fp)
Checks if a file is corrupted or not.
Parameters
              fp: Pointer to an already opened file
Warning
Not thread safe!

结束语

本文讨论如何用 doxygen 从遗留的 C/C++ 代码提取出大量相关信息。如果用 doxygen 标记生成代码文档,doxygen 会以容易阅读的格式生成输出。只要以适当的方式使用,doxygen 就可以帮助任何开发人员维护和管理遗留系统。

在 linux 下使用 CMake 构建应用程序【轉】

【原文鏈接】

https://www.ibm.com/developerworks/cn/linux/l-cn-cmake/

【原文內容】

本文介绍了一个跨平台的自动化构建系统 CMake 在 linux 上的使用方法。 CMake 是一个比 automake 更加容易使用的工具,能够使程序员从复杂的编译连接过程中解脱出来。文中通过一些例子介绍使用 CMake 处理多源文件目录的方法、查找并使用其他开发包的方法以及生成 debug 版和 release 版程序的方法。

CMake 简介

CMake 是一个跨平台的自动化建构系统,它使用一个名为 CMakeLists.txt 的文件来描述构建过程,可以产生标准的构建文件,如 Unix 的 Makefile 或Windows Visual C++ 的 projects/workspaces 。文件 CMakeLists.txt 需要手工编写,也可以通过编写脚本进行半自动的生成。CMake 提供了比 autoconfig 更简洁的语法。在 linux 平台下使用 CMake 生成 Makefile 并编译的流程如下:

  1. 编写 CmakeLists.txt
  2. 执行命令“cmake PATH”或者“ccmake PATH”生成 Makefile ( PATH 是 CMakeLists.txt 所在的目录 )。
  3. 使用 make 命令进行编译。

第一个工程

现假设我们的项目中只有一个源文件 main.cpp

清单 1 源文件 main.cpp
1 #include<iostream>
2 
3 int main()
4 {
5     std::cout<<"Hello word!"<<std::endl;
6     return 0;
7 }

为了构建该项目,我们需要编写文件 CMakeLists.txt 并将其与 main.cpp 放在
同一个目录下:

清单 2 CMakeLists.txt
1 PROJECT(main)
2 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
3 AUX_SOURCE_DIRECTORY(. DIR_SRCS)
4 ADD_EXECUTABLE(main ${DIR_SRCS})

CMakeLists.txt

的语法比较简单,由命令、注释和空格组成,其中命令是不区分大小写的,符号”#”后面的内容被认为是注释。命令由命令名称、小括号和参数组成,参数之间使用空格进行间隔。例如对于清单2的
CMakeLists.txt 文件:第一行是一条命令,名称是 PROJECT ,参数是 main ,该命令表示项目的名称是 main
。第二行的命令限定了 CMake 的版本。第三行使用命令 AUX_SOURCE_DIRECTORY 将当前目录中的源文件名称赋值给变量
DIR_SRCS 。 CMake 手册中对命令 AUX_SOURCE_DIRECTORY 的描述如下:

aux_source_directory(<dir> <variable>)


该命令会把参数 <dir> 中所有的源文件名称赋值给参数 <variable> 。 第四行使用命令 ADD_EXECUTABLE 指示变量 DIR_SRCS 中的源文件需要编译 成一个名称为 main 的可执行文件。


完成了文件 CMakeLists.txt 的编写后需要使用 cmake 或 ccmake 命令生成Makefile 。 ccmake 与命令 cmake 的不同之处在于 ccmake 提供了一个图形化的操作界面。cmake 命令的执行方式如下:

cmake [options] <path-to-source>


这里我们进入了 main.cpp 所在的目录后执行 “cmake .” 后就可以得到 Makefile 并使用 make 进行编译,如下图所示。

图 1. camke 的运行结果

camke 的运行结果

处理多源文件目录的方法

CMake 处理源代码分布在不同目录中的情况也十分简单。现假设我们的源代码分布情况如下:

图 2. 源代码分布情况

源代码分布情况

其中 src 目录下的文件要编译成一个链接库。

第一步,项目主目录中的 CMakeLists.txt

在目录 step2 中创建文件 CMakeLists.txt 。文件内容如下:

清单 3 目录 step2 中的 CMakeLists.txt

1 PROJECT(main)
2 CMAKE_MINIMUM_REQUIRED(VERSION 2.6) 
3 ADD_SUBDIRECTORY( src )
4 AUX_SOURCE_DIRECTORY(. DIR_SRCS)
5 ADD_EXECUTABLE(main ${DIR_SRCS}  )
6 TARGET_LINK_LIBRARIES( main Test )

相对于清单 2,该文件添加了下面的内容: 第三行,使用命令 ADD_SUBDIRECTORY 指明本项目包含一个子目录 src 。第六行,使用命令 TARGET_LINK_LIBRARIES 指明可执行文件 main 需要连接一个名为Test的链接库 。

第二步,子目录中的 CmakeLists.txt

在子目录 src 中创建 CmakeLists.txt。文件内容如下:

清单 4. 目录 src 中的 CmakeLists.txt

1 AUX_SOURCE_DIRECTORY(. DIR_TEST1_SRCS)
2 ADD_LIBRARY ( Test ${DIR_TEST1_SRCS})

在该文件中使用命令 ADD_LIBRARY 将 src 目录中的源文件编译为共享库。

第三步,执行 cmake

至此我们完成了项目中所有 CMakeLists.txt 文件的编写,进入目录 step2 中依次执行命令 “cmake .” 和 “make” 得到结果如下:

图3. 处理多源文件目录时 cmake 的执行结果

处理多源文件目录时 cmake 的执行结果

在执行 cmake 的过程中,首先解析目录 step2 中的 CMakeLists.txt ,当程序执行命令 ADD_SUBDIRECTORY( src ) 时进入目录 src 对其中的 CMakeLists.txt 进行解析。

在工程中查找并使用其他程序库的方法

在开发软件的时候我们会用到一些函数库,这些函数库在不同的系统中安装的位置可能不同,编译的时候需要首先找到这些软件包的头文件以及链接库所在的目录以便生成编译选项。例如一个需要使用博克利数据库项目,需要头文件db_cxx.h 和链接库 libdb_cxx.so ,现在该项目中有一个源代码文件 main.cpp ,放在项目的根目录中。

第一步,程序库说明文件

在项目的根目录中创建目录 cmake/modules/ ,在 cmake/modules/ 下创建文件 Findlibdb_cxx.cmake ,内容如下:

清单 5. 文件 Findlibdb_cxx.cmake

01 MESSAGE(STATUS "Using bundled Findlibdb.cmake...")
0203 FIND_PATH(
04   LIBDB_CXX_INCLUDE_DIR
05   db_cxx.h 
06   /usr/include/ 
07   /usr/local/include/ 
08   )
09 
10 FIND_LIBRARY(
11   LIBDB_CXX_LIBRARIES NAMES  db_cxx
12   PATHS /usr/lib/ /usr/local/lib/
13   )

文件 Findlibdb_cxx.cmake 的命名要符合规范: FindlibNAME.cmake ,其中NAME 是函数库的名称。Findlibdb_cxx.cmake 的语法与 CMakeLists.txt 相同。这里使用了三个命令: MESSAGE , FIND_PATH 和 FIND_LIBRARY 。

  • 命令 MESSAGE 将参数的内容输出到终端
  • 命令 FIND_PATH 指明头文件查找的路径,原型如下
    find_path(<VAR> name1 [path1 path2 ...])
    该命令在参数 path* 指示的目录中查找文件 name1 并将查找到的路径保存在变量 VAR 中。清单538行的意思是在 /usr/include/ /usr/local/include/ 中查找文件db_cxx.h ,并将db_cxx.h 所在的路径保存在 LIBDB_CXX_INCLUDE_DIR中。
  • 命令 FIND_LIBRARY 同 FIND_PATH 类似,用于查找链接库并将结果保存在变量中。清单5第10-13行的意思是在目录 /usr/lib/ 和 /usr/local/lib/ 中寻找名称为 db_cxx 的链接库,并将结果保存在 LIBDB_CXX_LIBRARIES。

第二步, 项目的根目录中的 CmakeList.txt


在项目的根目录中创建 CmakeList.txt :

清单 6. 可以查找链接库的 CMakeList.txt

01 PROJECT(main)
02 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
03 SET(CMAKE_SOURCE_DIR .)
04 SET(CMAKE_MODULE_PATH ${CMAKE_ROOT}/Modules ${CMAKE_SOURCE_DIR}/cmake/modules) 
05 AUX_SOURCE_DIRECTORY(. DIR_SRCS)
06 ADD_EXECUTABLE(main ${DIR_SRCS})
0708 FIND_PACKAGE( libdb_cxx REQUIRED)
09 MARK_AS_ADVANCED(
10 LIBDB_CXX_INCLUDE_DIR
11 LIBDB_CXX_LIBRARIES
12 )
13 IF (LIBDB_CXX_INCLUDE_DIR AND LIBDB_CXX_LIBRARIES)
14 MESSAGE(STATUS "Found libdb libraries")
15    INCLUDE_DIRECTORIES(${LIBDB_CXX_INCLUDE_DIR})
16     MESSAGE( ${LIBDB_CXX_LIBRARIES} )
17     TARGET_LINK_LIBRARIES(main ${LIBDB_CXX_LIBRARIES}18 )
19 ENDIF (LIBDB_CXX_INCLUDE_DIR AND LIBDB_CXX_LIBRARIES)

在该文件中第4行表示到目录
./cmake/modules 中查找 Findlibdb_cxx.cmake ,8-19 行表示查找链接库和头文件的过程。第8行使用命令
FIND_PACKAGE 进行查找,这条命令执行后 CMake 会到变量 CMAKE_MODULE_PATH 指示的目录中查找文件
Findlibdb_cxx.cmake 并执行。第13-19行是条件判断语句,表示如果 LIBDB_CXX_INCLUDE_DIR 和
LIBDB_CXX_LIBRARIES 都已经被赋值,则设置编译时到 LIBDB_CXX_INCLUDE_DIR 寻找头文件并且设置可执行文件
main 需要与链接库 LIBDB_CXX_LIBRARIES 进行连接。

第三步,执行 cmake


完成 Findlibdb_cxx.cmake 和 CMakeList.txt 的编写后在项目的根目录依次执行 “cmake . ” 和 “make ” 可以进行编译,结果如下图所示:

图 4. 使用其他程序库时 cmake 的执行结果

使用其他程序库时 cmake 的执行结果

使用 cmake 生成 debug 版和 release 版的程序

在 Visual Studio 中我们可以生成 debug 版和 release 版的程序,使用 CMake 我们也可以达到上述效果。debug 版的项目生成的可执行文件需要有调试信息并且不需要进行优化,而 release 版的不需要调试信息但需要优化。这些特性在 gcc/g++ 中是通过编译时的参数来决定的,如果将优化程度调到最高需要设置参数-O3,最低是 -O0 即不做优化;添加调试信息的参数是 -g -ggdb ,如果不添加这个参数,调试信息就不会被包含在生成的二进制文件中。

CMake 中有一个变量 CMAKE_BUILD_TYPE ,可以的取值是 Debug Release RelWithDebInfo 和 MinSizeRel。当这个变量值为 Debug 的时候,CMake 会使用变量 CMAKE_CXX_FLAGS_DEBUG 和 CMAKE_C_FLAGS_DEBUG 中的字符串作为编译选项生成 Makefile ,当这个变量值为 Release 的时候,工程会使用变量 CMAKE_CXX_FLAGS_RELEASE 和 CMAKE_C_FLAGS_RELEASE 选项生成 Makefile。

现假设项目中只有一个文件 main.cpp ,下面是一个可以选择生成 debug 版和 release 版的程序的 CMakeList.txt :

清单 7

1 PROJECT(main)
2 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
3 SET(CMAKE_SOURCE_DIR .)
45 SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
6 SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
78 AUX_SOURCE_DIRECTORY(. DIR_SRCS)
9 ADD_EXECUTABLE(main ${DIR_SRCS})

第 5 和 6 行设置了两个变量 CMAKE_CXX_FLAGS_DEBUG 和 CMAKE_CXX_FLAGS_RELEASE, 这两个变量是分别用于 debug 和 release 的编译选项。 编辑 CMakeList.txt 后需要执行 ccmake 命令生成 Makefile 。在进入项目的根目录,输入 “ccmake .” 进入一个图形化界面,如下图所示:

图 5. ccmake 的界面

ccmake 的界面

按照界面中的提示进行操作,按 “c” 进行 configure ,这时界面中显示出了配置变量 CMAKE_BUILD_TYPE 的条目。如下图所示:

图 6. 执行了 configure 以后 ccmake 的界面

执行了 configure 以后 ccmake 的界面

下面我们首先生成 Debug 版的 Makefile :将变量 CMAKE_BUILD_TYPE 设置为 Debug ,按 “c” 进行 configure ,按 “g” 生成 Makefile 并退出。这时执行命令 find * | xargs grep “O0” 后结果如下:

清单 8 find * | xargs grep “O0″的执行结果

CMakeFiles/main.dir/flags.make:CXX_FLAGS = -O0 -Wall -g -ggdb 
CMakeFiles/main.dir/link.txt:/usr/bin/c++ -O0 -Wall -g -ggdb 
CMakeFiles/main.dir/main.cpp.o -o main -rdynamic 
CMakeLists.txt:SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")

这个结果说明生成的 Makefile 中使用了变量 CMAKE_CXX_FLAGS_DEBUG 作为编译时的参数。

下面我们将生成 Release 版的 Makefile :再次执行命令 “ccmake .” 将变量CMAKE_BUILD_TYPE 设置为 Release ,生成 Makefile 并退出。执行命令 find * | xargs grep “O0” 后结果如下:

清单 9 find * | xargs grep “O0″的执行结果

CMakeLists.txt:SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")

而执行命令 find * | xargs grep “O3” 后结果如下:

清单 10. find * | xargs grep “O3″的执行结果

CMakeCache.txt:CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
CMakeCache.txt:CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
CMakeFiles/main.dir/flags.make:CXX_FLAGS = -O3 -Wall 
CMakeFiles/main.dir/link.txt:/usr/bin/c++ -O3 -Wall 
CMakeFiles/main.dir/main.cpp.o -o main -rdynamic 
CMakeLists.txt:SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")

这两个结果说明生成的 Makefile 中使用了变量 CMAKE_CXX_FLAGS_RELEASE 作为编译时的参数。

参考资料

Openssl源码方式添加国密SM2算法【轉】

【原文摘自】

http://blog.csdn.net/mrpre/article/details/51700884

【原文內容】

1:源码方式,只需要添加2部分,第一部分是 国密sm2的oid,第二部分是group。

如果不添加,则 EVP_PKEY 无法解析,ec_asn1_pkparameters2group 函数 因为找不到 oid对应的group导致解析私钥失败,或者解析x509的公钥为空。

注:如下修改 不会 让你支持生成SM2国密证书或者支持诸如ECC_SM4_SM3等国密加密套件。

该修改只是让你能够让openssl正常解密 sm2 证书。

1:添加sm2的oid

cd crypto/objects/

编辑  objects.txt ,添加: 1 2 156 10197 1 301: SM2: SM2

随便加在哪里即可,我添加在文件最后。

然后在当前目录下执行:
perl objects.pl objects.txt obj_mac.num obj_mac.h
perl obj_dat.pl obj_mac.h  obj_dat.h

2:添加 group

ec_curve.c 中添加 2 个定义:

static const struct { EC_CURVE_DATA h; unsigned char data[0+32*6]; }
_EC_X9_62_sm2 = {
{ NID_X9_62_prime_field,0,32,1 },
{  /* seed */
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,/* p */
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,    /* a */
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFc,
0x28,0xE9,0xFA,0x9E,0x9D,0x9F,0x5E,0x34,0x4D,0x5A,/* b */
0x9E,0x4B,0xCF,0x65,0x09,0xA7,0xF3,0x97,0x89,0xF5,
0x15,0xAB,0x8F,0x92,0xDD,0xBC,0xBD,0x41,0x4D,0x94,
0x0E,0x93,
0x32,0xC4,0xAE,0x2C,0x1F,0x19,0x81,0x19,0x5F,0x99,    /* x */
0x04,0x46,0x6A,0x39,0xC9,0x94,0x8F,0xE3,0x0B,0xBF,
0xF2,0x66,0x0B,0xE1,0x71,0x5A,0x45,0x89,0x33,0x4C,
0x74,0xC7,
0xBC,0x37,0x36,0xA2,0xF4,0xF6,0x77,0x9C,0x59,0xBD,    /* y */
0xCE,0xE3,0x6B,0x69,0x21,0x53,0xD0,0xA9,0x87,0x7C,
0xC6,0x2A,0x47,0x40,0x02,0xDF,0x32,0xE5,0x21,0x39,
0xF0,0xA0,
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x72,0x03,0xDF,0x6B,
0x21,0xC6,0x05,0x2B,0x53,0xBB,0xF4,0x09,0x39,0xD5,
0x41,0x23}
};

curve_list 中添加:

{ NID_SM2, &_EC_X9_62_sm2.h, 0, “sm2 curve over a 256 bit prime field” },

然后重新make一下。

上述添加完成之后,OpenSSL即支持 SM2国密算法,能够正常解析 SM2国密证书。

 

【附】

需要將./crypto/objects/obj_mac.h移動到./include/openssl/obj_mac.h下,才能進行編譯