Add IREE_COMPILER_BUILD_SHARED_LIBS option. (#12310)
* Balances all of the angels on the head of the pin such that when using
it, trivial changes to the compiler that would usually require a lengthy
re-link happen in <1s.
* Fixes some indirect dependencies that were missing (and enforced with
stricter linking).
* This is the equivalent of how LLVM interprets -DBUILD_SHARED_LIBS=ON,
scoped to just IREE's bundled LLVM, LLVM sub-projects and compiler
sources.
* As with all uses of BUILD_SHARED_LIBS, the support matrix for this
feature is sparse: there are many ways it will not work outside of its
strict case for supporting development.
* iree-run-module is not happy (complaining of duplicate option
registration). Will triage separately.
* This probably only works on Linux right now. It likely can work on
MacOS, but the libIREECompiler.dylib will need to be rigged with
--reexport_library (which is effectively the default for dynamically
loaded ELF). I don't think this will work on Windows without substantial
work.
* I am intending to use this mode to enable rapid reload of dynamically
built plugins, etc.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2c91aac..0c34543 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -94,6 +94,20 @@
option(IREE_BUILD_MICROBENCHMARKS "Builds IREE microbenchmark suites." OFF)
+# For development, builds LLVM (and in the future) the whole compiler as
+# individual shared libraries similar to if passing -DBUILD_SHARED_LIBS=ON
+# to a standalone LLVM build. This can dramatically reduce linking time and
+# makes the management of some dependencies more strict.
+# This option is considered experimental and should not be relied on until
+# CI coverage is established.
+option(IREE_COMPILER_BUILD_SHARED_LIBS "Enables BUILD_SHARED_LIBS CMake mode for LLVM and the compiler (this is only suitable for development)" OFF)
+
+# Must be defined as an option (CMake does not do it automatically), even though
+# we override it for different parts of the tree.
+# This option is considered experimental and should not be relied on until
+# CI coverage is established.
+option(BUILD_SHARED_LIBS "Instructs CMake to build libraries as shared if possible" OFF)
+
#-------------------------------------------------------------------------------
# Experimental project flags
#-------------------------------------------------------------------------------
@@ -668,6 +682,12 @@
if(NOT IREE_BUILD_COMPILER)
message(STATUS "Not adding LLVM/MLIR because the configuration does not require it")
else()
+ # Force enable BUILD_SHARED_LIBS for the compiler if instructed.
+ set(_IREE_ORIG_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
+ if(IREE_COMPILER_BUILD_SHARED_LIBS)
+ set(BUILD_SHARED_LIBS ON CACHE BOOL "" FORCE)
+ endif()
+
# Get the main LLVM deps.
if(IREE_BUILD_BUNDLED_LLVM)
iree_llvm_configure_bundled()
@@ -706,6 +726,8 @@
if(IREE_CLANG_TARGET)
add_dependencies(iree-test-deps ${IREE_CLANG_TARGET})
endif()
+
+ set(BUILD_SHARED_LIBS ${_IREE_ORIG_BUILD_SHARED_LIBS} CACHE BOOL "" FORCE)
endif()
#-------------------------------------------------------------------------------
diff --git a/build_tools/cmake/iree_cc_library.cmake b/build_tools/cmake/iree_cc_library.cmake
index e3d18d1..0392cb7 100644
--- a/build_tools/cmake/iree_cc_library.cmake
+++ b/build_tools/cmake/iree_cc_library.cmake
@@ -113,7 +113,7 @@
if(NOT _RULE_IS_INTERFACE)
add_library(${_OBJECTS_NAME} OBJECT)
- if(_RULE_SHARED)
+ if(_RULE_SHARED OR BUILD_SHARED_LIBS)
add_library(${_NAME} SHARED "$<TARGET_OBJECTS:${_OBJECTS_NAME}>")
if(_RULE_WINDOWS_DEF_FILE AND WIN32)
target_sources(${_NAME} PRIVATE "${_RULE_WINDOWS_DEF_FILE}")
@@ -197,6 +197,17 @@
${_RULE_DEFINES}
)
+ # If in BUILD_SHARED_LIBS mode, then we need to make sure that visibility
+ # is not hidden. We default to hidden visibility in the main copts so
+ # need to undo it here.
+ # TODO: Switch to the CXX_VISIBILITY_PRESET property and fix the global
+ # hidden setting to follow suit.
+ if(BUILD_SHARED_LIBS AND IREE_SUPPORTS_VISIBILITY_DEFAULT)
+ target_compile_options(${_OBJECTS_NAME} PRIVATE
+ "-fvisibility=default"
+ )
+ endif()
+
# Add all IREE targets to a folder in the IDE for organization.
if(_RULE_PUBLIC)
set_property(TARGET ${_NAME} PROPERTY FOLDER ${IREE_IDE_FOLDER})
@@ -388,9 +399,9 @@
# iree_cc_library_exclude_from_all(target exclude)
#
-# For a target previously defined in the same package, set the
+# For a target previously defined in the same package, set the
# EXCLUDE_FROM_ALL property.
-#
+#
# This is necessary because cc_library targets consist of multiple sub-targets
# and they all must have the property set.
function(iree_cc_library_exclude_from_all target exclude_from_all)
@@ -400,6 +411,6 @@
set(_NAME "${_PACKAGE_NAME}_${target}")
set(_OBJECTS_NAME ${_NAME}.objects)
- set_target_properties(${_NAME} ${_OBJECTS_NAME}
+ set_target_properties(${_NAME} ${_OBJECTS_NAME}
PROPERTIES EXCLUDE_FROM_ALL ${exclude_from_all})
endfunction()
diff --git a/build_tools/cmake/iree_setup_toolchain.cmake b/build_tools/cmake/iree_setup_toolchain.cmake
index f6f3c49..52d494b 100644
--- a/build_tools/cmake/iree_setup_toolchain.cmake
+++ b/build_tools/cmake/iree_setup_toolchain.cmake
@@ -29,6 +29,12 @@
endif()
#-------------------------------------------------------------------------------
+# Compiler flag support
+#-------------------------------------------------------------------------------
+
+check_cxx_compiler_flag(-fvisibility=default IREE_SUPPORTS_VISIBILITY_DEFAULT)
+
+#-------------------------------------------------------------------------------
# Linker setup
#-------------------------------------------------------------------------------
@@ -91,6 +97,13 @@
if(IREE_ENABLE_ASAN)
string(APPEND CMAKE_CXX_FLAGS " -fsanitize=address")
string(APPEND CMAKE_C_FLAGS " -fsanitize=address")
+ # If doing any kind of shared library builds, then we have to link against
+ # the shared libasan, and the user will be responsible for adding the
+ # appropriate path to LD_LIBRARY_PATH (or else binaries will fail to launch).
+ if(BUILD_SHARED_LIBS OR IREE_COMPILER_BUILD_SHARED_LIBS)
+ string(APPEND CMAKE_EXE_LINKER_FLAGS " -shared-libasan")
+ string(APPEND CMAKE_SHARED_LINKER_FLAGS " -shared-libasan")
+ endif()
endif()
if(IREE_ENABLE_MSAN)
string(APPEND CMAKE_CXX_FLAGS " -fsanitize=memory")
diff --git a/compiler/src/CMakeLists.txt b/compiler/src/CMakeLists.txt
index d6a8419..02571bc 100644
--- a/compiler/src/CMakeLists.txt
+++ b/compiler/src/CMakeLists.txt
@@ -17,4 +17,13 @@
# which provides common includes and copts for the tree.
set(IREE_IMPLICIT_DEFS_CC_DEPS iree::compiler::src::defs)
+# Force enable BUILD_SHARED_LIBS for the compiler if instructed.
+set(_IREE_ORIG_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
+if(IREE_COMPILER_BUILD_SHARED_LIBS)
+ set(BUILD_SHARED_LIBS ON CACHE BOOL "" FORCE)
+endif()
+
add_subdirectory(iree/compiler)
+
+# Reset BUILD_SHARED_LIBS.
+set(BUILD_SHARED_LIBS ${_IREE_ORIG_BUILD_SHARED_LIBS} CACHE BOOL "" FORCE)
diff --git a/compiler/src/iree/compiler/API/python/CMakeLists.txt b/compiler/src/iree/compiler/API/python/CMakeLists.txt
index 1667aea..7d8221f 100644
--- a/compiler/src/iree/compiler/API/python/CMakeLists.txt
+++ b/compiler/src/iree/compiler/API/python/CMakeLists.txt
@@ -135,8 +135,7 @@
)
target_link_libraries(${target}
iree_compiler_bindings_c_headers
- iree_compiler_API2_SharedImpl
- )
+ iree_compiler_API2_Impl)
set_target_properties(${target}
PROPERTIES
OUTPUT_NAME "${ARG_OUTPUT_NAME}"
diff --git a/compiler/src/iree/compiler/API2/CMakeLists.txt b/compiler/src/iree/compiler/API2/CMakeLists.txt
index 7a03c31..751ffe5 100644
--- a/compiler/src/iree/compiler/API2/CMakeLists.txt
+++ b/compiler/src/iree/compiler/API2/CMakeLists.txt
@@ -109,8 +109,12 @@
# The bazel side uses a "Impl" library alias to generically represent
# static or shared. Provide a corresponding one here.
+# When in BUILD_SHARED_LIBS mode, we do CMake level linking against the
+# non-shared library, since strict layering is enforced there. The mondo
+# shared library can still be generated and used dynamically but is not
+# generally depended on from a normal C++ link.
-if(IREE_LINK_COMPILER_SHARED_LIBRARY)
+if(IREE_LINK_COMPILER_SHARED_LIBRARY AND NOT BUILD_SHARED_LIBS)
iree_cc_library(
NAME
Impl
@@ -124,4 +128,4 @@
DEPS
::StaticImpl
)
-endif() # IREE_LINK_COMPILER_SHARED_LIBRARY
+endif()
diff --git a/compiler/src/iree/compiler/API2/Internal/BUILD b/compiler/src/iree/compiler/API2/Internal/BUILD
index 9d2dc51..d4ca338 100644
--- a/compiler/src/iree/compiler/API2/Internal/BUILD
+++ b/compiler/src/iree/compiler/API2/Internal/BUILD
@@ -25,6 +25,7 @@
"//compiler/bindings/c:headers",
"//compiler/src/iree/compiler/ConstEval",
"//compiler/src/iree/compiler/Dialect/VM/Target:init_targets",
+ "//compiler/src/iree/compiler/Dialect/VM/Target/Bytecode",
"//compiler/src/iree/compiler/Dialect/VM/Target/C",
"//compiler/src/iree/compiler/Pipelines",
"//compiler/src/iree/compiler/Tools:init_llvmir_translations",
diff --git a/compiler/src/iree/compiler/API2/Internal/CMakeLists.txt b/compiler/src/iree/compiler/API2/Internal/CMakeLists.txt
index e926eb0..5e03e14 100644
--- a/compiler/src/iree/compiler/API2/Internal/CMakeLists.txt
+++ b/compiler/src/iree/compiler/API2/Internal/CMakeLists.txt
@@ -24,6 +24,7 @@
MLIRParser
MLIRSupport
iree::compiler::ConstEval
+ iree::compiler::Dialect::VM::Target::Bytecode
iree::compiler::Dialect::VM::Target::C
iree::compiler::Dialect::VM::Target::init_targets
iree::compiler::Pipelines
diff --git a/compiler/src/iree/compiler/API2/test/BUILD b/compiler/src/iree/compiler/API2/test/BUILD
index 9d736a2..d7669e2 100644
--- a/compiler/src/iree/compiler/API2/test/BUILD
+++ b/compiler/src/iree/compiler/API2/test/BUILD
@@ -20,5 +20,6 @@
"//compiler/src/iree/compiler/API2:Impl",
"//compiler/src/iree/compiler/API2:MLIRInteropHeaders",
"//runtime/src/iree/base",
+ "@llvm-project//mlir:CAPIIRHeaders",
],
)
diff --git a/compiler/src/iree/compiler/API2/test/CMakeLists.txt b/compiler/src/iree/compiler/API2/test/CMakeLists.txt
index 47c07c3..7676f10 100644
--- a/compiler/src/iree/compiler/API2/test/CMakeLists.txt
+++ b/compiler/src/iree/compiler/API2/test/CMakeLists.txt
@@ -16,6 +16,7 @@
SRCS
"api-test-main.c"
DEPS
+ IREELLVMIncludeSetup
iree::base
iree::compiler::API2::Impl
iree::compiler::API2::MLIRInteropHeaders
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/CMakeLists.txt b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/CMakeLists.txt
index 673e634..4d5528c 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/CMakeLists.txt
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/CMakeLists.txt
@@ -143,19 +143,23 @@
add_library(IREELLVMCPUTargetDeps INTERFACE)
-function(_add_optional_llvm_dep dep)
- if(TARGET ${dep})
- target_link_libraries(IREELLVMCPUTargetDeps INTERFACE ${dep})
+function(_add_optional_llvm_target_deps target)
+ # Key off of the CodeGen target and then include the rest.
+ if(TARGET "LLVM${target}CodeGen")
+ target_link_libraries(IREELLVMCPUTargetDeps INTERFACE
+ "LLVM${target}AsmParser"
+ "LLVM${target}CodeGen"
+ "LLVM${target}Desc"
+ "LLVM${target}Info")
endif()
endfunction()
-_add_optional_llvm_dep(LLVMAArch64AsmParser)
-_add_optional_llvm_dep(LLVMAArch64CodeGen)
-_add_optional_llvm_dep(LLVMARMAsmParser)
-_add_optional_llvm_dep(LLVMARMCodeGen)
-_add_optional_llvm_dep(LLVMRISCVAsmParser)
-_add_optional_llvm_dep(LLVMRISCVCodeGen)
-_add_optional_llvm_dep(LLVMWebAssemblyAsmParser)
-_add_optional_llvm_dep(LLVMWebAssemblyCodeGen)
-_add_optional_llvm_dep(LLVMX86AsmParser)
-_add_optional_llvm_dep(LLVMX86CodeGen)
+# This is just the CPU backends that we hard-link to. Single-target backends
+# like CUDA and ROCM bring their dependencies explicitly.
+# TODO: More archaeology and tieing this to explicit top-level configuration
+# of backends.
+_add_optional_llvm_target_deps(AArch64)
+_add_optional_llvm_target_deps(ARM)
+_add_optional_llvm_target_deps(RISCV)
+_add_optional_llvm_target_deps(WebAssembly)
+_add_optional_llvm_target_deps(X86)