c++ - 如何在cmake中为cuda源代码添加定义

标签 c++ cuda cmake dllexport nvcc

我正在使用 Visual Studio 2013、Windows 10、CMake 3.5.1。

一切都可以使用标准 C++ 正确编译,例如:

CMakeLists.txt

project(Test)

add_definitions(/D "WINDOWS_DLL_API=__declspec(dllexport)")
add_definitions(/D "FOO=1")

set(PROJECT_SRCS ${PROJECT_SOURCE_DIR}/src/Test.cpp)    
set(PROJECT_INCS ${PROJECT_SOURCE_DIR}/include/Test.h)

include_directories(${PROJECT_SOURCE_DIR}/include)

add_library(${PROJECT_NAME} SHARED ${PROJECT_SRCS} ${PROJECT_INCS})

测试.h

class WINDOWS_DLL_API Test{
 public:
  Test();
};

测试.cpp

#include "Test.h" 

Test::Test(){
  int a = 0;
  if (FOO) a++;
}

但是,简单地更改 CMakeLists 以使用 CUDA NVCC 编译完全相同的代码会导致“标识符 FOO 和 WINDOWS_DLL_API 未定义”:

project(Test)

add_definitions(/D "WINDOWS_DLL_API=__declspec(dllexport)")
add_definitions(/D "FOO=1")

set(PROJECT_SRCS ${PROJECT_SOURCE_DIR}/src/Test.cu)    
set(PROJECT_INCS ${PROJECT_SOURCE_DIR}/include/Test.cuh)

include_directories(${PROJECT_SOURCE_DIR}/include)

find_package( CUDA REQUIRED )

cuda_add_library(${PROJECT_NAME} SHARED ${PROJECT_SRCS} ${PROJECT_INCS})

在谷歌上花了一些时间后,我得到的最接近的结果是更改 add_definitions 的语法,如下所示,它适用于“FOO”但不适用于“WINDOWS_DLL_API”。错误消息是“nvcc fatal:指定输出文件时,非链接阶段需要单个输入文件”。请注意,如果将此语法应用于标准 C++,则会发生错误。

project(Test)

add_definitions("-DWINDOWS_DLL_API=__declspec(dllexport)")
add_definitions("-DFOO=1")

set(PROJECT_SRCS ${PROJECT_SOURCE_DIR}/src/Test.cu)    
set(PROJECT_INCS ${PROJECT_SOURCE_DIR}/include/Test.cuh)

include_directories(${PROJECT_SOURCE_DIR}/include)

find_package( CUDA REQUIRED )

cuda_add_library(${PROJECT_NAME} SHARED ${PROJECT_SRCS} ${PROJECT_INCS})

我还验证了在没有在 CMake 中指定定义的情况下,即使使用 CUDA NVCC,所有内容都可以编译,如下所示:

测试.h

#define WINDOWS_DLL_API __declspec(dllexport)

class WINDOWS_DLL_API Test{
 public:
  Test();
};

测试.cpp

#include "Test.h" 
#define FOO 1

Test::Test(){
  int a = 0;
  if (FOO) a++;
}

如何使用 CMake 为 cuda 源代码指定宏(特别是 __declspec(dllexport))?

最佳答案

既然你在评论中提出了要求,下面是我/我们在我们的图书馆中的做法。

通用头文件根据预处理器标志(和一些内部默认标志:_WINxx)定义了实际的编译器可见性属性:

// eximport.h
#pragma once

#if defined(_WIN32) || defined(_WIN64)
#define DECL_EXPORT __declspec(dllexport)
#define DECL_IMPORT __declspec(dllimport)
#else
#define DECL_EXPORT
#define DECL_IMPORT
#endif

#if defined(mylib_SHARED) || defined(mylib_STATIC)
#ifdef mylib_SHARED
#define MYLIB_API DECL_EXPORT
#else
#define MYLIB_API
#endif
#else
#define MYLIB_API DECL_IMPORT
#endif

并按照以下方式使用它

#include "eximport.h"

class MYLIB_API MyLibClass
{
  //
};

在你的 CMake 中你就可以了

# in case myLib is build as shared
target_add_definition(myLibTarget mylib_SHARED)

# or

# in case myLib is build as static
target_add_definition(myLibTarget mylib_STATIC)

如果在某处使用了 myLib(无论是静态的还是共享的),则不要定义任何内容。

注意:使用 CMake 的 add_definitions/target_add_definitions 命令,您不需要(实际上不应该)显式指定编译器标志(/D/-D).当这些命令的参数是 CMake ;-lists 时,CMake 会为你做这件事。


使用 GitHub:Eyenseo/ABI 的一些宏(黑色)魔法应该可以实现更通用的方法(包括跨平台解决方案) . (免责声明:我还没有测试过。)

关于c++ - 如何在cmake中为cuda源代码添加定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39216622/

相关文章:

c++ - 编译器错误 : Undefined symbols for architecture x86_64

c++ - 使用 CUDA 和 Matlab 时如何将矩阵作为参数

search - ArrayFire帧搜索算法崩溃

c++ - 导出(安装)的 cmake 目标是否可分发?

c++ - 奇怪的 char**/calloc 行为

c++ - 将 Const char * 转换为 Unsigned long int - strtoul

c - 有人知道nvidia产品(Kepler)中warp报废的机制吗?

c++ - Visual Studio 奇怪的异常

python - Cmake - 使用 OpenCV 生成共享库

c++ - 基于模板类型的枚举值