Skip to content

Commit 81bc25d

Browse files
committed
Make TCC JIT functional on Linux and mac
1 parent ea13b4e commit 81bc25d

File tree

6 files changed

+55
-34
lines changed

6 files changed

+55
-34
lines changed

CMakeLists.txt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,6 @@ nanobind_add_module(
220220
target_link_libraries(ipopt_model_ext PUBLIC ipopt_model)
221221
install(TARGETS ipopt_model_ext LIBRARY DESTINATION ${POI_INSTALL_DIR})
222222

223-
# Set RPATH
224-
# set_rpath(nlcore_ext)
225-
set_rpath(ipopt_model_ext)
226-
227223
# stub
228224
nanobind_add_stub(
229225
core_ext_stub

src/pyoptinterface/_src/codegen_c.py

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@
3838
def generate_csrc_prelude(io: IO[str]):
3939
io.write(
4040
"""// includes
41-
# include <stddef.h>
42-
# include <math.h>
41+
#include <stddef.h>
42+
#include <math.h>
4343
4444
// typedefs
4545
typedef double float_point_t;
@@ -63,24 +63,6 @@ def generate_csrc_prelude(io: IO[str]):
6363
)
6464

6565

66-
def generate_csrc_prelude_declaration(io: IO[str]):
67-
io.write(
68-
"""// includes
69-
# include <stddef.h>
70-
# include <math.h>
71-
72-
// typedefs
73-
typedef double float_point_t;
74-
75-
// externals
76-
// azmul
77-
extern float_point_t azmul(float_point_t x, float_point_t y);
78-
// sign
79-
extern float_point_t sign(float_point_t x);
80-
"""
81-
)
82-
83-
8466
def generate_csrc_from_graph(
8567
io: IO[str],
8668
graph_obj,
@@ -299,7 +281,3 @@ def get_node_name(node: int) -> str:
299281
}
300282
"""
301283
)
302-
303-
extern_function_declaration = "extern " + function_prototype
304-
305-
return extern_function_declaration

src/pyoptinterface/_src/ipopt.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ def compile_functions_llvm(model: "Model", jit_compiler: LLJITCompiler):
194194
indirect_x=True,
195195
indirect_p=True,
196196
)
197+
export_functions.append(f_name)
197198
if autodiff_structure.has_jacobian:
198199
jacobian_name = name + "_jacobian"
199200
generate_llvmir_from_graph(
@@ -215,6 +216,7 @@ def compile_functions_llvm(model: "Model", jit_compiler: LLJITCompiler):
215216
indirect_y=True,
216217
add_y=True,
217218
)
219+
export_functions.extend([jacobian_name, gradient_name])
218220
if autodiff_structure.has_hessian:
219221
hessian_name = name + "_hessian"
220222
generate_llvmir_from_graph(
@@ -229,8 +231,7 @@ def compile_functions_llvm(model: "Model", jit_compiler: LLJITCompiler):
229231
indirect_y=True,
230232
add_y=True,
231233
)
232-
233-
export_functions.extend([f_name, jacobian_name, gradient_name, hessian_name])
234+
export_functions.append(hessian_name)
234235

235236
rt = jit_compiler.compile_module(module, export_functions)
236237

src/pyoptinterface/_src/jit_c.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
import tccbox
66

7+
system = platform.system()
8+
79
libtcc_dir = tccbox.tcc_lib_dir()
810
# windows: libtcc.dll
911
# linux: libtcc.so
@@ -12,9 +14,18 @@
1214
"Windows": "dll",
1315
"Linux": "so",
1416
"Darwin": "dylib",
15-
}[platform.system()]
17+
}[system]
1618
libtcc_path = os.path.join(libtcc_dir, f"libtcc.{sharedlib_suffix}")
1719

20+
# On Linux/Mac, tcc has lib/tcc/include/ and lib/tcc/libtcc1.a which must be included in compilation
21+
libtcc_extra_include_path = None
22+
libtcc_extra_lib_path = None
23+
libtcc_extra_lib_name = None
24+
if system in ["Linux", "Darwin"]:
25+
libtcc_extra_include_path = os.path.join(libtcc_dir, "tcc", "include")
26+
libtcc_extra_lib_path = os.path.join(libtcc_dir, "tcc")
27+
libtcc_extra_lib_name = "libtcc1.a"
28+
1829
# Define types
1930
TCCState = ctypes.c_void_p
2031
TCCReallocFunc = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_ulong)
@@ -49,6 +60,32 @@ def create_state(self):
4960
if self.libtcc.tcc_set_output_type(state, TCC_OUTPUT_MEMORY) == -1:
5061
raise Exception("Failed to set output type")
5162

63+
# Add extra include path and library path
64+
if libtcc_extra_include_path:
65+
if (
66+
self.libtcc.tcc_add_include_path(
67+
state, libtcc_extra_include_path.encode()
68+
)
69+
== -1
70+
):
71+
raise Exception("Failed to add extra include path")
72+
if (
73+
self.libtcc.tcc_add_sysinclude_path(
74+
state, libtcc_extra_include_path.encode()
75+
)
76+
== -1
77+
):
78+
raise Exception("Failed to add extra sysinclude path")
79+
if libtcc_extra_lib_path:
80+
if (
81+
self.libtcc.tcc_add_library_path(state, libtcc_extra_lib_path.encode())
82+
== -1
83+
):
84+
raise Exception("Failed to add extra library path")
85+
if libtcc_extra_lib_name:
86+
if self.libtcc.tcc_add_library(state, libtcc_extra_lib_name.encode()) == -1:
87+
raise Exception("Failed to add extra library")
88+
5289
self.states.append(state)
5390

5491
return state
@@ -65,6 +102,14 @@ def _initialize_function_prototypes(self):
65102
libtcc.tcc_add_symbol.restype = ctypes.c_int
66103
libtcc.tcc_get_symbol.argtypes = [TCCState, ctypes.c_char_p]
67104
libtcc.tcc_get_symbol.restype = ctypes.c_void_p
105+
libtcc.tcc_add_include_path.argtypes = [TCCState, ctypes.c_char_p]
106+
libtcc.tcc_add_include_path.restype = ctypes.c_int
107+
libtcc.tcc_add_sysinclude_path.argtypes = [TCCState, ctypes.c_char_p]
108+
libtcc.tcc_add_sysinclude_path.restype = ctypes.c_int
109+
libtcc.tcc_add_library_path.argtypes = [TCCState, ctypes.c_char_p]
110+
libtcc.tcc_add_library_path.restype = ctypes.c_int
111+
libtcc.tcc_add_library.argtypes = [TCCState, ctypes.c_char_p]
112+
libtcc.tcc_add_library.restype = ctypes.c_int
68113

69114
def compile_string(self, state, c_code: str):
70115
if self.libtcc.tcc_compile_string(state, c_code.encode()) == -1:

tests/test_nlp.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,5 +157,6 @@ def con(vars):
157157

158158

159159
if __name__ == "__main__":
160-
test_ipopt()
161-
test_nlp_param()
160+
test_ipopt(ipopt.Model)
161+
test_nlp_param(ipopt.Model)
162+
test_nlfunc_ifelse(ipopt.Model)

tests/test_nlp_rocket.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,4 @@ def test_rocket(ipopt_model_ctor):
9797

9898

9999
if __name__ == "__main__":
100-
test_rocket()
100+
test_rocket(ipopt.Model)

0 commit comments

Comments
 (0)