]> sourceware.org Git - systemtap.git/commitdiff
Add initial version of the python helper module.
authorDavid Smith <dsmith@redhat.com>
Mon, 10 Oct 2016 16:27:33 +0000 (11:27 -0500)
committerDavid Smith <dsmith@redhat.com>
Mon, 10 Oct 2016 16:27:33 +0000 (11:27 -0500)
* 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.

python/HelperSDT/README.txt [new file with mode: 0644]
python/HelperSDT/_HelperSDT.c [new file with mode: 0644]
python/HelperSDT/__init__.py [new file with mode: 0644]
python/HelperSDT/__main__.py [new file with mode: 0644]
python/Makefile.am
python/Makefile.in
python/setup.py [new file with mode: 0644]

diff --git a/python/HelperSDT/README.txt b/python/HelperSDT/README.txt
new file mode 100644 (file)
index 0000000..5d71ecc
--- /dev/null
@@ -0,0 +1,124 @@
+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).
diff --git a/python/HelperSDT/_HelperSDT.c b/python/HelperSDT/_HelperSDT.c
new file mode 100644 (file)
index 0000000..b08f1f4
--- /dev/null
@@ -0,0 +1,82 @@
+// 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;
+}
diff --git a/python/HelperSDT/__init__.py b/python/HelperSDT/__init__.py
new file mode 100644 (file)
index 0000000..4d8862b
--- /dev/null
@@ -0,0 +1,182 @@
+# 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)
diff --git a/python/HelperSDT/__main__.py b/python/HelperSDT/__main__.py
new file mode 100644 (file)
index 0000000..dbc646c
--- /dev/null
@@ -0,0 +1,10 @@
+# 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()
index d4b2e7a22b3ce15592aaae44284194bdd397f9a3..b08289fd9fecdf4aec0f68835f5b1ce62a1cce8e 100644 (file)
@@ -2,6 +2,10 @@
 
 AUTOMAKE_OPTIONS = subdir-objects
 
+# Any script in the following variable will get byte-compiled at
+# install time.
+pkglibexecpython_PYTHON =
+
 pkglibexecpython_DATA =
 
 pkglibexecpythondir = $(pkglibexecdir)/python
@@ -9,7 +13,7 @@ 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
@@ -17,4 +21,34 @@ if HAVE_PYTHON_PROBES
 # 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
index 611cc99c3fb9ccfc8e63c8fabc325ff39547c7b6..feb3c982a7c855a62e4d7ed7fa1bddc77269112e 100644 (file)
@@ -93,7 +93,7 @@ host_triplet = @host@
 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
@@ -112,7 +112,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
        $(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 =
@@ -162,7 +162,11 @@ am__uninstall_files_from_dir = { \
     || { 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@
@@ -358,6 +362,10 @@ top_build_prefix = @top_build_prefix@
 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
@@ -392,6 +400,54 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
 $(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=; \
@@ -421,9 +477,10 @@ cscope cscopelist:
 
 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
@@ -456,9 +513,11 @@ distclean-generic:
 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
@@ -482,7 +541,8 @@ install-dvi: install-dvi-am
 
 install-dvi-am:
 
-install-exec-am: install-pkglibexecpythonDATA
+install-exec-am: install-exec-local install-pkglibexecpythonDATA \
+       install-pkglibexecpythonPYTHON
 
 install-html: install-html-am
 
@@ -520,25 +580,49 @@ ps: ps-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:
diff --git a/python/setup.py b/python/setup.py
new file mode 100644 (file)
index 0000000..aea5ce9
--- /dev/null
@@ -0,0 +1,58 @@
+# 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,
+    },
+)
This page took 0.04645 seconds and 5 git commands to generate.