如何在cmake中为cuda源代码添加定义
How to add definitions for cuda source code in cmake
我在 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 编译完全相同的代码会导致 "identifier FOO and WINDOWS_DLL_API is undefined":
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 : A single input file is required for a non-link phase when an outputfile is specified"。请注意,如果将此语法应用于标准 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++;
}
如何使用 CMake 为 cuda 源代码指定宏(特别是 __declspec(dllexport))?
既然你在评论中提出了要求,下面是I/we如何在我们的图书馆中做到这一点。
通用头文件根据预处理器标志(和一些内部默认标志:_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 的一些宏(黑)魔法应该可以实现更通用的方法(包括跨平台解决方案)。 (免责声明:我还没有测试过。)
我在 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 编译完全相同的代码会导致 "identifier FOO and WINDOWS_DLL_API is undefined":
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 : A single input file is required for a non-link phase when an outputfile is specified"。请注意,如果将此语法应用于标准 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++;
}
如何使用 CMake 为 cuda 源代码指定宏(特别是 __declspec(dllexport))?
既然你在评论中提出了要求,下面是I/we如何在我们的图书馆中做到这一点。
通用头文件根据预处理器标志(和一些内部默认标志:_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.
使用 GitHub:Eyenseo/ABI 的一些宏(黑)魔法应该可以实现更通用的方法(包括跨平台解决方案)。 (免责声明:我还没有测试过。)