/*******************************************************************/ /* sbpython2: external configurable build project for Python-2.7. */ /* Copyright (C) 2018 SysDeer Technologies, LLC */ /* Released under the Standard MIT License; see COPYING.SBPYTHON2.*/ /*******************************************************************/ /*******************************************************************/ /* pyexts.c: a simple development-time utility for generating */ /* make rules for python's extension modules. The utility is */ /* included with the sbpython2 project for reference only. */ /* */ /* cc -std=c99 -D_XOPEN_SOURCE=700 pyexts.c */ /*******************************************************************/ #include #include #define PYEXT_LIST(...) (const char *[]){__VA_ARGS__,0} #define PYEXT_SIMPLE(name,...) {name,PYEXT_LIST(__VA_ARGS__),0,0,0,0} #define PYEXT_COMMON(name,hvar,lvar,...) {name,PYEXT_LIST(__VA_ARGS__), \ PYEXT_LIST(hvar),0, \ PYEXT_LIST(lvar),0} #define PYEXT_ALTSTD(name,cstd,...) {name,PYEXT_LIST(__VA_ARGS__), \ 0,PYEXT_LIST(cstd),0,0} struct pyext_meta { const char * name; const char ** srcs; const char ** hdrs; const char ** cstd; const char ** vars; const char ** deps; }; static const struct pyext_meta pyexts[] = { PYEXT_SIMPLE("_multibytecodec","cjkcodecs/multibytecodec"), PYEXT_SIMPLE("_codecs_cn", "cjkcodecs/_codecs_cn"), PYEXT_SIMPLE("_codecs_hk", "cjkcodecs/_codecs_hk"), PYEXT_SIMPLE("_codecs_jp", "cjkcodecs/_codecs_jp"), PYEXT_SIMPLE("_codecs_kr", "cjkcodecs/_codecs_kr"), PYEXT_SIMPLE("_codecs_tw", "cjkcodecs/_codecs_tw"), PYEXT_SIMPLE("_codecs_iso2022","cjkcodecs/_codecs_iso2022"), PYEXT_SIMPLE("_bisect", "_bisectmodule"), PYEXT_SIMPLE("_collections", "_collectionsmodule"), PYEXT_SIMPLE("_csv", "_csv"), PYEXT_SIMPLE("_ctypes_test", "_ctypes/_ctypes_test"), PYEXT_SIMPLE("_functools", "_functoolsmodule"), PYEXT_SIMPLE("_heapq", "_heapqmodule"), PYEXT_SIMPLE("_hotshot", "_hotshot"), PYEXT_SIMPLE("_json", "_json"), PYEXT_SIMPLE("_locale", "_localemodule"), PYEXT_SIMPLE("_lsprof", "_lsprof","rotatingtree"), PYEXT_SIMPLE("_random", "_randommodule"), PYEXT_SIMPLE("_socket", "socketmodule","timemodule"), PYEXT_SIMPLE("_struct", "_struct"), PYEXT_SIMPLE("_testcapi", "_testcapimodule"), PYEXT_SIMPLE("array", "arraymodule"), PYEXT_SIMPLE("audioop", "audioop"), PYEXT_SIMPLE("binascii", "binascii"), PYEXT_SIMPLE("cPickle", "cPickle"), PYEXT_SIMPLE("cStringIO", "cStringIO"), PYEXT_SIMPLE("cmath", "cmathmodule","_math"), PYEXT_SIMPLE("crypt", "cryptmodule"), PYEXT_SIMPLE("datetime", "datetimemodule","timemodule"), PYEXT_SIMPLE("fcntl", "fcntlmodule"), PYEXT_SIMPLE("future_builtins","future_builtins"), PYEXT_SIMPLE("grp", "grpmodule"), PYEXT_SIMPLE("itertools", "itertoolsmodule"), PYEXT_SIMPLE("math", "mathmodule","_math"), PYEXT_SIMPLE("mmap", "mmapmodule"), PYEXT_SIMPLE("operator", "operator"), PYEXT_SIMPLE("ossaudiodev", "ossaudiodev"), PYEXT_SIMPLE("parser", "parsermodule"), PYEXT_SIMPLE("resource", "resource"), PYEXT_SIMPLE("select", "selectmodule"), PYEXT_SIMPLE("spwd", "spwdmodule"), PYEXT_SIMPLE("strop", "stropmodule"), PYEXT_SIMPLE("syslog", "syslogmodule"), PYEXT_SIMPLE("termios", "termios"), PYEXT_SIMPLE("time", "timemodule"), PYEXT_SIMPLE("unicodedata", "unicodedata"), PYEXT_COMMON("_curses", "$(CFLAGS_NCURSES)", "$(LDFLAGS_NCURSES)", "_cursesmodule"), PYEXT_COMMON("_curses_panel", "$(CFLAGS_NCURSES)", "$(LDFLAGS_NCURSES)", "_curses_panel"), PYEXT_COMMON("_elementtree", "-UVERSION", "-lexpat", "_elementtree"), PYEXT_COMMON("_hashlib", 0, "-lssl -lcrypto", "_hashopenssl"), PYEXT_COMMON("_ssl", 0, "-lssl -lcrypto", "_ssl"), PYEXT_COMMON("bz2", 0, "-lbz2", "bz2module"), PYEXT_COMMON("gdbm", 0, "-lgdbm", "gdbmmodule"), PYEXT_COMMON("readline", 0, "-lreadline", "readline"), PYEXT_COMMON("pyexpat", 0, "-lexpat", "pyexpat"), PYEXT_COMMON("zlib", 0, "-lz", "zlibmodule"), PYEXT_COMMON("_ctypes",0,"-lffi", "_ctypes/_ctypes", "_ctypes/callbacks", "_ctypes/callproc", "_ctypes/stgdict", "_ctypes/cfield"), PYEXT_COMMON("_io",0,0, "_io/bufferedio", "_io/bytesio", "_io/fileio", "_io/iobase", "_io/_iomodule", "_io/stringio", "_io/textio"), PYEXT_COMMON("_multiprocessing",0,0, "_multiprocessing/multiprocessing", "_multiprocessing/socket_connection", "_multiprocessing/semaphore"), PYEXT_COMMON("_sqlite3", "$(CFLAGS_SQLITE)", "$(LDFLAGS_SQLITE)", "_sqlite/cache", "_sqlite/connection", "_sqlite/cursor", "_sqlite/microprotocols", "_sqlite/module", "_sqlite/prepare_protocol", "_sqlite/row", "_sqlite/statement", "_sqlite/util"), PYEXT_COMMON("dbm", "$(CFLAGS_DBM)", "$(LDFLAGS_DBM)", "dbmmodule"), PYEXT_ALTSTD("linuxaudiodev", "-std=gnu99", "linuxaudiodev"), {0,0,0,0,0,0}, }; static void pyext_uppercase(char * buf, const char * name) { const char * src; char * dst; src = name; dst = buf; for (; *src; ) *dst++ = ((*src >= 'a') && (*src <= 'z')) ? 'A' - 'a' + *src++ : *src++; *dst = 0; } int main(int argc, char ** argv) { const struct pyext_meta * p; size_t nlen; const char ** parg; const char * dtab; const char * otab; const char * htab; const char * stab; const char * ltab; const char * rtab; const char * vtab; const char * name; char uname[64]; if ((argc == 2) && !strcmp(argv[1],"--py-init-func")) { for (p=pyexts; p->name; p++) printf("PY_INIT_FUNC(init%s);\n",p->name); return 0; } if ((argc == 2) && !strcmp(argv[1],"--init-func-ptr")) { for (p=pyexts; p->name; p++) { nlen = strlen(p->name); if (nlen <= 3) dtab = "\t\t\t"; else if (nlen <= 11) dtab = "\t\t"; else dtab = "\t"; if (nlen <= 9) rtab = "\t\t"; else rtab = "\t"; printf("\t{\"%s\",%sinit%s},%s\\\n", p->name,dtab,p->name,rtab); } return 0; } for (p=pyexts; p->name; p++) { /* init */ name = (p->name[0] == '_') ? &p->name[1] : p->name; nlen = strlen(name); pyext_uppercase(uname,name); /* pretty */ dtab = (nlen <= 4) ? "\t\t\t" : (nlen <= 12) ? "\t\t" : "\t"; otab = (nlen <= 3) ? "\t\t\t" : (nlen <= 11) ? "\t\t" : "\t"; ltab = (nlen <= 2) ? "\t\t\t" : (nlen <= 10) ? "\t\t" : "\t"; rtab = (nlen <= 1) ? "\t\t\t" : (nlen <= 9) ? "\t\t" : "\t"; vtab = (nlen <= 6) ? "\t\t" : (nlen <= 14) ? "\t" : ""; htab = (nlen <= 8) ? "\t\t" : "\t"; stab = (nlen <= 9) ? "\t\t" : "\t"; /* output */ printf("# %s\n",p->name); for (parg=p->srcs; *parg; parg++) printf("PYEXT_%s_SRCS%s+= " "pyext/obj/%s.c\n", uname,dtab,*parg); printf("\n"); printf("PYEXT_%s_LOBJS%s= $(PYEXT_%s_SRCS:.c=.lo)\n",uname,otab,uname); printf("PYEXT_%s_OBJS%s= $(PYEXT_%s_SRCS:.c=.o)\n",uname,dtab,uname); printf("\n"); for (parg=p->hdrs; parg && *parg; parg++) printf("$(PYEXT_%s_LOBJS):%s" "CFLAGS_CONFIG += %s\n", uname,htab,*parg); for (parg=p->hdrs; parg && *parg; parg++) printf("$(PYEXT_%s_OBJS):%s" "CFLAGS_CONFIG += %s\n", uname,stab,*parg); for (parg=p->cstd; parg && *parg; parg++) printf("$(PYEXT_%s_LOBJS):%s" "CFLAGS_LAST += %s\n", uname,otab,*parg); for (parg=p->cstd; parg && *parg; parg++) printf("$(PYEXT_%s_OBJS):%s" "CFLAGS_LAST += %s\n", uname,dtab,*parg); if (p->hdrs || p->cstd) printf("\n"); printf("PYEXT_%s_SHARED%s= pyext/%s$(OS_LIB_SUFFIX)\n",uname,ltab,p->name); printf("PYEXT_%s_STATIC%s= pyext/%s$(OS_ARCHIVE_EXT)\n",uname,ltab,p->name); printf("\n"); for (parg=p->vars; parg && *parg; parg++) printf("$(PYEXT_%s_SHARED):%s" "LDFLAGS_DYNEXT += %s\n", uname,vtab,*parg); for (parg=p->deps; parg && *parg; parg++) printf("$(PYEXT_%s_SHARED):%s%s\n",uname,vtab,*parg); printf("$(PYEXT_%s_SHARED):%s$(PYEXT_%s_LOBJS)\n",uname,vtab,uname); printf("$(PYEXT_%s_STATIC):%s$(PYEXT_%s_OBJS)\n",uname,vtab,uname); printf("\n"); printf("pyext-%s-shared:%s$(PYEXT_%s_SHARED)\n",name,rtab,uname); printf("pyext-%s-static:%s$(PYEXT_%s_STATIC)\n",name,rtab,uname); printf("\n"); printf("pyext-%s-clean:\n",name); printf("\trm -f $(PYEXT_%s_LOBJS)\n",uname); printf("\trm -f $(PYEXT_%s_OBJS)\n",uname); printf("\trm -f $(PYEXT_%s_SHARED)\n",uname); printf("\trm -f $(PYEXT_%s_STATIC)\n",uname); printf("\n"); printf("clean:\tpyext-%s-clean\n",name); printf("\n"); printf(".PHONY:\tpyext-%s-shared\n",name); printf(".PHONY:\tpyext-%s-static\n",name); printf(".PHONY:\tpyext-%s-clean\n",name); printf("\n\n"); } return 0; }