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

Wrap LLD into python #898

Open
wants to merge 136 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
0af3ba0
Add lld recipe from conda-forge
certik Nov 14, 2018
730fc2f
Downgrade to LLD 6.0.0
certik Nov 14, 2018
63313d5
Disable RTTI for LLD
certik Nov 14, 2018
f1e8a88
Add initial LLD wrapper in C++
certik Nov 14, 2018
9f3889f
Add LLD libraries to link
certik Nov 14, 2018
e162690
Add the .a libraries first
certik Nov 15, 2018
5a2b50b
Rename the stub to lld_main
certik Nov 15, 2018
5c04cfd
Add lld_main_help() for testing
certik Nov 15, 2018
708d935
Add extern "C"
certik Nov 15, 2018
fc096d0
Add a Python wrapper for lld_main_help()
certik Nov 15, 2018
af1cba0
Pass the strings from Python, start with two
certik Nov 16, 2018
a0c6cf5
Make it work with arbitrary number of arguments
certik Nov 16, 2018
8708934
Remove the two unneeded functions
certik Nov 16, 2018
ba23294
Refactor the code
certik Nov 16, 2018
77e4548
Move lld_main_help() into docstring
certik Nov 16, 2018
b95a72a
Add a test for LLD in x86-64
certik Nov 17, 2018
caa3d44
Add a workaround for Python 2.7
certik Nov 18, 2018
5f09c70
Remove unnecessary initializers
certik Nov 18, 2018
e7c7bbd
Remove lld (it's in llvmdev)
certik Jan 26, 2019
2739f3d
Install backports.tempfile in build_llvmlite.sh
certik Jan 26, 2019
734590c
Use PYVER and the proper value for Python 2.7
certik Jan 26, 2019
364fb9d
Install backports.tempfile using conda
certik Jan 26, 2019
80f2414
Fix a typo
certik Jan 26, 2019
09cf908
Try conda-forge
certik Jan 26, 2019
c6ff417
Pip install it using the right pip
certik Jan 26, 2019
d6d85f5
Basic tests for vector
ArachnidAbby Jan 11, 2023
75c73dd
Update lld_main() function to work in modern llvmlite
ArachnidAbby Jan 11, 2023
4a72116
functions added for each platform lld drivers exist for
ArachnidAbby Jan 11, 2023
4f5b563
Rmove unused imports and better follow flake8
ArachnidAbby Jan 12, 2023
831b3c6
remove py27 code
ArachnidAbby Jan 12, 2023
dc777a0
hopefully made lld.cpp work on all platforms
ArachnidAbby Jan 12, 2023
b5bb1fc
hopefully got windows to build
ArachnidAbby Jan 12, 2023
beeb8b5
attempt to add lld options into Cmake
ArachnidAbby Jan 12, 2023
11cbea7
add -DLLVM_ENABLE_PROJECTS=lld to see if it works
ArachnidAbby Jan 12, 2023
e9f5850
Another attempt to get windows to compile
ArachnidAbby Jan 12, 2023
5ca4cab
Add quotes to LLVM_ENABLE_PROJECTS list
ArachnidAbby Jan 12, 2023
e91c501
Attempt to add ${LLD_SOURCE_DIR}/include
ArachnidAbby Jan 12, 2023
7c54827
trying more random things
ArachnidAbby Jan 12, 2023
8a214f6
change linking stuff
ArachnidAbby Jan 13, 2023
c591591
Merge remote-tracking branch 'origin/master'
ArachnidAbby Jan 13, 2023
b635461
attempt to fix latest link error
ArachnidAbby Jan 13, 2023
514d9b9
Another attempt
ArachnidAbby Jan 13, 2023
5faf248
hmmm. Not sure whats happening
ArachnidAbby Jan 13, 2023
ae7f212
remove lldCOFF to see what happens
ArachnidAbby Jan 13, 2023
fdeee7a
random commit name
ArachnidAbby Jan 13, 2023
cf4d4b6
try add_lld_library macro
ArachnidAbby Jan 13, 2023
1354956
Another attempt
ArachnidAbby Jan 13, 2023
2ec96ba
trying random shit.
ArachnidAbby Jan 13, 2023
e4cc1d6
debug message for testing
ArachnidAbby Jan 13, 2023
af79102
more message stuff
ArachnidAbby Jan 13, 2023
9dfb012
Another test
ArachnidAbby Jan 13, 2023
97bf22b
Another attempt
ArachnidAbby Jan 13, 2023
1e234d4
attempt number... idk
ArachnidAbby Jan 13, 2023
5f21d65
add_link_options test
ArachnidAbby Jan 13, 2023
47f4f5b
trying random stuff again
ArachnidAbby Jan 13, 2023
c11d26c
trying more stuff
ArachnidAbby Jan 13, 2023
0ad8163
I don't even know anymore
ArachnidAbby Jan 13, 2023
af1ceba
going to test if this works
ArachnidAbby Jan 15, 2023
641f535
This works locally
ArachnidAbby Jan 15, 2023
cd3a691
OMG I THINK I DID IT!
ArachnidAbby Jan 15, 2023
beb0c22
formatting
ArachnidAbby Jan 15, 2023
9743d14
Make LLD test work on all platforms
ArachnidAbby Jan 15, 2023
d9484c6
add lld.cpp to other make files
ArachnidAbby Jan 15, 2023
1935042
Another test + command output included on lld exceptions
ArachnidAbby Jan 15, 2023
6a4f8cc
Accounting for differences in windows lld.
ArachnidAbby Jan 15, 2023
8d8d29d
Fix tests to work on windows and linux.
ArachnidAbby Jan 15, 2023
e13cfe1
run tests with detail
ArachnidAbby Jan 15, 2023
b42d0cd
fix error?
ArachnidAbby Jan 15, 2023
95c9e85
fix premature exit on windows
ArachnidAbby Jan 15, 2023
626429b
Reduce the amount of needed llvmlibs
ArachnidAbby Jan 15, 2023
d8bf405
Docs and formatting
ArachnidAbby Jan 16, 2023
17c11f3
Forgotten file from previous commit
ArachnidAbby Jan 16, 2023
86534f4
spelling and formatting
ArachnidAbby Jan 16, 2023
22bb4c2
More concise docs
ArachnidAbby Jan 16, 2023
488a382
remove unused import
ArachnidAbby Jan 16, 2023
eca9f55
Merge remote-tracking branch 'llvmlite/main'
ArachnidAbby Jan 16, 2023
576dccb
Make Type Hinting compatible with older python
ArachnidAbby Jan 16, 2023
d03f6a2
trying something to make osx work
ArachnidAbby Jan 16, 2023
3c23bbd
I think this should fix mac builds
ArachnidAbby Jan 17, 2023
c50e618
cpp formatting fix
ArachnidAbby Jan 17, 2023
b8ec5f5
Readd macos lld linker
ArachnidAbby Jan 17, 2023
861180f
actually use ifdef properly
ArachnidAbby Jan 17, 2023
ff1d02c
print statement for debugging
ArachnidAbby Jan 17, 2023
6385952
Another test print
ArachnidAbby Jan 17, 2023
95557dd
add new "force_elf" option when creating target machine.
ArachnidAbby Jan 17, 2023
31c6334
General fixes
ArachnidAbby Jan 20, 2023
b4721de
add additional space in LLVM_LIBS
ArachnidAbby Jan 20, 2023
090b478
use ENV{lld_libs}
ArachnidAbby Jan 20, 2023
1f98b60
set the environment variable BEFORE doing cmake
ArachnidAbby Jan 20, 2023
678006d
fix the removal of `-l`
ArachnidAbby Jan 20, 2023
509585a
put semicolons
ArachnidAbby Jan 20, 2023
bfc33ee
Merge remote-tracking branch 'llvmlite/main'
ArachnidAbby Jul 10, 2023
a9da5ce
Update LLD binding
ArachnidAbby Jul 10, 2023
d88a118
possibly a fix, some libs don't exist anymore?
ArachnidAbby Jul 10, 2023
c94df90
Merge branch 'main' into master
ArachnidAbby Sep 20, 2023
5afb44c
Update Makefile.freebsd because I suck at merging
ArachnidAbby Sep 21, 2023
1f4065c
trying to update the conda setup to fix the build
ArachnidAbby Sep 25, 2023
dbdb038
hopefully correct channel this time?
ArachnidAbby Sep 25, 2023
a0ef848
honestly just trying things to see if they help.
ArachnidAbby Sep 25, 2023
2fe4425
Merge branch 'main' into master
ArachnidAbby Nov 20, 2023
927a044
Change build to hopefully show stdout on error (temporarily)
ArachnidAbby Dec 1, 2023
b4ef760
more info for more build testing
ArachnidAbby Dec 1, 2023
62076bd
more test info
ArachnidAbby Dec 1, 2023
9977306
use subprocess.run instead so I can get stdout
ArachnidAbby Dec 1, 2023
df963e5
again, trying to get stdout... I thought this would be easier lol.
ArachnidAbby Dec 1, 2023
5ece647
decode output so I can actually read it.
ArachnidAbby Dec 1, 2023
1125c9e
print cxx flags to see those
ArachnidAbby Dec 1, 2023
dadf3be
try to find lld?
ArachnidAbby Dec 1, 2023
fe85acb
Update build.py
ArachnidAbby Dec 1, 2023
e017e8a
another attempt to find lld
ArachnidAbby Dec 1, 2023
cebf195
Update build.py
ArachnidAbby Dec 1, 2023
4471e74
try something slightly different
ArachnidAbby Dec 1, 2023
98f9543
Update build.py
ArachnidAbby Dec 1, 2023
ff5a6a0
Update build.py
ArachnidAbby Dec 1, 2023
ea1c187
Update build.py
ArachnidAbby Dec 1, 2023
36cf85b
Update .readthedocs.yaml
ArachnidAbby Dec 1, 2023
9b98bbc
Update build.py
ArachnidAbby Dec 1, 2023
4d7d574
include liblld-14-dev on docs build
ArachnidAbby Dec 1, 2023
0165131
revert some of those build.py changes
ArachnidAbby Dec 1, 2023
2453b4f
revert last 2 things I messed up here.
ArachnidAbby Dec 1, 2023
a2f0554
store lld_libs as a list
ArachnidAbby Dec 4, 2023
654b75b
Merge branch 'main' into master
ArachnidAbby Dec 7, 2023
d7e9fdb
Merge branch 'main' into master
ArachnidAbby Dec 10, 2023
59c86b5
make underlines smaller on lld docs
ArachnidAbby Dec 18, 2023
c3d65a1
Merge branch 'main' into master
ArachnidAbby Aug 12, 2024
b4aadb4
Update setup_conda_environment.sh
ArachnidAbby Aug 22, 2024
6a8e8b4
Attempting to update libstdcxx-ng to fix llvm16 problem
ArachnidAbby Aug 27, 2024
d2d3105
Update setup_conda_environment.sh
ArachnidAbby Aug 27, 2024
96b6878
Update setup_conda_environment.cmd
ArachnidAbby Aug 27, 2024
3cdb40a
Update setup_conda_environment.sh
ArachnidAbby Aug 27, 2024
ee683a3
trying using clangxx instead
ArachnidAbby Aug 28, 2024
e4d9e5f
Update setup_conda_environment.sh
ArachnidAbby Aug 28, 2024
e6d8cb9
undo this mistake
ArachnidAbby Sep 8, 2024
c03f7ce
try adding libxml2 conda install
ArachnidAbby Sep 8, 2024
9a141d8
Update setup_conda_environment.cmd
ArachnidAbby Sep 8, 2024
4399d70
Merge branch 'main' into master
ArachnidAbby Sep 23, 2024
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 .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ build:
tools:
python: "3.11"
apt_packages:
- lld-15
- liblld-15-dev
- llvm-15
jobs:
post_checkout:
Expand Down
3 changes: 3 additions & 0 deletions buildscripts/incremental/setup_conda_environment.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ if "%LLVM%"=="16" (
)

call conda install -y -q -c %LLVMDEV_CHANNEL% llvmdev="%LLVM%" libxml2
if "%LLVM%"=="16" (
call conda install -y -q -c %LLVMDEV_CHANNEL% lld="16"
)
if %errorlevel% neq 0 exit /b %errorlevel%
9 changes: 7 additions & 2 deletions buildscripts/incremental/setup_conda_environment.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,20 @@ set -v

# Install llvmdev (separate channel, for now)
if [ "$LLVM" == "16" ]; then
$CONDA_INSTALL -c conda-forge llvmdev="16"
# also install lld, not required when using the numba channel because the numba
# channel includes lld.
$CONDA_INSTALL -c conda-forge llvmdev="16" lld="16"
else
$CONDA_INSTALL -c numba llvmdev="15.*"
fi

$CONDA_INSTALL -c numba libxml2

# 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
# $CONDA_INSTALL gcc_linux-64 gxx_linux-64
$CONDA_INSTALL -c conda-forge libstdcxx-ng=12
fi

# Install dependencies for code coverage (codecov.io)
Expand Down
1 change: 1 addition & 0 deletions docs/source/user-guide/binding/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ implement Numba_'s JIT compiler.
analysis-utilities
pass_timings
misc
lld
examples

63 changes: 63 additions & 0 deletions docs/source/user-guide/binding/lld.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
================
Linking with LLD
================

.. currentmodule:: llvmlite.binding

The LLD linker is automatically built into llvmlite to provide easy-to-use, cross-platform linking.

Known limitations
=================

Currently, only ``lld::elf::link`` is used and thus COFF and MACHO object files will **not** link.

The following llvm drivers are usable from :func:`lld_main`

* ld.lld (Linux)
* ld64.lld (macos/darwin)
* lld-link (windows)
* wasm-ld (Web Assembly)

Functions
=========

* .. function:: lld_main(args)

* ``args`` is a list of strings passed to the lld linker as arguments
* returns the output of the specific lld command being run. If there is an error, an :exc:`Exception` will be thrown.

example: ``binding.lld_main(["ld.lld", "--help"])``


* .. function:: lld_linux(output_file, objects, args=[])

* ``objects`` is a list of object files' names as **strings**.
* ``args`` is a list of strings passed to the lld linker as arguments (at the end of the command)
* returns the output of lld_main for the given arguments

Links given object files into an executable using :func:`lld_main()`


* .. function:: lld_windows(output_file, objects, args=[])

Link for Windows target


* .. function:: lld_macos(output_file, objects, args=[])

Link for Macos target


* .. function:: lld_wasm(output_file, objects, args=[])

Link for wasm target


* .. function:: lld_auto(output_file, objects, args=[], add_extension=True)

* ``add_extension`` should this function automatically add **.exe** and **.app** for windows and macos targets
* returns the output of lld_main for the given arguments

Automatically determines which function to use given the host operating system.
This will only use the ``lld_linux``, ``lld_windows``, and ``lld_macos`` functions.
Throws :exc:`Exception` if the host operating system isn't ``Darwin``, ``Windows``, or ``Linux``
3 changes: 2 additions & 1 deletion docs/source/user-guide/binding/target-information.rst
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ Classes

* .. method:: create_target_machine(cpu='', features='', \
opt=2, reloc='default', codemodel='jitdefault', \
abiname='')
abiname='', force_elf=False)

Create a new :class:`TargetMachine` instance for this
target and with the given options:
Expand All @@ -153,6 +153,7 @@ Classes
* *reloc* is the relocation model.
* *codemodel* is the code model.
* *abiname* is the name of the ABI.
* *force_elf* is an option that forces the target to use the ELF object format instead of the target's object format.

The defaults for reloc and codemodel are appropriate for
JIT compilation.
Expand Down
11 changes: 8 additions & 3 deletions ffi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ set(CMAKE_CXX_STANDARD 17)
include(GNUInstallDirs)

find_package(LLVM REQUIRED CONFIG)
find_package(LLD REQUIRED CONFIG)

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

# Set your project compile flags.
# E.g. if using the C++ header files
Expand All @@ -41,12 +44,14 @@ else()
message(STATUS "SVML not found")
endif()

add_definitions(-DLLVM_ENABLE_PROJECTS="lld")

# Define our shared library
add_library(llvmlite SHARED assembly.cpp bitcode.cpp core.cpp initfini.cpp
module.cpp value.cpp executionengine.cpp transforms.cpp type.cpp
passmanagers.cpp targets.cpp dylib.cpp linker.cpp object_file.cpp
custom_passes.cpp orcjit.cpp memorymanager.cpp newpassmanagers.cpp)
custom_passes.cpp orcjit.cpp memorymanager.cpp lld.cpp
newpassmanagers.cpp)

# Find the libraries that correspond to the LLVM components
# that we wish to use.
Expand All @@ -55,9 +60,9 @@ add_library(llvmlite SHARED assembly.cpp bitcode.cpp core.cpp initfini.cpp
# Bug reported upstream at: https://bugs.llvm.org/show_bug.cgi?id=47003
# BROKEN: llvm_map_components_to_libnames(llvm_libs all)
if ($ENV{LLVMLITE_SHARED})
set(llvm_libs LLVM)
set(llvm_libs $ENV{lld_libs} LLVM)
else()
set(llvm_libs ${LLVM_AVAILABLE_LIBS})
set(llvm_libs ${LLVM_AVAILABLE_LIBS} $ENV{lld_libs})
endif()

# Since LLVM 8 "OptRemarks" is built as a shared library only and also appears
Expand Down
2 changes: 1 addition & 1 deletion ffi/Makefile.freebsd
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ INCLUDE = core.h
SRC = assembly.cpp bitcode.cpp core.cpp initfini.cpp module.cpp value.cpp \
executionengine.cpp transforms.cpp passmanagers.cpp type.cpp targets.cpp \
dylib.cpp linker.cpp object_file.cpp orcjit.cpp custom_passes.cpp \
memorymanager.cpp newpassmanagers.cpp
memorymanager.cpp lld.cpp newpassmanagers.cpp
OUTPUT = libllvmlite.so

all: $(OUTPUT)
Expand Down
3 changes: 2 additions & 1 deletion ffi/Makefile.linux
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ LIBS = $(LLVM_LIBS)
INCLUDE = core.h
OBJ = assembly.o bitcode.o core.o initfini.o module.o value.o \
executionengine.o transforms.o passmanagers.o targets.o type.o dylib.o \
linker.o object_file.o custom_passes.o orcjit.o memorymanager.o newpassmanagers.o
linker.o object_file.o custom_passes.o orcjit.o memorymanager.o lld.o \
newpassmanagers.o
OUTPUT = libllvmlite.so

all: $(OUTPUT)
Expand Down
2 changes: 1 addition & 1 deletion ffi/Makefile.osx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ INCLUDE = core.h
SRC = assembly.cpp bitcode.cpp core.cpp initfini.cpp module.cpp value.cpp \
executionengine.cpp transforms.cpp passmanagers.cpp targets.cpp type.cpp \
dylib.cpp linker.cpp object_file.cpp custom_passes.cpp orcjit.cpp \
memorymanager.cpp newpassmanagers.cpp
memorymanager.cpp lld.cpp newpassmanagers.cpp
OUTPUT = libllvmlite.dylib
MACOSX_DEPLOYMENT_TARGET ?= 10.9

Expand Down
13 changes: 9 additions & 4 deletions ffi/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@

is_64bit = sys.maxsize >= 2**32

lld_libs = ["lldCommon", "lldELF", "lldWasm"]
cxx_lld_libs = ' '.join([f"-l{lib}" for lib in lld_libs])
cmake_lld_libs = ';'.join(lld_libs)


def try_cmake(cmake_dir, build_dir, generator, arch=None, toolkit=None):
old_dir = os.getcwd()
Expand All @@ -32,6 +36,7 @@ def try_cmake(cmake_dir, build_dir, generator, arch=None, toolkit=None):
args.append(cmake_dir)
try:
os.chdir(build_dir)
os.environ['lld_libs'] = cmake_lld_libs
print('Running:', ' '.join(args))
subprocess.check_call(args)
finally:
Expand Down Expand Up @@ -77,7 +82,6 @@ def find_windows_generator():
generators.append(
(env_generator, env_arch, env_toolkit)
)

generators.extend([
# use VS2019 to match how llvmdev is built
('Visual Studio 16 2019', ('x64' if is_64bit else 'Win32'), 'v142'),
Expand All @@ -104,7 +108,6 @@ def main_windows():
config = 'Release'
if not os.path.exists(build_dir):
os.mkdir(build_dir)
# 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)
Expand All @@ -119,6 +122,7 @@ def main_posix_cmake(kind, library_ext):
subprocess.check_call(['cmake', '--build', build_dir, '--config', config])
shutil.copy(os.path.join(build_dir, 'libllvmlite' + library_ext), target_dir)


def main_posix(kind, library_ext):
if os.environ.get("LLVMLITE_USE_CMAKE", "0") == "1":
return main_posix_cmake(kind, library_ext)
Expand Down Expand Up @@ -183,7 +187,8 @@ def main_posix(kind, library_ext):
# Get LLVM information for building
libs = run_llvm_config(llvm_config, "--system-libs --libs all".split())
# Normalize whitespace (trim newlines)
os.environ['LLVM_LIBS'] = ' '.join(libs.split())
os.environ['LLVM_LIBS'] = \
f'{cxx_lld_libs} ' + ' '.join(libs.split())

cxxflags = run_llvm_config(llvm_config, ["--cxxflags"])
# on OSX cxxflags has null bytes at the end of the string, remove them
Expand All @@ -203,6 +208,7 @@ def main_posix(kind, library_ext):

ldflags = run_llvm_config(llvm_config, ["--ldflags"])
os.environ['LLVM_LDFLAGS'] = ldflags.strip()

# static link libstdc++ for portability
if int(os.environ.get('LLVMLITE_CXX_STATIC_LINK', 0)):
os.environ['CXX_STATIC_LINK'] = "-static-libstdc++"
Expand All @@ -216,7 +222,6 @@ def main_posix(kind, library_ext):
subprocess.check_call(['make', '-f', makefile] + makeopts)
shutil.copy('libllvmlite' + library_ext, target_dir)


def main():
if sys.platform == 'win32':
main_windows()
Expand Down
21 changes: 21 additions & 0 deletions ffi/lld.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "core.h"
#include "lld/Common/Driver.h"
#include "llvm/Support/raw_ostream.h"

extern "C" {

API_EXPORT(bool)
LLVMPY_lld_main(int Argc, const char **Argv, const char **outstr) {
// InitLLVM X(Argc, Argv);
std::string command_output;
llvm::raw_string_ostream command_stream(command_output);
std::vector<const char *> Args(Argv, Argv + Argc);

bool linker_output =
!lld::elf::link(Args, command_stream, command_stream, false, false);

*outstr = LLVMPY_CreateString(command_output.c_str());
return linker_output;
}

} // end extern "C"
1 change: 1 addition & 0 deletions llvmlite/binding/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@
from .object_file import *
from .context import *
from .orcjit import *
from .lld import *
84 changes: 84 additions & 0 deletions llvmlite/binding/lld.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
from ctypes import c_bool, POINTER, c_char_p, c_int
import platform
from typing import List

from llvmlite.binding import ffi


ffi.lib.LLVMPY_lld_main.restype = c_bool
ffi.lib.LLVMPY_lld_main.argtypes = [c_int, POINTER(c_char_p), POINTER(c_char_p)]


def lld_main(lld_args) -> str:
"""
Calls LLD - the LLVM linker.

The function calls the `lld::elf::link()` with the `lld_args` (list of
strings) as arguments.

Examples
~~~~~~~~

Shows help:

>>> from llvmlite.binding import lld_main
>>> lld_main(["ld.lld", "--help"])
"""
args = (c_char_p * len(lld_args))()
for i, arg in enumerate(lld_args):
args[i] = arg.encode()
with ffi.OutputString() as outstr:
r = ffi.lib.LLVMPY_lld_main(len(lld_args), args, outstr)
if r:
raise Exception("lld_main() failed, error code: %d\
\nCommand Output: %s" % (r, str(outstr)))
return str(outstr)


def lld_runner(command: str):
def wrapped(output: str, objects: List[str], args: List[str] = []) -> str:
'''
runs the command:
"{platform's lld command} -o {output-file} {*input_files} {*args}"
output: output file as a str
object: a list of input .o files as strings
args: additional arguments for the command
'''
return lld_main([command, '-o', output, *objects, *args])
return wrapped


lld_windows = lld_runner("lld-link")
lld_macos = lld_runner("ld64.lld")
lld_linux = lld_runner("ld.lld")
lld_wasm = lld_runner("wasm-ld")


def lld_auto(output: str, objects: List[str],
args: List[str] = [],
add_extension=True) -> str:
'''
Automatically determines which lld function
to run based on the hosts system.

Does not use `lld_wasm()`

add_extension: adds `.exe` and other file endings automatically
'''
system = platform.system()

if system == "Linux":
# has no standard file extension
return lld_linux(output, objects, args)
elif system == "Windows":
name = output + ('.exe' * add_extension)
return lld_windows(name, objects, args)
elif system == "Darwin": # Macos
name = output + ('.app' * add_extension)
return lld_macos(name, objects, args)
else:
msg = (f'''Invalid host system name: {system}
If you are sure a driver exists for this system,
please use the `lld_main()` function
'''.strip())
raise RuntimeError(msg)
Loading
Loading