Error

C++博客 首页 新随笔 联系 聚合 管理
  217 Posts :: 61 Stories :: 32 Comments :: 0 Trackbacks

#

int *p = new int[10]; delete [] p; 既然 delete 时无需提供数组大小,那么显然编译器是知道数组的大小(或者说界限的)。 那么 编译器是如何知道数组大小的?(比如维护了一张表、按特定格式存储……) 既然知道数组大小,编译器能否自动检查数组越界的情况?不检查是否是为了性能? 编程时如何利用这份信息? 另外,不借助搜索引擎如何解答这个问题,有类似文档之类的东西可以参考吗?修改 1:拿msvc来说,在new/malloc返回的ptr前n个字节里保存了大小,msvc还可以用_msize()来获得size,具体保存在哪可以调试看看; 2:编译器未必知道,有些size是运行时决定的.真正记录大小是在运行时,而不是编译期.数组越界不能自动检查,ptr + offset,这种方式程序无法知道程序员的本意要访问的到底是不是数组那块内存 3:特定环境下可能有用啊.(例:一个妹子问我在vs里怎么通过一个new出来的指针获得size,然后就可以利用这些信息换妹子崇拜的眼神) PS:上调试器. 作者:吉林小伙 链接:https://www.zhihu.com/question/27112272/answer/35301722 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 1:new的时候已经多new了点空间把长度写进去了 2:不能检查,因为不是所有的指针都是new出来,谁知道到底指向的是什么 3:根据C++标准的话,没办法利用 4:反正VC++已经98%以上跟标准完全一致了,而且gcc跟clang的私货也不比VC++少,你去msdn看C++语法手册就好了 C++ Language Reference,手册只要你读两遍,你就什么都明白了。我初三就是读了两遍VC++5.0时代的msdn的语法手册学会C++的。当然要熟悉还是要靠练习,光读的话就算都记住了,也只能一知半解。 作者:vczh 链接:https://www.zhihu.com/question/27112272/answer/35291952 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
posted @ 2016-03-22 10:21 Enic 阅读(390) | 评论 (0)编辑 收藏

首先Ref不用解释。
cocos和常见的Ref或者智能指针稍微有点不一样:
首先介绍传统玩法:
传统玩法Ref一般要配合RefPtr使用的,也就是new出来的Ref派生类引用计数为0,要放到一个RefPtr里边来做生命周期管理。

在来看看cocos的玩法:
new出来Ref引用计数是为1的,那么问题来了,这样如果Add和Release成对出现则Ref永远回不到0了。
cocos是这样解决这个问题的:autorelease
调用autorelease,会把当前Ref为1的对象压入pool,然后在下一帧的调用release这样就天下太平了,如果有add到其他节点上他就会变1,如果没有就直接归零析构了
这样就省掉了RefPtr操作


为了保持风格统一,我也必须这样玩,这样的优势是不需要RefPtr,可能脚本绑定会方便不少吧
posted @ 2016-03-15 20:52 Enic 阅读(279) | 评论 (0)编辑 收藏

WebSocket is an underlying network protocol that enables you to build other standard
protocols on top of it.

The WebSocket Protocol enables full duplex communication between a client and
a remote server over the Web, and supports transmission of binary data and text strings.
The protocol consists of an opening handshake followed by basic message framing, and is
layered over TCP.


WebSocket programming follows an asynchronous programming model, which
means that as long as a WebSocket connection is open, your application simply listens
for events. Your client does not need to actively poll the server for more information. To
start listening for the events, you simply add callback functions to the WebSocket object.
Alternatively, you can use the addEventListener() DOM method to add event listeners
to your WebSocket objects.
A WebSocket object dispatches four different events:
· Open
· Message
· Error
· Close
As with all web APIs, you can listen for these events using on<eventname> handler
properties, as well as using the addEventListener(); method.

ws.onopen
ws.onmessage
ws.onerror
ws.onclose

e.data instanceof Blob
ws.binaryType = "blob"

WebSocket objects have two methods: send() and close()


Listing 2-12. Waiting for the Open Event Before Sending a Message
// Wait until the open event before calling send().
var ws = new WebSocket("ws://echo.websocket.org")
ws.onopen = function(e) {
ws.send("Initial data");
}

Listing 2-13. Checking the readyState Property for an Open WebSocket
// Handle outgoing data. Send on a WebSocket if that socket is open.
function myEventHandler(data) {
if (ws.readyState === WebSocket.OPEN) {
// The socket is open, so it is ok to send the data.
ws.send(data);
} else {
// Do something else in this case.
//Possibly ignore the data or enqueue it.
}
}


// Send a Blob
var blob = new Blob("blob contents");
ws.send(blob);
// Send an ArrayBuffer
var a = new Uint8Array([8,6,7,5,3,0,9]);
ws.send(a.buffer);


Listing 2-15. Calling the close() Method
// Close the WebSocket connection
ws.close();
You can optionally pass two arguments to the close() method: code (a numerical
status code) and reason (a text string). Passing these arguments transmits information
to the server about why the client closed the connection. We will discuss the status
codes and reasons in greater detail in Chapter 3, when we cover the WebSocket closing
handshake. Listing 2-16 shows an example of calling the close() method with an
argument.
Listing 2-16. Calling the close() Method with a Reason
// Close the WebSocket connection because the session has ended successfully
ws.close(1000, "Closing normally");
Listing 2-16 uses code 1000, which means, as it states in the code, that the
connection is closing normally.


WebSocket Object Attributes
There are several WebSocket Object attributes you can use to provide more information
about the WebSocket object: readyState, bufferedAmount, and protocol.

Table 2-1. readyState Attributes, Values, and Status Descriptions
Attribute Constant     Value     Status
WebSocket.CONNECTING   0   The connection is in progress but has not been established.
WebSocket.OPEN   1   The connection has been established. Messages can flow between the client and server.
WebSocket.CLOSING   2   The connection is going through the closing handshake.
WebSocket.CLOSED   3   The connection has been closed or could not be opened.

WebSocket Object Attribute: protocol
The protocol attribute is the empty string before the
opening handshake completes and remains an empty string if the server does not choose
one of the protocols offered by the client.

 

posted @ 2016-02-22 17:02 Enic 阅读(255) | 评论 (0)编辑 收藏

GDI+使用双缓冲绘图
————————————————————————
我再来详细解释一下刚才实现双缓冲的具体步骤:
1、在内存中建立一块“虚拟画布”:
Bitmap bmp = new Bitmap(600, 600);
2、获取这块内存画布的Graphics引用:
Graphics g = Graphics.FromImage(bmp);
3、在这块内存画布上绘图:
g.FillEllipse(brush, i * 10, j * 10, 10, 10);
4、将内存画布画到窗口中
this.CreateGraphics().DrawImage(bmp, 0, 0);
====================
maybe better
CDC dcMemory;
dcMemory.CreateCompatibleDC(&dc);
CBitmap bmp;
bmp.CreateCompatibleBitmap(&dc,1024,768);
dcMemory.SelectObject(&bmp);
   
Graphics _Graphics(dcMemory.m_hDC);
_Graphics.DrawImage(_pImage,0,0,1024,768);
//这是在GDI+中的写法。
   
dc.BitBlt(0,0,1024,768,&dcMemory,0,0,SRCCOPY);
   
_Graphics.ReleaseHDC(dcMemory.m_hDC);
dcMemory.DeleteDC();
bmp.DeleteObject(); 



-------------------------------------------------------------------------
补充:
1.对于GDI常见的做法都是MemDC一下不解释了
2.GDI+似乎也可以用MemDC生成一个graphics,然后画好了,在把MemDC bit到WndDC上,但是会有各种各样的问题。
3.不管是那种方式,都是一个宗旨:直接操作前台屏幕上的DC在绘图的过程中会显得比较慢,所以生成一个内存画布,把所有的贴图操作都在不可见的内存画布上操作完成,然后一次性贴图到前台DC上。这样实际上还多了一次贴图,但是对于前台DC的操作已经是无限小了。
4.GDI+还有一种更优的方式:创建一个内存bitmap,然后从内存bitmap创建出GDI+位图,然后使用做个位图作为渲染画布。渲染完成后,在直接把bitmap贴图到前台DC上面来,内存中的bitmap是复用的,不用在每个渲染事件中重新创建。
5.为了更好的GL或者其他的渲染接口融合,基于bitmap的内存画布应该是最优的做法。




posted @ 2015-11-12 14:28 Enic 阅读(401) | 评论 (0)编辑 收藏

数据库备份实例/** 
**数据库备份实例 
**朱二 2004年5月 
**备份策略: 
**数据库名:test 
**备份文件的路径e:\backup 
**每个星期天凌晨1点做一次完全备份,为保险起见,备份到两个同样的完全备份文件test_full_A.bak和test_full_B.bak 
**每天1点(除了星期天)做一次差异备份,分别备份到两个文件test_df_A.bak和test_df_B.bak(采用附加到原备份的方式) 
**每一个小时做一次事务日志备份,分别备份到两个文件test_log_A.bak和test_log_B.bak(采用附加到原备份的方式) 
**/ 


--第一 完全备份部分 
--新增作业 
EXEC sp_add_job @job_name = '完全备份' 
--新增作业步骤1,把数据库备份到test_full_backup_A.bak 
EXEC sp_add_jobstep @job_name = '完全备份', 
@step_name = 'Setp1', 
@subsystem = 'TSQL', 
@command = 'BACKUP DATABASE Test TO DISK=''e:\backup\test_full_A.bak'' WITH INIT', 
@on_fail_action=3, --失败后转到下一步 
@on_success_action=3,-- 成功后转到下一步 
@retry_attempts = 5, 
@retry_interval = 5 

--新增作业步骤2,把数据库备份到test_full_B.bak 
EXEC sp_add_jobstep @job_name = '完全备份', 
@step_name = 'Setp2', 
@subsystem = 'TSQL', 
@command = 'BACKUP DATABASE Test TO DISK=''e:\backup\test_full_B.bak'' WITH INIT', 
@retry_attempts = 5, 
@retry_interval = 5 

--调度 
EXEC sp_add_jobschedule @job_name = '完全备份', 
@name = 'Schedule_1', 
@freq_type = 8, -- 按周 
@freq_interval = 1, --每星期天执行 
@freq_recurrence_factor=1, 
@active_start_time = 10000 --开始时间: 凌晨1点 
--第二 差异备份部分 
--新增作业 
EXEC sp_add_job @job_name = '差异备份' 
--新增作业步骤1,把数据库备份到test_df_A.bak 
EXEC sp_add_jobstep @job_name = '差异备份', 
@step_name = 'Setp1', 
@subsystem = 'TSQL', 
@command = 'BACKUP DATABASE Test TO DISK=''e:\backup\test_df_A.bak'' WITH DIFFERENTIAL', 
@on_fail_action=3, --失败后转到下一步 
@on_success_action=3,-- 成功后转到下一步 
@retry_attempts = 5, 
@retry_interval = 5 

--新增作业步骤2,把数据库备份到test_df_B.bak 
EXEC sp_add_jobstep @job_name = '差异备份', 
@step_name = 'Setp2', 
@subsystem = 'TSQL', 
@command = 'BACKUP DATABASE Test TO DISK=''e:\backup\test_df_B.bak'' WITH DIFFERENTIAL', 
@retry_attempts = 5, 
@retry_interval = 5 

--调度 
EXEC sp_add_jobschedule @job_name = '差异备份', 
@name = 'Schedule_1', 
@freq_type = 8, -- 按周 
@freq_interval = 126, --星期一至星期六 
@freq_recurrence_factor=1, 
@active_start_time = 10000 --开始时间: 凌晨1点 


--第二 事务备份部分 
--新增作业 
EXEC sp_add_job @job_name = '事务备份' 
--新增作业步骤1,把数据库备份到test_log_A.bak 
EXEC sp_add_jobstep @job_name = '事务备份', 
@step_name = 'Setp1', 
@subsystem = 'TSQL', 
@command = 'BACKUP LOG Test TO DISK=''e:\backup\test_log_A.bak''', 
@on_fail_action=3, --失败后转到下一步 
@on_success_action=3,-- 成功后转到下一步 
@retry_attempts = 5, 
@retry_interval = 5 

--新增作业步骤2,把数据库备份到test_log_B.bak 
EXEC sp_add_jobstep @job_name = '事务备份', 
@step_name = 'Setp2', 
@subsystem = 'TSQL', 
@command = 'BACKUP LOG Test TO DISK=''e:\backup\test_log_B.bak''', 
@retry_attempts = 5, 
@retry_interval = 5 

--调度 
EXEC sp_add_jobschedule @job_name = '事务备份', 
@name = 'Schedule_1', 
@freq_type = 4, -- 按天 
@freq_interval=1,--每一天 
@freq_subday_type=8, --按小时 
@freq_subday_interval=1 --每一个小时 
posted @ 2015-09-06 09:33 Enic 阅读(173) | 评论 (0)编辑 收藏

bpack=string.pack
bunpack=string.unpack
-- 输出二进制
function hex(s)
 s=string.gsub(s,"(.)",function (x) return string.format("%02X",string.byte(x)) end)
 return s
end
--解包传入的是hex和FMT(><大小端),输出是FMT指定的类型:i int, n lua_num
--i=12345 f="i"
--a=bpack(f,i,i,i)
--print(hex(a))
--print(bunpack(a,f))
--打包输入fmt,实际类型,输出hex
local n = 0x12345678
--tb = {}
--dump(tb)
--tb = n
--dump(tb)
a = bpack('>n', n)
dump(hex(a))
posted @ 2015-09-01 18:30 Enic 阅读(286) | 评论 (0)编辑 收藏

--如何定义枚举
--下面的函数实现:
--转换 EnumTable = {1:Enum1, 2:Enum2}
--到   EnumTable = {Enum1:1, Enum2:2}
function CreateEnumTable(tb, indexStart)
    --assert(IsTable(tb))
    local enumTB = {}
    local enumIndex = indexStart or 0
    
    --转换字符table到枚举table
    for index, value ipairs(tb) do
        enumTB[v] = enumIndex + index
    end
    return enumTB
end
--只是返回值而已和C不一样
assert(0)
--用这个和字符串比较实现判断变量类型
print(type(CreateEnumTable))
--xpcall可以保护执行一个函数,通过返回值确定异常情况
posted @ 2015-09-01 17:29 Enic 阅读(869) | 评论 (0)编辑 收藏

VC++ Runtime Error 异常捕获之不挂的程序

 很多软件通过设置自己的异常捕获函数,捕获未处理的异常,生成报告或者日志(例如生成mini-dump文件),达到Release版本下追踪Bug的目的。但是,到了VS2005(即VC8),Microsoft对CRT(C运行时库)的一些与安全相关的代码做了些改动,典型的,例如增加了对缓冲溢出的检查。新CRT版本在出现错误时强制把异常抛给默认的调试器(如果没有配置的话,默认是Dr.Watson),而不再通知应用程序设置的异常捕获函数,这种行为主要在以下三种情况出现。

(1)       调用abort函数,并且设置了_CALL_REPORTFAULT选项(这个选项在Release版本是默认设置的)。

(2)       启用了运行时安全检查选项,并且在软件运行时检查出安全性错误,例如出现缓存溢出。(安全检查选项/GS 默认也是打开的)

(3)       遇到_invalid_parameter错误,而应用程序又没有主动调用

_set_invalid_parameter_handler设置错误捕获函数。

所以结论是,使用VS2005(VC8)编译的程序,许多错误都不能在SetUnhandledExceptionFilter捕获到。这是CRT相对于前面版本的一个比较大的改变,但是很遗憾,Microsoft却没有在相应的文档明确指出。

解决方法

       之所以应用程序捕获不到那些异常,原因是因为新版本的CRT实现在异常处理中强制删除所有应用程序先前设置的捕获函数,如下所示:

 /* Make sure any filter already in place is deleted. */

 SetUnhandledExceptionFilter(NULL);

 UnhandledExceptionFilter(&ExceptionPointers);

解决方法是拦截CRT调用SetUnhandledExceptionFilter函数,使之无效。在X86平台下,可以使用以下代码。

#ifndef _M_IX86

       #error "The following code only works for x86!"

#endif

 

void DisableSetUnhandledExceptionFilter()

{

    void *addr = (void*)GetProcAddress(LoadLibrary(_T("kernel32.dll")),

                                                         "SetUnhandledExceptionFilter");

    if (addr)

    {

              unsigned char code[16];

              int size = 0;

              code[size++] = 0x33;

              code[size++] = 0xC0;

              code[size++] = 0xC2;

              code[size++] = 0x04;

              code[size++] = 0x00;

 

               DWORD dwOldFlag, dwTempFlag;

              VirtualProtect(addr, size, PAGE_READWRITE, &dwOldFlag);

              WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL);

              VirtualProtect(addr, size, dwOldFlag, &dwTempFlag);

       }

}

在设置自己的异常处理函数后,调用DisableSetUnhandledExceptionFilter禁止CRT设置即可。

其它讨论

       上面通过设置api hook,解决了在VS2005上的异常捕获问题,这种虽然不是那么“干净”的解决方案,确是目前唯一简单有效的方式。

       虽然也可以通过_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT), signal(SIGABRT, ...), 和_set_invalid_parameter_handler(...) 解决(1)(3),但是对于(2),设置api hook是唯一的方式。

注:对于错误是否显示错误提示框,可以使用SetErrorMode()


后面又遇到WIN8.1上
VirtualProtect报错C0000005,最后还是想办法解决了

bool AdjustPrivileges() 
{     
    HANDLE hToken;     
    TOKEN_PRIVILEGES tp;     
    TOKEN_PRIVILEGES oldtp;     
    DWORD dwSize=sizeof(TOKEN_PRIVILEGES);     
    LUID luid;       
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 
    {         
        if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED) return true;         
        else return false;     
    }     

    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) 
    {        
        CloseHandle(hToken);         
        return false;     
    }     
    
    ZeroMemory(&tp, sizeof(tp));     
    tp.PrivilegeCount=1;     
    tp.Privileges[0].Luid=luid;     
    tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;     
    /* Adjust Token Privileges */    
    if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &oldtp, &dwSize)) 
    {        
        CloseHandle(hToken);         
        return false;     
    }     
    
    // close handles     
    CloseHandle(hToken);     
    return true



void DisableSetUnhandledExceptionFilter()

{

    void *addr = (void*)GetProcAddress(LoadLibrary(_T("kernel32.dll")),

        "SetUnhandledExceptionFilter");

    if (addr)

    {

        unsigned char code[16];

        int size = 0;

        code[size++] = 0x33;

        code[size++] = 0xC0;

        code[size++] = 0xC2;

        code[size++] = 0x04;

        code[size++] = 0x00;

        //SetProcessDEPPolicy(1);

        DWORD dwOldFlag, dwTempFlag;

        // win8.1下用百度找了下PAGE_READWRITE崩溃,实际测试提升debug权限,SetProcessDEPPolicy(1);都无效,改成PAGE_EXECUTE_READWRITE生效
        
//VirtualProtect(addr, size, PAGE_READWRITE, &dwOldFlag);
        VirtualProtect(addr, size, PAGE_EXECUTE_READWRITE, &dwOldFlag);
        WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL);

        VirtualProtect(addr, size, dwOldFlag, &dwTempFlag);

    }

}



posted @ 2015-08-28 11:14 Enic 阅读(691) | 评论 (0)编辑 收藏

在下面的章节中, 你将会学到如何用 Apache, Tomcat 和微软的 IIS 创建 MIME 类型.

" src="/CuteSoft_Client/CuteEditor/Images/anchor.gif">用 Apache 创建 MIME 类型

在 Apache 里, MIME 类型和文件扩展名之间的映射是被存放在配置文件 "apache根目录/conf/mime.types" 里的 (对于大多数 LINUX 系统, 是放在 /etc/apache2/mods-available 里的), 这里的 "apache根目录" 是 Apache 在你的服务器上的安装路径.

要创建 MIME 类型, 打开 mime.types 文件. 以 # 字符开头的行是注释行, Apache 会忽略它们. 其它每行都以某种 MIME 类型开头, 然后跟着一种或多种文件扩展名. 其形式如下:

mime类型 文件扩展名1 文件扩展名2 文件扩展名3 ... 

下面是一些例子:

text/html html htm application/vnd.wap.xhtml+xml xhtml text/vnd.wap.wml wml text/vnd.wap.wmlscript wmls image/vnd.wap.wbmp wbmp 

" src="/CuteSoft_Client/CuteEditor/Images/anchor.gif">用 Tomcat 创建 MIME 类型

在 Tomcat 5.x 和 4.x 里, MIME 类型和文件扩展名之间的缺省映射是被存放在文件 tomcat根目录/conf/web.xml 里的, 这里的 "tomcat根目录" 是 Tomcat 在你的服务器上的安装目录. 该文件里所指定的映射会被应用到你的 Tomcat 服务器所运行的所有 Web/WAP 应用程序上. 针对应用程序的映射应该 Web/WAP 应用的目录里的 WEB-INF/web.xml 文件里设置.

每种映射都要用 <mime-mapping>, <extension> 和 <mime-type> 标签来指定. 下面就是一个例子:

<web-app> ...    <mime-mapping>     <extension>xhtml</extension>     <mime-type>application/vnd.wap.xhtml+xml</mime-type>   </mime-mapping>    <mime-mapping>     <extension>wml</extension>     <mime-type>text/vnd.wap.wml</mime-type>   </mime-mapping>    <mime-mapping>     <extension>wmls</extension>     <mime-type>text/vnd.wap.wmlscript</mime-type>   </mime-mapping>    <mime-mapping>     <extension>wbmp</extension>     <mime-type>image/vnd.wap.wbmp</mime-type>   </mime-mapping>  ... </web-app> 

" src="/CuteSoft_Client/CuteEditor/Images/anchor.gif">用微软的 IIS 创建 MIME 类型

微软的 IIS 提供了一个创建 MIME 类型的图形界面. 下面列出了在 Windows Server 2003 上用 IIS 6.0 创建 MIME 类型步骤:

   1. 打开 IIS 窗口: 选择 控制面板 -> 管理工具 -> Internet 服务管理器.
   2. 在左手边的树状结构中, 你应当可以看到其中有一项标题为你的计算机的名字. 在其上点右键, 会弹出一个菜单.
   3. 点击菜单中的属性, 打开属性窗口.
   4. 点击 "HTTP 头" 选项卡, 下面有 "MIME 映射", 点击 "文件类型" 按纽.
   5. 在 "文件类型" 窗口中, 你可以看到一个 MIME 映射的列表. 用标有 "新类型...", "删除" 和 "编辑..."  的按纽作你想要的修改.

在其它版本的 IIS 中创建 MIME 类型应该与此类似.

posted @ 2015-08-21 16:25 Enic 阅读(126) | 评论 (0)编辑 收藏

使用CMake GCC和Clang的/ LLVM之间切换

cmake llvm clang
我公司拥有一批项目的CMake的,我希望能够方便地切换GCC或铛/ LLVM他们。我相信(请如果我错了!)表示锵我需要进行如下设置:
 SET (CMAKE_C_COMPILER    "/usr/bin/clang")  SET (CMAKE_C_FLAGS    "-Wall -std=c99")  SET (CMAKE_C_FLAGS_DEBUG   "-g")  SET (CMAKE_C_FLAGS_MINSIZEREL  "-Os -DNDEBUG")  SET (CMAKE_C_FLAGS_RELEASE  "-O4 -DNDEBUG")  SET (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g")  SET (CMAKE_CXX_COMPILER    "/usr/bin/clang++")  SET (CMAKE_CXX_FLAGS    "-Wall")  SET (CMAKE_CXX_FLAGS_DEBUG   "-g")  SET (CMAKE_CXX_FLAGS_MINSIZEREL  "-Os -DNDEBUG")  SET (CMAKE_CXX_FLAGS_RELEASE  "-O4 -DNDEBUG")  SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")  SET (CMAKE_AR  "/usr/bin/llvm-ar")  SET (CMAKE_LINKER "/usr/bin/llvm-ld")  SET (CMAKE_NM  "/usr/bin/llvm-nm")  SET (CMAKE_OBJDUMP "/usr/bin/llvm-objdump")  SET (CMAKE_RANLIB "/usr/bin/llvm-ranlib") 
是否有这些和默认的GCC变量之间的切换,最好是全系统的变化,而不是具体的项目(即不只是将它们添加到项目的的CMakeLists.txt)一个简单的方法? 另外,是否有必要的llvm-*节目铛的gcc时代替,而不是系统默认值?有什么区别?
本文地址 :CodeGo.net/340772/ 
------------------------------------------------------------------------------------------------------------------------- 
1. CMake的荣誉的变量CCCXX在检测到C和C ++编译器
$ export CC=/usr/bin/clang $ export CXX=/usr/bin/clang++ $ cmake .. -- The C compiler identification is Clang -- The CXX compiler identification is Clang 
具体标志可以通过将它们放入一个系统范围的CMake文件并指向CMAKE_USER_MAKE_RULES_OVERRIDE变量,它被覆盖。创建一个文件~/ClangOverrides.txt其内容如下:
SET (CMAKE_C_FLAGS_INIT    "-Wall -std=c99") SET (CMAKE_C_FLAGS_DEBUG_INIT   "-g") SET (CMAKE_C_FLAGS_MINSIZEREL_INIT  "-Os -DNDEBUG") SET (CMAKE_C_FLAGS_RELEASE_INIT  "-O4 -DNDEBUG") SET (CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "-O2 -g") SET (CMAKE_CXX_FLAGS_INIT    "-Wall") SET (CMAKE_CXX_FLAGS_DEBUG_INIT   "-g") SET (CMAKE_CXX_FLAGS_MINSIZEREL_INIT  "-Os -DNDEBUG") SET (CMAKE_CXX_FLAGS_RELEASE_INIT  "-O4 -DNDEBUG") SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-O2 -g") 
后缀_init会让CMake的初始化相应的*_FLAGS变量与给定的值。然后调用cmake的以下面的方式:
$ cmake -DCMAKE_USER_MAKE_RULES_OVERRIDE=~/ClangOverrides.txt .. 
终于到了LLVM的binutils力,设置内部变量_CMAKE_TOOLCHAIN_PREFIX。这个变量是由荣幸CMakeFindBinUtils模块:
$ cmake -D_CMAKE_TOOLCHAIN_PREFIX=llvm- .. 
把这个放在一起你可以写一个shell包装它设置了变量CCCXX然后调用cmake的可变覆盖。 
2. 全系统的C ++的变化对Ubuntu的: sudo用update-alternatives-配置C ++ 将打印是这样的:
 Selection Path    Priority Status ------------------------------------------------------------ * 0   /usr/bin/g++  20  auto mode  1   /usr/bin/clang++ 10  manual mode  2   /usr/bin/g++  20  manual mode 
然后,只需选择铛++。 
3. 你的
option(USE_CLANG "build application with clang" OFF) # OFF is the default 
然后在包裹如果()S中的设置:
if(USE_CLANG)  SET (...)  .... endif(USE_CLANG) 
这样,它会显示为在GUI配置工具的cmake的选项。 为了让您在整个系统可以在变量的默认值或保持与答案。 
4. 你绝对不需要不同的LLVM-AR等程序:
SET (CMAKE_AR  "/usr/bin/llvm-ar") SET (CMAKE_LINKER "/usr/bin/llvm-ld") SET (CMAKE_NM  "/usr/bin/llvm-nm") SET (CMAKE_OBJDUMP "/usr/bin/llvm-objdump") SET (CMAKE_RANLIB "/usr/bin/llvm-ranlib") 
这些都是为了工作,对LLVM内部格式,因此阿仁'到您的应用程序的生成。 作为一个说明 CodeGo.net,O4将在你的程序调用的LTO,你可能不希望(这样会大大)和铛默认为C99模式,使标志不是必需的两种。 
5. 你的语法:$ENV{environment-variable}在你的CMakeLists.txt访问变量。你可以适当地创建一个初始化的变量集的脚本,只是在引用这些变量的CMakeLists.txt文件。
posted @ 2015-08-20 11:52 Enic 阅读(1401) | 评论 (0)编辑 收藏

仅列出标题
共22页: 1 2 3 4 5 6 7 8 9 Last