* python/Makefile.am: Builds and installs python2 HelperSDT package.
* python/Makefile.in: Regenerated.
* python/setup.py: New file.
* HelperSDT/README.txt: Ditto.
* HelperSDT/_HelperSDT.c: Ditto.
* HelperSDT/__init__.py: Ditto.
* HelperSDT/__main__.py: Ditto.
--- /dev/null
+Developer Note
+==============
+
+The default prefix for developer builds is '/usr/local', the default
+prefix for production builds is '/usr'. This module ends up getting
+installed in
+'$(prefix)/lib/python-${PYTHON_VER}/site-packages/HelperSDT'. For a
+developer build for python 2.7, that would end up being the following
+directory: '/usr/local/lib/python2.7/site-packages/HelperSDT'. The
+problem is the '/usr/local/lib/python2.7/site-packages' directory
+isn't in the default python path on RHEL/Fedora.
+
+Observe the following from a RHEL7.2 system (as root):
+
+====
+# python -m site
+sys.path = [
+ '/root/rhel7-2.ppc64',
+ '/usr/lib64/python27.zip',
+ '/usr/lib64/python2.7',
+ '/usr/lib64/python2.7/plat-linux2',
+ '/usr/lib64/python2.7/lib-tk',
+ '/usr/lib64/python2.7/lib-old',
+ '/usr/lib64/python2.7/lib-dynload',
+ '/usr/lib64/python2.7/site-packages',
+ '/usr/lib64/python2.7/site-packages/gtk-2.0',
+ '/usr/lib/python2.7/site-packages',
+]
+USER_BASE: '/root/.local' (doesn't exist)
+USER_SITE: '/root/.local/lib/python2.7/site-packages' (doesn't exist)
+ENABLE_USER_SITE: True
+====
+
+So, when doing a developer build, we've got to arrange for the
+installation directory to appear in the python path. There are (at
+least) 2 ways of doing this:
+
+1) Put the developer build installation directory in the PYTHONPATH
+environment variable.
+
+====
+# PYTHONPATH=/usr/local/lib/python2.7/site-packages python -m site
+sys.path = [
+ '/root/rhel7-2.ppc64',
+ '/usr/local/lib/python2.7/site-packages',
+ '/usr/lib64/python27.zip',
+ '/usr/lib64/python2.7',
+ '/usr/lib64/python2.7/plat-linux2',
+ '/usr/lib64/python2.7/lib-tk',
+ '/usr/lib64/python2.7/lib-old',
+ '/usr/lib64/python2.7/lib-dynload',
+ '/usr/lib64/python2.7/site-packages',
+ '/usr/lib64/python2.7/site-packages/gtk-2.0',
+ '/usr/lib/python2.7/site-packages',
+]
+USER_BASE: '/root/.local' (doesn't exist)
+USER_SITE: '/root/.local/lib/python2.7/site-packages' (doesn't exist)
+ENABLE_USER_SITE: True
+====
+
+To make that change permanent, add
+'export PYTHONPATH=/usr/local/lib/python2.7/site-packages' to the user's
+~/.profile. Then log out and back in again.
+
+Note that this has to be done for every user that wants to use the
+HelperSDT module.
+
+
+2) Add a file, 'local.pth', to your 'USER_SITE'
+directory (by default '~/.local/lib/python2.7/site-packages' for
+python 2.7). Notice the USER_SITE directory specified above in the
+'python -m site' output. That file is just a list of directories to
+add to the python path.
+
+====
+# python -m site
+sys.path = [
+ '/home/dsmith',
+ '/usr/lib/python27.zip',
+ '/usr/lib/python2.7',
+ '/usr/lib/python2.7/plat-linux2',
+ '/usr/lib/python2.7/lib-tk',
+ '/usr/lib/python2.7/lib-old',
+ '/usr/lib/python2.7/lib-dynload',
+ '/usr/lib/python2.7/site-packages',
+]
+USER_BASE: '/home/dsmith/.local' (doesn't exist)
+USER_SITE: '/home/dsmith/.local/lib/python2.7/site-packages' (doesn't exist)
+ENABLE_USER_SITE: True
+# mkdir -p ~/.local/lib/python2.7/site-packages
+# echo '/usr/local/lib/python2.7/site-packages' > ~/.local/lib/python2.7/site-packages/local.pth
+# python -m site
+sys.path = [
+ '/home/dsmith',
+ '/usr/lib/python27.zip',
+ '/usr/lib/python2.7',
+ '/usr/lib/python2.7/plat-linux2',
+ '/usr/lib/python2.7/lib-tk',
+ '/usr/lib/python2.7/lib-old',
+ '/usr/lib/python2.7/lib-dynload',
+ '/home/dsmith/.local/lib/python2.7/site-packages',
+ '/usr/local/lib/python2.7/site-packages',
+ '/usr/lib/python2.7/site-packages',
+]
+USER_BASE: '/home/dsmith/.local' (exists)
+USER_SITE: '/home/dsmith/.local/lib/python2.7/site-packages' (exists)
+ENABLE_USER_SITE: True
+====
+
+Note that this has to be done for every user that wants to use the
+HelperSDT module. (This could be done system-wide by putting the .pth
+file in a system python path like /usr/lib/python2.7/site-packages.)
+
+Method 1) (setting the environment variable) is a bit more visible
+(since you can easily see the environment variable), but a bit more
+inconvenient since you have to log in/out for changes to take
+effect. Method 2) (adding the .pth file) is fairly easy, but a bit
+more 'magical' since it is easy to forget that file in a hidden
+directory exists.
+
+Also note that changing the python path must be undone when
+using/testing a production build installation, since you don't want 2
+copies of the same module in the python path (which is another vote
+for Method 2 since it is easier to undo).
--- /dev/null
+// systemtap python SDT marker C module
+// Copyright (C) 2016 Red Hat Inc.
+//
+// This file is part of systemtap, and is free software. You can
+// redistribute it and/or modify it under the terms of the GNU General
+// Public License (GPL); either version 2, or (at your option) any
+// later version.
+
+#include <Python.h>
+#include <sys/sdt.h>
+
+static PyObject *
+trace_callback(PyObject *self, PyObject *args)
+{
+ int what;
+ PyObject *frame_obj, *arg_obj;
+
+ /* Parse the input tuple */
+ if (!PyArg_ParseTuple(args, "iOO", &what, &frame_obj, &arg_obj))
+ return NULL;
+
+ /* We want to name the probes with the same name as the
+ * define. This is tricky, so, we'll just save the define,
+ * undefine it, call the STAP_PROBE2 macro, then redfine it. */
+ switch (what) {
+ case PyTrace_CALL:
+#define _PyTrace_CALL PyTrace_CALL
+#undef PyTrace_CALL
+ STAP_PROBE2(stap_pybridge, PyTrace_CALL, frame_obj, arg_obj);
+#define PyTrace_CALL _PyTrace_CALL
+#undef _PyTrace_CALL
+ break;
+ case PyTrace_EXCEPTION:
+#define _PyTrace_EXCEPTION PyTrace_EXCEPTION
+#undef PyTrace_EXCEPTION
+ STAP_PROBE2(stap_pybridge, PyTrace_EXCEPTION, frame_obj, arg_obj);
+#define PyTrace_EXCEPTION _PyTrace_EXCEPTION
+#undef _PyTrace_EXCEPTION
+ break;
+ case PyTrace_LINE:
+#define _PyTrace_LINE PyTrace_LINE
+#undef PyTrace_LINE
+ STAP_PROBE2(stap_pybridge, PyTrace_LINE, frame_obj, arg_obj);
+#define PyTrace_LINE _PyTrace_LINE
+#undef _PyTrace_LINE
+ break;
+ case PyTrace_RETURN:
+#define _PyTrace_RETURN PyTrace_RETURN
+#undef PyTrace_RETURN
+ STAP_PROBE2(stap_pybridge, PyTrace_RETURN, frame_obj, arg_obj);
+#define PyTrace_RETURN _PyTrace_RETURN
+#undef _PyTrace_RETURN
+ break;
+ // FIXME: What about PyTrace_C_CALL, PyTrace_C_EXCEPTION,
+ // PyTrace_C_RETURN? Fold them into their non-'_C_' versions or
+ // have unique probes?
+ default:
+ // FIXME: error/exception here?
+ return NULL;
+ }
+ return Py_BuildValue("i", 0);
+}
+
+static PyMethodDef HelperSDT_methods[] = {
+ {"trace_callback", trace_callback, METH_VARARGS,
+ "Trace callback function."},
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
+
+static const char const *HelperSDT_doc =
+ "This module provides an interface for interfacing between Python tracing events and systemtap.";
+
+PyMODINIT_FUNC
+init_HelperSDT(void)
+{
+ PyObject *m;
+
+ m = Py_InitModule3("_HelperSDT", HelperSDT_methods,
+ HelperSDT_doc);
+ if (m == NULL)
+ return;
+}
--- /dev/null
+# systemtap python module
+# Copyright (C) 2016 Red Hat Inc.
+#
+# This file is part of systemtap, and is free software. You can
+# redistribute it and/or modify it under the terms of the GNU General
+# Public License (GPL); either version 2, or (at your option) any
+# later version.
+
+# Note that we'd like for this module to be the same between python 2
+# and python 3, but the 'print' function has changed quite
+# dramatically between the two versions. You'd think we could use the
+# '__future__' module's 'print' function so we'd be able to use python
+# 3's 'print' function style everywhere. However, this causes python 2
+# scripts that get loaded to have to use python 3 print syntax, since
+# the '__future__' module's print function "leaks" through to the
+# python 2 script. There's probably a way to fix that, but we'll just
+# punt and use 'sys.stdout.write()', which is a little less
+# convenient, but works the same on both python 2 and python 3.
+import sys
+import _HelperSDT
+import os.path
+
+
+class _Breakpoint:
+ def __init__(self, index, filename, funcname, lineno=None,
+ returnp=None):
+ # We've got to have a filename and funcname with an optional
+ # lineno or returnp.
+ if not filename:
+ pass
+ if not funcname:
+ pass
+ self.index = index
+ self.filename = filename
+ self.funcname = funcname
+ self.lineno = lineno
+ self.returnp = returnp
+
+ def dump(self, out=None):
+ if out is None:
+ out = sys.stdout
+ out.write("%s\n" % self.bpformat())
+
+ def bpformat(self):
+ if self.lineno:
+ disp = '%d' % self.lineno
+ elif not self.returnp:
+ disp = self.funcname
+ else:
+ disp = '%s.return' % self.funcname
+ return '%-4dbreakpoint at %s:%s' % (self.index, self.filename, disp)
+
+
+class _BreakpointList:
+ def __init__(self):
+ self._index = 1
+ self._bynumber = [] # breakpoints indexed by number
+
+ # N.B. To make sure we're inside the right function, and not
+ # just executing a 'def' statement, we need the function name
+ # for line number breakpoints.
+ self._byline = {} # indexed by (file, function, lineno) tuple
+ self._byfunc = {} # indexed by (file, function) tuple
+ self._byfuncret = {} # indexed by (file, function) tuple
+
+ def add(self, filename, funcname, lineno=None, returnp=None):
+ bp = _Breakpoint(self._index, filename, funcname, lineno, returnp)
+ self._index += 1
+ self._bynumber.append(bp)
+ if bp.lineno:
+ if (filename, funcname, lineno) in self._byline:
+ self._byline[filename, funcname, lineno].append(bp)
+ else:
+ self._byline[filename, funcname, lineno] = [bp]
+ elif not bp.returnp:
+ if (filename, funcname) in self._byfunc:
+ self._byfunc[filename, funcname].append(bp)
+ else:
+ self._byfunc[filename, funcname] = [bp]
+ else:
+ if (filename, funcname) in self._byfuncret:
+ self._byfuncret[filename, funcname].append(bp)
+ else:
+ self._byfuncret[filename, funcname] = [bp]
+
+ def dump(self, out=None):
+ if out is None:
+ out = sys.stdout
+ for bp in self._bynumber:
+ bp.dump(out)
+
+ def break_here(self, frame, event):
+ if event == 'call':
+ # filename = self.canonic(frame.f_code.co_filename)
+ filename = frame.f_code.co_filename
+ funcname = frame.f_code.co_name
+ if (filename, funcname) in self._byfunc:
+ return self._byfunc[filename, funcname]
+ elif event == 'line':
+ filename = frame.f_code.co_filename
+ funcname = frame.f_code.co_name
+ lineno = frame.f_lineno
+ if (filename, funcname, lineno) in self._byline:
+ return self._byline[filename, funcname, lineno]
+ elif event == 'return':
+ filename = frame.f_code.co_filename
+ funcname = frame.f_code.co_name
+ if (filename, funcname) in self._byfuncret:
+ return self._byfuncret[filename, funcname]
+ return None
+
+
+class Dispatcher:
+ def __init__(self, pyfile):
+ self._bplist = _BreakpointList()
+ # FIXME: this is just for testing. Real code would read
+ # breakpoints from a formatted file.
+ self._bplist.add(pyfile, 'd', None)
+ self._bplist.add(pyfile, 'c', None)
+ self._bplist.add(pyfile, 'd', 18)
+ self._bplist.add(pyfile, 'd', 17)
+ self._bplist.add(pyfile, 'd', None, True)
+ self._bplist.add(pyfile, 'e', None)
+ self._bplist.add(pyfile, 'e', None, True)
+ self._bplist.dump()
+
+ def pytrace_dispatch(self, frame, event, arg):
+ if event == 'call':
+ if self._bplist.break_here(frame, event):
+ sys.stdout.write("CALL: %s %s\n"
+ % (frame.f_code.co_filename,
+ frame.f_code.co_name))
+ _HelperSDT.trace_callback(0, frame, arg)
+ return self.pytrace_dispatch
+ elif event == 'line':
+ if self._bplist.break_here(frame, event):
+ sys.stdout.write("LINE: %s %s\n"
+ % (frame.f_code.co_filename,
+ frame.f_code.co_name, frame.f_lineno))
+ _HelperSDT.trace_callback(0, frame, arg)
+ return self.pytrace_dispatch
+ elif event == 'return':
+ if self._bplist.break_here(frame, event):
+ sys.stdout.write("RETURN: %s %s %d"
+ % (frame.f_code.co_filename,
+ frame.f_code.co_name, frame.f_lineno))
+ _HelperSDT.trace_callback(0, frame, arg)
+ return self.pytrace_dispatch
+ return self.pytrace_dispatch
+
+
+def run():
+ # Now that we're attached, run the real python file.
+ mainpyfile = sys.argv[1]
+ if not os.path.exists(mainpyfile):
+ sys.stderr.write("Error: '%s' does not exist" % mainpyfile)
+ sys.exit(1)
+
+ del sys.argv[0] # Hide this module from the argument list
+
+ # Start tracing.
+ dispatcher = Dispatcher(mainpyfile)
+ sys.settrace(dispatcher.pytrace_dispatch)
+
+ # The script we're about to run has to run in __main__ namespace
+ # (or imports from __main__ will break).
+ #
+ # So we clear up the __main__ namespace and set several special
+ # variables (this gets rid of our globals).
+ import __main__
+ __main__.__dict__.clear()
+ __main__.__dict__.update({"__name__": "__main__",
+ "__file__": mainpyfile,
+ "__builtins__": __builtins__})
+
+ # Run the real file. When it finishes, remove tracing.
+ try:
+ # execfile(mainpyfile, __main__.__dict__, __main__.__dict__)
+ exec(compile(open(mainpyfile).read(), mainpyfile, 'exec'),
+ __main__.__dict__, __main__.__dict__)
+ finally:
+ sys.settrace(None)
--- /dev/null
+# systemtap python module
+# Copyright (C) 2016 Red Hat Inc.
+#
+# This file is part of systemtap, and is free software. You can
+# redistribute it and/or modify it under the terms of the GNU General
+# Public License (GPL); either version 2, or (at your option) any
+# later version.
+if __name__ == '__main__':
+ import HelperSDT
+ HelperSDT.run()
AUTOMAKE_OPTIONS = subdir-objects
+# Any script in the following variable will get byte-compiled at
+# install time.
+pkglibexecpython_PYTHON =
+
pkglibexecpython_DATA =
pkglibexecpythondir = $(pkglibexecdir)/python
if HAVE_PYTHON_PROBES
# Why aren't we putting stap-resolve-module-function.py into
-# pkglibexecpython_SCRIPTS? stap-resolve-module-function.py is a
+# pkglibexecpython_PYTHON? stap-resolve-module-function.py is a
# python script, but it will be run by the translator as either a
# python version 2 or python version 3 script. So, it doesn't need to
# be executable (since we'll be calling "python
# stap-resolve-module-function.y ARGS."
pkglibexecpython_DATA += stap-resolve-module-function.py
+all-local:
+if HAVE_PYTHON2_PROBES
+ (cd $(srcdir); $(PYTHON) setup.py build \
+ --build-base $(shell readlink -f $(builddir))/py2build \
+ --verbose)
+endif
+if HAVE_PYTHON3_PROBES
+# FIXME: Shared library module doesn't build with python3 yet.
+# (cd $(srcdir); $(PYTHON3) setup.py build \
+# --build-base $(shell readlink -f $(builddir))/py3build \
+# --verbose)
+endif
+
+
+install-exec-local:
+if HAVE_PYTHON2_PROBES
+ (cd $(srcdir); $(PYTHON) setup.py build \
+ --build-base $(shell readlink -f $(builddir))/py2build \
+ install --prefix $(DESTDIR)$(prefix) \
+ --single-version-externally-managed \
+ --record $(shell readlink -f $(builddir))/py2build/install_files.txt \
+ --verbose)
+endif
+if HAVE_PYTHON3_PROBES
+# FIXME: Shared library module doesn't build with python3 yet.
+endif
+
+clean-local:
+ rm -rf py2build py3build
+
endif
target_triplet = @target@
# Why aren't we putting stap-resolve-module-function.py into
-# pkglibexecpython_SCRIPTS? stap-resolve-module-function.py is a
+# pkglibexecpython_PYTHON? stap-resolve-module-function.py is a
# python script, but it will be run by the translator as either a
# python version 2 or python version 3 script. So, it doesn't need to
# be executable (since we'll be calling "python
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
-DIST_COMMON = $(srcdir)/Makefile.am
+DIST_COMMON = $(srcdir)/Makefile.am $(pkglibexecpython_PYTHON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
-am__installdirs = "$(DESTDIR)$(pkglibexecpythondir)"
+am__py_compile = PYTHON=$(PYTHON) $(SHELL) $(py_compile)
+am__installdirs = "$(DESTDIR)$(pkglibexecpythondir)" \
+ "$(DESTDIR)$(pkglibexecpythondir)"
+am__pep3147_tweak = \
+ sed -e 's|\.py$$||' -e 's|[^/]*$$|__pycache__/&.*.py|'
DATA = $(pkglibexecpython_DATA)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
ACLOCAL = @ACLOCAL@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = subdir-objects
+
+# Any script in the following variable will get byte-compiled at
+# install time.
+pkglibexecpython_PYTHON =
pkglibexecpython_DATA = $(am__append_1)
pkglibexecpythondir = $(pkglibexecdir)/python
all: all-am
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
+install-pkglibexecpythonPYTHON: $(pkglibexecpython_PYTHON)
+ @$(NORMAL_INSTALL)
+ @list='$(pkglibexecpython_PYTHON)'; dlist=; list2=; test -n "$(pkglibexecpythondir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(pkglibexecpythondir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(pkglibexecpythondir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \
+ if test -f $$b$$p; then \
+ $(am__strip_dir) \
+ dlist="$$dlist $$f"; \
+ list2="$$list2 $$b$$p"; \
+ else :; fi; \
+ done; \
+ for file in $$list2; do echo $$file; done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkglibexecpythondir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkglibexecpythondir)" || exit $$?; \
+ done || exit $$?; \
+ if test -n "$$dlist"; then \
+ $(am__py_compile) --destdir "$(DESTDIR)" \
+ --basedir "$(pkglibexecpythondir)" $$dlist; \
+ else :; fi
+
+uninstall-pkglibexecpythonPYTHON:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkglibexecpython_PYTHON)'; test -n "$(pkglibexecpythondir)" || list=; \
+ py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$py_files" || exit 0; \
+ dir='$(DESTDIR)$(pkglibexecpythondir)'; \
+ pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \
+ pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \
+ py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \
+ echo "$$py_files_pep3147";\
+ pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \
+ pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \
+ st=0; \
+ for files in \
+ "$$py_files" \
+ "$$pyc_files" \
+ "$$pyo_files" \
+ "$$pyc_files_pep3147" \
+ "$$pyo_files_pep3147" \
+ ; do \
+ $(am__uninstall_files_from_dir) || st=$$?; \
+ done; \
+ exit $$st
install-pkglibexecpythonDATA: $(pkglibexecpython_DATA)
@$(NORMAL_INSTALL)
@list='$(pkglibexecpython_DATA)'; test -n "$(pkglibexecpythondir)" || list=; \
check-am: all-am
check: check-am
-all-am: Makefile $(DATA)
+@HAVE_PYTHON_PROBES_FALSE@all-local:
+all-am: Makefile $(DATA) all-local
installdirs:
- for dir in "$(DESTDIR)$(pkglibexecpythondir)"; do \
+ for dir in "$(DESTDIR)$(pkglibexecpythondir)" "$(DESTDIR)$(pkglibexecpythondir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
+@HAVE_PYTHON_PROBES_FALSE@install-exec-local:
+@HAVE_PYTHON_PROBES_FALSE@clean-local:
clean: clean-am
-clean-am: clean-generic mostlyclean-am
+clean-am: clean-generic clean-local mostlyclean-am
distclean: distclean-am
-rm -f Makefile
install-dvi-am:
-install-exec-am: install-pkglibexecpythonDATA
+install-exec-am: install-exec-local install-pkglibexecpythonDATA \
+ install-pkglibexecpythonPYTHON
install-html: install-html-am
ps-am:
-uninstall-am: uninstall-pkglibexecpythonDATA
+uninstall-am: uninstall-pkglibexecpythonDATA \
+ uninstall-pkglibexecpythonPYTHON
.MAKE: install-am install-strip
-.PHONY: all all-am check check-am clean clean-generic cscopelist-am \
- ctags-am distclean distclean-generic dvi dvi-am html html-am \
- info info-am install install-am install-data install-data-am \
- install-dvi install-dvi-am install-exec install-exec-am \
- install-html install-html-am install-info install-info-am \
- install-man install-pdf install-pdf-am \
- install-pkglibexecpythonDATA install-ps install-ps-am \
+.PHONY: all all-am all-local check check-am clean clean-generic \
+ clean-local cscopelist-am ctags-am distclean distclean-generic \
+ dvi dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-exec-local install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pkglibexecpythonDATA \
+ install-pkglibexecpythonPYTHON install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-generic pdf pdf-am ps ps-am tags-am uninstall \
- uninstall-am uninstall-pkglibexecpythonDATA
+ uninstall-am uninstall-pkglibexecpythonDATA \
+ uninstall-pkglibexecpythonPYTHON
.PRECIOUS: Makefile
+@HAVE_PYTHON_PROBES_TRUE@all-local:
+@HAVE_PYTHON2_PROBES_TRUE@@HAVE_PYTHON_PROBES_TRUE@ (cd $(srcdir); $(PYTHON) setup.py build \
+@HAVE_PYTHON2_PROBES_TRUE@@HAVE_PYTHON_PROBES_TRUE@ --build-base $(shell readlink -f $(builddir))/py2build \
+@HAVE_PYTHON2_PROBES_TRUE@@HAVE_PYTHON_PROBES_TRUE@ --verbose)
+# FIXME: Shared library module doesn't build with python3 yet.
+# (cd $(srcdir); $(PYTHON3) setup.py build \
+# --build-base $(shell readlink -f $(builddir))/py3build \
+# --verbose)
+
+@HAVE_PYTHON_PROBES_TRUE@install-exec-local:
+@HAVE_PYTHON2_PROBES_TRUE@@HAVE_PYTHON_PROBES_TRUE@ (cd $(srcdir); $(PYTHON) setup.py build \
+@HAVE_PYTHON2_PROBES_TRUE@@HAVE_PYTHON_PROBES_TRUE@ --build-base $(shell readlink -f $(builddir))/py2build \
+@HAVE_PYTHON2_PROBES_TRUE@@HAVE_PYTHON_PROBES_TRUE@ install --prefix $(DESTDIR)$(prefix) \
+@HAVE_PYTHON2_PROBES_TRUE@@HAVE_PYTHON_PROBES_TRUE@ --single-version-externally-managed \
+@HAVE_PYTHON2_PROBES_TRUE@@HAVE_PYTHON_PROBES_TRUE@ --record $(shell readlink -f $(builddir))/py2build/install_files.txt \
+@HAVE_PYTHON2_PROBES_TRUE@@HAVE_PYTHON_PROBES_TRUE@ --verbose)
+# FIXME: Shared library module doesn't build with python3 yet.
+
+@HAVE_PYTHON_PROBES_TRUE@clean-local:
+@HAVE_PYTHON_PROBES_TRUE@ rm -rf py2build py3build
+
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
--- /dev/null
+# systemtap python module setup file
+# Copyright (C) 2016 Red Hat Inc.
+#
+# This file is part of systemtap, and is free software. You can
+# redistribute it and/or modify it under the terms of the GNU General
+# Public License (GPL); either version 2, or (at your option) any
+# later version.
+
+from setuptools import setup, Extension
+from setuptools.command.egg_info import egg_info
+from setuptools.command.install_egg_info import install_egg_info
+from setuptools.command.build_py import build_py
+import os
+
+
+# With the 'EggInfoCommand' class, we wrap the standard 'egg_info'
+# class and override the build directory, which is normally the source
+# directory. This is necessary since we're doing a VPATH build.
+#
+# This is based on ideas from the following link:
+# <https://blog.kevin-brown.com/programming/2014/09/24/combining-autotools-and-setuptools.html>
+class EggInfoCommand(egg_info):
+ def run(self):
+ if "build" in self.distribution.command_obj:
+ build_command = self.distribution.command_obj["build"]
+ self.egg_base = build_command.build_base
+ self.egg_info = os.path.join(self.egg_base,
+ os.path.basename(self.egg_info))
+ egg_info.run(self)
+
+
+# See discussion above about the 'EggInfoCommand' class.
+class InstallEggInfoCommand(install_egg_info):
+ def run(self):
+ if "build" in self.distribution.command_obj:
+ build_command = self.distribution.command_obj["build"]
+ self.source = os.path.join(build_command.build_base,
+ os.path.basename(self.source))
+ install_egg_info.run(self)
+
+setup(
+ name = 'HelperSDT',
+ version = '0.1.0',
+ description = 'Helper SDT python module',
+ long_description = 'A python module that gets loaded when systemtap wants to set breakpoints in a python file.',
+ url='http://sourceware.org/systemtap',
+ license = 'GPLv2+',
+ author = 'Systemtap Development Team',
+ author_email = 'systemtap@sourceware.org',
+ ext_modules = [
+ Extension("HelperSDT._HelperSDT", ["HelperSDT/_HelperSDT.c"]),
+ ],
+ packages = ['HelperSDT'],
+ cmdclass={
+ "egg_info": EggInfoCommand,
+ "install_egg_info": InstallEggInfoCommand,
+ },
+)