如何在cmake中添加cuda源代码的定义

How to add definitions for cuda source code in cmake

本文关键字:cuda 源代码 定义 添加 cmake      更新时间:2023-10-16

我使用的是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})

Test.h

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

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致命:当指定输出文件时,非链接阶段需要单个输入文件"。请注意,如果在标准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也可以编译,如下所示:

Test.h

#define WINDOWS_DLL_API __declspec(dllexport)
class WINDOWS_DLL_API Test{
 public:
  Test();
};

Test.cpp

#include "Test.h" 
#define FOO 1
Test::Test(){
  int a = 0;
  if (FOO) a++;
}

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

既然你在评论中要求了,下面是我/我们如何在我们的库中做到这一点。

一般头文件根据预处理器标志(和一些内部默认标志:_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。(免责声明:我还没有测试过)