Issue 159710
Summary Clang-Tidy Custom Check Plugin Not Loading on Windows
Labels clang-tidy
Assignees
Reporter jitre
    ## Issue Summary

I have developed an out-of-tree clang-tidy plugin that compiles successfully on Windows but fails to load at runtime. The plugin builds without errors and exports symbols correctly, but clang-tidy doesn't recognize or load the custom checks.

## Environment Details

### System Information
- **Operating System**: Windows 10 Build 26100
- **Architecture**: x86_64-pc-windows-msvc
- **Compiler**: Clang 20.1.8
  ```
  clang version 20.1.8
  Target: x86_64-pc-windows-msvc
  Thread model: posix
  InstalledDir: C:\Program Files\LLVM\bin
  ```

### LLVM/Clang Version
- **LLVM Version**: 20.1.8
- **Clang Version**: 20.1.8
- **Installation Path**: `D:\clang+llvm-20.1.8-x86_64-pc-windows-msvc\`

### Build Configuration

**CMakeLists.txt:**
```cmake
cmake_minimum_required(VERSION 3.10)

# CRITICAL: Set compiler before project() command to ensure it takes effect
if(APPLE)
    # macOS - Use Homebrew installation paths
    set(CMAKE_CXX_COMPILER "/opt/homebrew/opt/llvm/bin/clang++")
    set(CMAKE_C_COMPILER "/opt/homebrew/opt/llvm/bin/clang")
    set(LLVM_DIR "/opt/homebrew/Cellar/llvm/20.1.8/lib/cmake/llvm")
    set(Clang_DIR "/opt/homebrew/Cellar/llvm/20.1.8/lib/cmake/clang")
elseif(WIN32)
    # Windows - Use clang compiler (must be set before project())
    set(CMAKE_CXX_COMPILER "C:\\Program Files\\LLVM\\bin\\clang++.exe")
    set(CMAKE_C_COMPILER "C:\\Program Files\\LLVM\\bin\\clang.exe")
    set(LLVM_DIR "D:\\clang+llvm-20.1.8-x86_64-pc-windows-msvc\\lib\\cmake\\llvm")
    set(Clang_DIR "D:\\clang+llvm-20.1.8-x86_64-pc-windows-msvc\\lib\\cmake\\clang")
elseif(UNIX)
    # Linux - Configure your Linux paths here
    # TODO: Set your Linux LLVM and Clang paths
    # set(CMAKE_CXX_COMPILER "/usr/bin/clang++")
    # set(CMAKE_C_COMPILER "/usr/bin/clang")
    # set(LLVM_DIR "/usr/lib/llvm-XX/lib/cmake/llvm")
    # set(Clang_DIR "/usr/lib/llvm-XX/lib/cmake/clang")
    message(FATAL_ERROR "Linux paths not configured yet. Please set LLVM_DIR, Clang_DIR, and CMAKE_CXX_COMPILER for Linux.")
else()
    # Other operating systems
    message(FATAL_ERROR "Unsupported operating system. Please configure paths for your system.")
endif()

project(bf-clangtidycustomizedcheckers)

set(CMAKE_CXX_STANDARD 17)

# 在LLVM_DIR 下面寻找对应的库
find_package(LLVM REQUIRED CONFIG)
find_package(Clang REQUIRED CONFIG)

# 设置包含目录  LLVM  LLVM_DIR  LLVM_INCLUDE_DIRS 都是约定俗称的命名
include_directories(${LLVM_INCLUDE_DIRS})
include_directories(${CLANG_INCLUDE_DIRS})

# 添加LLM对应的对应的宏定义(预处理器)
add_definitions(${LLVM_DEFINITIONS})

# Ensure we use the same C++ standard library as LLVM
if(NOT WIN32)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
endif()

# Windows specific settings to match LLVM
if(WIN32)
    # Force Release mode to match LLVM libraries
    set(CMAKE_BUILD_TYPE "Release")
endif()

# 创建命名检查器的共享库
add_library(BFNameingCheck MODULE NamingCheck.cpp NamingCheck.h)

# Windows specific: Force static runtime library to match LLVM
if(WIN32)
    # Override CMake's default flags for shared library
    target_compile_options(BFNameingCheck PRIVATE 
        -U_DLL                          # Undefine _DLL
        -D_MT                           # Define _MT for static runtime
    )

endif()

target_link_libraries(BFNameingCheck PRIVATE clangASTMatchers clangTidy )
```

## Problem Evidence

### 1. Debug Logs Not Executed
I added debug logging in the `addCheckFactories` method:

```cpp
class StructMemberNamingModule : public ClangTidyModule {
public:
  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
    llvm::errs() << "[DEBUG] StructMemberNamingModule::addCheckFactories called - registering bf-readability-naming checker\n";
    CheckFactories.registerCheck<readability::StructMemberNamingCheck>(
        "bf-readability-naming");
    llvm::errs() << "[DEBUG] bf-readability-naming checker registered successfully\n";
  }
};
```

**Expected behavior**: These debug messages should print when the plugin loads.
**Actual behavior**: No debug output appears, indicating the `addCheckFactories` method is never called.

### 2. Symbol Export Verification
Using `dumpbin` to verify the DLL exports symbols correctly:

```
C:\Users\guodonghao\Desktop\bf-clangtidycustomizedcheckers> dumpbin /exports build\BFNameingCheck.dll

Dump of file C:\Users\guodonghao\Desktop\bf-clangtidycustomizedcheckers\build\BFNameingCheck.dll

File Type: DLL

  Section contains the following exports for BFNameingCheck.dll

    00000000 characteristics
           0 time date stamp
        0.00 version
           1 ordinal base
           1 number of functions
           1 number of names

    ordinal hint RVA      name

          1    0 00556B88 X

  Summary

      1EA000 .data
       19000 .pdata
       AD000 .rdata
        7000 .reloc
        1000 .rsrc
      46B000 .text
        1000 .tls
```

The symbol `X` is exported, which corresponds to:
```cpp
extern "C" __declspec(dllexport) ClangTidyModuleRegistry::Add<StructMemberNamingModule>
    X("struct-member-naming-module","Adds checks for struct member naming conventions.");
```

### 3. Clang-Tidy List Check Results
Running `clang-tidy --load build\BFNameingCheck.dll --list-checks`:

```
clangtidycustomizedcheckers\.clang-tidy --list-checks
Enabled checks:
    readability-identifier-naming
```

**Expected behavior**: Should show `bf-readability-naming` in the list.
**Actual behavior**: The custom check `bf-readability-naming` is not listed, indicating the plugin is not being loaded.

## Plugin Implementation Details

### Module Registration
```cpp
extern "C" __declspec(dllexport) ClangTidyModuleRegistry::Add<StructMemberNamingModule>
    X("struct-member-naming-module","Adds checks for struct member naming conventions.");
```

### Check Registration
```cpp
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
    CheckFactories.registerCheck<readability::StructMemberNamingCheck>(
        "bf-readability-naming");
}
```

## What I've Tried

1. **Verified symbol export**: The DLL correctly exports the registration symbol `X`
2. **Checked build configuration**: The MODULE library builds successfully without errors  
3. **Added debug logging**: Confirmed that `addCheckFactories` is never called
4. **Used correct export syntax**: Using `extern "C" __declspec(dllexport)` for Windows

## Questions

1. **Is there something specific to Windows plugin loading that I'm missing?**
2. **Are there additional requirements for clang-tidy plugin registration on Windows?**
3. **Could there be a runtime library mismatch issue preventing plugin loading?**
4. **Is the plugin loading mechanism different between Windows and Unix systems?**
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to