llvm / llvm/llvm-project

Clang-Tidy Custom Check Plugin Not Loading on Windows

Open
#159,710 3 comments 0 reactions 0 assignees View on GitHub
clang-tidy platform:windows
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

## 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(
"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
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
X("struct-member-naming-module","Adds checks for struct member naming conventions.");
```

### Check Registration
```cpp
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
CheckFactories.registerCheck(
"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?**

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the Windows command `clang-tidy --load build\BFNameingCheck.dll --list-checks`, then compare the CMakeLists.txt configuration with the module registration in NamingCheck.cpp and NamingCheck.h. Done means the DLL loads, `bf-readability-naming` appears in the listed checks, and the registration debug output is reached.

Written by the indexing model from the issue text.

Assessment

Tech stack
cmake, cpp
Domain
compilers, operating-systems, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.