需求:
我项目中使用了一个lib,但是这个lib不支持release,所以我想在release模式下不使用,不编译这个lib
通过条件生成器,的确可以做到在release模式下不依赖这个lib
cmake_minimum_required(VERSION 3.0.0)
set(app "lear-cmake")
project(${app} VERSION 0.1.0)
include(./lib/CMakeLists.txt)
add_executable(${app} ./index.cpp)
target_link_libraries(${app} PUBLIC $<$<CONFIG:Debug>:lib>)
- debug
- release
但是这个lib在release模式下仍旧会编译,想要的预期效果是:
查到的资料显示EXCLUDE_FROM_DEFAULT_BUILD
可以控制,但是不支持条件表达式
set_target_properties(${LIB_NAME} PROPERTIES
EXCLUDE_FROM_DEFAULT_BUILD
# ON
# $<$<CONFIG:Release>:OFF>
$<IF:$<CONFIG:Release>,ON,OFF>
)
vld_x86是可以生成release版本的
预处理器
在Debug模式下才添加_DEBUG预处理器
if(MSVC)
target_compile_definitions(${vld} PRIVATE
UNICODE
_UNICODE
_WIN32_WINNT=0x0502
WIN32
_USRDLL
)
target_compile_definitions(${vld} PRIVATE $<$<CONFIG:Debug>:_DEBUG>)
endif(MSVC)
11
void __thiscall CaptureContext::Set(void *,void *,void *,unsigned long)"
__forceinline void Set(HANDLE heap, LPVOID mem, LPVOID newmem, SIZE_T size);
具体看报错
error LNK2019: unresolved external symbol
"public: void
__thiscall
CaptureContext::Set(void *,void *,void *,unsigned long)"
(?Set@CaptureContext@@QAEXPAX00K@Z)
referenced in function
"private: static void *
__stdcall
VisualLeakDetector::_HeapAlloc(void *,unsigned long,unsigned long)"
(?_HeapAlloc@VisualLeakDetector@@CGPAXPAXKK@Z)
是调用约束不一致导致的这个问题,相关的代码为:
class CaptureContext {
public:
__forceinline void Set(HANDLE heap, LPVOID mem, LPVOID newmem, SIZE_T size);
}
static LPVOID __stdcall _HeapAlloc(HANDLE heap, DWORD flags, SIZE_T size);
LPVOID VisualLeakDetector::_HeapAlloc (HANDLE heap, DWORD flags, SIZE_T size)
{
CaptureContext cc(HeapAlloc, context_);
cc.Set(heap, block, NULL, size);// 在winapi里面调用了c++的函数
}
这个问题在Debug模式下可以正常通过编译,但是Release就报错
也尝试将CaptureContext的Set显示声明为__stdcall,仍旧报错
解决办法:
-
将
__forceinline
去掉,就是因为这个导致的 -
生成代码时禁止优化,因为这里使用了内联,所以只需要禁用内联函数展开即可
- 使用cmake设置禁用内联优化:
target_compile_options(${vld} PUBLIC $<$<CONFIG:RELEASE>:/Ob0>) # 和vs里面的值一一对应
microsoft的vc默认的是__cdecl方式,而windows API则是__stdcall,如果用vc开发dll给其他语言用,则应该指定__stdcall方式。
__cdelc: c调用规则
__stdcall:winapi
__fastcall
__thiscall:c++
1,工程中只有头文件,缺少源文件,只有声明没有定义
2,引入第三方库,工程中只有头文件,没有加载导入库(xxxx.lib)
3, 头文件,源文件中 函数声明和定义都有,
但是某个参数类型不一致
4,调用约定不一致,C++工程引用了C风格的导入库,
__forceinline
__forceinline
是一种编译器指令,它用于告诉编译器将函数的代码插入到每个调用该函数的地方,从而实现函数内联的效果。比起普通函数调用,函数内联可以减少函数调用时的开销,从而提高代码的执行效率。
需要注意的是,使用 __forceinline
并不能保证函数一定会被内联。编译器可能会忽略该指令,或者在某些情况下无法进行内联,比如递归函数、带有循环语句或复杂控制流的函数等。
另外,使用 __forceinline
也可能会导致代码体积增加,因为每个调用该函数的地方都会插入一遍函数的代码。因此,在使用 __forceinline
时需要进行权衡,根据具体情况综合考虑代码的性能和体积。
总之,__forceinline
可以用于优化代码的执行效率,但使用时需要谨慎,并根据实际情况进行权衡和调整。