Commits

Ronald Oussoren  committed 155808e

Add testcase for the build scenario mention in issue #69

  • Participants
  • Parent commits d470a96
  • Branches branch-0.7

Comments (0)

Files changed (7)

File py2app_tests/app_with_scripts/main.py

 import sys
 
-
 def function():
     import decimal
 

File py2app_tests/app_with_scripts/presetup.py

+from distutils.core import setup, Extension, Command
+from distutils import sysconfig
+from distutils.command.build_ext import build_ext
+import os, shutil, re, subprocess
+
+
+class my_build_ext (build_ext):
+    def run(self):
+        cmd = self.reinitialize_command('build_dylib')
+        cmd.run()
+        build_ext.run(self)
+
+
+class build_dylib (Command):
+    user_options = []
+
+    def initialize_options(self):
+        pass
+
+    def finalize_options(self):
+        pass
+
+    def get_arch_flags(self):
+        cflags = sysconfig.get_config_var('CFLAGS')
+        result = []
+        for item in re.findall('(-arch\s+\S+)', cflags):
+            result.extend(item.split())
+        return result
+
+    def run(self):
+        print "running build_dylib"
+        bdir = 'build/libdir'
+        if os.path.exists(bdir):
+            shutil.rmtree(bdir)
+
+        os.makedirs(bdir)
+        cflags = self.get_arch_flags()
+        cc = sysconfig.get_config_var('CC')
+
+
+        subprocess.check_call([cc] + cflags + [
+            '-c', '-o', os.path.join(bdir, 'libfoo.o'),
+            'src/libfoo.c'])
+
+        subprocess.check_call(['libtool',
+            '-dynamic', '-o', os.path.join(bdir, 'libfoo.dylib'),
+            '-install_name', os.path.abspath(os.path.join(bdir, 'libfoo.dylib')),
+            os.path.join(os.path.join(bdir, 'libfoo.o'))])
+        
+setup(
+    cmdclass = {
+        'build_dylib': build_dylib,
+        'build_ext': my_build_ext,
+    },
+    ext_modules=[
+        Extension("foo", ["src/modfoo.c"],
+            extra_link_args=["-L%s"%(os.path.abspath("build/libdir"),), "-lfoo"])
+    ],
+    options={
+        'build_ext': {
+            'inplace': True
+        },
+    },
+)

File py2app_tests/app_with_scripts/src/libfoo.c

+#include "libfoo.h"
+
+
+int square(int value)
+{
+	return value * value;
+}

File py2app_tests/app_with_scripts/src/libfoo.h

+/* Helper module */
+
+extern int square(int value);

File py2app_tests/app_with_scripts/src/modfoo.c

+#include "Python.h"
+#include "libfoo.h"
+
+
+static PyMethodDef mod_methods[] = {
+	{ 0, 0, 0, 0}
+};
+
+#if PY_VERSION_HEX >= 0x03000000
+
+static struct PyModuleDef mod_module = {
+	PyModuleDef_HEAD_INIT,
+	"foo",
+	NULL,
+	0,
+	mod_methods,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+#define INITERROR() return NULL
+#define INITDONE() return m
+
+PyObject* PyInit_foo(void);
+
+PyObject*
+PyInit_foo(void)
+
+#else
+
+#define INITERROR() return
+#define INITDONE() return
+
+void initfoo(void);
+
+void
+initfoo(void)
+#endif
+{
+	PyObject* m;
+
+#if PY_VERSION_HEX >= 0x03000000
+	m = PyModule_Create(&mod_module);
+#else
+	m = Py_InitModule4("foo", mod_methods,
+		NULL, NULL, PYTHON_API_VERSION);
+#endif
+	if (!m) {
+		INITERROR();
+	}
+
+	if (PyModule_AddIntConstant(m, "sq_1", square(1))) {
+		INITERROR();
+	}
+
+	if (PyModule_AddIntConstant(m, "sq_2", square(2))) {
+		INITERROR();
+	}
+
+	INITDONE();
+}

File py2app_tests/app_with_scripts/subdir/helper2.py

 import code
-print("Helper 2")
+import foo
+print("Helper 2: %s"%(foo.sq_2,))

File py2app_tests/test_app_with_scripts.py

     # a base-class.
     @classmethod
     def setUpClass(cls):
+        # Ensure build is clean:
+        cls.class_cleanup()
+
         env=os.environ.copy()
         pp = os.path.dirname(os.path.dirname(py2app.__file__))
         if 'PYTHONPATH' in env:
 
         p = subprocess.Popen([
                 sys.executable ] + cls.python_args + [
+                    'presetup.py', 'build_ext'],
+            cwd = cls.app_dir,
+            stdout=subprocess.PIPE,
+            stderr=subprocess.STDOUT,
+            close_fds=True,
+            env=env
+            )
+        lines = p.communicate()[0]
+        if p.wait() != 0:
+            print (lines)
+            raise AssertionError("Creating basic_app extension failed")
+
+        p = subprocess.Popen([
+                sys.executable ] + cls.python_args + [
                     'setup.py', 'py2app'] + cls.py2app_args,
             cwd = cls.app_dir,
             stdout=subprocess.PIPE,
 
     @classmethod
     def tearDownClass(cls):
+        cls.class_cleanup()
+
+    @classmethod
+    def class_cleanup(cls):
         if os.path.exists(os.path.join(cls.app_dir, 'build')):
             shutil.rmtree(os.path.join(cls.app_dir, 'build'))
 
         if os.path.exists(os.path.join(cls.app_dir, 'dist')):
             shutil.rmtree(os.path.join(cls.app_dir, 'dist'))
 
+        if os.path.exists(os.path.join(cls.app_dir, 'foo.so')):
+            os.unlink(os.path.join(cls.app_dir, 'foo.so'))
+
     def start_app(self):
         # Start the test app, return a subprocess object where
         # stdin and stdout are connected to pipes.
         lines = p.communicate()[0]
         p.wait()
 
-        self.assertEqual(lines, b'Helper 2\n')
+        self.assertEqual(lines, b'Helper 2: 4\n')
 
     def test_basic_start(self):
         p = self.start_app()