# mtpython — CPython 2.7.18 as a static library for the embedded 40250 script layer
# (docs/PORT-PLAN.md 批次 2P step 1). Upstream source is the official Python-2.7.18 tarball
# (sha256 b62c0e79...def43), trimmed of Doc/Demo/Tools/Mac/PCbuild and the stdlib test trees;
# see docs/THIRD-PARTY.md for the two vendor patches.
#
# The source list and the built-in module table (config/config.c, config/Setup.static) are SHARED
# by every platform: they are exactly the objects the reference autotools build puts in
# libpython2.7.a. `pyconfig.h` is NOT shared — it is the result of probing one platform's type
# sizes and system calls, so each platform keeps its own under config/<platform>/.
#
# Windows is not built here yet: it needs PC/pyconfig.h, PC/getpathp.c, Python/dynload_win.c and a
# PC built-in table of its own (nt instead of posix, no fcntl/pwd). Upstream 2.7 supports MSVC there,
# while our Windows gate cross-compiles with MinGW, where PC/pyconfig.h's gnu-win32 branch leaves
# HAVE_UNISTD_H unset and posixmodule.c/dynload_win.c collide with the MinGW headers — so it needs a
# patch series, decided in PORT-PLAN 批次 2P step 4. See docs/THIRD-PARTY.md.

set(MT_PYTHON_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}")

# MT_PYTHON_PLATFORM is the reference build's MACHDEP, which becomes sys.platform.
if(ANDROID)
    set(MT_PYTHON_CONFIG android)
    set(MT_PYTHON_PLATFORM linux2)
elseif(IOS OR CMAKE_SYSTEM_NAME STREQUAL "iOS")
    set(MT_PYTHON_CONFIG ios)
    set(MT_PYTHON_PLATFORM darwin)
elseif(APPLE)
    set(MT_PYTHON_CONFIG macos)
    set(MT_PYTHON_PLATFORM darwin)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
    set(MT_PYTHON_CONFIG linux)
    set(MT_PYTHON_PLATFORM linux2)
else()
    message(FATAL_ERROR "mtpython: no pyconfig.h for ${CMAKE_SYSTEM_NAME} yet (see the header of this file)")
endif()
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/config/${MT_PYTHON_CONFIG}/pyconfig.h")
    message(FATAL_ERROR "mtpython: config/${MT_PYTHON_CONFIG}/pyconfig.h is missing; generate it with "
                        "tools/py_embed/gen_pyconfig.sh ${MT_PYTHON_CONFIG}")
endif()

add_library(mtpython STATIC
    config/config.c
    Modules/_bisectmodule.c
    Modules/_codecsmodule.c
    Modules/_collectionsmodule.c
    Modules/_functoolsmodule.c
    Modules/_heapqmodule.c
    Modules/_localemodule.c
    Modules/_math.c
    Modules/_randommodule.c
    Modules/_sre.c
    Modules/_struct.c
    Modules/_weakref.c
    Modules/arraymodule.c
    Modules/binascii.c
    Modules/cPickle.c
    Modules/cStringIO.c
    Modules/datetimemodule.c
    Modules/errnomodule.c
    Modules/fcntlmodule.c
    Modules/gcmodule.c
    Modules/getbuildinfo.c
    Modules/getpath.c
    Modules/itertoolsmodule.c
    Modules/main.c
    Modules/mathmodule.c
    Modules/operator.c
    Modules/posixmodule.c
    Modules/pwdmodule.c
    Modules/selectmodule.c
    Modules/signalmodule.c
    Modules/stropmodule.c
    Modules/symtablemodule.c
    Modules/threadmodule.c
    Modules/timemodule.c
    Modules/xxsubtype.c
    Modules/zipimport.c
    Objects/abstract.c
    Objects/boolobject.c
    Objects/bufferobject.c
    Objects/bytearrayobject.c
    Objects/bytes_methods.c
    Objects/capsule.c
    Objects/cellobject.c
    Objects/classobject.c
    Objects/cobject.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/genobject.c
    Objects/intobject.c
    Objects/iterobject.c
    Objects/listobject.c
    Objects/longobject.c
    Objects/memoryobject.c
    Objects/methodobject.c
    Objects/moduleobject.c
    Objects/object.c
    Objects/obmalloc.c
    Objects/rangeobject.c
    Objects/setobject.c
    Objects/sliceobject.c
    Objects/stringobject.c
    Objects/structseq.c
    Objects/tupleobject.c
    Objects/typeobject.c
    Objects/unicodectype.c
    Objects/unicodeobject.c
    Objects/weakrefobject.c
    Parser/acceler.c
    Parser/bitset.c
    Parser/firstsets.c
    Parser/grammar.c
    Parser/grammar1.c
    Parser/listnode.c
    Parser/metagrammar.c
    Parser/myreadline.c
    Parser/node.c
    Parser/parser.c
    Parser/parsetok.c
    Parser/pgen.c
    Parser/tokenizer.c
    Python/Python-ast.c
    Python/_warnings.c
    Python/asdl.c
    Python/ast.c
    Python/bltinmodule.c
    Python/ceval.c
    Python/codecs.c
    Python/compile.c
    Python/dtoa.c
    Python/dynload_shlib.c
    Python/errors.c
    Python/formatter_string.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/graminit.c
    Python/import.c
    Python/importdl.c
    Python/marshal.c
    Python/modsupport.c
    Python/mysnprintf.c
    Python/mystrtoul.c
    Python/peephole.c
    Python/pyarena.c
    Python/pyctype.c
    Python/pyfpe.c
    Python/pymath.c
    Python/pystate.c
    Python/pystrcmp.c
    Python/pystrtod.c
    Python/pythonrun.c
    Python/random.c
    Python/structmember.c
    Python/symtable.c
    Python/sysmodule.c
    Python/thread.c
    Python/traceback.c
)

# Python/mactoolboxglue.c is compiled only where pyconfig.h sets USE_TOOLBOX_OBJECT_GLUE (macOS).
if(MT_PYTHON_CONFIG STREQUAL macos)
    target_sources(mtpython PRIVATE Python/mactoolboxglue.c)
endif()

target_include_directories(mtpython PUBLIC
    "${CMAKE_CURRENT_SOURCE_DIR}/config/${MT_PYTHON_CONFIG}"
    "${CMAKE_CURRENT_SOURCE_DIR}/Include"
)
target_include_directories(mtpython PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/Modules")

# The reference Makefile's PY_CFLAGS, plus the per-file defines it passes to getpath.c and
# getplatform.c. The interpreter runs with Py_IgnoreEnvironmentFlag/Py_NoSiteFlag and gets its
# sys.path from the host, so PREFIX/PYTHONPATH only feed getpath.c's unused defaults.
target_compile_definitions(mtpython PRIVATE
    Py_BUILD_CORE
    NDEBUG
    PREFIX="/usr/local"
    EXEC_PREFIX="/usr/local"
    VERSION="2.7"
    VPATH=""
    PYTHONPATH=""
    PLATFORM="${MT_PYTHON_PLATFORM}"
)
target_compile_options(mtpython PRIVATE -fno-strict-aliasing -fwrapv -w)
# The 2.7 headers still use `register`, which C++17 removed; every C++ consumer needs this (MSVC: /wd5033).
target_compile_options(mtpython INTERFACE $<$<COMPILE_LANGUAGE:CXX>:-Wno-register>)
set_target_properties(mtpython PROPERTIES C_STANDARD 99 POSITION_INDEPENDENT_CODE ON)
if(NOT ANDROID AND NOT IOS AND NOT CMAKE_SYSTEM_NAME STREQUAL "iOS")
    find_library(MT_PYTHON_DL dl)
    if(MT_PYTHON_DL)
        target_link_libraries(mtpython PUBLIC ${MT_PYTHON_DL})
    endif()
endif()
find_package(Threads REQUIRED)
target_link_libraries(mtpython PUBLIC Threads::Threads m)
add_library(mt3p::python ALIAS mtpython)

# --- the stdlib the host puts on sys.path (批次 2P step 3) ---
# Built from the same vendored Lib/, so the interpreter and its library always match. MT_PYTHON_STDLIB_ZIP
# is where every consumer (the native tests now, the mobile staging in step 3c) picks it up.
find_package(Python3 COMPONENTS Interpreter REQUIRED)
set(MT_PYTHON_STDLIB_ZIP "${CMAKE_BINARY_DIR}/python27.zip" CACHE INTERNAL "stdlib zip for the embedded interpreter")
set(MT_PYTHON_STDLIB_SHA "${MT_PYTHON_STDLIB_ZIP}.sha256" CACHE INTERNAL "sha256 of MT_PYTHON_STDLIB_ZIP")
file(GLOB_RECURSE MT_PYTHON_STDLIB_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/Lib/*.py")
add_custom_command(OUTPUT "${MT_PYTHON_STDLIB_ZIP}" "${MT_PYTHON_STDLIB_SHA}"
    COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/tools/py_embed/make_stdlib_zip.py"
            "${CMAKE_CURRENT_SOURCE_DIR}/Lib" "${MT_PYTHON_STDLIB_ZIP}"
    DEPENDS "${CMAKE_SOURCE_DIR}/tools/py_embed/make_stdlib_zip.py" ${MT_PYTHON_STDLIB_SOURCES}
    COMMENT "Packing python27.zip from the vendored Lib/")
add_custom_target(mtpython_stdlib ALL DEPENDS "${MT_PYTHON_STDLIB_ZIP}" "${MT_PYTHON_STDLIB_SHA}")
