Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit f653fb8

Browse files
Add auto-exporting of symbols from tools so that plugins work on Windows
The problem with plugins on Windows is that when building a plugin DLL it needs to explicitly link against something (an exe or DLL) if it uses symbols from that thing, and that thing must explicitly export those symbols. Also there's a limit of 65535 symbols that can be exported. This means that currently plugins only work on Windows when using BUILD_SHARED_LIBS, and that doesn't work with MSVC. This patch adds an LLVM_EXPORT_SYMBOLS_FOR_PLUGINS option, which when enabled automatically exports from all LLVM tools the symbols that a plugin could want to use so that a plugin can link against a tool directly. Plugins can specify what tool they link against by using PLUGIN_TOOL argument to llvm_add_library. The option can also be enabled on Linux, though there all it should do is restrict the set of symbols that are exported as by default all symbols are exported. This option is currently OFF by default, as while I've verified that it works with MSVC, linux gcc, and cygwin gcc, I haven't tried mingw gcc and I have no idea what will happen on OSX. Also unfortunately we can't turn on LLVM_ENABLE_PLUGINS when the option is ON as bugpoint-passes needs to be loaded by both bugpoint.exe and opt.exe which is incompatible with this approach. Also currently clang plugins don't work with this approach, which will be fixed in future patches. Differential Revision: http://reviews.llvm.org/D18826 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@270839 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent c8706b2 commit f653fb8

File tree

5 files changed

+577
-13
lines changed

5 files changed

+577
-13
lines changed

cmake/modules/AddLLVM.cmake

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -328,11 +328,13 @@ endfunction(set_windows_version_resource_properties)
328328
# May specify header files for IDE generators.
329329
# SONAME
330330
# Should set SONAME link flags and create symlinks
331+
# PLUGIN_TOOL
332+
# The tool (i.e. cmake target) that this plugin will link against
331333
# )
332334
function(llvm_add_library name)
333335
cmake_parse_arguments(ARG
334336
"MODULE;SHARED;STATIC;OBJECT;DISABLE_LLVM_LINK_LLVM_DYLIB;SONAME"
335-
"OUTPUT_NAME"
337+
"OUTPUT_NAME;PLUGIN_TOOL"
336338
"ADDITIONAL_HEADERS;DEPENDS;LINK_COMPONENTS;LINK_LIBS;OBJLIBS"
337339
${ARGN})
338340
list(APPEND LLVM_COMMON_DEPENDS ${ARG_DEPENDS})
@@ -350,11 +352,15 @@ function(llvm_add_library name)
350352
if(ARG_SHARED OR ARG_STATIC)
351353
message(WARNING "MODULE with SHARED|STATIC doesn't make sense.")
352354
endif()
353-
if(NOT LLVM_ENABLE_PLUGINS)
355+
# Plugins that link against a tool are allowed even when plugins in general are not
356+
if(NOT LLVM_ENABLE_PLUGINS AND NOT (ARG_PLUGIN_TOOL AND LLVM_EXPORT_SYMBOLS_FOR_PLUGINS))
354357
message(STATUS "${name} ignored -- Loadable modules not supported on this platform.")
355358
return()
356359
endif()
357360
else()
361+
if(ARG_PLUGIN_TOOL)
362+
message(WARNING "PLUGIN_TOOL without MODULE doesn't make sense.")
363+
endif()
358364
if(BUILD_SHARED_LIBS AND NOT ARG_STATIC)
359365
set(ARG_SHARED TRUE)
360366
endif()
@@ -468,7 +474,10 @@ function(llvm_add_library name)
468474
endif()
469475
endif()
470476

471-
if (DEFINED LLVM_LINK_COMPONENTS OR DEFINED ARG_LINK_COMPONENTS)
477+
if(ARG_MODULE AND LLVM_EXPORT_SYMBOLS_FOR_PLUGINS AND ARG_PLUGIN_TOOL AND (WIN32 OR CYGWIN))
478+
# On DLL platforms symbols are imported from the tool by linking against it.
479+
set(llvm_libs ${ARG_PLUGIN_TOOL})
480+
elseif (DEFINED LLVM_LINK_COMPONENTS OR DEFINED ARG_LINK_COMPONENTS)
472481
if (LLVM_LINK_LLVM_DYLIB AND NOT ARG_DISABLE_LLVM_LINK_LLVM_DYLIB)
473482
set(llvm_libs LLVM)
474483
else()
@@ -673,7 +682,67 @@ macro(add_llvm_executable name)
673682
endmacro(add_llvm_executable name)
674683

675684
function(export_executable_symbols target)
676-
if (NOT MSVC) # MSVC's linker doesn't support exporting all symbols.
685+
if (LLVM_EXPORTED_SYMBOL_FILE)
686+
# The symbol file should contain the symbols we want the executable to
687+
# export
688+
set_target_properties(${target} PROPERTIES ENABLE_EXPORTS 1)
689+
elseif (LLVM_EXPORT_SYMBOLS_FOR_PLUGINS)
690+
# Extract the symbols to export from the static libraries that the
691+
# executable links against.
692+
set_target_properties(${target} PROPERTIES ENABLE_EXPORTS 1)
693+
set(exported_symbol_file ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${target}.symbols)
694+
# We need to consider not just the direct link dependencies, but also the
695+
# transitive link dependencies. Do this by starting with the set of direct
696+
# dependencies, then the dependencies of those dependencies, and so on.
697+
get_target_property(new_libs ${target} LINK_LIBRARIES)
698+
set(link_libs ${new_libs})
699+
while(NOT "${new_libs}" STREQUAL "")
700+
foreach(lib ${new_libs})
701+
get_target_property(lib_type ${lib} TYPE)
702+
if("${lib_type}" STREQUAL "STATIC_LIBRARY")
703+
list(APPEND static_libs ${lib})
704+
else()
705+
list(APPEND other_libs ${lib})
706+
endif()
707+
get_target_property(transitive_libs ${lib} INTERFACE_LINK_LIBRARIES)
708+
foreach(transitive_lib ${transitive_libs})
709+
list(FIND link_libs ${transitive_lib} idx)
710+
if(TARGET ${transitive_lib} AND idx EQUAL -1)
711+
list(APPEND newer_libs ${transitive_lib})
712+
list(APPEND link_libs ${transitive_lib})
713+
endif()
714+
endforeach(transitive_lib)
715+
endforeach(lib)
716+
set(new_libs ${newer_libs})
717+
set(newer_libs "")
718+
endwhile()
719+
if (MSVC)
720+
set(mangling microsoft)
721+
else()
722+
set(mangling itanium)
723+
endif()
724+
add_custom_command(OUTPUT ${exported_symbol_file}
725+
COMMAND ${PYTHON_EXECUTABLE} ${LLVM_MAIN_SRC_DIR}/utils/extract_symbols.py --mangling=${mangling} ${static_libs} -o ${exported_symbol_file}
726+
WORKING_DIRECTORY ${LLVM_LIBRARY_OUTPUT_INTDIR}
727+
DEPENDS ${LLVM_MAIN_SRC_DIR}/utils/extract_symbols.py ${static_libs}
728+
VERBATIM
729+
COMMENT "Generating export list for ${target}")
730+
add_llvm_symbol_exports( ${target} ${exported_symbol_file} )
731+
# If something links against this executable then we want a
732+
# transitive link against only the libraries whose symbols
733+
# we aren't exporting.
734+
set_target_properties(${target} PROPERTIES INTERFACE_LINK_LIBRARIES "${other_libs}")
735+
# The default import library suffix that cmake uses for cygwin/mingw is
736+
# ".dll.a", but for clang.exe that causes a collision with libclang.dll,
737+
# where the import libraries of both get named libclang.dll.a. Use a suffix
738+
# of ".exe.a" to avoid this.
739+
if(CYGWIN OR MINGW)
740+
set_target_properties(${target} PROPERTIES IMPORT_SUFFIX ".exe.a")
741+
endif()
742+
elseif(NOT (WIN32 OR CYGWIN))
743+
# On Windows auto-exporting everything doesn't work because of the limit on
744+
# the size of the exported symbol table, but on other platforms we can do
745+
# it without any trouble.
677746
set_target_properties(${target} PROPERTIES ENABLE_EXPORTS 1)
678747
if (APPLE)
679748
set_property(TARGET ${target} APPEND_STRING PROPERTY

cmake/modules/HandleLLVMOptions.cmake

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -594,15 +594,6 @@ if(NOT CYGWIN AND NOT WIN32)
594594
endif()
595595
endif()
596596

597-
if(CYGWIN OR MINGW)
598-
# Prune --out-implib from executables. It doesn't make sense even
599-
# with --export-all-symbols.
600-
string(REGEX REPLACE "-Wl,--out-implib,[^ ]+ " " "
601-
CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE}")
602-
string(REGEX REPLACE "-Wl,--out-implib,[^ ]+ " " "
603-
CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE}")
604-
endif()
605-
606597
if(MSVC)
607598
# Remove flags here, for exceptions and RTTI.
608599
# Each target property or source property should be responsible to control
@@ -640,6 +631,19 @@ elseif(LLVM_ENABLE_LTO)
640631
CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS)
641632
endif()
642633

634+
# This option makes utils/extract_symbols.py be used to determine the list of
635+
# symbols to export from LLVM tools. This is necessary when using MSVC if you
636+
# want to allow plugins, though note that the plugin has to explicitly link
637+
# against (exactly one) tool so we can't unilaterally turn on
638+
# LLVM_ENABLE_PLUGINS when it's enabled.
639+
option(LLVM_EXPORT_SYMBOLS_FOR_PLUGINS "Export symbols from LLVM tools so that plugins can import them" OFF)
640+
if(BUILD_SHARED_LIBS AND LLVM_EXPORT_SYMBOLS_FOR_PLUGINS)
641+
message(FATAL_ERROR "BUILD_SHARED_LIBS not compatible with LLVM_EXPORT_SYMBOLS_FOR_PLUGINS")
642+
endif()
643+
if(LLVM_LINK_LLVM_DYLIB AND LLVM_EXPORT_SYMBOLS_FOR_PLUGINS)
644+
message(FATAL_ERROR "LLVM_LINK_LLVM_DYLIB not compatible with LLVM_EXPORT_SYMBOLS_FOR_PLUGINS")
645+
endif()
646+
643647
# Plugin support
644648
# FIXME: Make this configurable.
645649
if(WIN32 OR CYGWIN)

cmake/modules/LLVMConfig.cmake.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ set(LLVM_NATIVE_ARCH @LLVM_NATIVE_ARCH@)
4040
set(LLVM_ENABLE_PIC @LLVM_ENABLE_PIC@)
4141

4242
set(LLVM_ENABLE_PLUGINS @LLVM_ENABLE_PLUGINS@)
43+
set(LLVM_EXPORT_SYMBOLS_FOR_PLUGINS @LLVM_EXPORT_SYMBOLS_FOR_PLUGINS@)
4344
set(LLVM_PLUGIN_EXT @LLVM_PLUGIN_EXT@)
4445

4546
set(LLVM_ON_UNIX @LLVM_ON_UNIX@)

lib/Transforms/Hello/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,6 @@ add_llvm_loadable_module( LLVMHello
1515

1616
DEPENDS
1717
intrinsics_gen
18+
PLUGIN_TOOL
19+
opt
1820
)

0 commit comments

Comments
 (0)