Hello,
-
I am developping a clang plugin out-of-tree.
-
My plugin generates some extra code, and
use the ClangFormat lib to format it. -
I have a strange linking error with a clangFormat.a symbol
but only on some llvm installations.
I compile as shown below, i.e. not linking with any ClangASTxxx.a, Clangxxx.a lib.
It works, but on one of our machines, a symbol in clangFormat.a is not found. -
Tiny example of a plugin which reproduces the issue
(the PrintFunctionNames of the llvm sources, where I removed almost everything but a call to clang::format::getLLVMStyle).
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Frontend/CompilerInstance.h"
#include "llvm/Support/raw_ostream.h"
#include "clang/Format/Format.h"
using namespace clang;
namespace {
class PrintFunctionsConsumer : public ASTConsumer {
public:
PrintFunctionsConsumer() = default;
bool HandleTopLevelDecl(DeclGroupRef DG) override { return true; }
void HandleTranslationUnit(ASTContext& context) override {
auto style = clang::format::getLLVMStyle(); // <<-------- PROBLEM ...
}
};
class PrintFunctionNamesAction : public PluginASTAction {
protected:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, llvm::StringRef) override {
return std::make_unique<PrintFunctionsConsumer>();
}
PluginASTAction::ActionType getActionType() override { return ReplaceAction; }
bool ParseArgs(const CompilerInstance &CI, const std::vector<std::string> &args) override { return true; }
void PrintHelp(llvm::raw_ostream& ros) { }
};
}
static FrontendPluginRegistry::Add<PrintFunctionNamesAction>
X("print-fns", "print function names");
Which I compile using a simple cmake
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
project(pfn VERSION 0.1.0 LANGUAGES C CXX)
# Load LLVM/Clang cmake
set(LLVM_CONFIG llvm-config CACHE STRING "llvm-config")
execute_process(COMMAND ${LLVM_CONFIG} --prefix OUTPUT_VARIABLE LLVM_ROOT_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
list(APPEND CMAKE_PREFIX_PATH "${LLVM_ROOT_DIR}/lib/cmake/clang/")
find_package(LLVM REQUIRED CONFIG)
find_package(Clang REQUIRED CONFIG)
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}")
include(AddLLVM)
# Plugin
add_llvm_library(pfn MODULE PrintFunctionNames.cpp PLUGIN_TOOL clang)
target_link_libraries(pfn PRIVATE "$<$<PLATFORM_ID:Darwin>:-undefined dynamic_lookup>")
target_include_directories(pfn PRIVATE ${LLVM_INCLUDE_DIR})
# Necessary on some machines ?
#target_link_libraries(pfn PRIVATE ${LLVM_LIBRARY_DIR}/libclangFormat.a)
When I use it
clang++ -fplugin=./pfn.so -c a_small_piece_of_code.cpp
it works well on OS X (clang 16, brew installed), Ubuntu (22.10, clang-15),
but on one of our computing center machine, CentOS, llvm-15 installed by Spack,
I get the error
.../clang-15: symbol lookup error: ./pfn.so: undefined symbol: _ZN5clang6format12getLLVMStyleENS0_11FormatStyle12LanguageKindE
I could solve there it by explicitly linking to clangFormat.a (Cmakefile last line).
But then, it works ok on OS X, but on Ubuntu it fails as
pure virtual method called
terminate called without an active exception
Questions :
-
Can someone tell me how exactly an out-of-tree plugin should be compiled ?
The documentation does not cover this. -
Is
add_llvm_library
correct here ? -
Why is the behaviour of clang different on some installation ???