Enable code indexing of Cuda in Clion
Asked Answered
A

8

9

I am using Clion to develop a cuda program. The code highlight works fine when the extension is .h. However, when it is changed to .cuh, Clion just consider the new file a plain text file, and I have not been able to enable code highlight. I understand a complete Cuda toolchain is out of the question, so I will not hope Clion to parse statements like mykernel<<<1024, 100>>>. Still I will be more than satisfied if it can parse the file just like parsing a normal header/cpp file.

Many thanks

Anitraaniweta answered 11/10, 2016 at 15:13 Comment(0)
B
10

Right click file in project tool window -> Associate with file type -> C++

However, Clion doesn't support cuda officially now, it cannot parse cuda syntax.

UPDATE:

From CLion 2020.1, we have official CUDA C/C++ support. CLion could handle them correctly now.

Bravura answered 12/10, 2016 at 4:24 Comment(4)
Solved the problem! ThanksAnitraaniweta
I have the same problem but the solution does not work. I am using Clion 2016.2.2 on Ubuntu 16.04. What OS are you using?Scyros
Found the problem, just make sure the file with the main function is a .cpp.Scyros
There is no such context menu option in CLion 19.1Unset
T
15

First, make sure you tell CLion to treat .cu and .cuh files as C++ using the File Types settings menu.

CLion is not able to parse CUDA's language extensions, but it does provide a preprocessor macro that is defined only when clion is parsing the code. You can use this to implement almost complete CUDA support yourself.

Much of the problem is that CLion's parser is derailed by keywords like __host__ or __device__, causing it to fail to do things it otherwise knows how to do: Fail

CLion has failed to understand Dtype in this example, because the CUDA stuff confused its parsing.

The most minimal solution to this problem is to give clion preprocessor macros to ignore the new keywords, fixing the worst of the brokenness:

#ifdef __JETBRAINS_IDE__
    #define __host__
    #define __device__
    #define __shared__
    #define __constant__
    #define __global__
#endif

This fixes the above example:

Yay!

However, CUDA functions like __syncthreads, __popc will still fail to index. So will CUDA builtins like threadIdx. One option is to provide endless preprocessor macros (or even struct definitions) for these, but that's ugly and sacrifices type-safety.

If you're using Clang's CUDA frontend, you can do better. Clang implements the implicitly-defined CUDA builtins by defining them in headers, which it then includes when compiling your code. These provide definitions of things like threadIdx. By pretending to be the CUDA compiler's preprocessor and including device_functions.h, we can get __popc and friends to work, too:

#ifdef __JETBRAINS_IDE__
    #define __host__
    #define __device__
    #define __shared__
    #define __constant__
    #define __global__

    // This is slightly mental, but gets it to properly index device function calls like __popc and whatever.
    #define __CUDACC__
    #include <device_functions.h>

    // These headers are all implicitly present when you compile CUDA with clang. Clion doesn't know that, so
    // we include them explicitly to make the indexer happy. Doing this when you actually build is, obviously,
    // a terrible idea :D
    #include <__clang_cuda_builtin_vars.h>
    #include <__clang_cuda_intrinsics.h>
    #include <__clang_cuda_math_forward_declares.h>
    #include <__clang_cuda_complex_builtins.h>
    #include <__clang_cuda_cmath.h>
#endif // __JETBRAINS_IDE__

This will get you perfect indexing of virtually all CUDA code. CLion even gracefully copes with <<<...>>> syntax. It puts a little red line under one character on each end of the launch block, but otherwise treats it as a function call - which is perfectly fine:

Launch

Trometer answered 17/2, 2017 at 2:37 Comment(2)
If you use cuda-api-wrappers you don't even need to use those annoying chevrons (note: self-plug.)Unset
I actually like the chevrons, though. Separation of the launch configuration parameters from the kernel parameters is pretty nifty. Kernels often have a largeish number of positional arguments, adding four more is irritating :DTrometer
B
10

Right click file in project tool window -> Associate with file type -> C++

However, Clion doesn't support cuda officially now, it cannot parse cuda syntax.

UPDATE:

From CLion 2020.1, we have official CUDA C/C++ support. CLion could handle them correctly now.

Bravura answered 12/10, 2016 at 4:24 Comment(4)
Solved the problem! ThanksAnitraaniweta
I have the same problem but the solution does not work. I am using Clion 2016.2.2 on Ubuntu 16.04. What OS are you using?Scyros
Found the problem, just make sure the file with the main function is a .cpp.Scyros
There is no such context menu option in CLion 19.1Unset
S
8

Thanks! I added more "fake" declarations to allow CLion to parse CUDA better:

#ifdef __JETBRAINS_IDE__
#define __CUDACC__ 1
#define __host__
#define __device__
#define __global__
#define __forceinline__
#define __shared__
inline void __syncthreads() {}
inline void __threadfence_block() {}
template<class T> inline T __clz(const T val) { return val; }
struct __cuda_fake_struct { int x; };
extern __cuda_fake_struct blockDim;
extern __cuda_fake_struct threadIdx;
extern __cuda_fake_struct blockIdx;
#endif
Slick answered 18/4, 2017 at 1:41 Comment(4)
You need to update your answer to describe what do you mean exactly by "extended. Provide some comments.Madancy
How do you do this?Toulon
Probably by just adding the snippet to C++ code or making a header that doesn't build outside of IDE (see JETBRAINS_IDE) defineCytotaxonomy
I am surprised that this looked confusing. Jut put that in a header somewhere to define the stuff that CLion parser doesn;t recignizeSlick
F
4

I've expanded upon this answer using the method found in this answer to provide a more comprehensive parsing macro, you can now have .x, .y and .z work properly with out issue, and use grid dim. In addition to that I've updated the list to include most intrinsics and values found in the CUDA 8.0 documentation guide. Note that this should have full C++ compatibility, and maybe C. This does not have all functions accounted for (missing atomics, math functions (just include math.h for most), texture, surface, timing, warp votie and shuffle, assertion, launch bounds, and video function)

#ifdef __JETBRAINS_IDE__
    #include "math.h"
    #define __CUDACC__ 1
    #define __host__
    #define __device__
    #define __global__
    #define __noinline__
    #define __forceinline__
    #define __shared__
    #define __constant__
    #define __managed__
    #define __restrict__  
    // CUDA Synchronization
    inline void __syncthreads() {};
    inline void __threadfence_block() {};
    inline void __threadfence() {};
    inline void __threadfence_system();
    inline int __syncthreads_count(int predicate) {return predicate};
    inline int __syncthreads_and(int predicate) {return predicate};
    inline int __syncthreads_or(int predicate) {return predicate};
    template<class T> inline T __clz(const T val) { return val; }
    template<class T> inline T __ldg(const T* address){return *address};
    // CUDA TYPES
    typedef unsigned short uchar;
    typedef unsigned short ushort;
    typedef unsigned int uint;
    typedef unsigned long ulong;
    typedef unsigned long long ulonglong;
    typedef long long longlong;

    typedef struct uchar1{
        uchar x;
    }uchar1;

    typedef struct uchar2{
        uchar x;
        uchar y;
    }uchar2;

    typedef struct uchar3{
        uchar x;
        uchar y;
        uchar z;
    }uchar3;

    typedef struct uchar4{
        uchar x;
        uchar y;
        uchar z;
        uchar w;
    }uchar4;

    typedef struct char1{
        char x;
    }char1;

    typedef struct char2{
        char x;
        char y;
    }char2;

    typedef struct char3{
        char x;
        char y;
        char z;
    }char3;

    typedef struct char4{
        char x;
        char y;
        char z;
        char w;
    }char4;

    typedef struct ushort1{
        ushort x;
    }ushort1;

    typedef struct ushort2{
        ushort x;
        ushort y;
    }ushort2;

    typedef struct ushort3{
        ushort x;
        ushort y;
        ushort z;
    }ushort3;

    typedef struct ushort4{
        ushort x;
        ushort y;
        ushort z;
        ushort w;
    }ushort4;

    typedef struct short1{
        short x;
    }short1;

    typedef struct short2{
        short x;
        short y;
    }short2;

    typedef struct short3{
        short x;
        short y;
        short z;
    }short3;

    typedef struct short4{
        short x;
        short y;
        short z;
        short w;
    }short4;

    typedef struct uint1{
        uint x;
    }uint1;

    typedef struct uint2{
        uint x;
        uint y;
    }uint2;

    typedef struct uint3{
        uint x;
        uint y;
        uint z;
    }uint3;

    typedef struct uint4{
        uint x;
        uint y;
        uint z;
        uint w;
    }uint4;

    typedef struct int1{
        int x;
    }int1;

    typedef struct int2{
        int x;
        int y;
    }int2;

    typedef struct int3{
        int x;
        int y;
        int z;
    }int3;

    typedef struct int4{
        int x;
        int y;
        int z;
        int w;
    }int4;

    typedef struct ulong1{
        ulong x;
    }ulong1;

    typedef struct ulong2{
        ulong x;
        ulong y;
    }ulong2;

    typedef struct ulong3{
        ulong x;
        ulong y;
        ulong z;
    }ulong3;

    typedef struct ulong4{
        ulong x;
        ulong y;
        ulong z;
        ulong w;
    }ulong4;

    typedef struct long1{
        long x;
    }long1;

    typedef struct long2{
        long x;
        long y;
    }long2;

    typedef struct long3{
        long x;
        long y;
        long z;
    }long3;

    typedef struct long4{
        long x;
        long y;
        long z;
        long w;
    }long4;

    typedef struct ulonglong1{
        ulonglong x;
    }ulonglong1;

    typedef struct ulonglong2{
        ulonglong x;
        ulonglong y;
    }ulonglong2;

    typedef struct ulonglong3{
        ulonglong x;
        ulonglong y;
        ulonglong z;
    }ulonglong3;

    typedef struct ulonglong4{
        ulonglong x;
        ulonglong y;
        ulonglong z;
        ulonglong w;
    }ulonglong4;

    typedef struct longlong1{
        longlong x;
    }longlong1;

    typedef struct longlong2{
        longlong x;
        longlong y;
    }longlong2;

    typedef struct float1{
        float x;
    }float1;

    typedef struct float2{
        float x;
        float y;
    }float2;

    typedef struct float3{
        float x;
        float y;
        float z;
    }float3;

    typedef struct float4{
        float x;
        float y;
        float z;
        float w;
    }float4;  

    typedef struct double1{
        double x;
    }double1;

    typedef struct double2{
        double x;
        double y;
    }double2;

    typedef uint3 dim3;

    extern dim3 gridDim;
    extern uint3 blockIdx;
    extern dim3 blockDim;
    extern uint3 threadIdx;
    extern int warpsize;
#endif
Fini answered 7/9, 2017 at 17:1 Comment(2)
You might find my revised approach of interest - a general solution that avoids having to redefine the universe yourself :DTrometer
@ChrisKitching Wow, if are using that compiler that would definitely be the better approach. Another tick in the box for using Clang over GCC. Unfortunately I already upvoted your answer before I even posted mine. That seems like it would tie into the inline editing syntax checks quite easily as I believe Clion and pretty much every C++ IDE uses Clang to do before compile error checking. I imagine Jetbrains could implement this into the IDE quite easily, even if only as a plugin.Fini
I
3

if you want clion to parse all your .cu files as .cpp or any other supported file type, you can do this:

  1. Go to File -> Settings -> Editor -> File Types
  2. Select the file type you want it to be parsed as in the first column (.cpp)
  3. Click the plus sign of the second column and write *.cu

  4. Press apply and clion will parse all your .cu files as it was the file type you specified in the upper column (.cpp)

you can see more documentation here

Incite answered 27/3, 2017 at 20:6 Comment(2)
This helped me out, no clue what the heck the "project tool window" is in the top answer.Fini
Thank you for letting me know :) happy to helpIncite
C
1

The solution copied from what was mentioned in CLion issues: https://youtrack.jetbrains.com/issue/CPP-20722

If someone else facing the issue of incorrect syntax highlighting and using a newer version of CLion where the file type link already exists:

  1. Check C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v(YOUR_VERSION)\version.txt file exists

Most probably you find that there is a version.json, but you need specifically .txt file.

  1. The file should contain the following text "CUDA Version YOUR_FULL_VERSION"

To check the full version you can run cmd and type nvcc --version. If you can not create the file in the directory and have admin rights, just create a file somewhere else and move it later.

  1. Restart the CLion
Certain answered 31/1, 2024 at 20:56 Comment(0)
F
0

I've found that clion seems to code-index all build targets, not just the target you've selected to build. My strategy has been to make .cpp symbolic links out of my .cu files and make a child clion/cmake c++ build target (for indexing only) that references those .cpp links. This approach appears to be working on small cuda/thrust c++11 projects in clion 2017.3.3 in Unbuntu 16.04.3.

I do this by:

  • register the .cu/cuh files with clion, as in the other answers
  • add the cuda/clion macro voodoo to my .cu files, as in the other answers (the position of the voodoo may be important, but I haven't run into any troubles yet)
  • make .cpp/.hpp symbolic links to your .cu/.cuh files in your project directory
  • make a new folder with the single file named clionShadow/CMakeLists.txt that contains:
cmake_minimum_required(VERSION 3.9)
project(cudaNoBuild)
set(CMAKE_CXX_STANDARD 11)
add_executable(cudaNoBuild ../yourcudacode.cpp ../yourcudacode.hpp)
target_include_directories(cudaNoBuild PUBLIC ${CUDA_INCLUDE_DIRS})
  • add a dependency to clionShadow/CMakeLists.txt at the end of your main CMakeLists.txt with a line like this:
add_subdirectory(clionShadow)

Now, clion parses and code-indexes .cu files 'through' the .cpp files.

Remember, the cudaNoBuild target is not for building - it will use the c++ toolchain which won't work. If you suddenly get compilation errors check clion's build target settings - I've noticed that it sometimes mixes and matches the current build settings between the projects. In this case go to the Edit_Configurations dialog under the Run menu and ensure that clion has not changed the target_executable to be from the cudaNoBuild target.

Edit: Gah! Upon rebuilding the CMake and ide cache after an update to clion 2017.3.3 things are not really working the way they did before. Indexing only works for .cpp files and breakpoints only work for .cu files.

Felt answered 4/2, 2018 at 19:52 Comment(0)
R
0

Though not particularly related, somehow this question was in the google search result 'Pycharm cuda highlight'. However, use CLion for C/C++ projects then!

As of PyCharm 2020.3 Community Edition for Mac, it is under File > File Types > Associate with file types.

If uncertain, search 'file type' with the search bar under Help menu.

Read answered 1/2, 2021 at 2:15 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.