Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Statically link compiler-rt #986

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
*.a
*.lib
*.pyc
*.pyd
*.o
Expand Down
2 changes: 1 addition & 1 deletion buildscripts/azure/azure-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
call conda remove --all -q -y -n %CONDA_ENV%
call conda create -n %CONDA_ENV% -q -y python=%PYTHON% cmake
call activate %CONDA_ENV%
call conda install -y -q -c numba/label/dev llvmdev="14.*" libxml2
call conda install -y -q --override-channels -c gmarkall llvmdev="14.*" libxml2
oliverhu marked this conversation as resolved.
Show resolved Hide resolved
displayName: 'Before Install'

- script: |
Expand Down
3 changes: 2 additions & 1 deletion buildscripts/incremental/setup_conda_environment.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ call activate %CONDA_ENV%
if %errorlevel% neq 0 exit /b %errorlevel%

@rem Install llvmdev
%CONDA_INSTALL% -c numba/label/dev llvmdev="14.*"
%CONDA_INSTALL% -c gmarkall llvmdev="14.*"
oliverhu marked this conversation as resolved.
Show resolved Hide resolved
@REM %CONDA_INSTALL% -c numba/label/dev llvmdev="14.*"
if %errorlevel% neq 0 exit /b %errorlevel%
4 changes: 3 additions & 1 deletion buildscripts/incremental/setup_conda_environment.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ set +v
source activate $CONDA_ENV
set -v

# TEMPORARY
$CONDA_INSTALL -c gmarkall llvmdev="14.*"
oliverhu marked this conversation as resolved.
Show resolved Hide resolved
# Install llvmdev (separate channel, for now)
$CONDA_INSTALL -c numba/label/dev llvmdev="14.*"
# $CONDA_INSTALL -c numba/label/dev llvmdev="14.*"

# Install the compiler toolchain, for osx, bootstrapping needed
# which happens in build.sh
Expand Down
33 changes: 30 additions & 3 deletions ffi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,38 @@ 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)

message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")

# Copy builtins archive
oliverhu marked this conversation as resolved.
Show resolved Hide resolved
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "AMD64") # for desktop
set(ARCH "x86_64")
else()
set(ARCH ${CMAKE_SYSTEM_PROCESSOR})
endif()

if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
set(COMPILER_RT_LOCATION ${LLVM_LIBRARY_DIR}/windows/clang_rt.builtins-${ARCH}.lib)
else()
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()
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
Expand All @@ -42,6 +65,10 @@ 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
set_target_properties(llvmlite PROPERTIES
LINK_FLAGS "-Lfoobar -Wl,--whole-archive,${COMPILER_RT_LOCATION},--no-whole-archive ")

# 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
Expand All @@ -63,7 +90,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")
Expand Down
14 changes: 11 additions & 3 deletions ffi/Makefile.freebsd
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
16 changes: 12 additions & 4 deletions ffi/Makefile.linux
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -16,15 +17,22 @@ 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)
$(CXX) -c $(CXXFLAGS) $< -o $@

$(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)
11 changes: 9 additions & 2 deletions ffi/Makefile.osx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,17 @@ SRC = assembly.cpp bitcode.cpp core.cpp initfini.cpp module.cpp value.cpp \
executionengine.cpp transforms.cpp passmanagers.cpp targets.cpp dylib.cpp \
linker.cpp object_file.cpp custom_passes.cpp orcjit.cpp
OUTPUT = libllvmlite.dylib

ifneq ("$(wildcard $(LLVM_LIBDIR)/clang)","")
BUILTINS_ARCHIVE := $(LLVM_LIBDIR)/clang/*/lib/darwin/libclang_rt.builtins-${ARCH}.a
else
BUILTINS_ARCHIVE := $(LLVM_LIBDIR)/darwin/libclang_rt.builtins-$(ARCH).a
endif

MACOSX_DEPLOYMENT_TARGET ?= 10.9

all: $(SRC) $(INCLUDE)
MACOSX_DEPLOYMENT_TARGET=$(MACOSX_DEPLOYMENT_TARGET) $(CXX) -dynamiclib $(CXXFLAGS) $(SRC) -o $(OUTPUT) $(LDFLAGS) $(LIBS)
MACOSX_DEPLOYMENT_TARGET=$(MACOSX_DEPLOYMENT_TARGET) $(CXX) -dynamiclib $(CXXFLAGS) $(SRC) -o $(OUTPUT) $(LDFLAGS) $(LIBS) -Wl,--whole-archive ${BUILTINS_ARCHIVE} -Wl,--no-whole-archive

clean:
rm -rf test
rm -rf test $(BUILTINS_ARCHIVE)
18 changes: 17 additions & 1 deletion ffi/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -100,7 +101,15 @@ def main_windows():
# Run configuration step
try_cmake(here_dir, build_dir, *generator)
subprocess.check_call(['cmake', '--build', build_dir, '--config', config])
shutil.copy(os.path.join(build_dir, config, 'llvmlite.dll'), target_dir)
try:
shutil.copy(os.path.join(build_dir, config, 'llvmlite.dll'), target_dir)
except shutil.SameFileError:
oliverhu marked this conversation as resolved.
Show resolved Hide resolved
pass

try:
shutil.copy(os.path.join(build_dir, 'clang_rt.builtins.lib'), target_dir)
oliverhu marked this conversation as resolved.
Show resolved Hide resolved
except shutil.SameFileError:
pass


def main_posix_cmake(kind, library_ext):
Expand Down Expand Up @@ -177,6 +186,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
Expand Down Expand Up @@ -208,6 +223,7 @@ def main_posix(kind, library_ext):
makeopts = os.environ.get('LLVMLITE_MAKEOPTS', default_makeopts).split()
subprocess.check_call(['make', '-f', makefile] + makeopts)
shutil.copy('libllvmlite' + library_ext, target_dir)
shutil.copy('libclang_rt.builtins.a', target_dir)


def main():
Expand Down
2 changes: 2 additions & 0 deletions llvmlite/binding/ffi.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ def _load_lib(self):
self._lib_handle = ctypes.CDLL(str(lib_path))
# Check that we can look up expected symbols.
_ = self._lib_handle.LLVMPY_GetVersionInfo()
# Make sure we can look up symbols from compiler-rt.
_ = self._lib_handle.__gnu_f2h_ieee()
except (OSError, AttributeError) as e:
# OSError may be raised if the file cannot be opened, or is not
# a shared library.
Expand Down
8 changes: 7 additions & 1 deletion llvmlite/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,17 @@ def get_library_name():
return 'llvmlite.dll'


def get_builtins_archive_name():
if os.name == 'nt':
return 'clang_rt.builtins.lib'
return 'libclang_rt.builtins.a'


def get_library_files():
"""
Return the names of shared library files needed for this platform.
"""
files = [get_library_name()]
files = [get_library_name(), get_builtins_archive_name()]
if os.name == 'nt':
files.extend(['msvcr120.dll', 'msvcp120.dll'])
return files
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down