diff --git a/.gitignore b/.gitignore index dd191b234..968f9e7c2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +*.a +*.lib *.pyc *.pyd *.o @@ -15,3 +17,4 @@ MANIFEST docs/_build/ docs/gh-pages/ .*.swp +.vscode/ \ No newline at end of file diff --git a/buildscripts/incremental/setup_conda_environment.sh b/buildscripts/incremental/setup_conda_environment.sh index 20008b264..682f9b16a 100755 --- a/buildscripts/incremental/setup_conda_environment.sh +++ b/buildscripts/incremental/setup_conda_environment.sh @@ -26,13 +26,15 @@ set +v source activate $CONDA_ENV set -v -# Install llvmdev (separate channel, for now) -$CONDA_INSTALL -c numba/label/dev llvmdev="14.*" - -# Install the compiler toolchain, for osx, bootstrapping needed -# which happens in build.sh if [[ $(uname) == Linux ]]; then -$CONDA_INSTALL gcc_linux-64 gxx_linux-64 + # Install the compiler toolchain, for osx, bootstrapping needed + # which happens in build.sh + $CONDA_INSTALL gcc_linux-64 gxx_linux-64 + # Install llvmdev (separate channel, for now) + $CONDA_INSTALL ohu::llvmdev + # $CONDA_INSTALL -c numba/label/dev llvmdev="14.*" +else + $CONDA_INSTALL -c numba/label/dev llvmdev="14.*" fi # Install dependencies for code coverage (codecov.io) diff --git a/docs/source/admin-guide/install.rst b/docs/source/admin-guide/install.rst index 7bf5eea18..1c38d685c 100644 --- a/docs/source/admin-guide/install.rst +++ b/docs/source/admin-guide/install.rst @@ -41,9 +41,13 @@ maintainers do *not* use any LLVM shared libraries that may be present on the system, and/or in the Conda environment. The parts of LLVM required by llvmlite are statically linked at build time. As a result, installing llvmlite from a binary package from the Numba channel does not also require the end user to -install LLVM. (For more -details on the reasoning behind this, see: :ref:`faq_why_static`). Note however -also that llvmlite packages compiled by other parties, e.g. conda-forge may +install LLVM. (For more details on the reasoning behind this, see: +:ref:`faq_why_static`). From version 0.42, `compiler-rt `_ +builtin is also statically linked at build time to provide an implementation of the +low-level target-specific hooks required by code generation and other runtime +components. You can find a a list of supported IR from the builtin `here `_. + +Note also that llvmlite packages compiled by other parties, e.g. conda-forge may split this into and ``llvmlite`` and ``llvm`` package and link dynamically. Conda packages: diff --git a/ffi/CMakeLists.txt b/ffi/CMakeLists.txt index e4ce2c12c..a16b55f4f 100755 --- a/ffi/CMakeLists.txt +++ b/ffi/CMakeLists.txt @@ -7,8 +7,8 @@ project(llvmlite_ffi) include(CheckIncludeFiles) if(NOT MSVC) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -g") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -g") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -g $ENV{CXX_STATIC_LINK}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -g $ENV{CXX_STATIC_LINK}") endif() find_package(LLVM REQUIRED CONFIG) @@ -16,6 +16,18 @@ find_package(LLVM REQUIRED CONFIG) message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") +if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "AMD64") # for desktop + set(ARCH "x86_64") +else() + set(ARCH ${CMAKE_SYSTEM_PROCESSOR}) +endif() + +file(GLOB LLVM_EXCLUDE_LIB + "${LLVM_LIBRARY_DIR}/*LLVM*.a" +) + +STRING(REPLACE ";" "," LLVM_EXCLUDE_LIB "${LLVM_EXCLUDE_LIB}") + # Set your project compile flags. # E.g. if using the C++ header files # you will need to enable C++11 support @@ -42,6 +54,18 @@ add_library(llvmlite SHARED assembly.cpp bitcode.cpp core.cpp initfini.cpp passmanagers.cpp targets.cpp dylib.cpp linker.cpp object_file.cpp custom_passes.cpp orcjit.cpp) +# Link compiler-rt whole archive +if(${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") + if (EXISTS "$(LLVM_LIBDIR)/clang") + set(COMPILER_RT_LOCATION ${LLVM_LIBRARY_DIR}/linux/libclang_rt.builtins-${ARCH}.a) + else() + set(COMPILER_RT_LOCATION ${LLVM_LIBRARY_DIR}/clang/${LLVM_PACKAGE_VERSION}/lib/linux/libclang_rt.builtins-${ARCH}.a) + endif() + set_target_properties(llvmlite PROPERTIES + LINK_FLAGS "-Wl,--whole-archive,${COMPILER_RT_LOCATION},--no-whole-archive ") +endif() + + # Find the libraries that correspond to the LLVM components # that we wish to use. # The following line is broken with LLVM 10.0.0 due to a potential bug in @@ -63,7 +87,7 @@ list(REMOVE_ITEM llvm_libs "OptRemarks") target_link_libraries(llvmlite ${llvm_libs}) # -flto and --exclude-libs allow us to remove those parts of LLVM we don't use if(${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") - set_property(TARGET llvmlite APPEND_STRING PROPERTY LINK_FLAGS "-flto -Wl,--exclude-libs,ALL") + set_property(TARGET llvmlite APPEND_STRING PROPERTY LINK_FLAGS "-flto -Wl,--exclude-libs,${LLVM_EXCLUDE_LIB}") # On Darwin we only include the LLVMPY symbols we require and exclude # everything else. elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") diff --git a/ffi/Makefile.freebsd b/ffi/Makefile.freebsd index 7b869e876..437c37569 100644 --- a/ffi/Makefile.freebsd +++ b/ffi/Makefile.freebsd @@ -3,8 +3,9 @@ CXX = clang++ -stdlib=libc++ # -flto and --exclude-libs allow us to remove those parts of LLVM we don't use CXX_FLTO_FLAGS ?= -flto -LD_FLTO_FLAGS ?= -flto -Wl,--exclude-libs=ALL +LD_FLTO_FLAGS ?= -flto -Wl,--exclude-libs=$(LLVM_EXCLUDE_LIB) +ARCH := `uname -m` CXXFLAGS := $(CPPFLAGS) $(CXXFLAGS) $(LLVM_CXXFLAGS) $(CXX_FLTO_FLAGS) LDFLAGS := $(LDFLAGS) $(LLVM_LDFLAGS) $(LD_FLTO_FLAGS) LIBS = $(LLVM_LIBS) @@ -14,10 +15,17 @@ SRC = assembly.cpp bitcode.cpp core.cpp initfini.cpp module.cpp value.cpp \ linker.cpp object_file.cpp OUTPUT = libllvmlite.so +ifneq ("$(wildcard $(LLVM_LIBDIR)/clang)","") + BUILTINS_ARCHIVE := $(LLVM_LIBDIR)/clang/*/lib/freebsd/libclang_rt.builtins-${ARCH}.a +else + BUILTINS_ARCHIVE := $(LLVM_LIBDIR)/freebsd/libclang_rt.builtins-$(ARCH).a +endif + all: $(OUTPUT) $(OUTPUT): $(SRC) $(INCLUDE) - $(CXX) -shared $(CXXFLAGS) $(SRC) -o $(OUTPUT) $(LDFLAGS) $(LIBS) + $(CXX) -shared $(CXXFLAGS) $(SRC) -o $(OUTPUT) $(LDFLAGS) $(LIBS) \ + -Wl,--whole-archive ${BUILTINS_ARCHIVE} -Wl,--no-whole-archive clean: - rm -rf test + rm -rf test $(OUTPUT) $(OBJ) diff --git a/ffi/Makefile.linux b/ffi/Makefile.linux index c1df42dbb..1a844013f 100644 --- a/ffi/Makefile.linux +++ b/ffi/Makefile.linux @@ -3,10 +3,11 @@ CXX ?= g++ # -flto and --exclude-libs allow us to remove those parts of LLVM we don't use CXX_FLTO_FLAGS ?= -flto -LD_FLTO_FLAGS ?= -flto -Wl,--exclude-libs=ALL +LD_FLTO_FLAGS ?= -flto=auto -flto -Wl,--exclude-libs=$(LLVM_EXCLUDE_LIB) # -fPIC is required when compiling objects for a shared library CXX_FPIC_FLAGS ?= -fPIC +ARCH = `uname -m` CXXFLAGS := $(CPPFLAGS) $(CXXFLAGS) $(LLVM_CXXFLAGS) $(CXX_FLTO_FLAGS) $(CXX_FPIC_FLAGS) LDFLAGS := $(LDFLAGS) $(LLVM_LDFLAGS) $(LD_FLTO_FLAGS) LIBS = $(LLVM_LIBS) @@ -16,6 +17,12 @@ OBJ = assembly.o bitcode.o core.o initfini.o module.o value.o \ linker.o object_file.o custom_passes.o orcjit.o OUTPUT = libllvmlite.so +ifneq ("$(wildcard $(LLVM_LIBDIR)/clang)","") + BUILTINS_ARCHIVE := $(LLVM_LIBDIR)/clang/*/lib/linux/libclang_rt.builtins-${ARCH}.a +else + BUILTINS_ARCHIVE := $(LLVM_LIBDIR)/linux/libclang_rt.builtins-$(ARCH).a +endif + all: $(OUTPUT) .cpp.o: $(INCLUDE) @@ -23,8 +30,9 @@ all: $(OUTPUT) $(OUTPUT): $(OBJ) # static-libstdc++ avoids runtime dependencies on a - # particular libstdc++ version. - $(CXX) $(CXX_STATIC_LINK) -shared $(CXXFLAGS) $(OBJ) -o $(OUTPUT) $(LDFLAGS) $(LIBS) + # particular libstdc++ version.' + $(CXX) $(CXX_STATIC_LINK) -shared $(CXXFLAGS) $(OBJ) -o $(OUTPUT) $(LDFLAGS) $(LIBS) \ + -Wl,--whole-archive $(BUILTINS_ARCHIVE) -Wl,--no-whole-archive clean: - rm -rf test $(OUTPUT) $(OBJ) + rm -rf test $(OUTPUT) $(OBJ) \ No newline at end of file diff --git a/ffi/build.py b/ffi/build.py index f4f8c69fa..4176630f9 100755 --- a/ffi/build.py +++ b/ffi/build.py @@ -6,6 +6,7 @@ from __future__ import print_function from ctypes.util import find_library +from glob import glob import re import multiprocessing import os @@ -177,6 +178,12 @@ def main_posix(kind, library_ext): libs = run_llvm_config(llvm_config, "--system-libs --libs all".split()) # Normalize whitespace (trim newlines) os.environ['LLVM_LIBS'] = ' '.join(libs.split()) + # Get LLVM information for building + llvm_libdir = run_llvm_config(llvm_config, ["--libdir"]).strip() + os.environ['LLVM_LIBDIR'] = llvm_libdir + + exclude_file = glob(llvm_libdir + '/*LLVM*.a') + os.environ['LLVM_EXCLUDE_LIB'] = (',').join(exclude_file) cxxflags = run_llvm_config(llvm_config, ["--cxxflags"]) # on OSX cxxflags has null bytes at the end of the string, remove them diff --git a/llvmlite/tests/test_binding.py b/llvmlite/tests/test_binding.py index d0955508d..967a96e5c 100644 --- a/llvmlite/tests/test_binding.py +++ b/llvmlite/tests/test_binding.py @@ -2120,6 +2120,13 @@ def test_libm(self): llvm.load_library_permanently(libm) +class TestArchive(BaseTest): + @unittest.skipUnless(platform.system() in ["Linux"], + "test only works on Linux") + def test_compiler_rt(self): + ffi.lib._lib_handle['__ashldi3']() + + class TestAnalysis(BaseTest): def build_ir_module(self): m = ir.Module() diff --git a/setup.py b/setup.py index 75150ea4b..bbeaf30d1 100644 --- a/setup.py +++ b/setup.py @@ -139,7 +139,8 @@ def _rm_walk(self): else: for fname in files: if (fname.endswith('.pyc') or fname.endswith('.so') - or fname.endswith('.o')): + or fname.endswith('.o') or fname.endswith('.a') + or fname.endswith('.dll') or fname.endswith('.lib')): fpath = os.path.join(path, fname) os.remove(fpath) log.info("removing '%s'", fpath)