# 中午吃完饭,就到了办公室,开始看 OGRE 的CMake配置文件。
# 想根据实例,再配合 CMake 安装包里自带了官方Manual,学习CMakeLists文件的编写。
# 不得不承认,没有外网真心惨。用手机查资料眼睛都瞅瞎了。
# 中间出去吃了个晚饭,然后一直研究到10点,还算是有点收获
本文内容要点:
1. 多目录下,头文件路径包含
2. 项目依赖关系设置
3. 发现的一些问题
本文涉及到的CMake命令:
project(name) : 设置project的名字为name。
add_dependencies:设置依赖关系
add_subdirectory:添加子目录
add_executable:添加可执行文件
add_library:添加库
cmake_minimum_required:设置cmake最低版本要求
include_directories:包含目录
target_link_libraries:链接库
set:可以用于设置变量
补充命令:
file(GLOB_RECURSE HEADER_FILES dir/*.h??)
此命令可以用来收集源文件 HEADER_FILES 作为变量保存收集的结果。 后面为文件过滤器,其中dir为起始搜索的文件夹,即在dir目录下,开始收集,而且会遍历子目录。 ? 代表 a-z。
首先给出目录结构(“-”表示目录级数)
-sin
--include
---sin.h
--src
---sin.cpp
-sinutil
--include
---sinutil.h
--src
---sinutil.cpp
-main
--main.cpp
目的:
main.cpp 要使用 sin 里面 sin.h 和 sin.cpp 生成的静态库 sin.lib,而 sin.lib 的生成要使用 sinutil 里面的 sinutil.h 和 sinutil.cpp 生成的静态库 sinutil.lib 。
sinutil.cpp 要包含 sinutil.h,而 sinutil.h 不在 sinutil.cpp 目录下。同理 sin.cpp 也要包含 sinutil.h ,main.cpp 要包含 sin.h。
根据CMake的规则,在根目录下和每个子目录下加入 CMakeLists.txt 文件。
# 为了便于区分,我给每个 CMakeLists.txt 加了编号后缀。
# 真正运行的时候,CMake配置文件只能命名为 CMakeLists.txt。
得到的目录结构如下:
- CMakeLists.txt - 1
-sin
-- CMakeLists.txt - 2
--include
---sin.h
--src
---sin.cpp
-sinutil
-- CMakeLists.txt - 3
--include
---sinutil.h
--src
---sinutil.cpp
-main
-- CMakeLists.txt - 4
--main.cpp
CMake配置文件内容如下:
#CMakeLists.txt - 1
cmake_minimum_required(VERSION 2.8.1)
project(CMakeDemo)
include_directories(${CMakeDemo_SOURCE_DIR}/sin/include)
include_directories(${CMakeDemo_SOURCE_DIR}/sinutil/include)
add_subdirectory(sin)
add_subdirectory(sinutil)
add_subdirectory(main)
#CMakeLists.txt - 4
project(MainDemo)
set(SRC_LIST main.cpp)
add_executable(demo ${SRC_LIST})
add_dependencies(demo SinLibrary)
target_link_libraries(demo ${SinLibrary})
#CMakeLists.txt - 2
set(HEADER_LIST include/sin.h)
set(SRC_LIST src/sin.cpp)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
add_library(SinLibrary ${HEADER_LIST} ${SRC_LIST})
add_dependencies(SinLibrary SinUtilLibrary)
target_link_libraries(SinLibrary ${SinUtilLibrary})
#CMakeLists.txt - 3
set(HEADER_LIST include/sinutil.h)
set(SRC_LIST src/sinutil.cpp)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
add_library(SinUtilLibrary ${HEADER_LIST} ${SRC_LIST})
结论:
1. CMake使用 include_directories 命令来添加头文件包含路径,且 include_directories 命令具有继承性。下级目录继承了上级目录中CMakeLists.txt 里面 include 的 directrories。但是平级目录之间的 CMakeList.txt 里面的include_directories 不能共享。
2. CMAKE_CURRENT_SOURCE_DIR 为 CMake 定义的环境变量,指向当前 CMakeLists.txt 所在的目录。
3. 当使用 project(name) 命令时,CMake会自动生成两个变量 name_SOURCE_DIR 和 name_BINARY_DIR,前一个指向使用 project 命令的CMakeLists.txt 所在的文件夹,后一个指向用cmake构建时,Build 目录下对应的目录。
问题:
1. 目前还没搞清 project 与 VS 里面的 解决方案(solution)和 工程(项目,project)的对应关系。
2. 使用 add_dependencies 来设置依赖关系时,在VS 2003 下,会为每一个subdirectory里面的project生成一个额外的带 UTILITY 后缀的工程,能不生成吗?
空协的。。。。自己看http://page.renren.com/601515204/note/892301714?ref=hotnewsfeed&sfet=2012&fin=1&fid=21075429468&ff_id=601515204&platform=0&expose_time=1357989999&feed=page_blog&tagid=892301714&statID=page_601515204_2&level=1
// FileScan.cpp : 定义控制台应用程序的入口点。//
#include "stdafx.h"
#include <filesystem>
#include <windows.h>
#define OK 0
#define ERR -1
#define TEST_FILE_MAX_SIZE "4.67G"
#define EXT_LEN 8
#define TYPE_LEN 8
#define DIR_MAX_LEN 260 //文件路径最多256个字符,加上D:\\
//ftell()返回int,最大2G 1<<32-1
typedef enum COND_VALUE
{
COND_VALUE_MORE = 0 ,//大于
COND_VALUE_LESS = 1 ,//小于
COND_VALUE_EUAQL = 2 ,//等于
COND_VALUE_MAX = 0xf
}COND_VALUE_E
typedef enum COND_TYPE
{
COND_TYPE_SIZE = 0 ,
COND_TYPE_CTIME = 1 ,
COND_TYPE_MTIME = 2,
COND_TYPE_EXTNAME = 4,
COND_TYPE_FILETYPE = 8,
COND_TYPE_MAX = 0xf
}COND_TYPE_E
typedef struct COND_INFO
{
char cCondType : 4
char cCondValue : 4
}COND_INFO_S
typedef struct FILE_COND
{
//按照bit位来划分,前面四个bit位表示条件类型,后面四个bit位表示条件值
char cSymbol//用来标志大于或者小于,搜索时间,大小,类型,扩展名,属性
char szRes[ 3 ]//预留3个字节,四字节对齐
unsigned int uiSizeHigh//文件大小 高位
unsigned int uiSizeLow//低位
unsigned int uiCStartTime//创建时间
unsigned int uiCEndTime
unsigned int uiMStartTime//修改时间
unsigned int uiMEndTime
char szExtName[ EXT_LEN ]//扩展名
char szFileType[ TYPE_LEN ]//文件类型
unsigned int uiFileAttrib//文件属性
unsigned int uiFolderSizeHight//文件夹大小
unsigned int uiFolderSizeLow
}FILE_COND_S
//最大允许多少个条件搜索
#define CONDITION_MAX 4
FILE_COND_S g_astCond[ CONDITION_MAX ] = { 0 }
int g_iCondCnt = 0
int DisposeFile(char szFilePath[] , WIN32_FIND_DATA stWinFile)
{
DWORDLONG dwHighBase = MAXDWORD
dwHighBase += 1
DWORDLONG FileSize = stWinFile.nFileSizeHigh* dwHighBase + stWinFile.nFileSizeLow
printf("%s\\%s--Size:%lu\n" , szFilePath , stWinFile.cFileName , FileSize)
return OK
}
//转换字符串文件大小(如 45.67G)到int类型的文件大小
#define SECTION_CNT 2
#define MAX_NUM_DEC 100
#define UNIT_CNT 4
#define KB_OFFSET 10 //1KB == 1BIT<<10
#define MB_OFFSET 20
#define GB_OFFSET 30
#define TB_OFFSET 40
#define INT_OFFSET 32
int ConvertSizeStr2SizeLong(char szSizeStr[],unsigned int* puiSizeHigh,unsigned int* puiSizeLow)
{
int aNumSect[ SECTION_CNT ] = { 0 }//分别存整数位和小数位
//char sz = "..."
char acValidUint[UNIT_CNT] = { 'K' , 'M' , 'G' , 'T' }//数组
//char acValidUint[] = "KMGT"//字符串
char acOffset[ UNIT_CNT ] = { KB_OFFSET , MB_OFFSET , GB_OFFSET , TB_OFFSET }
char cOffset = 0
int iBaseNum
char* pcTmp
int index = 0
int i
int iMask
//入参判断
if (szSizeStr == NULL)
{
return ERR
}
pcTmp = szSizeStr
while (*pcTmp!=0)
{
if (*pcTmp == '.')
{
index++
if ( index >= SECTION_CNT )
{
return ERR
}
}
else if ( *pcTmp >= '0' && *pcTmp <= '9' )
{
//小数位取3位,剩余的舍去
if ( index == 1 && aNumSect[ index ] > MAX_NUM_DEC )
{
pcTmp++
continue
}
else if (index == 0 && aNumSect[index] > MAX_NUM_DEC)
{
//1234G 不合法,应该写成1.234T
return ERR
}
aNumSect[ index ] = aNumSect[ index ] * 10 + *pcTmp - '0'
}
else
{
for ( i = 0 i < UNIT_CNT++i )
{
if ( toupper(*pcTmp) == acValidUint[ i ] )
{
break
}
}
if (i == UNIT_CNT)
{
return ERR
}
}
pcTmp++
}
if (cOffset == 0)
{
*puiSizeHigh = 0
*puiSizeLow = aNumSect[ 0 ]
}
else
{
//先转为下一级单位
iBaseNum = ( aNumSect[ 0 ] << KB_OFFSET ) + aNumSect[ 0 ]//能保证小于MAX_UNIT
cOffset -= KB_OFFSET
}
iMask = ( 1 << cOffset ) - 1//用于取低于(INT_OFFSET - cOffset)数据
*puiSizeHigh = ( iBaseNum >> ( INT_OFFSET - cOffset ) ) & iMask
*puiSizeLow = iBaseNum << cOffset
return OK
}
//比较文件大小
int CompareFileSize(WIN32_FIND_DATA stWinFile , FILE_COND_S stCond,char cCondValue)
{
switch ( cCondValue )
{
case COND_VALUE_LESS:
{
if ( stWinFile.nFileSizeHigh > stCond.uiSizeHigh )
{
return ERR
}
else if ( stWinFile.nFileSizeHigh ==stCond.uiSizeHigh )
{
if ( stWinFile.nFileSizeLow > stCond.uiSizeLow )
{
return ERR
}
}
break
}
case COND_VALUE_MORE:
{
if ( stWinFile.nFileSizeHigh < stCond.uiSizeHigh )
{
return ERR
}
else if ( stWinFile.nFileSizeHigh == stCond.uiSizeHigh )
{
if ( stWinFile.nFileSizeLow < stCond.uiSizeLow )
{
return ERR
}
}
break
}
case COND_VALUE_EUAQL:
{
if ( stWinFile.nFileSizeHigh != stCond.uiSizeHigh || stWinFile.nFileSizeLow != stCond.uiSizeLow )
{
return ERR
}
break
}
default:
break
}
return OK
}
int CompareFileTime(WIN32_FIND_DATA stWinFile , FILE_COND_S stCond , char cCondValue)
{
return OK
}
int CheckCondition(char szFilePath[],WIN32_FIND_DATA stWinFile)
{
int i
int iCondType
int iCondValue
COND_INFO_S* pstCondInfo
for ( i = 0 i < g_iCondCnt ++i )
{
pstCondInfo = (COND_INFO_S*)(&( g_astCond[ i ].cSymbol))
switch (pstCondInfo->cCondType)
{
case COND_TYPE_SIZE:
{
if ( CompareFileSize(stWinFile , g_astCond[ i ],pstCondInfo->cCondValue) != OK )
{
return ERR
}
break
}
case COND_TYPE_CTIME:
{
if ( CompareFileTime(stWinFile , g_astCond[ i ] , pstCondInfo->cCondValue) != OK )
{
return ERR
}
break
}
//...
default:
break
}
}
return OK
}
int ScanDir(char szDir[])
{
if ( szDir == NULL )
{
return ERR
}
char szSubDir[ DIR_MAX_LEN ] = { 0 }
char szFind[ DIR_MAX_LEN ] = { 0 }
WIN32_FIND_DATA stWinFile
HANDLE hd
_snprintf_c(szFind ,
DIR_MAX_LEN ,
"%s\\*" ,
szDir)//两个反斜杠表示一个反斜杠转义符
hd = FindFirstFile(szFind , &stWinFile)//hd标志文件位置,用于查找下一个文件
if ( hd == INVALID_HANDLE_VALUE )
{
return ERR
}
while (1)
{
if (strcmp(stWinFile.cFileName,".") == 0 || strcmp(stWinFile.cFileName,"..") == 0)
{
//NULL
}
//判断是否是文件夹
else if ( stWinFile.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY )
{
//清空szSubDir,因为在重新对szSubDir赋值时,是直接覆盖的,后者比当前保存的数据短,所以需要先清空再赋值
memset(szSubDir , 0 , DIR_MAX_LEN)
_snprintf_c(szSubDir , DIR_MAX_LEN , "%s\\%s" , szDir , stWinFile.cFileName)
ScanDir(szSubDir)//递归处理
}
else
{
if ( CheckCondition(szDir , stWinFile) == OK )
{
DisposeFile(szDir , stWinFile)
}
}
//查找下一个文件失败就跳出循环
if ( !FindNextFile(hd , &stWinFile) )
{
break
}
}
FindClose(hd)
return OK
}
int _tmain(int argc, _TCHAR* argv[])
{
COND_INFO_S stCond = { 0 }
COND_INFO_S* pstCond
char szDir[] = "C:"
stCond.cCondValue = COND_TYPE_SIZE
stCond.cCondValue = COND_VALUE_MORE
if (ConvertSizeStr2SizeLong(TEST_FILE_MAX_SIZE,&(g_astCond[0].uiSizeHigh),&(g_astCond[0].uiSizeLow)) == OK)
{
memcpy(&(g_astCond[ 0 ].cSymbol),&stCond,1)
pstCond = (COND_INFO_S*)( &g_astCond[ 0 ].cSymbol )
g_iCondCnt = 1
ScanDir(szDir)
}
system("pause")
return 0
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)