diff --git a/build.zig b/build.zig index 078afd1..8f3acf9 100644 --- a/build.zig +++ b/build.zig @@ -3,14 +3,9 @@ // SPDX-License-Identifier: GPL-3.0-only const std = @import("std"); -const CpythonStep = @import("build/CpythonStep.zig"); const cases = @import("tests/cases.zig"); -var trace: bool = false; -var @"enable-bench": ?bool = false; -var backend: TraceBackend = .None; - pub fn build(b: *std.Build) !void { const optimize = b.standardOptimizeOption(.{}); const target = b.standardTargetOptions(.{}); @@ -22,31 +17,29 @@ pub fn build(b: *std.Build) !void { .optimize = optimize, }); - trace = b.option(bool, "trace", + const trace = b.option(bool, "trace", \\Enables tracing of the compiler using the default backend (spall) ) orelse false; + const backend: TraceBackend = bend: { + if (trace) { + break :bend b.option(TraceBackend, "trace-backend", + \\Switch between what backend to use. None is default. + ) orelse .None; + } + break :bend .None; + }; - if (trace) { - backend = b.option(TraceBackend, "trace-backend", - \\Switch between what backend to use. None is default. - ) orelse .None; - } - - const use_llvm = b.option(bool, "use-llvm", - \\Uses llvm to compile Osmium. Default true. - ) orelse true; + const use_llvm = b.option(bool, "use-llvm", "Uses llvm to compile Osmium. Default true.") orelse true; + exe.use_llvm = use_llvm; + exe.use_lld = use_llvm; const enable_logging = b.option(bool, "log", "Enable debug logging.") orelse false; - const enable_debug_extensions = b.option( bool, "debug-extensions", "Enable commands and options useful for debugging the compiler", ) orelse (optimize == .Debug); - exe.use_llvm = use_llvm; - exe.use_lld = use_llvm; - const exe_options = b.addOptions(); exe_options.addOption(bool, "trace", trace); exe_options.addOption(TraceBackend, "backend", backend); @@ -56,38 +49,28 @@ pub fn build(b: *std.Build) !void { exe.root_module.addOptions("options", exe_options); const tracer_dep = b.dependency("tracer", .{ .optimize = optimize, .target = target }); - exe.root_module.addImport("tracer", tracer_dep.module("tracer")); - const libgc_dep = b.dependency("libgc", .{ .optimize = optimize, .target = target }); + exe.root_module.addImport("tracer", tracer_dep.module("tracer")); exe.root_module.addImport("gc", libgc_dep.module("gc")); - const build_libpython = b.step("libpython", "Builds libpython"); - const libpython_path = try generateLibPython(b, build_libpython, target, optimize); - - const libpython_install = b.addInstallFile(libpython_path, "lib/libpython3.10.a"); - libpython_install.step.dependOn(build_libpython); + const libpython, const lib_path = try generateLibPython(b, target, optimize); + exe.linkLibrary(libpython); + exe_options.addOption([]const u8, "lib_path", lib_path); - exe.step.dependOn(build_libpython); - exe.addObjectFile(libpython_path); - - b.getInstallStep().dependOn(&libpython_install.step); b.installArtifact(exe); + b.installArtifact(libpython); const run_cmd = b.addRunArtifact(exe); run_cmd.step.dependOn(b.getInstallStep()); - if (b.args) |args| { - run_cmd.addArgs(args); - } + if (b.args) |args| run_cmd.addArgs(args); const run_step = b.step("run", "Run the app"); run_step.dependOn(&run_cmd.step); - // Generate steps const opcode_step = b.step("opcode", "Generate opcodes"); generateOpCode(b, opcode_step); - // Test cases const test_step = b.step("test", "Test Osmium"); try cases.addCases(b, exe, test_step); } @@ -119,12 +102,776 @@ fn generateOpCode( fn generateLibPython( b: *std.Build, - step: *std.Build.Step, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, -) !std.Build.LazyPath { +) !struct { *std.Build.Step.Compile, []const u8 } { const source = b.dependency("python", .{}); - const cpython = CpythonStep.create(b, source.path("."), target, optimize); - step.dependOn(&cpython.step); - return .{ .generated = .{ .file = &cpython.output_file } }; + const t = target.result; + + const python = b.addStaticLibrary(.{ + .name = "python", + .target = target, + .optimize = optimize, + }); + python.linkLibC(); + python.addIncludePath(source.path(".")); + python.addIncludePath(source.path("Include")); + python.addIncludePath(source.path("Include/internal")); + python.defineCMacro("PLATLIBDIR", "\"lib\""); + + python.addConfigHeader(b.addConfigHeader(.{ + .style = .{ .autoconf = source.path("pyconfig.h.in") }, + .include_path = "pyconfig.h", + }, .{ + .ALIGNOF_LONG = 8, + .ALIGNOF_SIZE_T = 8, + .DOUBLE_IS_LITTLE_ENDIAN_IEEE754 = 1, + .ENABLE_IPV6 = 1, + .HAVE_ACCEPT4 = 1, + .HAVE_ACOSH = 1, + .HAVE_ADDRINFO = 1, + .HAVE_ALARM = 1, + .HAVE_ALLOCA_H = 1, + .HAVE_ASINH = 1, + .HAVE_ASM_TYPES_H = 1, + .HAVE_ATANH = 1, + .HAVE_BIND_TEXTDOMAIN_CODESET = 1, + .HAVE_BUILTIN_ATOMIC = 1, + .HAVE_CHOWN = 1, + .HAVE_CHROOT = 1, + .HAVE_CLOCK = 1, + .HAVE_CLOCK_GETRES = 1, + .HAVE_CLOCK_GETTIME = 1, + .HAVE_CLOCK_SETTIME = 1, + .HAVE_CLOSE_RANGE = have(t.isGnuLibC()), + .HAVE_COMPUTED_GOTOS = 1, + .HAVE_CONFSTR = 1, + .HAVE_COPY_FILE_RANGE = 1, + .HAVE_CTERMID = 1, + .HAVE_DECL_RTLD_DEEPBIND = 0, + .HAVE_DECL_RTLD_GLOBAL = 1, + .HAVE_DECL_RTLD_LAZY = 1, + .HAVE_DECL_RTLD_LOCAL = 1, + .HAVE_DECL_RTLD_MEMBER = 0, + .HAVE_DECL_RTLD_NODELETE = 1, + .HAVE_DECL_RTLD_NOLOAD = 1, + .HAVE_DECL_RTLD_NOW = 1, + .HAVE_DEVICE_MACROS = 1, + .HAVE_DEV_PTMX = 1, + .HAVE_DIRENT_D_TYPE = 1, + .HAVE_DIRENT_H = 1, + .HAVE_DIRFD = 1, + .HAVE_DLFCN_H = 1, + .HAVE_DLOPEN = 1, + .EXPERIMENTAL_ISOLATED_SUBINTERPRETERS = null, + .FLOCK_NEEDS_LIBBSD = null, + .HAVE_COPYSIGN = 1, + .HAVE_DECL_ISFINITE = 1, + .HAVE_DECL_ISINF = 1, + .HAVE_DECL_ISNAN = 1, + .HAVE_FINITE = 1, + .HAVE_GAMMA = 1, + .HAVE_HYPOT = 1, + .HAVE_LIBUUID = 1, + .HAVE_ROUND = 1, + .HAVE_TGAMMA = 1, + .HAVE_UCS4_TCL = null, + .SHM_NEEDS_LIBRT = null, + .HAVE_LGAMMA = 1, + .HAVE_DUP2 = 1, + .HAVE_DUP3 = 1, + .HAVE_DYNAMIC_LOADING = 0, + .HAVE_ENDIAN_H = 1, + .HAVE_EPOLL = 1, + .HAVE_EPOLL_CREATE1 = 1, + .HAVE_ERF = 1, + .HAVE_ERFC = 1, + .HAVE_ERRNO_H = 1, + .HAVE_EVENTFD = 1, + .HAVE_EXECV = 1, + .HAVE_EXPLICIT_BZERO = 1, + .HAVE_EXPM1 = 1, + .HAVE_FACCESSAT = 1, + .HAVE_FCHDIR = 1, + .HAVE_FCHMOD = 1, + .HAVE_FCHMODAT = 1, + .HAVE_FCHOWN = 1, + .HAVE_FCHOWNAT = 1, + .HAVE_FCNTL_H = 1, + .HAVE_FDATASYNC = 1, + .HAVE_FDOPENDIR = 1, + .HAVE_FEXECVE = 1, + .HAVE_FLOCK = 1, + .HAVE_FORK = 1, + .HAVE_FORKPTY = 1, + .HAVE_FPATHCONF = 1, + .HAVE_FSEEKO = 1, + .HAVE_FSTATAT = 1, + .HAVE_FSTATVFS = 1, + .HAVE_FSYNC = 1, + .HAVE_FTELLO = 1, + .HAVE_FTIME = 1, + .HAVE_FTRUNCATE = 1, + .HAVE_FUTIMENS = 1, + .HAVE_FUTIMES = 1, + .HAVE_FUTIMESAT = 1, + .HAVE_GAI_STRERROR = 1, + .HAVE_GCC_ASM_FOR_X64 = 1, + .HAVE_GCC_ASM_FOR_X87 = 1, + .HAVE_GCC_UINT128_T = 1, + .HAVE_GETADDRINFO = 1, + .HAVE_GETC_UNLOCKED = 1, + .HAVE_GETENTROPY = 1, + .HAVE_GETGRGID_R = 1, + .HAVE_GETGRNAM_R = 1, + .HAVE_GETGROUPLIST = 1, + .HAVE_GETGROUPS = 1, + .HAVE_GETHOSTBYNAME = 1, + .HAVE_GETHOSTBYNAME_R = 1, + .HAVE_GETHOSTBYNAME_R_6_ARG = 1, + .HAVE_GETITIMER = 1, + .HAVE_GETLOADAVG = 1, + .HAVE_GETLOGIN = 1, + .HAVE_GETNAMEINFO = 1, + .HAVE_GETPAGESIZE = 1, + .HAVE_GETPEERNAME = 1, + .HAVE_GETPGID = 1, + .HAVE_GETPGRP = 1, + .HAVE_GETPID = 1, + .HAVE_GETPRIORITY = 1, + .HAVE_GETPWENT = 1, + .HAVE_GETPWNAM_R = 1, + .HAVE_GETPWUID_R = 1, + .HAVE_GETRANDOM = 1, + .HAVE_GETRANDOM_SYSCALL = 1, + .HAVE_GETRESGID = 1, + .HAVE_GETRESUID = 1, + .HAVE_GETSID = 1, + .HAVE_GETSPENT = 1, + .HAVE_GETSPNAM = 1, + .HAVE_GETWD = 1, + .HAVE_GRP_H = 1, + .HAVE_HSTRERROR = 1, + .HAVE_HTOLE64 = 1, + .HAVE_IF_NAMEINDEX = 1, + .HAVE_INET_ATON = 1, + .HAVE_INET_PTON = 1, + .HAVE_INITGROUPS = 1, + .HAVE_INTTYPES_H = 1, + .HAVE_KILL = 1, + .HAVE_KILLPG = 1, + .HAVE_LANGINFO_H = 1, + .HAVE_LCHOWN = 1, + .HAVE_LIBDL = 1, + .HAVE_LIBINTL_H = 1, + .HAVE_LINK = 1, + .HAVE_LINKAT = 1, + .HAVE_LINUX_AUXVEC_H = 1, + .HAVE_LINUX_CAN_BCM_H = 1, + .HAVE_LINUX_CAN_H = 1, + .HAVE_LINUX_CAN_J1939_H = 1, + .HAVE_LINUX_CAN_RAW_FD_FRAMES = 1, + .HAVE_LINUX_CAN_RAW_H = 1, + .HAVE_LINUX_CAN_RAW_JOIN_FILTERS = 1, + .HAVE_LINUX_MEMFD_H = 1, + .HAVE_LINUX_NETLINK_H = 1, + .HAVE_LINUX_QRTR_H = 1, + .HAVE_LINUX_RANDOM_H = 1, + .HAVE_LINUX_TIPC_H = 1, + .HAVE_LINUX_VM_SOCKETS_H = 1, + .HAVE_LINUX_WAIT_H = 1, + .HAVE_LOCKF = 1, + .HAVE_LOG1P = 1, + .HAVE_LOG2 = 1, + .HAVE_LONG_DOUBLE = 1, + .HAVE_LSTAT = 1, + .HAVE_LUTIMES = 1, + .HAVE_MADVISE = 1, + .HAVE_MAKEDEV = 1, + .HAVE_MBRTOWC = 1, + .HAVE_MEMFD_CREATE = 1, + .HAVE_MEMRCHR = 1, + .HAVE_MKDIRAT = 1, + .HAVE_MKFIFO = 1, + .HAVE_MKFIFOAT = 1, + .HAVE_MKNOD = 1, + .HAVE_MKNODAT = 1, + .HAVE_MKTIME = 1, + .HAVE_MMAP = 1, + .HAVE_MREMAP = 1, + .HAVE_NETPACKET_PACKET_H = 1, + .HAVE_NET_IF_H = 1, + .HAVE_NICE = 1, + .HAVE_OPENAT = 1, + .HAVE_OPENPTY = 1, + .HAVE_PATHCONF = 1, + .HAVE_PAUSE = 1, + .HAVE_PIPE2 = 1, + .HAVE_POLL = 1, + .HAVE_POLL_H = 1, + .HAVE_POSIX_FADVISE = 1, + .HAVE_POSIX_FALLOCATE = 1, + .HAVE_POSIX_SPAWN = 1, + .HAVE_POSIX_SPAWNP = 1, + .HAVE_PREAD = 1, + .HAVE_PREADV = 1, + .HAVE_PREADV2 = have(t.isGnuLibC()), + .HAVE_PRLIMIT = 1, + .HAVE_PROTOTYPES = 1, + .HAVE_PTHREAD_CONDATTR_SETCLOCK = 1, + .HAVE_PTHREAD_GETCPUCLOCKID = 1, + .HAVE_PTHREAD_H = 1, + .HAVE_PTHREAD_KILL = 1, + .HAVE_PTHREAD_SIGMASK = 1, + .HAVE_PTY_H = 1, + .HAVE_PWRITE = 1, + .HAVE_PWRITEV = 1, + .HAVE_PWRITEV2 = have(t.isGnuLibC()), + .HAVE_READLINK = 1, + .HAVE_READLINKAT = 1, + .HAVE_READV = 1, + .HAVE_REALPATH = 1, + .HAVE_RENAMEAT = 1, + .HAVE_SCHED_GET_PRIORITY_MAX = 1, + .HAVE_SCHED_H = 1, + .HAVE_SCHED_RR_GET_INTERVAL = 1, + .HAVE_SCHED_SETAFFINITY = 1, + .HAVE_SCHED_SETPARAM = 1, + .HAVE_SCHED_SETSCHEDULER = 1, + .HAVE_SEM_CLOCKWAIT = have(t.isGnuLibC()), + .HAVE_SEM_GETVALUE = 1, + .HAVE_SEM_OPEN = 1, + .HAVE_SEM_TIMEDWAIT = 1, + .HAVE_SEM_UNLINK = 1, + .HAVE_SENDFILE = 1, + .HAVE_SETEGID = 1, + .HAVE_SETEUID = 1, + .HAVE_SETGID = 1, + .HAVE_SETGROUPS = 1, + .HAVE_SETHOSTNAME = 1, + .HAVE_SETITIMER = 1, + .HAVE_SETLOCALE = 1, + .HAVE_SETPGID = 1, + .HAVE_SETPGRP = 1, + .HAVE_SETPRIORITY = 1, + .HAVE_SETREGID = 1, + .HAVE_SETRESGID = 1, + .HAVE_SETRESUID = 1, + .HAVE_SETREUID = 1, + .HAVE_SETSID = 1, + .HAVE_SETUID = 1, + .HAVE_SETVBUF = 1, + .HAVE_SHADOW_H = 1, + .HAVE_SHM_OPEN = 1, + .HAVE_SHM_UNLINK = 1, + .HAVE_SIGACTION = 1, + .HAVE_SIGALTSTACK = 1, + .HAVE_SIGFILLSET = 1, + .HAVE_SIGINFO_T_SI_BAND = 1, + .HAVE_SIGINTERRUPT = 1, + .HAVE_SIGNAL_H = 1, + .HAVE_SIGPENDING = 1, + .HAVE_SIGRELSE = 1, + .HAVE_SIGTIMEDWAIT = 1, + .HAVE_SIGWAIT = 1, + .HAVE_SIGWAITINFO = 1, + .HAVE_SNPRINTF = 1, + .HAVE_SOCKADDR_ALG = 1, + .HAVE_SOCKADDR_STORAGE = 1, + .HAVE_SOCKETPAIR = 1, + .HAVE_SPAWN_H = 1, + .HAVE_SPLICE = 1, + .HAVE_SSIZE_T = 1, + .HAVE_STATVFS = 1, + .HAVE_STAT_TV_NSEC = 1, + .HAVE_STDARG_PROTOTYPES = 1, + .HAVE_STDINT_H = 1, + .HAVE_STDLIB_H = 1, + .HAVE_STD_ATOMIC = 1, + .HAVE_STRFTIME = 1, + .HAVE_STRINGS_H = 1, + .HAVE_STRING_H = 1, + .HAVE_STRSIGNAL = 1, + .HAVE_STRUCT_PASSWD_PW_GECOS = 1, + .HAVE_STRUCT_PASSWD_PW_PASSWD = 1, + .HAVE_STRUCT_STAT_ST_BLKSIZE = 1, + .HAVE_STRUCT_STAT_ST_BLOCKS = 1, + .HAVE_STRUCT_STAT_ST_RDEV = 1, + .HAVE_STRUCT_TM_TM_ZONE = 1, + .HAVE_SYMLINK = 1, + .HAVE_SYMLINKAT = 1, + .HAVE_SYNC = 1, + .HAVE_SYSCONF = 1, + .HAVE_SYSEXITS_H = 1, + .HAVE_SYS_AUXV_H = 1, + .HAVE_SYS_EPOLL_H = 1, + .HAVE_SYS_EVENTFD_H = 1, + .HAVE_SYS_FILE_H = 1, + .HAVE_SYS_IOCTL_H = 1, + .HAVE_SYS_MMAN_H = 1, + .HAVE_SYS_PARAM_H = 1, + .HAVE_SYS_POLL_H = 1, + .HAVE_SYS_RANDOM_H = 1, + .HAVE_SYS_RESOURCE_H = 1, + .HAVE_SYS_SELECT_H = 1, + .HAVE_SYS_SENDFILE_H = 1, + .HAVE_SYS_SOCKET_H = 1, + .HAVE_SYS_STATVFS_H = 1, + .HAVE_SYS_STAT_H = 1, + .HAVE_SYS_SYSCALL_H = 1, + .HAVE_SYS_SYSMACROS_H = 1, + .HAVE_SYS_TIMES_H = 1, + .HAVE_SYS_TIME_H = 1, + .HAVE_SYS_TYPES_H = 1, + .HAVE_SYS_UIO_H = 1, + .HAVE_SYS_UN_H = 1, + .HAVE_SYS_UTSNAME_H = 1, + .HAVE_SYS_WAIT_H = 1, + .HAVE_SYS_XATTR_H = 1, + .HAVE_TCGETPGRP = 1, + .HAVE_TCSETPGRP = 1, + .HAVE_TEMPNAM = 1, + .HAVE_TERMIOS_H = 1, + .HAVE_TIMEGM = 1, + .HAVE_TIMES = 1, + .HAVE_TMPFILE = 1, + .HAVE_TMPNAM = 1, + .HAVE_TMPNAM_R = 1, + .HAVE_TM_ZONE = 1, + .HAVE_TRUNCATE = 1, + .HAVE_UNAME = 1, + .HAVE_UNISTD_H = 1, + .HAVE_UNLINKAT = 1, + .HAVE_UTIMENSAT = 1, + .HAVE_UTIMES = 1, + .HAVE_UTIME_H = 1, + .HAVE_VFORK = 1, + .HAVE_WAIT3 = 1, + .HAVE_WAIT4 = 1, + .HAVE_WAITID = 1, + .HAVE_WAITPID = 1, + .HAVE_WCHAR_H = 1, + .HAVE_WCSCOLL = 1, + .HAVE_WCSFTIME = 1, + .HAVE_WCSXFRM = 1, + .HAVE_WMEMCMP = 1, + .HAVE_WORKING_TZSET = 1, + .HAVE_WRITEV = 1, + .MAJOR_IN_SYSMACROS = 1, + .PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT = 1, + .PTHREAD_SYSTEM_SCHED_SUPPORTED = 1, + .PY_BUILTIN_HASHLIB_HASHES = "md5,sha1,sha256,sha512,sha3,blake2", + .PY_COERCE_C_LOCALE = 1, + .PY_FORMAT_SIZE_T = "z", + .PY_SSL_DEFAULT_CIPHERS = 1, + .RETSIGTYPE = .void, + .SIZEOF_DOUBLE = 8, + .SIZEOF_FLOAT = 4, + .SIZEOF_FPOS_T = 16, + .SIZEOF_INT = 4, + .SIZEOF_LONG = 8, + .SIZEOF_LONG_DOUBLE = 16, + .SIZEOF_LONG_LONG = 8, + .SIZEOF_OFF_T = 8, + .SIZEOF_PID_T = 4, + .SIZEOF_PTHREAD_KEY_T = 4, + .SIZEOF_PTHREAD_T = 8, + .SIZEOF_SHORT = 2, + .SIZEOF_SIZE_T = 8, + .SIZEOF_TIME_T = 8, + .SIZEOF_UINTPTR_T = 8, + .SIZEOF_VOID_P = 8, + .SIZEOF_WCHAR_T = 4, + .SIZEOF__BOOL = 1, + .STDC_HEADERS = 1, + .SYS_SELECT_WITH_SYS_TIME = 1, + .TIME_WITH_SYS_TIME = 1, + .WITH_DECIMAL_CONTEXTVAR = 1, + .WITH_DOC_STRINGS = 1, + .WITH_PYMALLOC = 1, + ._DARWIN_C_SOURCE = 1, + ._FILE_OFFSET_BITS = 64, + ._LARGEFILE_SOURCE = 1, + ._NETBSD_SOURCE = 1, + ._POSIX_C_SOURCE = .@"200809L", + ._PYTHONFRAMEWORK = "", + ._REENTRANT = 1, + ._XOPEN_SOURCE = 700, + ._XOPEN_SOURCE_EXTENDED = 1, + .__BSD_VISIBLE = 1, + ._ALL_SOURCE = 1, + ._POSIX_PTHREAD_SEMANTICS = 1, + ._TANDEM_SOURCE = 1, + .__EXTENSIONS__ = 1, + .AC_APPLE_UNIVERSAL_BUILD = null, + .AIX_BUILDDATE = null, + .AIX_GENUINE_CPLUSPLUS = null, + .ALT_SOABI = null, + .ANDROID_API_LEVEL = null, + .DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754 = null, + .DOUBLE_IS_BIG_ENDIAN_IEEE754 = null, + .FLOAT_WORDS_BIGENDIAN = null, + .GETPGRP_HAVE_ARG = null, + .HAVE_ALIGNED_REQUIRED = null, + .HAVE_ALTZONE = null, + .HAVE_BLUETOOTH_BLUETOOTH_H = null, + .HAVE_BLUETOOTH_H = null, + .HAVE_BROKEN_MBSTOWCS = null, + .HAVE_BROKEN_NICE = null, + .HAVE_BROKEN_PIPE_BUF = null, + .HAVE_BROKEN_POLL = null, + .HAVE_BROKEN_POSIX_SEMAPHORES = null, + .HAVE_BROKEN_PTHREAD_SIGMASK = null, + .HAVE_BROKEN_SEM_GETVALUE = null, + .HAVE_BROKEN_UNSETENV = null, + .HAVE_CHFLAGS = null, + .HAVE_CONIO_H = null, + .HAVE_CRYPT_H = null, + .HAVE_CRYPT_R = null, + .HAVE_CTERMID_R = null, + .HAVE_CURSES_FILTER = null, + .HAVE_CURSES_H = null, + .HAVE_CURSES_HAS_KEY = null, + .HAVE_CURSES_IMMEDOK = null, + .HAVE_CURSES_IS_PAD = null, + .HAVE_CURSES_IS_TERM_RESIZED = null, + .HAVE_CURSES_RESIZETERM = null, + .HAVE_CURSES_RESIZE_TERM = null, + .HAVE_CURSES_SYNCOK = null, + .HAVE_CURSES_TYPEAHEAD = null, + .HAVE_CURSES_USE_ENV = null, + .HAVE_CURSES_WCHGAT = null, + .HAVE_DECL_TZNAME = null, + .HAVE_DEV_PTC = null, + .HAVE_DIRECT_H = null, + .HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH = null, + .HAVE_EXPLICIT_MEMSET = null, + .HAVE_FDWALK = null, + ._GNU_SOURCE = 1, + .HAVE_FSEEK64 = null, + .HAVE_FTELL64 = null, + .HAVE_GCC_ASM_FOR_MC68881 = null, + .HAVE_GETHOSTBYNAME_R_3_ARG = null, + .HAVE_GETHOSTBYNAME_R_5_ARG = null, + .HAVE_GLIBC_MEMMOVE_BUG = null, + .HAVE_IEEEFP_H = null, + .HAVE_IO_H = null, + .HAVE_IPA_PURE_CONST_BUG = null, + .HAVE_KQUEUE = null, + .HAVE_LARGEFILE_SUPPORT = null, + .HAVE_LCHFLAGS = null, + .HAVE_LCHMOD = null, + .HAVE_LIBDLD = null, + .HAVE_LIBIEEE = null, + .HAVE_LIBREADLINE = null, + .HAVE_LIBRESOLV = null, + .HAVE_LIBSENDFILE = null, + .HAVE_LIBUTIL_H = null, + .HAVE_MEMORY_H = null, + .HAVE_NCURSES_H = null, + .HAVE_NDIR_H = null, + .HAVE_NON_UNICODE_WCHAR_T_REPRESENTATION = null, + .HAVE_PLOCK = null, + .HAVE_PROCESS_H = null, + .HAVE_PTHREAD_DESTRUCTOR = null, + .HAVE_PTHREAD_INIT = null, + .HAVE_RL_APPEND_HISTORY = null, + .HAVE_RL_CATCH_SIGNAL = null, + .HAVE_RL_COMPLETION_APPEND_CHARACTER = null, + .HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK = null, + .HAVE_RL_COMPLETION_MATCHES = null, + .HAVE_RL_COMPLETION_SUPPRESS_APPEND = null, + .HAVE_RL_PRE_INPUT_HOOK = null, + .HAVE_RL_RESIZE_TERMINAL = null, + .HAVE_RTPSPAWN = null, + .HAVE_SOCKADDR_SA_LEN = null, + .HAVE_STAT_TV_NSEC2 = null, + .HAVE_STRLCPY = null, + .HAVE_STROPTS_H = null, + .HAVE_STRUCT_STAT_ST_BIRTHTIME = null, + .HAVE_STRUCT_STAT_ST_FLAGS = null, + .HAVE_STRUCT_STAT_ST_GEN = null, + .HAVE_SYS_AUDIOIO_H = null, + .HAVE_SYS_BSDTTY_H = null, + .HAVE_SYS_DEVPOLL_H = null, + .HAVE_SYS_DIR_H = null, + .HAVE_SYS_ENDIAN_H = null, + .HAVE_SYS_EVENT_H = null, + .HAVE_SYS_KERN_CONTROL_H = null, + .HAVE_SYS_LOADAVG_H = null, + .HAVE_SYS_LOCK_H = null, + .HAVE_SYS_MEMFD_H = null, + .HAVE_SYS_MKDEV_H = null, + .HAVE_SYS_MODEM_H = null, + .HAVE_SYS_NDIR_H = null, + .HAVE_SYS_SYS_DOMAIN_H = null, + .HAVE_SYS_TERMIO_H = null, + .HAVE_TERM_H = null, + .HAVE_TZNAME = null, + .HAVE_USABLE_WCHAR_T = null, + .HAVE_UTIL_H = null, + .HAVE_UUID_CREATE = null, + .HAVE_UUID_ENC_BE = null, + .HAVE_UUID_GENERATE_TIME_SAFE = null, + .HAVE_UUID_H = null, + .HAVE_UUID_UUID_H = null, + .HAVE_ZLIB_COPY = 1, + .HAVE__GETPTY = null, + .MAJOR_IN_MKDEV = null, + .MVWDELCH_IS_EXPRESSION = null, + .PACKAGE_BUGREPORT = null, + .PACKAGE_NAME = null, + .PACKAGE_STRING = null, + .PACKAGE_TARNAME = null, + .PACKAGE_URL = null, + .PACKAGE_VERSION = null, + .POSIX_SEMAPHORES_NOT_ENABLED = null, + .PYLONG_BITS_IN_DIGIT = null, + .PY_SSL_DEFAULT_CIPHER_STRING = null, + .Py_DEBUG = null, + .Py_ENABLE_SHARED = null, + .Py_HASH_ALGORITHM = null, + .Py_TRACE_REFS = null, + .SETPGRP_HAVE_ARG = null, + .SIGNED_RIGHT_SHIFT_ZERO_FILLS = null, + .THREAD_STACK_SIZE = null, + .TIMEMODULE_LIB = null, + .TM_IN_SYS_TIME = null, + .USE_COMPUTED_GOTOS = null, + .WINDOW_HAS_FLAGS = null, + .WITH_DTRACE = null, + .WITH_DYLD = null, + .WITH_EDITLINE = null, + .WITH_LIBINTL = null, + .WITH_NEXT_FRAMEWORK = null, + .WITH_VALGRIND = null, + .X87_DOUBLE_ROUNDING = null, + ._BSD_SOURCE = null, + ._INCLUDE__STDC_A1_SOURCE = null, + ._LARGE_FILES = null, + ._MINIX = null, + ._POSIX_1_SOURCE = null, + ._POSIX_SOURCE = null, + ._POSIX_THREADS = null, + .clock_t = null, + .@"const" = null, + .gid_t = null, + .mode_t = null, + .off_t = null, + .pid_t = null, + .signed = null, + .size_t = null, + .socklen_t = null, + .uid_t = null, + .WORDS_BIGENDIAN = null, + })); + + python.addCSourceFiles(.{ .root = source.path("."), .files = &.{ + "Modules/_abc.c", + "Modules/_codecsmodule.c", + "Modules/_collectionsmodule.c", + "Modules/_contextvarsmodule.c", + "Modules/_functoolsmodule.c", + "Modules/_io/_iomodule.c", + "Modules/_io/bufferedio.c", + "Modules/_io/bytesio.c", + "Modules/_io/fileio.c", + "Modules/_io/iobase.c", + "Modules/_io/stringio.c", + "Modules/_io/textio.c", + "Modules/_localemodule.c", + "Modules/_operator.c", + "Modules/_posixsubprocess.c", + "Modules/_randommodule.c", + "Modules/_sre.c", + "Modules/_ssl.c", + "Modules/_stat.c", + "Modules/_struct.c", + "Modules/_threadmodule.c", + "Modules/_tracemalloc.c", + "Modules/_weakref.c", + "Modules/arraymodule.c", + "Modules/atexitmodule.c", + "Modules/binascii.c", + "Modules/config.c", + "Modules/errnomodule.c", + "Modules/faulthandler.c", + "Modules/gcmodule.c", + "Modules/getbuildinfo.c", + "Modules/itertoolsmodule.c", + "Modules/main.c", + "Modules/mathmodule.c", + "Modules/md5module.c", + "Modules/sha1module.c", + "Modules/sha256module.c", + + "Modules/_blake2/blake2module.c", + "Modules/_blake2/blake2b_impl.c", + "Modules/_blake2/blake2s_impl.c", + + "Modules/_sha3/sha3module.c", + + "Modules/posixmodule.c", + "Modules/pwdmodule.c", + "Modules/selectmodule.c", + "Modules/sha512module.c", + "Modules/signalmodule.c", + "Modules/socketmodule.c", + "Modules/symtablemodule.c", + "Modules/timemodule.c", + "Modules/unicodedata.c", + "Modules/xxsubtype.c", + "Modules/zlibmodule.c", + "Objects/abstract.c", + "Objects/accu.c", + "Objects/boolobject.c", + "Objects/bytearrayobject.c", + "Objects/bytes_methods.c", + "Objects/bytesobject.c", + "Objects/call.c", + "Objects/capsule.c", + "Objects/cellobject.c", + "Objects/classobject.c", + "Objects/codeobject.c", + "Objects/complexobject.c", + "Objects/descrobject.c", + "Objects/dictobject.c", + "Objects/enumobject.c", + "Objects/exceptions.c", + "Objects/fileobject.c", + "Objects/floatobject.c", + "Objects/frameobject.c", + "Objects/funcobject.c", + "Objects/genericaliasobject.c", + "Objects/genobject.c", + "Objects/interpreteridobject.c", + "Objects/iterobject.c", + "Objects/listobject.c", + "Objects/longobject.c", + "Objects/memoryobject.c", + "Objects/methodobject.c", + "Objects/moduleobject.c", + "Objects/namespaceobject.c", + "Objects/object.c", + "Objects/obmalloc.c", + "Objects/odictobject.c", + "Objects/picklebufobject.c", + "Objects/rangeobject.c", + "Objects/setobject.c", + "Objects/sliceobject.c", + "Objects/structseq.c", + "Objects/tupleobject.c", + "Objects/typeobject.c", + "Objects/unicodectype.c", + "Objects/unicodeobject.c", + "Objects/unionobject.c", + "Objects/weakrefobject.c", + "Parser/myreadline.c", + "Parser/parser.c", + "Parser/peg_api.c", + "Parser/pegen.c", + "Parser/string_parser.c", + "Parser/token.c", + "Parser/tokenizer.c", + "Python/Python-ast.c", + "Python/_warnings.c", + "Python/asdl.c", + "Python/ast.c", + "Python/ast_opt.c", + "Python/ast_unparse.c", + "Python/bltinmodule.c", + "Python/bootstrap_hash.c", + "Python/ceval.c", + "Python/codecs.c", + "Python/compile.c", + "Python/context.c", + "Python/dtoa.c", + "Python/dynamic_annotations.c", + "Python/errors.c", + "Python/fileutils.c", + "Python/formatter_unicode.c", + "Python/frozen.c", + "Python/frozenmain.c", + "Python/future.c", + "Python/getargs.c", + "Python/getcompiler.c", + "Python/getcopyright.c", + "Python/getopt.c", + "Python/getplatform.c", + "Python/getversion.c", + "Python/hamt.c", + "Python/hashtable.c", + "Python/import.c", + "Python/importdl.c", + "Python/initconfig.c", + "Python/marshal.c", + "Python/modsupport.c", + "Python/mysnprintf.c", + "Python/mystrtoul.c", + "Python/pathconfig.c", + "Python/preconfig.c", + "Python/pyarena.c", + "Python/pyctype.c", + "Python/pyfpe.c", + "Python/pyhash.c", + "Python/pylifecycle.c", + "Python/pymath.c", + "Python/pystate.c", + "Python/pystrcmp.c", + "Python/pystrhex.c", + "Python/pystrtod.c", + "Python/pythonrun.c", + "Python/pytime.c", + "Python/structmember.c", + "Python/suggestions.c", + "Python/symtable.c", + "Python/sysmodule.c", + "Python/thread.c", + "Python/traceback.c", + }, .flags = &.{ + "-fwrapv", + "-std=c11", + "-fvisibility=hidden", + "-DPy_BUILD_CORE", + } }); + + python.addCSourceFiles(.{ .root = source.path("."), .files = &.{ + "Modules/getpath.c", + }, .flags = &.{ + "-fwrapv", + "-std=c11", + "-fvisibility=hidden", + "-DPy_BUILD_CORE", + + "-DPYTHONPATH=\"\"", + "-DPREFIX=\"/usr/local\"", + "-DEXEC_PREFIX=\"/usr/local\"", + "-DVERSION=\"3.10\"", + "-DVPATH=\"\"", + "-DPLATLIBDIR=\"lib\"", + "-DPYTHONFRAMEWORK=\"\"", + } }); + + python.addCSourceFiles(.{ .root = source.path("."), .files = &.{ + "Python/dynload_shlib.c", + }, .flags = &.{ + "-fwrapv", + "-std=c11", + "-fvisibility=hidden", + "-DPy_BUILD_CORE", + + b.fmt("-DSOABI=\"cpython-310-{s}\"", .{try t.linuxTriple(b.allocator)}), + } }); + + b.installDirectory(.{ + .source_dir = source.path("Lib"), + .install_dir = .{ .custom = "python" }, + .install_subdir = "Lib", + }); + + return .{ python, b.fmt("{s}/python/Lib", .{b.install_path}) }; +} + +fn have(x: bool) ?u1 { + return if (x) 1 else null; } diff --git a/build.zig.zon b/build.zig.zon index ef029fd..c300c2c 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -14,8 +14,8 @@ .hash = "122057453dba0b0cf6f07610d692cc7ab3f1d66defa150c936b398144812564a0c08", }, .python = .{ - .url = "https://github.com/python/cpython/archive/333c7dccd87c637d0b15cf81f9bbec28e39664fd.tar.gz", - .hash = "1220c520b358bd5e0bbcfae04b2e9e963ad3c3d7cc3b5ba24a0721e60a0123bfb1ea", + .url = "https://github.com/Rexicon226/cpython/archive/cdb93314157b15ba6ba0832f4ad7c84c11088331.tar.gz", + .hash = "12201233efd4fb9453166782f1beb083953b3e9cc2b347621a55482addf0714e6962", }, .libgc = .{ .url = "https://github.com/Rexicon226/zig-libgc/archive/1ea12e140ec1471af5d15dae71b225764c9747ba.tar.gz", diff --git a/build/CpythonStep.zig b/build/CpythonStep.zig deleted file mode 100644 index 3c47f43..0000000 --- a/build/CpythonStep.zig +++ /dev/null @@ -1,153 +0,0 @@ -//! A step for building libcpython that allows for caching the output - -const std = @import("std"); -const CpythonStep = @This(); - -step: std.Build.Step, -cpython_dir: std.Build.LazyPath, -target: std.Build.ResolvedTarget, -optimize: std.builtin.OptimizeMode, -output_file: std.Build.GeneratedFile, - -pub fn create( - b: *std.Build, - cpython_dir: std.Build.LazyPath, - target: std.Build.ResolvedTarget, - optimize: std.builtin.OptimizeMode, -) *CpythonStep { - const self = b.allocator.create(CpythonStep) catch @panic("OOM"); - self.* = .{ - .step = std.Build.Step.init(.{ - .id = .custom, - .name = "Build libpython", - .owner = b, - .makeFn = make, - }), - .cpython_dir = cpython_dir, - .target = target, - .optimize = optimize, - .output_file = .{ .step = &self.step }, - }; - return self; -} - -fn make(step: *std.Build.Step, prog: std.Progress.Node) anyerror!void { - const b = step.owner; - const self: *CpythonStep = @fieldParentPtr("step", step); - - var man = b.graph.cache.obtain(); - defer man.deinit(); - - man.hash.add(@as(u32, 0x5a2b3c4d)); - - man.hash.addBytes(try self.target.result.linuxTriple(b.allocator)); - man.hash.add(self.optimize); - - if (try step.cacheHit(&man)) { - const digest = man.final(); - self.output_file.path = try b.cache_root.join( - b.allocator, - &.{ "o", &digest, "libpython3.10.a" }, - ); - step.result_cached = true; - return; - } - - const digest = man.final(); - const cache_path = "o" ++ std.fs.path.sep_str ++ digest; - - var cache_dir = b.cache_root.handle.makeOpenPath(cache_path, .{}) catch |err| { - return step.fail("unable to make path = 1,{}{s} = 1,: {s}", .{ - b.cache_root, cache_path, @errorName(err), - }); - }; - defer cache_dir.close(); - - const target_triple = try self.target.result.linuxTriple(b.allocator); - - var args = std.ArrayList([]const u8).init(b.allocator); - defer args.deinit(); - - { - const cpython_dir = self.cpython_dir; - try args.append(cpython_dir.path(b, "configure").getPath2(b, step)); - try args.appendSlice(&.{ - "--disable-shared", - if (self.optimize == .Debug) "" else "--enable-optimizations", - }); - try args.append(b.fmt("--host={s}", .{target_triple})); - try args.append(b.fmt("--build={s}", .{try b.host.result.linuxTriple(b.allocator)})); - try args.append("--disable-ipv6"); - - var configure_env_map = std.process.EnvMap.init(b.allocator); - try configure_env_map.put("READELF", "llvm-readelf"); - try configure_env_map.put("CC", b.fmt("{s} {s}", .{ b.graph.zig_exe, "cc" })); - try configure_env_map.put("CXX", b.fmt("{s} {s}", .{ b.graph.zig_exe, "c++" })); - try configure_env_map.put("CFLAGS", b.fmt("-target {s}", .{target_triple})); - - var iter = b.graph.env_map.iterator(); - while (iter.next()) |entry| { - try configure_env_map.put(entry.key_ptr.*, entry.value_ptr.*); - } - - const configure_args = try args.toOwnedSlice(); - try std.Build.Step.handleVerbose(b, null, configure_args); - - const configure_prog = prog.start("Configure libpython3.10.a", 0); - defer configure_prog.end(); - - const configure_result = std.process.Child.run(.{ - .allocator = b.allocator, - .argv = configure_args, - .env_map = &configure_env_map, - .cwd_dir = cache_dir, - }) catch |err| return step.fail("unable to spawn {s}: {s}", .{ configure_args[0], @errorName(err) }); - if (configure_result.term != .Exited) return step.fail("configure not exited", .{}); - if (configure_result.term.Exited != 0) return step.fail( - "configure exited with code {d}", - .{configure_result.term.Exited}, - ); - } - - { - try args.appendSlice(&.{ - "make", - "-s", - b.fmt("-j{d}", .{try std.Thread.getCpuCount()}), - "libpython3.10.a", - }); - - var make_env_map = std.process.EnvMap.init(b.allocator); - try make_env_map.put("CFLAGS", b.fmt("-target {s}", .{target_triple})); - - var iter = b.graph.env_map.iterator(); - while (iter.next()) |entry| { - try make_env_map.put(entry.key_ptr.*, entry.value_ptr.*); - } - - const make_args = try args.toOwnedSlice(); - try std.Build.Step.handleVerbose(b, null, make_args); - - const make_prog = prog.start("Make libpython3.10.a", 0); - defer make_prog.end(); - - const make_result = std.process.Child.run(.{ - .allocator = b.allocator, - .argv = make_args, - .env_map = &make_env_map, - .cwd_dir = cache_dir, - }) catch |err| return step.fail("unable to spawn {s}: {s}", .{ make_args[0], @errorName(err) }); - if (make_result.term != .Exited) return step.fail("make not exited", .{}); - if (make_result.term.Exited != 0) return step.fail( - "make exited with code {d}", - .{make_result.term.Exited}, - ); - } - - self.output_file.path = try b.cache_root.join( - b.allocator, - &.{ "o", &digest, "libpython3.10.a" }, - ); - - try step.writeManifest(&man); -} diff --git a/src/frontend/Python.zig b/src/frontend/Python.zig index ac6c0e9..1781905 100644 --- a/src/frontend/Python.zig +++ b/src/frontend/Python.zig @@ -19,12 +19,7 @@ pub fn parse( const t = tracer.trace(@src(), "", .{}); defer t.end(); - // TODO: investigate how to correctly pre init, this keeps crashing for some reason - // cpython.PreInitialize(); - // const cname = cpython.DecodeLocale(std.mem.span(std.os.argv[0])); - // cpython.SetProgramName(cname); - - cpython.Initialize(); + try cpython.Initialize(allocator, build_options.lib_path); const compiled = cpython.CompileString(source, filename); if (null == compiled) { @@ -44,7 +39,6 @@ pub fn parse( } // construct the final pyc bytes - const pyc_bytes = ptr.?[0..size]; const bytes = try allocator.alloc(u8, size + 16); @@ -74,3 +68,4 @@ const log = std.log.scoped(.python); const cpython = @import("cpython.zig"); const tracer = @import("tracer"); +const build_options = @import("options"); diff --git a/src/frontend/cpython.zig b/src/frontend/cpython.zig index d3dae7d..538dca5 100644 --- a/src/frontend/cpython.zig +++ b/src/frontend/cpython.zig @@ -8,6 +8,92 @@ const std = @import("std"); const tracer = @import("tracer"); const log = std.log.scoped(.cpython); +const assert = std.debug.assert; + +const PyWideStringList = extern struct { + length: isize, + items: [*][*]u16, + + pub fn utf8ToUtf32Z( + in: []const u8, + allocator: std.mem.Allocator, + ) ![:0]const u32 { + var buffer = std.ArrayList(u32).init(allocator); + for (in) |char| { + try buffer.append(char); + } + return buffer.toOwnedSliceSentinel(0); + } +}; + +const PyConfig = extern struct { + _config_init: c_int, + + isolated: c_int, + use_environment: c_int, + dev_mode: c_int, + install_signal_handlers: c_int, + use_hash_seed: c_int, + hash_seed: u64, + faulthandler: c_int, + tracemalloc: c_int, + import_time: c_int, + show_ref_count: c_int, + dump_refs: c_int, + malloc_stats: c_int, + filesystem_encoding: [*:0]u16, + filesystem_errors: [*:0]u16, + pycache_prefix: [*:0]u16, + parse_argv: c_int, + orig_argv: PyWideStringList, + argv: PyWideStringList, + xoptions: PyWideStringList, + warnoptions: PyWideStringList, + site_import: c_int, + bytes_warning: c_int, + warn_default_encoding: c_int, + inspect: c_int, + interactive: c_int, + optimization_level: c_int, + parser_debug: c_int, + write_bytecode: c_int, + verbose: c_int, + quiet: c_int, + user_site_directory: c_int, + configure_c_stdio: c_int, + buffered_stdio: c_int, + stdio_encoding: [*:0]u16, + stdio_errors: [*:0]u16, + check_hash_pycs_mode: [*:0]u16, + + // --- Path configuration inputs ------------ + pathconfig_warnings: c_int, + program_name: [*:0]u16, + pythonpath_env: [*:0]u16, + home: [*:0]u16, + platlibdir: [*:0]u16, + + // --- Path configuration outputs ----------- + module_search_paths_set: c_int, + module_search_paths: PyWideStringList, + executable: [*:0]u16, + base_executable: [*:0]u16, + prefix: [*:0]u16, + base_prefix: [*:0]u16, + exec_prefix: [*:0]u16, + base_exec_prefix: [*:0]u16, + + // --- Py_Main() --- + skip_source_first_line: c_int, + run_command: [*:0]u16, + run_module: [*:0]u16, + run_filename: [*:0]u16, + + _install_importlib: c_int, + _init_main: c_int, + _isolated_interpreter: c_int, +}; + const PyPreConfig = extern struct { _config_init: c_int, parse_argv: c_int, @@ -43,7 +129,7 @@ const PyStatus = extern struct { func: [*:0]const u8, }; -extern fn Py_PreInitialize(*PyPreConfig) PyStatus; +extern fn Py_PreInitialize(*const PyPreConfig) PyStatus; extern fn PyPreConfig_InitPythonConfig(*PyPreConfig) void; extern fn PyStatus_Exception(PyStatus) bool; extern fn Py_ExitStatusException(PyStatus) noreturn; @@ -51,9 +137,12 @@ extern fn Py_ExitStatusException(PyStatus) noreturn; extern fn Py_Initialize() void; extern fn Py_Finalize() void; +extern fn PySys_SetPath([*:0]const u16) void; + extern fn Py_DecRef(?*anyopaque) void; extern fn Py_DecodeLocale([*:0]const u8, *usize) ?[*:0]u8; +extern fn PyConfig_SetBytesString(*PyConfig, *const [*:0]u16, [*:0]const u8) PyStatus; extern fn Py_SetProgramName([*:0]const u8) void; extern fn Py_CompileString([*:0]const u8, [*:0]const u8, c_int) ?*anyopaque; @@ -65,29 +154,45 @@ extern fn PyErr_Print() void; extern fn PyErr_Fetch(?*anyopaque, ?*anyopaque, ?*anyopaque) void; extern fn PyErr_NormalizeException(?*anyopaque, ?*anyopaque, ?*anyopaque) void; -const Py_file_input: c_int = 257; -const Py_MARSHAL_VERSION: c_int = 4; - -pub fn PreInitialize() void { - var preconfig: PyPreConfig = undefined; - PyPreConfig_InitPythonConfig(&preconfig); +extern fn PyConfig_InitPythonConfig(*PyConfig) void; +extern fn PyConfig_Clear(*PyConfig) void; +extern fn PyConfig_Read(*PyConfig) PyStatus; +extern fn Py_InitializeFromConfig(*PyConfig) PyStatus; - // Enables CPython's UTF-8 Mode. - preconfig.utf8_mode = 0; +extern fn PyWideStringList_Append(*PyWideStringList, [*:0]const u32) PyStatus; - // log.debug("PreConfig:\n{}", .{preconfig}); - - const status = Py_PreInitialize(&preconfig); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } -} - -pub fn Initialize() void { - const t = tracer.trace(@src(), "", .{}); - defer t.end(); +const Py_file_input: c_int = 257; +const Py_MARSHAL_VERSION: c_int = 4; - Py_Initialize(); +pub fn Initialize( + allocator: std.mem.Allocator, + lib_path: []const u8, +) !void { + var config: PyConfig = undefined; + PyConfig_InitPythonConfig(&config); + defer PyConfig_Clear(&config); + + // mute some silly errors that probably do infact matter + config.pathconfig_warnings = 0; + + _ = PyConfig_SetBytesString( + &config, + &config.program_name, + "osmium".ptr, + ); + _ = PyConfig_Read(&config); + + const utf32_path = try PyWideStringList.utf8ToUtf32Z(lib_path, allocator); + + config.module_search_paths_set = 1; + _ = PyWideStringList_Append( + &config.module_search_paths, + utf32_path.ptr, + ); + + const status = Py_InitializeFromConfig(&config); + // needs to be a pointer discard because the stack protector gets overrun? + _ = &status; } pub fn Finalize() void { @@ -97,22 +202,16 @@ pub fn Finalize() void { Py_Finalize(); } -pub fn DecRef(code: ?*anyopaque) void { - const t = tracer.trace(@src(), "", .{}); - defer t.end(); - - Py_DecRef(code); +/// Takes a UTF-8 +pub fn Sys_SetPath(path: [:0]const u16) void { + PySys_SetPath(path.ptr); } -pub fn DecodeLocale(argv: [:0]const u8) [:0]const u8 { +pub fn DecRef(code: ?*anyopaque) void { const t = tracer.trace(@src(), "", .{}); defer t.end(); - var len: u64 = undefined; - if (Py_DecodeLocale(argv.ptr, &len)) |program| { - return program[0 .. len + 1 :0]; - } - std.debug.panic("Fatal error: cannot decode {s}", .{argv}); + Py_DecRef(code); } pub fn SetProgramName(name: [:0]const u8) void {