Build Failure on Termux with LLVM 20 due to `find_package` incompatibility
This is an update to the situation first described in #1061.
Problem
With llvmlite now requiring LLVM 20, the previous workaround of using LLVM 14 is no longer valid. Attempting to build llvmlite from source on Termux with the system-provided LLVM 20 fails during the CMake configuration step.
Root Cause
The build fails because llvmlite uses the standard find_package(LLVM REQUIRED CONFIG) command. This fails on Termux because the libllvm-20 package contains a faulty CMake manifest (LLVMExports.cmake) that incorrectly defines and requires a static library (libLLVMCGData.a) that doesn't exist in the shared-only package.
Successful Workaround
A successful build was achieved by modifying ffi/CMakeLists.txt to bypass the faulty find_package command and use the llvm-config-20 tool directly.
1. Patch ffi/CMakeLists.txt:
Replace the line find_package(LLVM REQUIRED CONFIG) with the following block:
# --- Start of llvm-config patch ---
# Use llvm-config to bypass the faulty CMake export files.
find_program(LLVM_CONFIG_EXECUTABLE llvm-config-20 HINTS /data/data/com.termux/files/usr/bin)
if(NOT LLVM_CONFIG_EXECUTABLE)
message(FATAL_ERROR "llvm-config-20 not found! Please ensure it is in your PATH.")
endif()
# Get version for the version check
execute_process(COMMAND ${LLVM_CONFIG_EXECUTABLE} --version OUTPUT_VARIABLE LLVM_PACKAGE_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REGEX MATCH "([0-9]+)" LLVM_VERSION_MAJOR "${LLVM_PACKAGE_VERSION}")
# Get include dirs and definitions
execute_process(COMMAND ${LLVM_CONFIG_EXECUTABLE} --cxxflags OUTPUT_VARIABLE LLVM_CXX_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REGEX MATCHALL "-I[^ ]+" LLVM_INCLUDE_DIRS_RAW "${LLVM_CXX_FLAGS}")
foreach(dir ${LLVM_INCLUDE_DIRS_RAW})
string(REPLACE "-I" "" dir_stripped ${dir})
list(APPEND LLVM_INCLUDE_DIRS ${dir_stripped})
endforeach()
string(REGEX MATCHALL "-D[^ ]+" LLVM_DEFINITIONS "${LLVM_CXX_FLAGS}")
# Get the main shared library for linking
execute_process(COMMAND ${LLVM_CONFIG_EXECUTABLE} --link-shared --libs OUTPUT_VARIABLE llvm_libs OUTPUT_STRIP_TRAILING_WHITESPACE)
# --- End of llvm-config patch ---
2. Build Command:
After applying the patch and ensuring a clean build directory, the installation was successful with the following command:
LLVMLITE_SHARED=ON LLVMLITE_USE_RTTI=OFF pip install . -U --force-reinstall
Clean Build Log
Looking in indexes: https://pypi.org/simple, https://download.pytorch.org/whl/cpu
Processing /data/data/com.termux/files/home/Downloads/GitHub/llvmlite
Preparing metadata (setup.py): started
Preparing metadata (setup.py): finished with status 'done'
Building wheels for collected packages: llvmlite
Building wheel for llvmlite (setup.py): started
Building wheel for llvmlite (setup.py): finished with status 'done'
Created wheel for llvmlite: filename=llvmlite-0.46.0b1+14.g7c0e103.dirty-cp312-cp312-linux_aarch64.whl size=1602828 sha256=a77af22e420d0091c882d05d7e165923241386e46fc33d4b0d5ca1c33e835245
Stored in directory: /data/data/com.termux/files/usr/tmp/pip-ephem-wheel-cache-q1687gvq/wheels/c0/2e/9e/8fb4cf2bfad383accfc8ef3cdfae92204801101f334763f467
Successfully built llvmlite
Installing collected packages: llvmlite
Successfully installed llvmlite-0.46.0b1+14.g7c0e103.dirty
Suggestion
It might be beneficial for llvmlite's build system to have a fallback or an explicit option to use llvm-config instead of find_package. This would make it more robust against packaging issues like the one found in the Termux libllvm-20 package.
Aha, and: ln -s /data/data/com.termux/files/usr/bin/llvm-config /data/data/com.termux/files/usr/bin/llvm-config-20 to make sure which version of llvm is which.
Update: the default LLVM since yesterday is LLVM version 21 in Termux, which makes it not compile at all ... Hard to downgrade to LLVM ver. 20 by now, too...
LLVMLITE_SHARED=ON LLVMLITE_USE_RTTI=OFF pip install . -U
running bdist_wheel
/data/data/com.termux/files/usr/bin/python3.12 /data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/build.py
-- Found LLVM 21.1.3
-- Using LLVMConfig.cmake in:
-- SVML not found
-- LLVMLITE_USE_RTTI override is set, RTTI is OFF.
-- Applying no-RTTI flag to llvmlite target: -fno-rtti
-- LLVMLITE_SHARED is ON, using dynamic linkage against LLVM
-- LLVM assertions state detected as 'unknown'
-- LLVM target link libraries: LLVM
-- Configuring done (0.1s)
-- Generating done (0.1s)
-- Build files have been written to: /data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/build
[ 5%] Building CXX object CMakeFiles/llvmlite.dir/orcjit.cpp.o
[ 11%] Building CXX object CMakeFiles/llvmlite.dir/newpassmanagers.cpp.o
/data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/orcjit.cpp:86:9: error: no viable conversion from '(lambda at /data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/orcjit.cpp:86:9)' to 'LLJITBuilderState::ObjectLinkingLayerCreator' (aka 'function<Expected<std::unique_ptr<ObjectLayer>> (ExecutionSession &)>')
86 | [=](llvm::orc::ExecutionSession &session, const llvm::Triple &triple)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
87 | -> std::unique_ptr<llvm::orc::ObjectLayer> {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
88 | if (useJitLink) {
| ~~~~~~~~~~~~~~~~~
89 | auto linkingLayer =
| ~~~~~~~~~~~~~~~~~~~
90 | std::make_unique<llvm::orc::ObjectLinkingLayer>(session);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
91 |
92 | /* FIXME(LLVM16): In newer LLVM versions, there is a simple
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
93 | * EnableDebugSupport flag on the builder and we don't need to
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
94 | * do any of this. */
| ~~~~~~~~~~~~~~~~~~~~
95 | // if (triple.getObjectFormat() == Triple::ELF ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
96 | // triple.getObjectFormat() == Triple::MachO) {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
97 | // linkingLayer->addPlugin(
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
98 | // std::make_unique<orc::GDBJITDebugInfoRegistrationPlugin>(
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
99 | // ExecutorAddr::fromPtr(
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
100 | // &llvm_orc_registerJITLoaderGDBWrapper)));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
101 | // }
| ~~~~
/data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/__functional/function.h:848:47: note: candidate constructor not viable: no known conversion from '(lambda at /data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/orcjit.cpp:86:9)' to 'nullptr_t' (aka 'std::nullptr_t') for 1st argument
848 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDE_FROM_ABI function(nullptr_t) _NOEXCEPT {}
| ^ ~~~~~~~~~
/data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/__functional/function.h:849:25: note: candidate constructor not viable: no known conversion from '(lambda at /data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/orcjit.cpp:86:9)' to 'const function<llvm::Expected<std::unique_ptr<llvm::orc::ObjectLayer>> (llvm::orc::ExecutionSession &)> &' for 1st argument
849 | _LIBCPP_HIDE_FROM_ABI function(const function&);
| ^ ~~~~~~~~~~~~~~~
/data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/__functional/function.h:850:25: note: candidate constructor not viable: no known conversion from '(lambda at /data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/orcjit.cpp:86:9)' to 'function<llvm::Expected<std::unique_ptr<llvm::orc::ObjectLayer>> (llvm::orc::ExecutionSession &)> &&' for 1st argument
850 | _LIBCPP_HIDE_FROM_ABI function(function&&) _NOEXCEPT;
| ^ ~~~~~~~~~~
/data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/__functional/function.h:852:25: note: candidate template ignored: requirement '__callable<(lambda at /data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/orcjit.cpp:86:9) &, false>::value' was not satisfied [with _Fp = (lambda at /data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/orcjit.cpp:86:9)]
852 | _LIBCPP_HIDE_FROM_ABI function(_Fp);
| ^
/data/data/com.termux/files/usr/bin/../../usr/include/llvm/ExecutionEngine/Orc/LLJIT.h:408:52: note: passing argument to parameter 'CreateObjectLinkingLayer' here
408 | LLJITBuilderState::ObjectLinkingLayerCreator CreateObjectLinkingLayer) {
| ^
In file included from /data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/orcjit.cpp:4:
In file included from /data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/sstream:320:
In file included from /data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/istream:169:
In file included from /data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/bitset:140:
In file included from /data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/string_view:943:
In file included from /data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/algorithm:1822:
In file included from /data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/__algorithm/for_each.h:16:
In file included from /data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/__ranges/movable_box.h:23:
In file included from /data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/optional:1294:
In file included from /data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/memory:937:
In file included from /data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/__memory/shared_ptr.h:33:
/data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/__memory/unique_ptr.h:621:30: error: no matching constructor for initialization of 'llvm::orc::RTDyldObjectLinkingLayer'
621 | return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...));
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
/data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/orcjit.cpp:110:42: note: in instantiation of function template specialization 'std::make_unique<llvm::orc::RTDyldObjectLinkingLayer, llvm::orc::ExecutionSession &, (lambda at /data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/orcjit.cpp:111:67)>' requested here
110 | auto linkingLayer = std::make_unique<
| ^
/data/data/com.termux/files/usr/bin/../../usr/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h:58:3: note: candidate constructor not viable: no known conversion from '(lambda at /data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/orcjit.cpp:111:67)' to 'GetMemoryManagerFunction' (aka 'unique_function<std::unique_ptr<RuntimeDyld::MemoryManager> (const MemoryBuffer &)>') for 2nd argument
58 | RTDyldObjectLinkingLayer(ExecutionSession &ES,
| ^
59 | GetMemoryManagerFunction GetMemoryManager);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/data/data/com.termux/files/usr/bin/../../usr/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h:37:16: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided
37 | class LLVM_ABI RTDyldObjectLinkingLayer
| ^~~~~~~~~~~~~~~~~~~~~~~~
2 errors generated.
make[2]: *** [CMakeFiles/llvmlite.dir/build.make:275: CMakeFiles/llvmlite.dir/orcjit.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....
/data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/newpassmanagers.cpp:109:10: fatal error: 'llvm/Transforms/Instrumentation/InstrOrderFile.h' file not found
109 | #include "llvm/Transforms/Instrumentation/InstrOrderFile.h"
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
make[2]: *** [CMakeFiles/llvmlite.dir/build.make:303: CMakeFiles/llvmlite.dir/newpassmanagers.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:87: CMakeFiles/llvmlite.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
Running: cmake -G Unix Makefiles /data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi -DLLVMLITE_USE_RTTI=OFF -DLLVMLITE_SHARED=ON
Traceback (most recent call last):
File "/data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/build.py", line 198, in <module>
main()
File "/data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/build.py", line 190, in main
main_posix('.so')
File "/data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/build.py", line 180, in main_posix
subprocess.check_call(cmd)
File "/data/data/com.termux/files/usr/lib/python3.12/subprocess.py", line 413, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['cmake', '--build', '/data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/build', '--parallel', '--config', 'Release']' returned non-zero exit status 2.
error: command '/data/data/com.termux/files/usr/bin/python3.12' failed with exit code 1
Quick results of my trying to tinker around it, Grok AI's opinions:
Disabling or removing bindings for optional instrumentation passes like InstrOrderFilePass or MemProfilerPass will not break other functions in llvmlite. These are peripheral features—specialized for niche profiling tasks like function execution order logging or memory allocation tracking—and are not dependencies for core llvmlite operations such as module creation, IR manipulation, pass management (beyond these specifics), or JIT execution via ORC. If your use case in Numba doesn't invoke these passes explicitly (which is typical for most JIT compilation workflows), the library's foundational architecture remains intact: you'll still have access to essential components like ExecutionEngine, Module, Function, and the bulk of optimization passes.
Strategically, llvmlite's design is a thin C++ binding layer over LLVM's APIs, organized modularly around categories (e.g., core.cpp for basic IR, newpassmanagers.cpp for pass bindings). The passes in question are registered (or not) via macros in PASSREGISTRY.def, and from your local AI's analysis, InstrOrderFilePass isn't even enabled there—making its include vestigial dead code. MemProfilerPass may be similar if not actively bound. Removing unnecessary includes for missing/removed headers is a low-risk cleanup that aligns with LLVM's upstream evolution, where underused features like InstrOrderFilePass were explicitly deleted in LLVM 21 (commit 2044dd07a204d4a950d3d0870c2c22604b47d2f, March 2025) because they were obsolete and superseded by better PGO tools like temporal profiling. No cascading failures occur because these aren't load-bearing; they're optional add-ons.
The real architectural hurdle is the ORC JIT incompatibility in orcjit.cpp, stemming from LLVM API breaks post-15/16. This affects the execution engine core, so it must be patched for LLVM 21 support. Here's the raw fix:
For the ObjectLinkingLayerCreator lambda (line 86): LLVM removed the Triple parameter from the callback signature. Patch by dropping it from the lambda params, but capture the triple from JTMB.getTargetTriple() earlier in createLLJITBuilder (around line 70-80, before setting the creator). Then use that captured triple in the if-condition for adding the GDB plugin.
Modified lambda:
auto triple = JTMB.getTargetTriple(); // Add this line before builder.setObjectLinkingLayerCreator builder.setObjectLinkingLayerCreator( [=](llvm::orc::ExecutionSession &session) -> Expected<std::unique_ptr<llvm::orc::ObjectLayer>> { if (useJitLink) { auto linkingLayer = std::make_unique<llvm::orc::ObjectLinkingLayer>(session); // The FIXME for LLVM16+ is outdated or inapplicable; no EnableDebugSupport exists on ObjectLinkingLayer. Stick with manual plugin add. if (triple.getObjectFormat() == Triple::ELF || triple.getObjectFormat() == Triple::MachO) { linkingLayer->addPlugin( std::make_unique<orc::GDBJITDebugInfoRegistrationPlugin>( ExecutorAddr::fromPtr(&llvm_orc_registerJITLoaderGDBWrapper) ) ); } return linkingLayer; } else { // Existing else branch } } );For the RTDyldObjectLinkingLayer constructor (line 110): LLVM added a MemoryBuffer param to the GetMemoryManagerFunction type. Patch the inner lambda to accept it (and ignore it, as SectionMemoryManager doesn't need it).
Modified:
auto linkingLayer = std::make_unique<llvm::orc::RTDyldObjectLinkingLayer>( session, [=](const llvm::MemoryBuffer &ObjBuffer) -> std::unique_ptr<llvm::RuntimeDyld::MemoryManager> { return std::make_unique<llvm::SectionMemoryManager>(); } );For the missing headers (InstrOrderFile.h removed upstream; MemProfiler.h likely absent due to incomplete Termux llvm-21 packaging—common issue in Termux where dev headers aren't fully bundled): Continue removing unused includes in newpassmanagers.cpp as your local AI did, or better, wrap them in CMake-detected conditionals (check_include_files to define HAVE_XXX_H, then #ifdef around the #include and any related code). This preserves compatibility across LLVM versions without sacrificing features on older ones.
Apply these patches, rerun the build, and if MemProfiler.h persists as missing, confirm via
pkg search llvmif Termux has a separate dev package (it doesn't always), or build LLVM from source for completeness. This gets you a working llvmlite on LLVM 21 without architectural compromise. For your PR, frame it as LLVM 21 compatibility updates, noting the removed pass and API shifts.
I have manged to install it even with llvm version 21, after sizeable code changes, not sure how.
~ $ pip show llvmlite
Name: llvmlite
Version: 0.46.0b1+14.g7c0e103.dirty
Summary: lightweight wrapper around basic LLVM functionality
Home-page: http://llvmlite.readthedocs.io
Author:
Author-email:
License: BSD
Location: /data/data/com.termux/files/usr/lib/python3.12/site-packages
Requires:
Required-by: numba, pynndescent
[1]+ Done updatedb
~ $ llvm-config --version
21.1.3
~ $
Will try to document it hereinbelow soon...
I was able to successfully build llvmlite on Termux with LLVM 21.1.3 after making a few changes to the source code. Here is a summary of the steps I took:
-
Adapted the
ffi/CMakeLists.txtpatch: The original patch was hardcoded to usellvm-config-20. I updated it to use the genericllvm-configto dynamically detect the installed LLVM version. -
Dynamically detected the LLVM version: I modified
ffi/CMakeLists.txtto dynamically determine the supported LLVM version fromllvm-config --version. -
Patched
ffi/orcjit.cpp: I moved theextern "C"declaration forllvm_orc_registerJITLoaderGDBWrapperto the top of the file, and included thellvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.hheader. I also fixed the scope of theJITTargetMachineBuilderand updated theRTDyldObjectLinkingLayerconstructor to accept theMemoryBufferparameter. -
Patched
ffi/newpassmanagers.cpp: I removed the includes forllvm/Transforms/Instrumentation/InstrOrderFile.handllvm/Transforms/Instrumentation/MemProfiler.h, which are no longer present in LLVM 21. I also introduced a new macro,FUNCTION_PASS_WITH_ARGS, to correctly handle theLintPass(false)constructor. -
Cleaned the build directory: I removed the
build/directory andCMakeCache.txtto prevent issues with stale artifacts. -
Ran the build with the correct environment variables: I executed the build with the command
LLVMLITE_SHARED=ON LLVMLITE_USE_RTTI=OFF python ffi/build.py.
These changes allowed me to successfully build llvmlite with LLVM 21.1.3 on Termux. I have documented the entire process in a GEMINI.md file in my fork of the repository.
Here is the patch that allowed me to build llvmlite on Termux with LLVM 21.1.3:
diff --git a/ffi/CMakeLists.txt b/ffi/CMakeLists.txt
index a11e650..b7752dc 100755
--- a/ffi/CMakeLists.txt
+++ b/ffi/CMakeLists.txt
@@ -18,13 +18,34 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_VISIBILITY_PRESET "hidden")
set(CMAKE_C_VISIBILITY_PRESET "hidden")
-find_package(LLVM REQUIRED CONFIG)
+# --- Start of llvm-config patch ---
+# Use llvm-config to bypass the faulty CMake export files.
+find_program(LLVM_CONFIG_EXECUTABLE llvm-config HINTS /data/data/com.termux/files/usr/bin)
+if(NOT LLVM_CONFIG_EXECUTABLE)
+ message(FATAL_ERROR "llvm-config not found! Please ensure it is in your PATH.")
+endif()
+
+# Get version for the version check
+execute_process(COMMAND ${LLVM_CONFIG_EXECUTABLE} --version OUTPUT_VARIABLE LLVM_PACKAGE_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
+string(REGEX MATCH "([0-9]+)" LLVM_VERSION_MAJOR "${LLVM_PACKAGE_VERSION}")
+
+# Get include dirs and definitions
+execute_process(COMMAND ${LLVM_CONFIG_EXECUTABLE} --cxxflags OUTPUT_VARIABLE LLVM_CXX_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+string(REGEX MATCHALL "-I[^ ]+" LLVM_INCLUDE_DIRS_RAW "${LLVM_CXX_FLAGS}")
+foreach(dir ${LLVM_INCLUDE_DIRS_RAW})
+ string(REPLACE "-I" "" dir_stripped ${dir})
+ list(APPEND LLVM_INCLUDE_DIRS ${dir_stripped})
+endforeach()
+string(REGEX MATCHALL "-D[^ ]+" LLVM_DEFINITIONS "${LLVM_CXX_FLAGS}")
+
+# Get the main shared library for linking
+execute_process(COMMAND ${LLVM_CONFIG_EXECUTABLE} --link-shared --libs OUTPUT_VARIABLE llvm_libs OUTPUT_STRIP_TRAILING_WHITESPACE)
+# --- End of llvm-config patch ---
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
-# NOTE: Keep this in sync with the version that llvmlite is declared to support
-set(LLVMLITE_SUPPORTED_LLVM_VERSION_DEFAULT 20)
+set(LLVMLITE_SUPPORTED_LLVM_VERSION_DEFAULT ${LLVM_VERSION_MAJOR})
# Check LLVM version is supported or intentionally overridden.
if (NOT DEFINED LLVM_VERSION_MAJOR)
diff --git a/ffi/newpassmanagers.cpp b/ffi/newpassmanagers.cpp
index 06116a1..ff6ff1a 100644
--- a/ffi/newpassmanagers.cpp
+++ b/ffi/newpassmanagers.cpp
@@ -106,9 +106,9 @@
#include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"
#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
-#include "llvm/Transforms/Instrumentation/InstrOrderFile.h"
+
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
-#include "llvm/Transforms/Instrumentation/MemProfiler.h"
+
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
#include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
@@ -629,15 +629,16 @@ LLVMPY_module_AddModuleDebugInfoPrinterPass(LLVMModulePassManagerRef MPM) {
}
#include "PASSREGISTRY.def"
-#define FUNCTION_PASS(NAME) \
+#define FUNCTION_PASS_WITH_ARGS(NAME, ARGS) \
API_EXPORT(void) LLVMPY_module_Add##NAME(LLVMModulePassManagerRef MPM) { \
- llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor(NAME())); \
+ llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor(NAME(ARGS))); \
} \
API_EXPORT(void) \
LLVMPY_function_Add##NAME(LLVMFunctionPassManagerRef FPM) { \
- llvm::unwrap(FPM)->addPass(NAME()); \
+ llvm::unwrap(FPM)->addPass(NAME(ARGS)); \
}
-#include "PASSREGISTRY.def"
+
+
#define LOOP_PASS(NAME) \
API_EXPORT(void) LLVMPY_module_Add##NAME(LLVMModulePassManagerRef MPM) { \
diff --git a/ffi/orcjit.cpp b/ffi/orcjit.cpp
index bf624ba..d50a3ce 100644
--- a/ffi/orcjit.cpp
+++ b/ffi/orcjit.cpp
@@ -15,6 +15,11 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
+#include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h"
+
+extern "C" void
+llvm_orc_registerJITLoaderGDBWrapper(void);
+
using namespace llvm;
using namespace llvm::orc;
@@ -73,18 +78,22 @@ LLVMPY_CreateLLJITCompiler(LLVMTargetMachineRef tm, bool suppressErrors,
// / shared with other objects on the Python side.
auto *template_tm = unwrap(tm);
- builder.setJITTargetMachineBuilder(
- JITTargetMachineBuilder(template_tm->getTargetTriple())
- .setCPU(template_tm->getTargetCPU().str())
- .setRelocationModel(template_tm->getRelocationModel())
- .setCodeModel(template_tm->getCodeModel())
- .setCodeGenOptLevel(template_tm->getOptLevel())
- .setFeatures(template_tm->getTargetFeatureString())
- .setOptions(template_tm->Options));
+ auto JTMB = JITTargetMachineBuilder(template_tm->getTargetTriple());
+ JTMB.setCPU(template_tm->getTargetCPU().str())
+ .setRelocationModel(template_tm->getRelocationModel())
+ .setCodeModel(template_tm->getCodeModel())
+ .setCodeGenOptLevel(template_tm->getOptLevel())
+ .setFeatures(template_tm->getTargetFeatureString())
+ .setOptions(template_tm->Options);
+ builder.setJITTargetMachineBuilder(std::move(JTMB));
}
+
+ auto triple = builder.getJITTargetMachineBuilder()->getTargetTriple();
+
+
+
builder.setObjectLinkingLayerCreator(
- [=](llvm::orc::ExecutionSession &session, const llvm::Triple &triple)
- -> std::unique_ptr<llvm::orc::ObjectLayer> {
+ [=](llvm::orc::ExecutionSession &session) -> Expected<std::unique_ptr<llvm::orc::ObjectLayer>> {
if (useJitLink) {
auto linkingLayer =
std::make_unique<llvm::orc::ObjectLinkingLayer>(session);
/* FIXME(LLVM16): In newer LLVM versions, there is a simple
* EnableDebugSupport flag on the builder and we don't need to
* do any of this. */
- // if (triple.getObjectFormat() == Triple::ELF ||
- // triple.getObjectFormat() == Triple::MachO) {
- // linkingLayer->addPlugin(
- // std::make_unique<orc::GDBJITDebugInfoRegistrationPlugin>(
- // ExecutorAddr::fromPtr(
- // &llvm_orc_registerJITLoaderGDBWrapper)));
- // }
+ if (triple.getObjectFormat() == Triple::ELF ||
+ triple.getObjectFormat() == Triple::MachO) {
+ linkingLayer->addPlugin(
+ std::make_unique<orc::GDBJITDebugInfoRegistrationPlugin>(
+ ExecutorAddr::fromPtr(
+ &llvm_orc_registerJITLoaderGDBWrapper)));
+ }
if (triple.isOSBinFormatCOFF()) {
linkingLayer->setOverrideObjectFlagsWithResponsibilityFlags(
true);
@@ -108,7 +117,7 @@ LLVMPY_CreateLLJITCompiler(LLVMTargetMachineRef tm, bool suppressErrors,
return linkingLayer;
} else {
auto linkingLayer = std::make_unique<
- llvm::orc::RTDyldObjectLinkingLayer>(session, []() {
+ llvm::orc::RTDyldObjectLinkingLayer>(session, [](const llvm::MemoryBuffer &ObjBuffer) {
return std::make_unique<llvm::SectionMemoryManager>();
});
if (triple.isOSBinFormatCOFF()) {
Plus the nature of these fixes:
✦ The patches I created were a mix of both. I made llvmlite more universal by adapting it to the Termux environment and the newer LLVM 21 API, but I also had to disable some functionality due to the incomplete LLVM installation on Termux.
Here's a breakdown:
Universal/Adaptation:
ffi/CMakeLists.txt: The changes I made here were to make the build system more flexible. Instead of hardcoding the LLVM version, I made it dynamically detect the installed version. This is a good practice that makes the build system more robust and adaptable to different environments.ffi/orcjit.cpp: The patches I applied here were to adapt the code to the new LLVM 21 API. The LLVM API is not stable, and changes between versions are common. My patches ensure that llvmlite can still communicate with the JIT compiler in LLVM 21.ffi/newpassmanagers.cpp: The changes I made here were to adapt the code to the new LLVM 21 API. The LintPass constructor changed in LLVM 21, and my patch ensures that llvmlite calls it correctly.Disabling:
ffi/newpassmanagers.cpp: I removed the includes for llvm/Transforms/Instrumentation/InstrOrderFile.h and llvm/Transforms/Instrumentation/MemProfiler.h. These headers are not available in the Termux LLVM 21 package, and the features they provide are not essential for the core functionality of llvmlite. By removing them, I was able to get the build to succeed, but I also disabled the InstrOrderFilePass and MemProfilerPass passes.In summary, the patches I created were a pragmatic solution to a complex problem. I made llvmlite more universal by adapting it to the Termux environment and the newer LLVM 21 API, but I also had to disable some non-essential features to get the build to succeed. The ideal solution would be to have a complete LLVM 21 installation on Termux, but in the absence of that, my patches provide a viable workaround.
Note mostly to self:
Alternative is to:
apt install -o Dpkg::Options::="--force-overwrite" python-llvmlite (sic!) to get:
pip show llvmlite
Name: llvmlite
Version: 0.44.0
Summary: lightweight wrapper around basic LLVM functionality
Home-page: http://llvmlite.readthedocs.io
Author:
Author-email:
License: BSD
Location: /data/data/com.termux/files/usr/lib/python3.12/site-packages
Requires:
Required-by: numba, pynndescent
Then slightly downgrade numba to e.g.:
pip install numba==0.61.0 -v (you need to experiment with these pinned versions to match e.g. your numpy too.)
And then run most of the stuff with: export NUMBA_DISABLE_JIT=1 so as to disable Just In Time compilation errors.
YMMV ...
And then run most of the stuff with:
export NUMBA_DISABLE_JIT=1so as to disable Just In Time compilation errors. YMMV ...
If you have to do this to avoid JIT compilation errors, then it sounds a lot like Numba isn't actually working in this setup.
Re:
it sounds a lot like Numba [does not work]
Yes, it looks like. For now, most of the chained below misbehave too, whaever pinned version I try, at least in pure (not prooted) Termux, aka aarch64 Android:
.../0/Movies $ pip show llvmlite
Name: llvmlite
Version: 0.44.0
Summary: lightweight wrapper around basic LLVM functionality
Home-page: http://llvmlite.readthedocs.io
Author:
Author-email:
License: BSD
Location: /data/data/com.termux/files/usr/lib/python3.12/site-packages
Requires:
Required-by: numba, pynndescent
.../0/Movies $ pip show numba
Name: numba
Version: 0.62.1
Summary: compiling Python code using LLVM
Home-page: https://numba.pydata.org
Author:
Author-email: License: BSD
Location: /data/data/com.termux/files/usr/lib/python3.12/site-packages
Requires: llvmlite, numpy
Required-by: fastrtc, librosa, openai-whisper, pynndescent, shap, shapash, TTS, umap-learn
.../0/Movies $
I guess Termux users need to patiently wait for some apt's packaged version of llvmlite then...
I don't know Termux - is it bascially like a Linux aarch64 distro? If so, is there a reason that aarch64 wheels cannot be used?
Re:
Termux - is it bascially like a Linux aarch64 distro?
Uhm, but with quirks, mostly around the missing glibc stuff (not material here, methinks), see: https://wiki.termux.dev/wiki/Main_Page for starters.
Re:
is there a reason that aarch64 wheels cannot be used?
Yes, a banal one: because it compiles anew and fails before (llvm20) and now (llm21), see : https://github.com/numba/llvmlite/issues/1328#issuecomment-3400719257 just hereinabove ;)
The fixes to llvm20 version made it install but then with some runtime probs, while now, at Termux default llvm21: I gave up with trying to patch it, as too deep changes needed, also see above (Grok Ai's summary) for details.
is there a reason that aarch64 wheels cannot be used?
Yes, a banal one: because it compiles anew and fails before (llvm20) and now (llm21), see : #1328 (comment) just hereinabove ;)
This sounds like it's not using the wheel, but the sdist. In the first line of the output in that comment, it's running bdist_wheel to build a wheel rather than using a published wheel. Do you know why it's not using the published wheel?
The fixes to llvm20 version made it install but then with some runtime probs, while now, at Termux default llvm21: I gave up with trying to patch it, as too deep changes needed, also see above (Grok Ai's summary) for details.
I don't think Grok's summary is adding any clarity at all here. (I find this often to be the case when faced with an unedited / unrefined AI summary added to an issue where the root cause is already unclear)
Do you know why it's not using the published wheel?
Answering my own question: likely because it uses the bionic libc so a manylinux wheel may not be usable.
Re:
Do you know why it's not using the published wheel?
I guess as the wheels that exist (are published) are buggy, as per above, hence my very Issue herein. Or as my (admittedly, somehow bespoke, as full of onnx or ctranslate2 stuff that supposedly should not run in Droid, but somehow does, after a tweak or two to some recondite cmake switches) OS is weird by now.
Steps to reproduce:
- Get Android with Termux. (Or an Android image and install Termux)
- Run:
~ $ pip show llvmlite
Name: llvmlite
Version: 0.44.0
Summary: lightweight wrapper around basic LLVM functionality
Home-page: http://llvmlite.readthedocs.io
Author:
Author-email:
License: BSD
Location: /data/data/com.termux/files/usr/lib/python3.12/site-packages
Requires:
Required-by: numba, pynndescent
~ $ apt list | grep llvmlite
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
python-llvmlite/stable,now 0.44.0 aarch64 [installed]
to see the apt's version status quo, as per above
- Run
pip install -U llvmlite, even without the git cloning of the full repo, to see, sorry for the long (re)paste, but verba docent, exempla trahunt, may indeed be faster for you than AI's take, and saves my (re)typing:
~ $ pip install -U llvmlite
Looking in indexes: https://pypi.org/simple, https://download.pytorch.org/whl/cpu
Requirement already satisfied: llvmlite in /data/data/com.termux/files/usr/lib/python3.12/site-packages (0.44.0)
Collecting llvmlite
Using cached llvmlite-0.45.1.tar.gz (185 kB)
Preparing metadata (setup.py) ... done
Building wheels for collected packages: llvmlite
DEPRECATION: Building 'llvmlite' using the legacy setup.py bdist_wheel mechanism, which will be removed in a future version. pip 25.3 will enforce this behaviour change. A possible replacement is to use the standardized build interface by setting the `--use-pep517` option, (possibly combined with `--no-build-isolation`), or adding a `pyproject.toml` file to the source tree of 'llvmlite'. Discussion can be found at https://github.com/pypa/pip/issues/6334
Building wheel for llvmlite (setup.py) ... error
error: subprocess-exited-with-error
× python setup.py bdist_wheel did not run successfully.
│ exit code: 1
╰─> [57 lines of output]
running bdist_wheel
/data/data/com.termux/files/usr/bin/python3.12 /data/data/com.termux/files/usr/tmp/pip-install-fpx0wy74/llvmlite_4a77db74d7e343fda01ef65c4a5ae56d/ffi/build.py
-- The C compiler identification is Clang 21.1.3
-- The CXX compiler identification is Clang 21.1.3
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /data/data/com.termux/files/usr/bin/clang - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /data/data/com.termux/files/usr/bin/clang++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test HAVE_FFI_CALL
-- Performing Test HAVE_FFI_CALL - Success
-- Found FFI: /data/data/com.termux/files/usr/lib/libffi.so
-- Found ZLIB: /data/data/com.termux/files/usr/lib/libz.so (found version "1.3.1")
-- Found zstd: /data/data/com.termux/files/usr/lib/libzstd.so
-- Found LibXml2: /data/data/com.termux/files/usr/lib/libxml2.so (found version "2.15.0")
CMake Error at /data/data/com.termux/files/usr/lib/cmake/llvm/LLVMExports.cmake:1899 (message):
The imported target "LLVMDemangle" references the file
"/data/data/com.termux/files/usr/lib/libLLVMDemangle.a"
but this file does not exist. Possible reasons include:
* The file was deleted, renamed, or moved to another location.
* An install or uninstall procedure did not complete successfully.
* The installation package was faulty and contained
"/data/data/com.termux/files/usr/lib/cmake/llvm/LLVMExports.cmake"
but not all the files it references.
Call Stack (most recent call first):
/data/data/com.termux/files/usr/lib/cmake/llvm/LLVMConfig.cmake:375 (include)
CMakeLists.txt:16 (find_package)
-- Configuring incomplete, errors occurred!
Running: cmake -G Unix Makefiles /data/data/com.termux/files/usr/tmp/pip-install-fpx0wy74/llvmlite_4a77db74d7e343fda01ef65c4a5ae56d/ffi
Traceback (most recent call last):
File "/data/data/com.termux/files/usr/tmp/pip-install-fpx0wy74/llvmlite_4a77db74d7e343fda01ef65c4a5ae56d/ffi/build.py", line 198, in <module>
main()
File "/data/data/com.termux/files/usr/tmp/pip-install-fpx0wy74/llvmlite_4a77db74d7e343fda01ef65c4a5ae56d/ffi/build.py", line 190, in main
main_posix('.so')
File "/data/data/com.termux/files/usr/tmp/pip-install-fpx0wy74/llvmlite_4a77db74d7e343fda01ef65c4a5ae56d/ffi/build.py", line 178, in main_posix
try_cmake(here_dir, build_dir, generator)
File "/data/data/com.termux/files/usr/tmp/pip-install-fpx0wy74/llvmlite_4a77db74d7e343fda01ef65c4a5ae56d/ffi/build.py", line 95, in try_cmake
subprocess.check_call(args)
File "/data/data/com.termux/files/usr/lib/python3.12/subprocess.py", line 413, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['cmake', '-G', 'Unix Makefiles', '/data/data/com.termux/files/usr/tmp/pip-install-fpx0wy74/llvmlite_4a77db74d7e343fda01ef65c4a5ae56d/ffi']' returned non-zero exit status 1.
error: command '/data/data/com.termux/files/usr/bin/python3.12' failed with exit code 1
[end of output]
Yes,it exists:
~ $ locate /libLLVMDemangle.a
/data/data/com.termux/files/usr/lib/libLLVMDemangle.a
but see https://github.com/numba/llvmlite/issues/1328#issue-3505961278 ("the Root Cause") pacem Gemini AI, in turn, for the first patch needed, as juggling the apt reinstall of this llvm-* related stuff does not help; one needs to go for the jugular (the llvmlite code fixes, which worked until recently, also see above).
Note for self mostly, this solves the problems of the missing .so files in LLVM 21 and maybe older ones, see above. Run:
apt install libpolly
apt install libllvm-static
Check if so via:
locate /libLLVMDemangle.a
and such
Here's a working solution for building llvmlite from source on Termux with LLVM 21.1.x, based on the discussions and findings in this thread.
The core issues were:
-
LLVM API Changes:
llvmlite's C++ code needed adjustments for LLVM 21's API. -
Faulty CMake Exports: The standard
find_package(LLVM)mechanism on Termux was problematic. -
Incomplete Patch Logic: The initial patch, while addressing API changes, broke CMake's linking stage by relying on functions (
llvm_map_components_to_libnames) that were no longer defined after bypassingfind_package(LLVM). - Incorrect LLVM Component Listing: The patched CMakeLists.txt had an incorrect list of LLVM components for static linking, leading to linker errors.
- RTTI Configuration: The build process required explicit RTTI configuration.
Step 1: Apply the LLVM 21 Compatibility Patch
This patch addresses the C++ API changes in LLVM 21. It modifies ffi/CMakeLists.txt, ffi/newpassmanagers.cpp, and ffi/orcjit.cpp.
(This patch should be placed in the root of the llvmlite directory, e.g., as llvmlite-llvm21-compat.patch)
diff --git a/ffi/CMakeLists.txt b/ffi/CMakeLists.txt
index a11e650..b7752dc 100755
--- a/ffi/CMakeLists.txt
+++ b/ffi/CMakeLists.txt
@@ -18,13 +18,34 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_VISIBILITY_PRESET "hidden")
set(CMAKE_C_VISIBILITY_PRESET "hidden")
-find_package(LLVM REQUIRED CONFIG)
+# --- Start of llvm-config patch ---
+# Use llvm-config to bypass the faulty CMake export files.
+find_program(LLVM_CONFIG_EXECUTABLE llvm-config HINTS /data/data/com.termux/files/usr/bin)
+if(NOT LLVM_CONFIG_EXECUTABLE)
+ message(FATAL_ERROR "llvm-config not found! Please ensure it is in your PATH.")
+endif()
+
+# Get version for the version check
+execute_process(COMMAND ${LLVM_CONFIG_EXECUTABLE} --version OUTPUT_VARIABLE LLVM_PACKAGE_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
+string(REGEX MATCH "([0-9]+)" LLVM_VERSION_MAJOR "${LLVM_PACKAGE_VERSION}")
+
+# Get include dirs and definitions
+execute_process(COMMAND ${LLVM_CONFIG_EXECUTABLE} --cxxflags OUTPUT_VARIABLE LLVM_CXX_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+string(REGEX MATCHALL "-I[^ ]+" LLVM_INCLUDE_DIRS_RAW "${LLVM_CXX_FLAGS}")
+foreach(dir ${LLVM_INCLUDE_DIRS_RAW})
+ string(REPLACE "-I" "" dir_stripped ${dir})
+ list(APPEND LLVM_INCLUDE_DIRS ${dir_stripped})
+endforeach()
+string(REGEX MATCHALL "-D[^ ]+" LLVM_DEFINITIONS "${LLVM_CXX_FLAGS}")
+
+# Get the main shared library for linking
+execute_process(COMMAND ${LLVM_CONFIG_EXECUTABLE} --link-shared --libs OUTPUT_VARIABLE llvm_libs OUTPUT_STRIP_TRAILING_WHITESPACE)
+# --- End of llvm-config patch ---
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
-# NOTE: Keep this in sync with the version that llvmlite is declared to support
-set(LLVMLITE_SUPPORTED_LLVM_VERSION_DEFAULT 20)
+set(LLVMLITE_SUPPORTED_LLVM_VERSION_DEFAULT ${LLVM_VERSION_MAJOR})
# Check LLVM version is supported or intentionally overridden.
if (NOT DEFINED LLVM_VERSION_MAJOR)
diff --git a/ffi/newpassmanagers.cpp b/ffi/newpassmanagers.cpp
index 06116a1..ff6ff1a 100644
--- a/ffi/newpassmanagers.cpp
+++ b/ffi/newpassmanagers.cpp
@@ -106,9 +106,9 @@
#include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"
#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
-#include "llvm/Transforms/Instrumentation/InstrOrderFile.h"
+
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
-#include "llvm/Transforms/Instrumentation/MemProfiler.h"
+
#include "llvm/Transforms/Instrumentation/MemProfiler.h"
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
#include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
@@ -629,15 +629,16 @@ LLVMPY_module_AddModuleDebugInfoPrinterPass(LLVMModulePassManagerRef MPM) {
}
#include "PASSREGISTRY.def"
-#define FUNCTION_PASS(NAME) \
+#define FUNCTION_PASS_WITH_ARGS(NAME, ARGS) \
API_EXPORT(void) LLVMPY_module_Add##NAME(LLVMModulePassManagerRef MPM) { \
- llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor(NAME())); \
+ llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor(NAME(ARGS))); \
} \
API_EXPORT(void) \
LLVMPY_function_Add##NAME(LLVMFunctionPassManagerRef FPM) { \
- llvm::unwrap(FPM)->addPass(NAME()); \
+ llvm::unwrap(FPM)->addPass(NAME(ARGS)); \
}
-#include "PASSREGISTRY.def"
+
+
#define LOOP_PASS(NAME) \
API_EXPORT(void) LLVMPY_module_Add##NAME(LLVMModulePassManagerRef MPM) { \
diff --git a/ffi/orcjit.cpp b/ffi/orcjit.cpp
index bf624ba..d50a3ce 100644
--- a/ffi/orcjit.cpp
+++ b/ffi/orcjit.cpp
@@ -15,6 +15,11 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
+#include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h"
+
+extern "C" void
+llvm_orc_registerJITLoaderGDBWrapper(void);
+
using namespace llvm;
using namespace llvm::orc;
@@ -73,18 +78,22 @@ LLVMPY_CreateLLJITCompiler(LLVMTargetMachineRef tm, bool suppressErrors,\
// / shared with other objects on the Python side.\
auto *template_tm = unwrap(tm);\
- builder.setJITTargetMachineBuilder(\
- JITTargetMachineBuilder(template_tm->getTargetTriple())\
- .setCPU(template_tm->getTargetCPU().str())\
- .setRelocationModel(template_tm->getRelocationModel())\
- .setCodeModel(template_tm->getCodeModel())\
- .setCodeGenOptLevel(template_tm->getOptLevel())\
- .setFeatures(template_tm->getTargetFeatureString())\
- .setOptions(template_tm->Options));
+ auto JTMB = JITTargetMachineBuilder(template_tm->getTargetTriple());\
+ JTMB.setCPU(template_tm->getTargetCPU().str())\
+ .setRelocationModel(template_tm->getRelocationModel())\
+ .setCodeModel(template_tm->getCodeModel())\
+ .setCodeGenOptLevel(template_tm->getOptLevel())\
+ .setFeatures(template_tm->getTargetFeatureString())\
+ .setOptions(template_tm->Options);\
+ builder.setJITTargetMachineBuilder(std::move(JTMB));
}\
+\
+ auto triple = builder.getJITTargetMachineBuilder()->getTargetTriple();\
+\
+\
+
builder.setObjectLinkingLayerCreator(\
- [=](llvm::orc::ExecutionSession &session, const llvm::Triple &triple)\
- -> std::unique_ptr<llvm::orc::ObjectLayer> {\
+ [=](llvm::orc::ExecutionSession &session) -> Expected<std::unique_ptr<llvm::orc::ObjectLayer>> {\
if (useJitLink) {\
auto linkingLayer =\
std::make_unique<llvm::orc::ObjectLinkingLayer>(session);\
@@ -92,13 +101,13 @@ LLVMPY_CreateLLJITCompiler(LLVMTargetMachineRef tm, bool suppressErrors,\
/* FIXME(LLVM16): In newer LLVM versions, there is a simple\
* EnableDebugSupport flag on the builder and we don't need to\
* do any of this. */\
- // if (triple.getObjectFormat() == Triple::ELF ||\
- // triple.getObjectFormat() == Triple::MachO) {\
- // linkingLayer->addPlugin(\
- // std::make_unique<orc::GDBJITDebugInfoRegistrationPlugin>(\
- // ExecutorAddr::fromPtr(\
- // &llvm_orc_registerJITLoaderGDBWrapper)));\
- // }\
+ if (triple.getObjectFormat() == Triple::ELF ||\
+ triple.getObjectFormat() == Triple::MachO) {\
+ linkingLayer->addPlugin(\
+ std::make_unique<orc::GDBJITDebugInfoRegistrationPlugin>(\
+ ExecutorAddr::fromPtr(\
+ &llvm_orc_registerJITLoaderGDBWrapper)));\
+ }\
if (triple.isOSBinFormatCOFF()) {\
linkingLayer->setOverrideObjectFlagsWithResponsibilityFlags(\
true);\
@@ -108,7 +117,7 @@ LLVMPY_CreateLLJITCompiler(LLVMTargetMachineRef tm, bool suppressErrors,\
return linkingLayer;\
} else {\
auto linkingLayer = std::make_unique<\
- llvm::orc::RTDyldObjectLinkingLayer>(session, []() {\
+ llvm::orc::RTDyldObjectLinkingLayer>(session, [](const llvm::MemoryBuffer &ObjBuffer) {\
return std::make_unique<llvm::SectionMemoryManager>();\
});\
if (triple.isOSBinFormatCOFF()) {\
Step 2: Manually modify ffi/CMakeLists.txt
The above patch introduced a problem where llvm_map_components_to_libnames was called but not defined. This manual modification replaces that logic with a direct llvm-config --libs call. It also updates the list of LLVM components for static linking to reflect correct component names found via llvm-config --components.
New content for ffi/CMakeLists.txt:
cmake_minimum_required(VERSION 3.13)
# This will define the name of the solution file in the build directory
project(llvmlite_ffi)
include(CheckIncludeFiles)
include(CheckLibraryExists)
include(CheckCXXCompilerFlag)
include(CMakePushCheckState)
# Work around llvm/llvm-project#83802 - LLVM's Findzstd.cmake uses variables
# that require including `GNUInstallDirs`, but it does not include it itself.
include(GNUInstallDirs)
set(CMAKE_CXX_STANDARD 17)
# Preset function visibility to hidden, API functions
# are annotated explicitly to use 'default' visibility.
set(CMAKE_CXX_VISIBILITY_PRESET "hidden")
set(CMAKE_C_VISIBILITY_PRESET "hidden")
# --- Start of llvm-config patch ---
# Use llvm-config to bypass the faulty CMake export files.
find_program(LLVM_CONFIG_EXECUTABLE llvm-config HINTS /data/data/com.termux/files/usr/bin)
if(NOT LLVM_CONFIG_EXECUTABLE)
message(FATAL_ERROR "llvm-config not found! Please ensure it is in your PATH.")
endif()
# Get version for the version check
execute_process(COMMAND ${LLVM_CONFIG_EXECUTABLE} --version OUTPUT_VARIABLE LLVM_PACKAGE_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REGEX MATCH "([0-9]+)" LLVM_VERSION_MAJOR "${LLVM_PACKAGE_VERSION}")
# Get include dirs and definitions
execute_process(COMMAND ${LLVM_CONFIG_EXECUTABLE} --cxxflags OUTPUT_VARIABLE LLVM_CXX_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REGEX MATCHALL "-I[^ ]+" LLVM_INCLUDE_DIRS_RAW "${LLVM_CXX_FLAGS}")
foreach(dir ${LLVM_INCLUDE_DIRS_RAW})
string(REPLACE "-I" "" dir_stripped ${dir})
list(APPEND LLVM_INCLUDE_DIRS ${dir_stripped})
endforeach()
string(REGEX MATCHALL "-D[^ ]+" LLVM_DEFINITIONS "${LLVM_CXX_FLAGS}")
# Get the main shared library for linking
execute_process(COMMAND ${LLVM_CONFIG_EXECUTABLE} --link-shared --libs OUTPUT_VARIABLE llvm_libs OUTPUT_STRIP_TRAILING_WHITESPACE)
# --- End of llvm-config patch ---
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
set(LLVMLITE_SUPPORTED_LLVM_VERSION_DEFAULT ${LLVM_VERSION_MAJOR})
# Check LLVM version is supported or intentionally overridden.
if (NOT DEFINED LLVM_VERSION_MAJOR)
message(FATAL_ERROR "LLVM CMake export does not define LLVM_VERSION_MAJOR")
else()
if (LLVMLITE_SKIP_LLVM_VERSION_CHECK)
if (LLVM_VERSION_MAJOR EQUAL LLVMLITE_SUPPORTED_LLVM_VERSION_DEFAULT)
message(WARNING
"LLVMLITE_SKIP_LLVM_VERSION_CHECK is set but the current version \
${LLVMLITE_SUPPORTED_LLVM_VERSION_DEFAULT} is supported!")
else()
message(WARNING
"LLVMLITE_SKIP_LLVM_VERSION_CHECK is set, build is against an \
unsupported version of LLVM (${LLVM_VERSION_MAJOR}). Supported \
version is ${LLVMLITE_SUPPORTED_LLVM_VERSION_DEFAULT}.")
endif()
else()
if (NOT LLVM_VERSION_MAJOR EQUAL LLVMLITE_SUPPORTED_LLVM_VERSION_DEFAULT)
message(FATAL_ERROR
"LLVM CMake export states LLVM version is ${LLVM_VERSION_MAJOR}, \
llvmlite only officially supports \
${LLVMLITE_SUPPORTED_LLVM_VERSION_DEFAULT}.")
endif()
endif()
endif()
include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
# Check for presence of the SVML patch in the LLVM build
set(CMAKE_REQUIRED_INCLUDES ${LLVM_INCLUDE_DIRS})
CHECK_INCLUDE_FILES("llvm/IR/SVML.inc" HAVE_SVML)
if(HAVE_SVML)
message(STATUS "SVML found")
add_definitions(-DHAVE_SVML)
else()
message(STATUS "SVML not found")
endif()
# Capture the package format
# LLVMLITE_PACKAGE_FORMAT the target package format, if set must be one of
# 'wheel' or 'conda', this is used by the llvmlite maintainers in testing.
# Keep in sync with config.cpp defines
set(LLVMLITE_PACKAGE_FORMAT_CONDA "1")
set(LLVMLITE_PACKAGE_FORMAT_WHEEL "2")
string(TOLOWER "${LLVMLITE_PACKAGE_FORMAT}" lowercase_LLVMLITE_PACKAGE_FORMAT)
if(lowercase_LLVMLITE_PACKAGE_FORMAT STREQUAL "conda" OR
lowercase_LLVMLITE_PACKAGE_FORMAT STREQUAL "wheel")
message(STATUS
"LLVMLITE_PACKAGE_FORMAT option is set, capturing this is a \
'${lowercase_LLVMLITE_PACKAGE_FORMAT}' format build")
if(lowercase_LLVMLITE_PACKAGE_FORMAT STREQUAL "conda")
add_definitions(
-DLLVMLITE_PACKAGE_FORMAT=${LLVMLITE_PACKAGE_FORMAT_CONDA})
else()
add_definitions(
-DLLVMLITE_PACKAGE_FORMAT=${LLVMLITE_PACKAGE_FORMAT_WHEEL})
endif()
message(STATUS
"LLVMLITE_PACKAGE_FORMAT is ${lowercase_LLVMLITE_PACKAGE_FORMAT}")
elseif("${lowercase_LLVMLITE_PACKAGE_FORMAT}" STREQUAL "")
# present but not set
else()
message(FATAL_ERROR "Invalid value for package format: \
'${LLVMLITE_PACKAGE_FORMAT}', expect one of 'conda' or 'wheel'.")
endif()
# RTTI handling: This is a little awkward, it's a 3-state variable so cannot be
# an option. The states are user defined as ON or OFF, or user has not set so
# inherit from LLVM. This part removes the `-fno-rtti` option from
# CMAKE_CXX_FLAGS if appropriate, `-fno-rtti` is then added back in later as
# a flag on the compilation target if the compiler supports it and no-RTTI was
# determined to be appropriate.
if(UNIX)
string(TOLOWER "${LLVMLITE_USE_RTTI}" lowercase_LLVMLITE_USE_RTTI)
if(lowercase_LLVMLITE_USE_RTTI STREQUAL "on")
message(STATUS
"LLVMLITE_USE_RTTI override is set, RTTI is ON.")
set(LLVMLITE_USE_RTTI_FLAG ON)
elseif(lowercase_LLVMLITE_USE_RTTI STREQUAL "off")
message(STATUS
"LLVMLITE_USE_RTTI override is set, RTTI is OFF.")
set(LLVMLITE_USE_RTTI_FLAG OFF)
elseif(lowercase_LLVMLITE_USE_RTTI STREQUAL "")
if(DEFINED LLVM_ENABLE_RTTI)
message(STATUS
"LLVMLITE_USE_RTTI not set, inheriting RTTI flags from LLVM as: \
${LLVM_ENABLE_RTTI}.")
set(LLVMLITE_USE_RTTI_FLAG ${LLVM_ENABLE_RTTI})
else()
message(FATAL_ERROR "Both LLVMLITE_USE_RTTI and LLVM_ENABLE_RTTI \
are not set, cannot inherit RTTI setting from \
LLVM, user must override by setting \
LLVMLITE_USE_RTTI")
endif()
else()
message(FATAL_ERROR "LLVMLITE_USE_RTTI is set to an unknown value:
${LLVMLITE_USE_RTTI}.")
endif()
# unconditionally strip out -fno-rtti, it will be added to the target
# if needed
set(FLAG_NO_RTTI "-fno-rtti")
set(OLD_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
separate_arguments(CMAKE_CXX_FLAGS_AS_LIST UNIX_COMMAND
"${CMAKE_CXX_FLAGS}")
list(FILTER CMAKE_CXX_FLAGS_AS_LIST EXCLUDE REGEX "^${FLAG_NO_RTTI}$")
string(JOIN " " CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS_AS_LIST})
if(LLVMLITE_USE_RTTI_FLAG)
if(NOT ${OLD_CMAKE_CXX_FLAGS} STREQUAL ${CMAKE_CXX_FLAGS})
message(STATUS "-fno-rtti was removed from CXXFLAGS.")
else()
message(STATUS "-fno-rtti is not in CXXFLAGS, nothing to do.")
endif()
else()
# check the flag works.
check_cxx_compiler_flag(${FLAG_NO_RTTI} HAVE_FNO_RTTI)
if (NOT HAVE_FNO_RTTI)
message(FATAL_ERROR
"Compiler must support ${FLAG_NO_RTTI} option if it is requested")
endif()
endif()
endif()
# Define the shared library
add_library(llvmlite SHARED assembly.cpp bitcode.cpp config.cpp core.cpp initfini.cpp
module.cpp value.cpp executionengine.cpp type.cpp
targets.cpp dylib.cpp linker.cpp object_file.cpp
custom_passes.cpp orcjit.cpp memorymanager.cpp newpassmanagers.cpp)
# Determine whether libstdc++ should be statically linked (or not).
# GNU g++ and presumably clang on non-apple systems can probably deal with this.
if(UNIX AND NOT APPLE)
set(LLVMLITE_CXX_STATIC_LINK_DEFAULT OFF)
option(LLVMLITE_CXX_STATIC_LINK
"Enable C++ static linking in llvmlite (GNU Compilers)"
${LLVMLITE_CXX_STATIC_LINK_DEFAULT})
# See if static libc++ is requested
if (LLVMLITE_CXX_STATIC_LINK)
check_cxx_compiler_flag(-static-libstdc++ HAVE_STATIC_LIBSTDCXX)
if(NOT HAVE_STATIC_LIBSTDCXX)
message(FATAL_ERROR "LLVMLITE_CXX_STATIC_LINK was requested but
the compiler does not support the flag")
endif()
add_definitions(-DLLVMLITE_CXX_STATIC_LINK=1)
target_link_options(llvmlite PRIVATE -static-libstdc++)
endif()
endif()
# Apply no-RTTI flag if RTTI use is off, must happen after target definition
if(UNIX AND NOT LLVMLITE_USE_RTTI_FLAG)
message(STATUS "Applying no-RTTI flag to llvmlite target: ${FLAG_NO_RTTI}")
target_compile_options(llvmlite PRIVATE ${FLAG_NO_RTTI})
endif()
# Check for LTO / IPO
set(LLVMLITE_LTO_DEFAULT ON)
option(LLVMLITE_LTO "Enable LTO" ${LLVMLITE_LTO_DEFAULT})
if(LLVMLITE_LTO)
include(CheckIPOSupported)
check_ipo_supported(RESULT LLVMLITE_HAVE_LTO OUTPUT output)
if(LLVMLITE_HAVE_LTO)
message(STATUS "Enabling interprocedural optimization (LTO)")
set_property(TARGET llvmlite PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
else()
message(WARNING "IPO/LTO is not supported: ${output}")
endif()
else()
message(STATUS "IPO/LTO is disabled")
endif()
# Check if the LLVMLITE_SHARED build flag is set. Default is static. This option
# is baked into the binary for testing purposes.
# Find the libraries that correspond to the LLVM components needed based on the
# build flag.
set(LLVMLITE_SHARED_DEFAULT OFF)
option(LLVMLITE_SHARED
"Enable dynamic linkage against LLVM, default is OFF (i.e. static link)"
${LLVMLITE_SHARED_DEFAULT})
if (LLVMLITE_SHARED)
check_library_exists(LLVM LLVMGetVersion "" HAVE_LIBRARY_LLVM)
if(NOT HAVE_LIBRARY_LLVM)
message(FATAL_ERROR "Could not find libLLVM")
endif()
set(llvm_libs LLVM)
message(STATUS
"LLVMLITE_SHARED is ON, using dynamic linkage against LLVM")
add_definitions(-DHAVE_LLVMLITE_SHARED)
else()
set(LLVM_COMPONENTS mcjit
orcjit
orcdebugging
asmprinter
all-targets)
# Statically link
execute_process(COMMAND ${LLVM_CONFIG_EXECUTABLE} --libs ${LLVM_COMPONENTS}
OUTPUT_VARIABLE llvm_libs
OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS
"LLVMLITE_SHARED is OFF, using static linkage against LLVM")
endif()
# If this is a static link to LLVM, bake in whether LLVM has assertions enabled.
# 3 states, on, off, and unknown
# Keep in sync with config.cpp defines
set(LLVMLITE_LLVM_ASSERTIONS_OFF "0")
set(LLVMLITE_LLVM_ASSERTIONS_ON "1")
set(LLVMLITE_LLVM_ASSERTIONS_UNKNOWN "2")
if(LLVMLITE_SHARED)
add_definitions(
-DLLVMLITE_LLVM_ASSERTIONS_STATE=${LLVMLITE_LLVM_ASSERTIONS_UNKNOWN})
message(STATUS "LLVM assertions state detected as 'unknown'")
else()
if(LLVM_ENABLE_ASSERTIONS)
add_definitions(
-DLLVMLITE_LLVM_ASSERTIONS_STATE=${LLVMLITE_LLVM_ASSERTIONS_ON})
message(STATUS "LLVM assertions state detected as 'on'")
else()
add_definitions(
-DLLVMLITE_LLVM_ASSERTIONS_STATE=${LLVMLITE_LLVM_ASSERTIONS_OFF})
message(STATUS "LLVM assertions state detected as 'off'")
endif()
endif()
# Setup and report on linkage against LLVM libraries
message(STATUS "LLVM target link libraries: ${llvm_libs}")
target_link_libraries(llvmlite ${llvm_libs})
# --exclude-libs allow removal of unused parts of LLVM
# TODO: these options are just set, they should really be tested for
# suitability.
if(UNIX AND NOT APPLE)
set(FORCED_LINK_FLAGS "-Wl,--exclude-libs,ALL -Wl,--no-undefined")
if(NOT LLVMLITE_SHARED)
# If LLVM is statically linked, we specify -Bsymbolic to prevent
# that LLVM symbols can be interposed upon by previously
# loaded shared objects that export LLVM symbols.
STRING(APPEND FORCED_LINK_FLAGS " -Wl,-Bsymbolic")
endif()
set_property(TARGET llvmlite APPEND_STRING PROPERTY LINK_FLAGS
"${FORCED_LINK_FLAGS}")
elseif(APPLE)
set(FORCED_LINK_FLAGS "-Wl,-exported_symbol,_LLVMPY_*")
set_property(TARGET llvmlite APPEND_STRING PROPERTY LINK_FLAGS
"${FORCED_LINK_FLAGS}")
endif()
Quick proof that he above works:
pip show llvmlite
Name: llvmlite
Version: 0.47.0.dev0+7.gadfb1dd.dirty
Summary: lightweight wrapper around basic LLVM functionality
Home-page: http://llvmlite.readthedocs.io
Author:
Author-email:
License-Expression: BSD-2-Clause AND Apache-2.0 WITH LLVM-exception
Location: /data/data/com.termux/files/usr/lib/python3.12/site-packages
Requires:
Required-by: numba, pynndescent
~/.../GitHub/Ubuntu_Scripts_1 $ uname -a
Linux localhost 4.14.186+ #1 SMP PREEMPT Thu Mar 17 16:28:22 CST 2022 aarch64 Android
~/.../GitHub/Ubuntu_Scripts_1 $
But I spoke too soon, as it fails at runtime now:
whisper /storage/emulated/0/Movies/Dolinska_AboveTrans_Eventogram_Demo_2025-10-27T13_14_56.783Z.webm --threads 2
Traceback (most recent call last):
File "/data/data/com.termux/files/usr/bin/whisper", line 3, in <module>
from whisper.transcribe import cli
File "/data/data/com.termux/files/usr/lib/python3.12/site-packages/whisper/__init__.py", line 13, in <module>
from .model import ModelDimensions, Whisper
File "/data/data/com.termux/files/usr/lib/python3.12/site-packages/whisper/model.py", line 14, in <module>
from .transcribe import transcribe as transcribe_function
File "/data/data/com.termux/files/usr/lib/python3.12/site-packages/whisper/transcribe.py", line 21, in <module>
from .timing import add_word_timestamps
File "/data/data/com.termux/files/usr/lib/python3.12/site-packages/whisper/timing.py", line 7, in <module>
import numba
File "/data/data/com.termux/files/usr/lib/python3.12/site-packages/numba/__init__.py", line 73, in <module>
from numba.core import config
File "/data/data/com.termux/files/usr/lib/python3.12/site-packages/numba/core/config.py", line 17, in <module>
import llvmlite.binding as ll
File "/data/data/com.termux/files/usr/lib/python3.12/site-packages/llvmlite/binding/__init__.py", line 10, in <module>
from .newpassmanagers import *
File "/data/data/com.termux/files/usr/lib/python3.12/site-packages/llvmlite/binding/newpassmanagers.py", line 649, in <module>
ffi.lib.LLVMPY_module_AddAAEvaluator.argtypes = [ffi.LLVMModulePassManagerRef,]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/data/com.termux/files/usr/lib/python3.12/site-packages/llvmlite/binding/ffi.py", line 159, in __getattr__
cfn = getattr(self._lib, name)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/data/com.termux/files/usr/lib/python3.12/ctypes/__init__.py", line 392, in __getattr__
func = self.__getitem__(name)
^^^^^^^^^^^^^^^^^^^^^^
File "/data/data/com.termux/files/usr/lib/python3.12/ctypes/__init__.py", line 397, in __getitem__
func = self._FuncPtr((name_or_ordinal, self))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: undefined symbol: LLVMPY_module_AddAAEvaluator
~/.../GitHub/Ubuntu_Scripts_1
For whom it may concern: the new yamls and maybe the llm updates:
git pull
remote: Enumerating objects: 67, done.
remote: Counting objects: 100% (49/49), done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 67 (delta 35), reused 39 (delta 35), pack-reused 18 (from 1)
Unpacking objects: 100% (67/67), 38.28 KiB | 12.00 KiB/s, done.
From https://github.com/numba/llvmlite
adfb1dd..c0b9e8d main -> origin/main
8f5c1e0..50404fd release0.46 -> origin/release0.46
+ f8b33e3...9702bc9 renovate/actions-setup-python-6.x -> origin/renovate/actions-setup-python-6.x (forced update)
+ 8bdea6b...6c17283 renovate/macos-15.x -> origin/renovate/macos-15.x (forced update)
e62ad32..7b85e20 renovate/major-github-artifact-actions -> origin/renovate/major-github-artifact-actions
* [new tag] v0.46.0 -> v0.46.0
Updating adfb1dd..c0b9e8d
Fast-forward
.../ISSUE_TEMPLATE/sub_rc_checklist.md | 2 +-
.github/workflows/llvmdev_build.yml | 19 ++++-
.../llvmlite_conda_builder.yml | 4 +-
.../llvmlite_linux-64_wheel_builder.yml | 4 +-
...lite_linux-aarch64_wheel_builder.yml | 4 +-
...llvmlite_osx-arm64_wheel_builder.yml | 4 +-
.../llvmlite_win-64_wheel_builder.yml | 4 +-
.github/workflows/upload_packages.yml | 4 +-
CHANGE_LOG | 62 +++++++++++++++
9 files changed, 92 insertions(+), 15 deletions(-)
make it compile fine:
running bdist_wheel
/data/data/com.termux/files/usr/bin/python3.12 /data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/build.py
-- The C compiler identification is Clang 21.1.6
-- The CXX compiler identification is Clang 21.1.6
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /data/data/com.termux/files/usr/bin/clang - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /data/data/com.termux/files/usr/bin/clang++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found LLVM 21.1.6
-- Using LLVMConfig.cmake in:
CMake Warning at CMakeLists.txt:56 (message):
LLVMLITE_SKIP_LLVM_VERSION_CHECK is set but the current version 21 is
supported!
-- SVML not found
-- LLVMLITE_USE_RTTI override is set, RTTI is OFF.
-- Applying no-RTTI flag to llvmlite target: -fno-rtti
-- Enabling interprocedural optimization (LTO)
-- LLVMLITE_SHARED is OFF, using static linkage against LLVM
-- LLVM assertions state detected as 'off'
-- LLVM target link libraries: -lLLVM-21
-- Configuring done (7.1s)
-- Generating done (0.0s)
-- Build files have been written to: /data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/build
[ 5%] Linking CXX shared library libllvmlite.so
[100%] Built target llvmlite
Running: cmake -G Unix Makefiles /data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi -Dpybind11_INCLUDE_DIR=/data/data/com.termux/files/usr/lib/python3.12/site-packages/pybind11/include
running build
got version from VCS {'version': '0.47.0dev0+17.gc0b9e8d.dirty', 'full': 'c0b9e8d3733b5b6289ee6acd64f4b2040a3fed6b.dirty'}
running build_ext
/data/data/com.termux/files/usr/bin/python3.12 /data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/build.py
-- Found LLVM 21.1.6
-- Using LLVMConfig.cmake in:
CMake Warning at CMakeLists.txt:56 (message):
LLVMLITE_SKIP_LLVM_VERSION_CHECK is set but the current version 21 is
supported!
-- SVML not found
-- LLVMLITE_USE_RTTI override is set, RTTI is OFF.
-- Applying no-RTTI flag to llvmlite target: -fno-rtti
-- Enabling interprocedural optimization (LTO)
-- LLVMLITE_SHARED is OFF, using static linkage against LLVM
-- LLVM assertions state detected as 'off'
-- LLVM target link libraries: -lLLVM-21
-- Configuring done (3.3s)
-- Generating done (0.0s)
-- Build files have been written to: /data/data/com.termux/files/home/Downloads/GitHub/llvmlite/ffi/build
And:
pip show llvmlite
Name: llvmlite
Version: 0.47.0.dev0+7.gadfb1dd.dirty
Summary: lightweight wrapper around basic LLVM functionality
Home-page: http://llvmlite.readthedocs.io
Author:
Author-email:
License-Expression: BSD-2-Clause AND Apache-2.0 WITH LLVM-exception
Location: /data/data/com.termux/files/usr/lib/python3.12/site-packages
Requires:
Required-by: numba, pynndescent
but see below....
Oh, but the regular wheels still fail as of now:
LLVMLITE_SKIP_LLVM_VERSION_CHECK=1LLVMLITE_SHARED=ON LLVMLITE_USE_RTTI=OFF pip install llvmlite -U --force-reinstall -v, so git cloning and hacks be needed, so I keep above.
Ref:
...
Successfully installed setuptools-80.9.0
Installing build dependencies ... done
Running command Getting requirements to build wheel
/data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/versioneer.py:415: SyntaxWarning: invalid escape sequence '\s'
mo = re.search(r'=\s*"(.*)"', line)
running egg_info
creating llvmlite.egg-info
writing llvmlite.egg-info/PKG-INFO
writing dependency_links to llvmlite.egg-info/dependency_links.txt
writing top-level names to llvmlite.egg-info/top_level.txt
writing manifest file 'llvmlite.egg-info/SOURCES.txt'
reading manifest file 'llvmlite.egg-info/SOURCES.txt'
adding license file 'LICENSE'
adding license file 'LICENSE.thirdparty'
writing manifest file 'llvmlite.egg-info/SOURCES.txt'
Getting requirements to build wheel ... done
Running command Preparing metadata (pyproject.toml)
running dist_info
creating /data/data/com.termux/files/usr/tmp/pip-modern-metadata-94a641z8/llvmlite.egg-info
writing /data/data/com.termux/files/usr/tmp/pip-modern-metadata-94a641z8/llvmlite.egg-info/PKG-INFO
writing dependency_links to /data/data/com.termux/files/usr/tmp/pip-modern-metadata-94a641z8/llvmlite.egg-info/dependency_links.txt
writing top-level names to /data/data/com.termux/files/usr/tmp/pip-modern-metadata-94a641z8/llvmlite.egg-info/top_level.txt
writing manifest file '/data/data/com.termux/files/usr/tmp/pip-modern-metadata-94a641z8/llvmlite.egg-info/SOURCES.txt'
reading manifest file '/data/data/com.termux/files/usr/tmp/pip-modern-metadata-94a641z8/llvmlite.egg-info/SOURCES.txt'
adding license file 'LICENSE'
adding license file 'LICENSE.thirdparty'
writing manifest file '/data/data/com.termux/files/usr/tmp/pip-modern-metadata-94a641z8/llvmlite.egg-info/SOURCES.txt'
creating '/data/data/com.termux/files/usr/tmp/pip-modern-metadata-94a641z8/llvmlite-0.46.0.dist-info'
Preparing metadata (pyproject.toml) ... done
Building wheels for collected packages: llvmlite
Running command Building wheel for llvmlite (pyproject.toml)
running bdist_wheel
/data/data/com.termux/files/usr/bin/python3.12 /data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/build.py
-- The C compiler identification is Clang 21.1.6
-- The CXX compiler identification is Clang 21.1.6
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /data/data/com.termux/files/usr/bin/clang - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /data/data/com.termux/files/usr/bin/clang++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test HAVE_FFI_CALL
-- Performing Test HAVE_FFI_CALL - Success
-- Found FFI: /data/data/com.termux/files/usr/lib/libffi.so
-- Found ZLIB: /data/data/com.termux/files/usr/lib/libz.so (found version "1.3.1")
-- Found zstd: /data/data/com.termux/files/usr/lib/libzstd.so
-- Found LibXml2: /data/data/com.termux/files/usr/lib/libxml2.so (found version "2.15.1")
-- Found LLVM 21.1.6
-- Using LLVMConfig.cmake in: /data/data/com.termux/files/usr/lib/cmake/llvm
CMake Warning at CMakeLists.txt:39 (message):
LLVMLITE_SKIP_LLVM_VERSION_CHECK is set, build is against an unsupported
version of LLVM (21). Supported version is 20.
-- Looking for include file llvm/IR/SVML.inc
-- Looking for include file llvm/IR/SVML.inc - not found
-- SVML not found
-- LLVMLITE_USE_RTTI override is set, RTTI is OFF.
-- Performing Test HAVE_FNO_RTTI
-- Performing Test HAVE_FNO_RTTI - Success
-- Applying no-RTTI flag to llvmlite target: -fno-rtti
-- Enabling interprocedural optimization (LTO)
-- Looking for LLVMGetVersion in LLVM
-- Looking for LLVMGetVersion in LLVM - found
-- LLVMLITE_SHARED is ON, using dynamic linkage against LLVM
-- LLVM assertions state detected as 'unknown'
-- LLVM target link libraries: LLVM
-- Configuring done (10.4s)
-- Generating done (0.1s)
CMake Warning:
Manually-specified variables were not used by the project:
pybind11_INCLUDE_DIR
-- Build files have been written to: /data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/build
[ 5%] Building CXX object CMakeFiles/llvmlite.dir/core.cpp.o
[ 11%] Building CXX object CMakeFiles/llvmlite.dir/config.cpp.o
[ 22%] Building CXX object CMakeFiles/llvmlite.dir/module.cpp.o
[ 22%] Building CXX object CMakeFiles/llvmlite.dir/initfini.cpp.o
[ 27%] Building CXX object CMakeFiles/llvmlite.dir/assembly.cpp.o
[ 33%] Building CXX object CMakeFiles/llvmlite.dir/bitcode.cpp.o
[ 38%] Building CXX object CMakeFiles/llvmlite.dir/value.cpp.o
[ 44%] Building CXX object CMakeFiles/llvmlite.dir/executionengine.cpp.o
[ 50%] Building CXX object CMakeFiles/llvmlite.dir/type.cpp.o
[ 55%] Building CXX object CMakeFiles/llvmlite.dir/dylib.cpp.o
[ 61%] Building CXX object CMakeFiles/llvmlite.dir/targets.cpp.o
[ 66%] Building CXX object CMakeFiles/llvmlite.dir/linker.cpp.o
clang++: warning: -lpthread: 'linker' input unused [-Wunused-command-line-argument]
clang++: warning: -lpthread: 'linker' input unused [-Wunused-command-line-argument]
[ 72%] Building CXX object CMakeFiles/llvmlite.dir/object_file.cpp.o
clang++: warning: -lpthread: 'linker' input unused [-Wunused-command-line-argument]
clang++: warning: -lpthread: 'linker' input unused [-Wunused-command-line-argument]
clang++: warning: -lpthread: 'linker' input unused [-Wunused-command-line-argument]
clang++: warning: -lpthread: 'linker' input unused [-Wunused-command-line-argument]
clang++: warning: -lpthread: 'linker' input unused [-Wunused-command-line-argument]
clang++: warning: -lpthread: 'linker' input unused [-Wunused-command-line-argument]
[ 77%] Building CXX object CMakeFiles/llvmlite.dir/custom_passes.cpp.o
[ 83%] Building CXX object CMakeFiles/llvmlite.dir/orcjit.cpp.o
[ 88%] Building CXX object CMakeFiles/llvmlite.dir/memorymanager.cpp.o
[ 94%] Building CXX object CMakeFiles/llvmlite.dir/newpassmanagers.cpp.o
clang++: warning: -lpthread: 'linker' input unused [-Wunused-command-line-argument]
clang++: warning: -lpthread: 'linker' input unused [-Wunused-command-line-argument]
clang++clang++: warning: -lpthread: 'linker' input unused [-Wunused-command-line-argument]
: warning: -lpthread: 'linker' input unused [-Wunused-command-line-argument]
clang++: warning: -lpthread: 'linker' input unused [-Wunused-command-line-argument]
clang++: warning: -lpthread: 'linker' input unused [-Wunused-command-line-argument]
clang++: warning: -lpthread: 'linker' input unused [-Wunused-command-line-argument]
clang++: warning: -lpthread: 'linker' input unused [-Wunused-command-line-argument]
clang++: warning: -lpthread: 'linker' input unused [-Wunused-command-line-argument]
/data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/targets.cpp:205:28: warning: 'createTargetMachine' is deprecated: Use overload accepting Triple instead [-Wdeprecated-declarations]
205 | return wrap(unwrap(T)->createTargetMachine(Triple, CPU, Features, opt, rm,
| ^
/data/data/com.termux/files/usr/bin/../../usr/include/llvm/MC/TargetRegistry.h:477:5: note: 'createTargetMachine' has been explicitly marked deprecated here
477 | [[deprecated("Use overload accepting Triple instead")]]
| ^
1 warning generated.
/data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/orcjit.cpp:86:9: error: no viable conversion from '(lambda at /data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/orcjit.cpp:86:9)' to 'LLJITBuilderState::ObjectLinkingLayerCreator' (aka 'function<Expected<std::unique_ptr<ObjectLayer>> (ExecutionSession &)>')
86 | [=](llvm::orc::ExecutionSession &session, const llvm::Triple &triple)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
87 | -> std::unique_ptr<llvm::orc::ObjectLayer> {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
88 | if (useJitLink) {
| ~~~~~~~~~~~~~~~~~
89 | auto linkingLayer =
| ~~~~~~~~~~~~~~~~~~~
90 | std::make_unique<llvm::orc::ObjectLinkingLayer>(session);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
91 |
92 | /* FIXME(LLVM16): In newer LLVM versions, there is a simple
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
93 | * EnableDebugSupport flag on the builder and we don't need to
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
94 | * do any of this. */
| ~~~~~~~~~~~~~~~~~~~~
95 | // if (triple.getObjectFormat() == Triple::ELF ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
96 | // triple.getObjectFormat() == Triple::MachO) {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
97 | // linkingLayer->addPlugin(
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
98 | // std::make_unique<orc::GDBJITDebugInfoRegistrationPlugin>(
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
99 | // ExecutorAddr::fromPtr(
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
100 | // &llvm_orc_registerJITLoaderGDBWrapper)));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
101 | // }
| ~~~~
/data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/__functional/function.h:862:25: note: candidate constructor not viable: no known conversion from '(lambda at /data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/orcjit.cpp:86:9)' to 'nullptr_t' (aka 'std::nullptr_t') for 1st argument
862 | _LIBCPP_HIDE_FROM_ABI function(nullptr_t) _NOEXCEPT {}
| ^ ~~~~~~~~~
/data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/__functional/function.h:863:25: note: candidate constructor not viable: no known conversion from '(lambda at /data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/orcjit.cpp:86:9)' to 'const function<llvm::Expected<std::unique_ptr<llvm::orc::ObjectLayer>> (llvm::orc::ExecutionSession &)> &' for 1st argument
863 | _LIBCPP_HIDE_FROM_ABI function(const function&);
| ^ ~~~~~~~~~~~~~~~
/data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/__functional/function.h:864:25: note: candidate constructor not viable: no known conversion from '(lambda at /data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/orcjit.cpp:86:9)' to 'function<llvm::Expected<std::unique_ptr<llvm::orc::ObjectLayer>> (llvm::orc::ExecutionSession &)> &&' for 1st argument
864 | _LIBCPP_HIDE_FROM_ABI function(function&&) _NOEXCEPT;
| ^ ~~~~~~~~~~
/data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/__functional/function.h:866:25: note: candidate template ignored: requirement '__callable<(lambda at /data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/orcjit.cpp:86:9) &, false>::value' was not satisfied [with _Fp = (lambda at /data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/orcjit.cpp:86:9)]
866 | _LIBCPP_HIDE_FROM_ABI function(_Fp);
| ^
/data/data/com.termux/files/usr/bin/../../usr/include/llvm/ExecutionEngine/Orc/LLJIT.h:408:52: note: passing argument to parameter 'CreateObjectLinkingLayer' here
408 | LLJITBuilderState::ObjectLinkingLayerCreator CreateObjectLinkingLayer) {
| ^
In file included from /data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/orcjit.cpp:4:
In file included from /data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/sstream:323:
In file included from /data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/__ostream/basic_ostream.h:18:
/data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/__memory/unique_ptr.h:767:30: error: no matching constructor for initialization of 'llvm::orc::RTDyldObjectLinkingLayer'
767 | return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...));
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
/data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/orcjit.cpp:110:42: note: in instantiation of function template specialization 'std::make_unique<llvm::orc::RTDyldObjectLinkingLayer, llvm::orc::ExecutionSession &, (lambda at /data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/orcjit.cpp:111:67), 0>' requested here
110 | auto linkingLayer = std::make_unique<
| ^
/data/data/com.termux/files/usr/bin/../../usr/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h:58:3: note: candidate constructor not viable: no known conversion from '(lambda at /data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/orcjit.cpp:111:67)' to 'GetMemoryManagerFunction' (aka 'unique_function<std::unique_ptr<RuntimeDyld::MemoryManager> (const MemoryBuffer &)>') for 2nd argument
58 | RTDyldObjectLinkingLayer(ExecutionSession &ES,
| ^
59 | GetMemoryManagerFunction GetMemoryManager);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/data/data/com.termux/files/usr/bin/../../usr/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h:37:16: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided
37 | class LLVM_ABI RTDyldObjectLinkingLayer
| ^~~~~~~~~~~~~~~~~~~~~~~~
2 errors generated.
make[2]: *** [CMakeFiles/llvmlite.dir/build.make:275: CMakeFiles/llvmlite.dir/orcjit.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....
/data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/newpassmanagers.cpp:109:10: fatal error: 'llvm/Transforms/Instrumentation/InstrOrderFile.h' file not found
109 | #include "llvm/Transforms/Instrumentation/InstrOrderFile.h"
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
make[2]: *** [CMakeFiles/llvmlite.dir/build.make:303: CMakeFiles/llvmlite.dir/newpassmanagers.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:252: CMakeFiles/llvmlite.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
Running: cmake -G Unix Makefiles /data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi -DLLVMLITE_USE_RTTI=OFF -DLLVMLITE_SHARED=ON -DLLVMLITE_SKIP_LLVM_VERSION_CHECK=ON -Dpybind11_INCLUDE_DIR=/data/data/com.termux/files/usr/lib/python3.12/site-packages/pybind11/include
Traceback (most recent call last):
File "/data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/build.py", line 209, in <module>
main()
File "/data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/build.py", line 201, in main
main_posix('.so')
File "/data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/build.py", line 191, in main_posix
subprocess.check_call(cmd)
File "/data/data/com.termux/files/usr/lib/python3.12/subprocess.py", line 413, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['cmake', '--build', '/data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a/ffi/build', '--parallel', '--config', 'Release']' returned non-zero exit status 2.
error: command '/data/data/com.termux/files/usr/bin/python3.12' failed with exit code 1
error: subprocess-exited-with-error
× Building wheel for llvmlite (pyproject.toml) did not run successfully.
│ exit code: 1
╰─> No available output.
note: This error originates from a subprocess, and is likely not a problem with pip.
full command: /data/data/com.termux/files/usr/bin/python3.12 /data/data/com.termux/files/usr/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py build_wheel /data/data/com.termux/files/usr/tmp/tmpgcijj37a
cwd: /data/data/com.termux/files/usr/tmp/pip-install-sbf_a8gw/llvmlite_3c07fc28a08a417d94c3cfb56ab2bd0a
Building wheel for llvmlite (pyproject.toml) ... error
ERROR: Failed building wheel for llvmlite
Failed to build llvmlite
error: failed-wheel-build-for-install
× Failed to build installable wheels for some pyproject.toml based projects
╰─> llvmlite