/*******************************************************************/
/* sbpython3: external configurable build project for Python-3.x. */
/* Copyright (C) 2018 Z. Gilboa */
/* Released under the Standard MIT License; see COPYING.SBPYTHON3.*/
/*******************************************************************/
/*******************************************************************/
/* pyexts.c: a simple development-time utility for generating */
/* make rules for python's extension modules. The utility is */
/* included with the sbpython3 project for reference only. */
/* */
/* cc -std=c99 -D_XOPEN_SOURCE=700 pyexts.c */
/*******************************************************************/
#include <stdio.h>
#include <string.h>
#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("_asyncio", "_asynciomodule"),
PYEXT_SIMPLE("_bisect", "_bisectmodule"),
PYEXT_SIMPLE("_crypt", "_cryptmodule"),
PYEXT_SIMPLE("_csv", "_csv"),
PYEXT_SIMPLE("_ctypes_test", "_ctypes/_ctypes_test"),
PYEXT_SIMPLE("_datetime", "_datetimemodule"),
PYEXT_SIMPLE("_elementtree", "_elementtree"),
PYEXT_SIMPLE("_heapq", "_heapqmodule"),
PYEXT_SIMPLE("_json", "_json"),
PYEXT_SIMPLE("_md5", "md5module"),
PYEXT_SIMPLE("_opcode", "_opcode"),
PYEXT_SIMPLE("_pickle", "_pickle"),
PYEXT_SIMPLE("_posixsubprocess", "_posixsubprocess"),
PYEXT_SIMPLE("_random", "_randommodule"),
PYEXT_SIMPLE("_sha1", "sha1module"),
PYEXT_SIMPLE("_sha256", "sha256module"),
PYEXT_SIMPLE("_sha3", "_sha3/sha3module"),
PYEXT_SIMPLE("_sha512", "sha512module"),
PYEXT_SIMPLE("_socket", "socketmodule"),
PYEXT_SIMPLE("_struct", "_struct"),
PYEXT_SIMPLE("_testbuffer", "_testbuffer"),
PYEXT_SIMPLE("_testcapi", "_testcapimodule"),
PYEXT_SIMPLE("_testimportmultiple", "_testimportmultiple"),
PYEXT_SIMPLE("_testmultiphase", "_testmultiphase"),
PYEXT_SIMPLE("array", "arraymodule"),
PYEXT_SIMPLE("audioop", "audioop"),
PYEXT_SIMPLE("fcntl", "fcntlmodule"),
PYEXT_SIMPLE("grp", "grpmodule"),
PYEXT_SIMPLE("mmap", "mmapmodule"),
PYEXT_SIMPLE("ossaudiodev", "ossaudiodev"),
PYEXT_SIMPLE("parser", "parsermodule"),
PYEXT_SIMPLE("resource", "resource"),
PYEXT_SIMPLE("select", "selectmodule"),
PYEXT_SIMPLE("spwd", "spwdmodule"),
PYEXT_SIMPLE("syslog", "syslogmodule"),
PYEXT_SIMPLE("termios", "termios"),
PYEXT_SIMPLE("unicodedata", "unicodedata"),
PYEXT_SIMPLE("xxlimited", "xxlimited"),
PYEXT_SIMPLE("_blake2",
"_blake2/blake2module",
"_blake2/blake2b_impl",
"_blake2/blake2s_impl"),
PYEXT_SIMPLE("_lsprof",
"_lsprof",
"rotatingtree"),
PYEXT_SIMPLE("_multiprocessing",
"_multiprocessing/multiprocessing",
"_multiprocessing/semaphore"),
PYEXT_SIMPLE("cmath",
"cmathmodule",
"_math"),
PYEXT_SIMPLE("math",
"mathmodule",
"_math"),
PYEXT_COMMON("_bz2",0,"-lbz2",
"_bz2module"),
PYEXT_COMMON("_ctypes",0,"-lffi",
"_ctypes/_ctypes",
"_ctypes/callbacks",
"_ctypes/callproc",
"_ctypes/stgdict",
"_ctypes/cfield"),
PYEXT_COMMON("_curses",
"$(CFLAGS_NCURSES)",
"$(LDFLAGS_NCURSES)",
"_cursesmodule"),
PYEXT_COMMON("_curses_panel",
"$(CFLAGS_NCURSES)",
"$(LDFLAGS_NCURSES)",
"_curses_panel"),
PYEXT_COMMON("_decimal",
"-I$(SOURCE_DIR)/Modules/_decimal/libmpdec",0,
"_decimal/_decimal",
"_decimal/libmpdec/basearith",
"_decimal/libmpdec/constants",
"_decimal/libmpdec/context",
"_decimal/libmpdec/convolute",
"_decimal/libmpdec/crt",
"_decimal/libmpdec/difradix2",
"_decimal/libmpdec/fnt",
"_decimal/libmpdec/fourstep",
"_decimal/libmpdec/io",
"_decimal/libmpdec/memory",
"_decimal/libmpdec/mpdecimal",
"_decimal/libmpdec/numbertheory",
"_decimal/libmpdec/sixstep",
"_decimal/libmpdec/transpose"),
PYEXT_COMMON("_dbm",
"$(CFLAGS_DBM)",
"$(LDFLAGS_DBM)",
"_dbmmodule"),
PYEXT_COMMON("_gdbm",0,"-lgdbm",
"_gdbmmodule"),
PYEXT_COMMON("_hashlib",0,"-lssl -lcrypto",
"_hashopenssl"),
PYEXT_COMMON("_lzma",0,"-llzma",
"_lzmamodule"),
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("_ssl",0,"-lssl -lcrypto",
"_ssl"),
PYEXT_COMMON("_tkinter",
"$(CFLAGS_TCLTK)",
"$(LDFLAGS_TCLTK)",
"_tkinter",
"tkappinit"),
PYEXT_COMMON("binascii",0,"-lz",
"binascii"),
PYEXT_COMMON("pyexpat",0,"-lexpat",
"pyexpat"),
PYEXT_COMMON("readline",0,"-lreadline",
"readline"),
PYEXT_COMMON("zlib",0,"-lz",
"zlibmodule"),
{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 fmt[64];
char uname[64];
if ((argc == 2) && !strcmp(argv[1],"--py-init-func")) {
for (p=pyexts; p->name; p++)
printf("PY_INIT_FUNC(%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);
sprintf(fmt,"\t{\"%%s\",%%-%zusPyInit_%%s},%%-%zus\\\n",
20-nlen,23-nlen);
printf(fmt,p->name," ",p->name," ");
}
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$(PYTHON_SOEXT)\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;
}