From 8ab4868d763f70e0a4d7d2b608307e6ce30defb3 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 16 Oct 2018 23:00:28 +0200 Subject: [PATCH 01/20] Fixed build on Windows (tl::InputPipe::wait was missing) --- src/tl/tl/tlStream.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/tl/tl/tlStream.cc b/src/tl/tl/tlStream.cc index 60758c7ed..0ce17a848 100644 --- a/src/tl/tl/tlStream.cc +++ b/src/tl/tl/tlStream.cc @@ -883,10 +883,17 @@ InputPipe::~InputPipe () void InputPipe::close () { + wait (); +} + +int InputPipe::wait () +{ + int ret = 0; if (m_file != NULL) { - fclose (m_file); + ret = _pclose (m_file); m_file = NULL; } + return ret; } size_t From e452a4305c850065ecc14d53032e4a505e3979dc Mon Sep 17 00:00:00 2001 From: klayoutmatthias Date: Thu, 18 Oct 2018 09:41:38 +0200 Subject: [PATCH 02/20] setup.py changes for MSVC builds - Using "Library" rather than "Extension" for building shared libs (does not try to export extension-specific symbols) - Linking against import libs - Using os.path.join consistently for backslash/slash difference --- setup.py | 195 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 118 insertions(+), 77 deletions(-) diff --git a/setup.py b/setup.py index 78cc876c2..d060f76bf 100644 --- a/setup.py +++ b/setup.py @@ -54,7 +54,8 @@ and won't find them. So we need to take away the path with "-Wl,-soname" on Linux (see Config.link_args). """ -from setuptools import setup, Extension, Distribution +from setuptools import setup, Distribution +from setuptools.extension import Extension, Library import glob import os import platform @@ -137,6 +138,13 @@ class Config(object): build_cmd = Distribution().get_command_obj('build') build_cmd.finalize_options() self.build_platlib = build_cmd.build_platlib + self.build_temp = build_cmd.build_temp + if platform.system() == "Windows": + # Windows uses separate temp build folders for debug and release + if build_cmd.debug: + self.build_temp = os.path.join(self.build_temp, "Debug") + else: + self.build_temp = os.path.join(self.build_temp, "Release") self.ext_suffix = sysconfig.get_config_var("EXT_SUFFIX") @@ -155,18 +163,30 @@ class Config(object): ext_suffix = ext_suffix.replace('.so', '.dylib') return mod + ext_suffix - def path_of(self, mod): + def path_of(self, mod, mod_src_path): """ Returns the build path of the library for a given module """ - return os.path.join(self.build_platlib, self.root, self.libname_of(mod)) + if platform.system() == "Windows": + # On Windows, the library to link is the import library + (dll_name, dll_ext) = os.path.splitext(self.libname_of(mod)) + return os.path.join(self.build_temp, mod_src_path, dll_name + ".lib") + else: + return os.path.join(self.build_platlib, self.root, self.libname_of(mod)) def compile_args(self, mod): """ Gets additional compiler arguments """ if platform.system() == "Windows": - return [] + bits = os.getenv("KLAYOUT_BITS") + if bits: + return ["\"-I" + os.path.join(bits, "zlib", "include") + "\"", + "\"-I" + os.path.join(bits, "ptw", "include") + "\"", + "\"-I" + os.path.join(bits, "expat", "include") + "\"", + "\"-I" + os.path.join(bits, "curl", "include") + "\""] + else: + return [] elif platform.system() == "Darwin": return [] else: @@ -174,12 +194,31 @@ class Config(object): "-std=c++11", # because we use unordered_map/unordered_set ] + def libraries(self, mod): + """ + Gets the libraries to add + """ + if platform.system() == "Windows": + if mod == "_tl": + return [ "libcurl", "expat", "pthreadVCE2", "zlib", "wsock32" ] + else: + if mod == "_tl": + ['curl', 'expat'], + return [] + def link_args(self, mod): """ Gets additional linker arguments """ if platform.system() == "Windows": - return [] + args = ["/DLL"] + bits = os.getenv("KLAYOUT_BITS") + if bits: + args += ["\"/LIBPATH:" + os.path.join(bits, "zlib", "libraries") + "\"", + "\"/LIBPATH:" + os.path.join(bits, "ptw", "libraries") + "\"", + "\"/LIBPATH:" + os.path.join(bits, "expat", "libraries") + "\"", + "\"/LIBPATH:" + os.path.join(bits, "curl", "libraries") + "\""] + return args elif platform.system() == "Darwin": # For the dependency modules, make sure we produce a dylib. # We can only link against such, but the bundles produced otherwise. @@ -222,7 +261,6 @@ config = Config() # _tl dependency library _tl_path = os.path.join("src", "tl", "tl") - _tl_sources = set(glob.glob(os.path.join(_tl_path, "*.cc"))) # Exclude sources which are compatible with Qt only @@ -233,41 +271,43 @@ _tl_sources.discard(os.path.join(_tl_path, "tlHttpStreamNoQt.cc")) _tl_sources.discard(os.path.join(_tl_path, "tlFileSystemWatcher.cc")) _tl_sources.discard(os.path.join(_tl_path, "tlDeferredExecutionQt.cc")) -_tl = Extension(config.root + '._tl', - define_macros=config.macros() + [('MAKE_TL_LIBRARY', 1)], - language='c++', - libraries=['curl', 'expat'], - extra_link_args=config.link_args('_tl'), - extra_compile_args=config.compile_args('_tl'), - sources=list(_tl_sources)) +_tl = Library(config.root + '._tl', + define_macros=config.macros() + [('MAKE_TL_LIBRARY', 1)], + language='c++', + libraries=config.libraries('_tl'), + extra_link_args=config.link_args('_tl'), + extra_compile_args=config.compile_args('_tl'), + sources=list(_tl_sources)) # ------------------------------------------------------------------ # _gsi dependency library -_gsi_sources = glob.glob("src/gsi/gsi/*.cc") +_gsi_path = os.path.join("src", "gsi", "gsi") +_gsi_sources = set(glob.glob(os.path.join(_gsi_path, "*.cc"))) -_gsi = Extension(config.root + '._gsi', - define_macros=config.macros() + [('MAKE_GSI_LIBRARY', 1)], - include_dirs=['src/tl/tl'], - extra_objects=[config.path_of('_tl')], - language='c++', - extra_link_args=config.link_args('_gsi'), - extra_compile_args=config.compile_args('_gsi'), - sources=_gsi_sources) +_gsi = Library(config.root + '._gsi', + define_macros=config.macros() + [('MAKE_GSI_LIBRARY', 1)], + include_dirs=[_tl_path], + extra_objects=[config.path_of('_tl', _tl_path)], + language='c++', + extra_link_args=config.link_args('_gsi'), + extra_compile_args=config.compile_args('_gsi'), + sources=list(_gsi_sources)) # ------------------------------------------------------------------ # _pya dependency library -_pya_sources = glob.glob("src/pya/pya/*.cc") +_pya_path = os.path.join("src", "pya", "pya") +_pya_sources = set(glob.glob(os.path.join(_pya_path, "*.cc"))) -_pya = Extension(config.root + '._pya', - define_macros=config.macros() + [('MAKE_PYA_LIBRARY', 1)], - include_dirs=['src/tl/tl', 'src/gsi/gsi'], - extra_objects=[config.path_of('_tl'), config.path_of('_gsi')], - language='c++', - extra_link_args=config.link_args('_pya'), - extra_compile_args=config.compile_args('_pya'), - sources=_pya_sources) +_pya = Library(config.root + '._pya', + define_macros=config.macros() + [('MAKE_PYA_LIBRARY', 1)], + include_dirs=[_tl_path, _gsi_path], + extra_objects=[config.path_of('_tl', _tl_path), config.path_of('_gsi', _gsi_path)], + language='c++', + extra_link_args=config.link_args('_pya'), + extra_compile_args=config.compile_args('_pya'), + sources=list(_pya_sources)) # ------------------------------------------------------------------ # _db dependency library @@ -280,93 +320,94 @@ _db_sources = set(glob.glob(os.path.join(_db_path, "*.cc"))) # not exist. So we need an error-free discard method instead of list's remove. _db_sources.discard(os.path.join(_db_path, "fonts.cc")) -_db = Extension(config.root + '._db', - define_macros=config.macros() + [('MAKE_DB_LIBRARY', 1)], - include_dirs=['src/tl/tl', 'src/gsi/gsi', 'src/db/db'], - extra_objects=[config.path_of('_tl'), config.path_of('_gsi')], - language='c++', - extra_link_args=config.link_args('_db'), - extra_compile_args=config.compile_args('_db'), - sources=list(_db_sources)) +_db = Library(config.root + '._db', + define_macros=config.macros() + [('MAKE_DB_LIBRARY', 1)], + include_dirs=[_tl_path, _gsi_path, _db_path], + extra_objects=[config.path_of('_tl', _tl_path), config.path_of('_gsi', _gsi_path)], + language='c++', + extra_link_args=config.link_args('_db'), + extra_compile_args=config.compile_args('_db'), + sources=list(_db_sources)) # ------------------------------------------------------------------ # _rdb dependency library -_rdb_sources = glob.glob("src/rdb/rdb/*.cc") +_rdb_path = os.path.join("src", "rdb", "rdb") +_rdb_sources = set(glob.glob(os.path.join(_rdb_path, "*.cc"))) -_rdb = Extension(config.root + '._rdb', - define_macros=config.macros() + [('MAKE_RDB_LIBRARY', 1)], - include_dirs=['src/db/db', 'src/tl/tl', 'src/gsi/gsi'], - extra_objects=[config.path_of('_tl'), config.path_of( - '_gsi'), config.path_of('_db')], - language='c++', - extra_link_args=config.link_args('_rdb'), - extra_compile_args=config.compile_args('_rdb'), - sources=_rdb_sources) +_rdb = Library(config.root + '._rdb', + define_macros=config.macros() + [('MAKE_RDB_LIBRARY', 1)], + include_dirs=[_db_path, _tl_path, _gsi_path], + extra_objects=[config.path_of('_tl', _tl_path), config.path_of('_gsi', _gsi_path), config.path_of('_db', _db_path)], + language='c++', + extra_link_args=config.link_args('_rdb'), + extra_compile_args=config.compile_args('_rdb'), + sources=list(_rdb_sources)) # ------------------------------------------------------------------ # dependency libraries from db_plugins db_plugins = [] -for pi in glob.glob("src/plugins/*/db_plugin") + glob.glob("src/plugins/*/*/db_plugin"): +dbpi_dirs = glob.glob(os.path.join("src", "plugins", "*", "db_plugin")) +dbpi_dirs += glob.glob(os.path.join("src", "plugins", "*", "*", "db_plugin")) + +for pi in dbpi_dirs: mod_name = "_" + os.path.split(os.path.split(pi)[-2])[-1] + "_dbpi" - pi_sources = glob.glob(pi + "/*.cc") + pi_sources = glob.glob(os.path.join(pi, "*.cc")) - pi_ext = Extension(config.root + '.db_plugins.' + mod_name, - define_macros=config.macros() + [('MAKE_DB_PLUGIN_LIBRARY', 1)], - include_dirs=['src/plugins/common', - 'src/db/db', 'src/tl/tl', 'src/gsi/gsi'], - extra_objects=[config.path_of('_tl'), config.path_of( - '_gsi'), config.path_of('_db')], - language='c++', - extra_link_args=config.link_args(mod_name), - extra_compile_args=config.compile_args(mod_name), - sources=pi_sources) + pi_ext = Library(config.root + '.db_plugins.' + mod_name, + define_macros=config.macros() + [('MAKE_DB_PLUGIN_LIBRARY', 1)], + include_dirs=[os.path.join("src", "plugins", "common"), + _db_path, _tl_path, _gsi_path], + extra_objects=[config.path_of('_tl', _tl_path), config.path_of('_gsi', _gsi_path), config.path_of('_db', _db_path)], + language='c++', + extra_link_args=config.link_args(mod_name), + extra_compile_args=config.compile_args(mod_name), + sources=pi_sources) db_plugins.append(pi_ext) # ------------------------------------------------------------------ # tl extension library -tl_sources = glob.glob("src/pymod/tl/*.cc") +tl_path = os.path.join("src", "pymod", "tl") +tl_sources = set(glob.glob(os.path.join(tl_path, "*.cc"))) tl = Extension(config.root + '.tl', define_macros=config.macros(), - include_dirs=['src/tl/tl', 'src/gsi/gsi', 'src/pya/pya'], - extra_objects=[config.path_of('_tl'), config.path_of( - '_gsi'), config.path_of('_pya')], + include_dirs=[_tl_path, _gsi_path, _pya_path], + extra_objects=[config.path_of('_tl', _tl_path), config.path_of('_gsi', _gsi_path), config.path_of('_pya', _pya_path)], extra_link_args=config.link_args('tl'), - sources=tl_sources) + sources=list(tl_sources)) # ------------------------------------------------------------------ # db extension library -db_sources = glob.glob("src/pymod/db/*.cc") +db_path = os.path.join("src", "pymod", "db") +db_sources = set(glob.glob(os.path.join(db_path, "*.cc"))) db = Extension(config.root + '.db', define_macros=config.macros(), - include_dirs=['src/db/db', 'src/tl/tl', 'src/gsi/gsi', 'src/pya/pya'], - extra_objects=[config.path_of('_db'), config.path_of( - '_tl'), config.path_of('_gsi'), config.path_of('_pya')], + include_dirs=[_db_path, _tl_path, _gsi_path, _pya_path], + extra_objects=[config.path_of('_db', _db_path), config.path_of('_tl', _tl_path), config.path_of('_gsi', _gsi_path), config.path_of('_pya', _pya_path)], extra_link_args=config.link_args('db'), - sources=db_sources) + sources=list(db_sources)) # ------------------------------------------------------------------ # rdb extension library -rdb_sources = glob.glob("src/pymod/rdb/*.cc") +rdb_path = os.path.join("src", "pymod", "rdb") +rdb_sources = set(glob.glob(os.path.join(rdb_path, "*.cc"))) rdb = Extension(config.root + '.rdb', define_macros=config.macros(), - include_dirs=['src/rdb/rdb', 'src/db/db', - 'src/tl/tl', 'src/gsi/gsi', 'src/pya/pya'], - extra_objects=[config.path_of('_rdb'), config.path_of( - '_gsi'), config.path_of('_pya')], + include_dirs=[_rdb_path, _db_path, _tl_path, _gsi_path, _pya_path], + extra_objects=[config.path_of('_rdb', _rdb_path), config.path_of('_tl', _tl_path), config.path_of('_gsi', _gsi_path), config.path_of('_pya', _pya_path)], extra_link_args=config.link_args('rdb'), - sources=rdb_sources) + sources=list(rdb_sources)) # ------------------------------------------------------------------ # Core setup function From a57b855e12bd4310610324151f6fba29390b0fca Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 18 Oct 2018 23:29:51 +0200 Subject: [PATCH 03/20] Updated version to check CD --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index d060f76bf..53beff5eb 100644 --- a/setup.py +++ b/setup.py @@ -252,7 +252,7 @@ class Config(object): """ Gets the version string """ - return "0.26.0.dev4" + return "0.26.0.dev5" config = Config() From d3fa4465f66aac823d6b10f8bbd088332cbe8d24 Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Fri, 19 Oct 2018 17:53:10 -0400 Subject: [PATCH 04/20] Renaming core modules to klayout.dbcore, klayout.rdbcore and klayout.tlcore --- setup.py | 14 +++++++------- src/pymod/db/dbMain.cc | 2 +- src/pymod/distutils_src/__init__.py | 3 +-- src/pymod/distutils_src/db.py | 1 + src/pymod/distutils_src/rdb.py | 1 + src/pymod/distutils_src/tl.py | 1 + src/pymod/rdb/rdbMain.cc | 2 +- src/pymod/tl/tlMain.cc | 2 +- 8 files changed, 14 insertions(+), 12 deletions(-) create mode 100644 src/pymod/distutils_src/db.py create mode 100644 src/pymod/distutils_src/rdb.py create mode 100644 src/pymod/distutils_src/tl.py diff --git a/setup.py b/setup.py index 78cc876c2..6c9dc2e17 100644 --- a/setup.py +++ b/setup.py @@ -213,7 +213,7 @@ class Config(object): """ Gets the version string """ - return "0.26.0.dev4" + return "0.26.0.dev5" config = Config() @@ -333,12 +333,12 @@ for pi in glob.glob("src/plugins/*/db_plugin") + glob.glob("src/plugins/*/*/db_p tl_sources = glob.glob("src/pymod/tl/*.cc") -tl = Extension(config.root + '.tl', +tl = Extension(config.root + '.tlcore', define_macros=config.macros(), include_dirs=['src/tl/tl', 'src/gsi/gsi', 'src/pya/pya'], extra_objects=[config.path_of('_tl'), config.path_of( '_gsi'), config.path_of('_pya')], - extra_link_args=config.link_args('tl'), + extra_link_args=config.link_args('tlcore'), sources=tl_sources) # ------------------------------------------------------------------ @@ -346,12 +346,12 @@ tl = Extension(config.root + '.tl', db_sources = glob.glob("src/pymod/db/*.cc") -db = Extension(config.root + '.db', +db = Extension(config.root + '.dbcore', define_macros=config.macros(), include_dirs=['src/db/db', 'src/tl/tl', 'src/gsi/gsi', 'src/pya/pya'], extra_objects=[config.path_of('_db'), config.path_of( '_tl'), config.path_of('_gsi'), config.path_of('_pya')], - extra_link_args=config.link_args('db'), + extra_link_args=config.link_args('dbcore'), sources=db_sources) # ------------------------------------------------------------------ @@ -359,13 +359,13 @@ db = Extension(config.root + '.db', rdb_sources = glob.glob("src/pymod/rdb/*.cc") -rdb = Extension(config.root + '.rdb', +rdb = Extension(config.root + '.rdbcore', define_macros=config.macros(), include_dirs=['src/rdb/rdb', 'src/db/db', 'src/tl/tl', 'src/gsi/gsi', 'src/pya/pya'], extra_objects=[config.path_of('_rdb'), config.path_of( '_gsi'), config.path_of('_pya')], - extra_link_args=config.link_args('rdb'), + extra_link_args=config.link_args('rdbcore'), sources=rdb_sources) # ------------------------------------------------------------------ diff --git a/src/pymod/db/dbMain.cc b/src/pymod/db/dbMain.cc index 9a773e0e6..81a2b9421 100644 --- a/src/pymod/db/dbMain.cc +++ b/src/pymod/db/dbMain.cc @@ -33,4 +33,4 @@ static PyObject *db_module_init (const char *mod_name, const char *mod_descripti return module_init (mod_name, mod_description); } -DEFINE_PYMOD_WITH_INIT(db, "db", "KLayout core module 'db'", db_module_init) +DEFINE_PYMOD_WITH_INIT(dbcore, "dbcore", "KLayout core module 'dbcore'", db_module_init) diff --git a/src/pymod/distutils_src/__init__.py b/src/pymod/distutils_src/__init__.py index dce96f8e4..51c551f9b 100644 --- a/src/pymod/distutils_src/__init__.py +++ b/src/pymod/distutils_src/__init__.py @@ -1,5 +1,4 @@ # klayout library definition file -__all__ = [ "tl", "db", "lay", "rdb" ] - +__all__ = ["tl", "db", "rdb"] diff --git a/src/pymod/distutils_src/db.py b/src/pymod/distutils_src/db.py new file mode 100644 index 000000000..2b4ae260c --- /dev/null +++ b/src/pymod/distutils_src/db.py @@ -0,0 +1 @@ +from dbcore import * diff --git a/src/pymod/distutils_src/rdb.py b/src/pymod/distutils_src/rdb.py new file mode 100644 index 000000000..6dd00e138 --- /dev/null +++ b/src/pymod/distutils_src/rdb.py @@ -0,0 +1 @@ +from rdbcore import * diff --git a/src/pymod/distutils_src/tl.py b/src/pymod/distutils_src/tl.py new file mode 100644 index 000000000..cd1abfb00 --- /dev/null +++ b/src/pymod/distutils_src/tl.py @@ -0,0 +1 @@ +from tlcore import * diff --git a/src/pymod/rdb/rdbMain.cc b/src/pymod/rdb/rdbMain.cc index e0008b22a..0da6e19c6 100644 --- a/src/pymod/rdb/rdbMain.cc +++ b/src/pymod/rdb/rdbMain.cc @@ -25,4 +25,4 @@ // to force linking of the rdb module #include "../../rdb/rdb/rdbForceLink.h" -DEFINE_PYMOD(rdb, "rdb", "KLayout core module 'rdb'") +DEFINE_PYMOD(rdbcore, "rdbcore", "KLayout core module 'rdbcore'") diff --git a/src/pymod/tl/tlMain.cc b/src/pymod/tl/tlMain.cc index db6a278fb..cc75be08b 100644 --- a/src/pymod/tl/tlMain.cc +++ b/src/pymod/tl/tlMain.cc @@ -22,4 +22,4 @@ #include "../pymodHelper.h" -DEFINE_PYMOD(tl, "tl", "KLayout core module 'tl'") +DEFINE_PYMOD(tlcore, "tlcore", "KLayout core module 'tlcore'") From 87a49007ff1ebbd7da515fb17b87f96a4c1cae0c Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Fri, 19 Oct 2018 18:53:37 -0400 Subject: [PATCH 05/20] Fixing distutils_src folder structure due to setuptools bug Also: adding PCellDeclarationHelper to klayout.db --- setup.py | 6 +- src/pymod/db/dbMain.cc | 2 +- src/pymod/distutils_src/db.py | 1 - .../distutils_src/{ => klayout}/__init__.py | 3 - .../distutils_src/klayout/db/__init__.py | 3 + .../klayout/db/pcell_declaration_helper.py | 280 ++++++++++++++++++ src/pymod/distutils_src/klayout/rdb.py | 1 + src/pymod/distutils_src/klayout/tl.py | 1 + src/pymod/distutils_src/rdb.py | 1 - src/pymod/distutils_src/tl.py | 1 - src/pymod/rdb/rdbMain.cc | 2 +- src/pymod/tl/tlMain.cc | 2 +- 12 files changed, 291 insertions(+), 12 deletions(-) delete mode 100644 src/pymod/distutils_src/db.py rename src/pymod/distutils_src/{ => klayout}/__init__.py (51%) create mode 100644 src/pymod/distutils_src/klayout/db/__init__.py create mode 100644 src/pymod/distutils_src/klayout/db/pcell_declaration_helper.py create mode 100644 src/pymod/distutils_src/klayout/rdb.py create mode 100644 src/pymod/distutils_src/klayout/tl.py delete mode 100644 src/pymod/distutils_src/rdb.py delete mode 100644 src/pymod/distutils_src/tl.py diff --git a/setup.py b/setup.py index 6c9dc2e17..ccb1caad3 100644 --- a/setup.py +++ b/setup.py @@ -54,7 +54,7 @@ and won't find them. So we need to take away the path with "-Wl,-soname" on Linux (see Config.link_args). """ -from setuptools import setup, Extension, Distribution +from setuptools import setup, Extension, Distribution, find_packages import glob import os import platform @@ -380,6 +380,6 @@ if __name__ == '__main__': author='Matthias Koefferlein', author_email='matthias@klayout.de', url='https://github.com/klayoutmatthias/klayout', - packages=[config.root], - package_dir={config.root: 'src/pymod/distutils_src'}, + packages=find_packages('src/pymod/distutils_src'), + package_dir={'': 'src/pymod/distutils_src'}, # https://github.com/pypa/setuptools/issues/230 ext_modules=[_tl, _gsi, _pya, _db, _rdb] + db_plugins + [tl, db, rdb]) diff --git a/src/pymod/db/dbMain.cc b/src/pymod/db/dbMain.cc index 81a2b9421..97c6388df 100644 --- a/src/pymod/db/dbMain.cc +++ b/src/pymod/db/dbMain.cc @@ -33,4 +33,4 @@ static PyObject *db_module_init (const char *mod_name, const char *mod_descripti return module_init (mod_name, mod_description); } -DEFINE_PYMOD_WITH_INIT(dbcore, "dbcore", "KLayout core module 'dbcore'", db_module_init) +DEFINE_PYMOD_WITH_INIT(dbcore, "db", "KLayout core module 'db'", db_module_init) diff --git a/src/pymod/distutils_src/db.py b/src/pymod/distutils_src/db.py deleted file mode 100644 index 2b4ae260c..000000000 --- a/src/pymod/distutils_src/db.py +++ /dev/null @@ -1 +0,0 @@ -from dbcore import * diff --git a/src/pymod/distutils_src/__init__.py b/src/pymod/distutils_src/klayout/__init__.py similarity index 51% rename from src/pymod/distutils_src/__init__.py rename to src/pymod/distutils_src/klayout/__init__.py index 51c551f9b..a01e9cdd4 100644 --- a/src/pymod/distutils_src/__init__.py +++ b/src/pymod/distutils_src/klayout/__init__.py @@ -1,4 +1 @@ - # klayout library definition file - -__all__ = ["tl", "db", "rdb"] diff --git a/src/pymod/distutils_src/klayout/db/__init__.py b/src/pymod/distutils_src/klayout/db/__init__.py new file mode 100644 index 000000000..c3270bfb8 --- /dev/null +++ b/src/pymod/distutils_src/klayout/db/__init__.py @@ -0,0 +1,3 @@ +from klayout.dbcore import * + +from klayout.db.pcell_declaration_helper import PCellDeclarationHelper diff --git a/src/pymod/distutils_src/klayout/db/pcell_declaration_helper.py b/src/pymod/distutils_src/klayout/db/pcell_declaration_helper.py new file mode 100644 index 000000000..9367f787f --- /dev/null +++ b/src/pymod/distutils_src/klayout/db/pcell_declaration_helper.py @@ -0,0 +1,280 @@ +from klayout.db import Trans, PCellDeclaration, PCellParameterDeclaration + + +class _PCellDeclarationHelperLayerDescriptor(object): + """ + A descriptor object which translates the PCell parameters into class attributes + """ + + def __init__(self, param_index): + self.param_index = param_index + + def __get__(self, obj, type=None): + return obj._layers[self.param_index] + + def __set__(self, obj, value): + raise AttributeError("can't change layer attribute") + + +class _PCellDeclarationHelperParameterDescriptor(object): + """ + A descriptor object which translates the PCell parameters into class attributes + + In some cases (i.e. can_convert_from_shape), these placeholders are not + connected to real parameters (obj._param_values is None). In this case, + the descriptor acts as a value holder (self.value) + """ + + def __init__(self, param_index): + self.param_index = param_index + self.value = None + + def __get__(self, obj, type=None): + if obj._param_values: + return obj._param_values[self.param_index] + else: + return self.value + + def __set__(self, obj, value): + if obj._param_values: + obj._param_values[self.param_index] = value + else: + self.value = value + + +class _PCellDeclarationHelper(PCellDeclaration): + """ + A helper class that somewhat simplifies the implementation + of a PCell + """ + + def __init__(self): + """ + initialize this instance + """ + # "private" attributes + self._param_decls = [] + self._param_values = None + self._layer_param_index = [] + self._layers = [] + # public attributes + self.layout = None + self.shape = None + self.layer = None + self.cell = None + + def param(self, name, value_type, description, hidden=False, readonly=False, unit=None, default=None, choices=None): + """ + Defines a parameter + name -> the short name of the parameter + type -> the type of the parameter + description -> the description text + named parameters + hidden -> (boolean) true, if the parameter is not shown in the dialog + readonly -> (boolean) true, if the parameter cannot be edited + unit -> the unit string + default -> the default value + choices -> ([ [ d, v ], ...) choice descriptions/value for choice type + this method defines accessor methods for the parameters + {name} -> read accessor + set_{name} -> write accessor ({name}= does not work because the + Ruby confuses that method with variables) + {name}_layer -> read accessor for the layer index for TypeLayer parameters + """ + + # create accessor methods for the parameters + param_index = len(self._param_decls) + setattr(type(self), name, _PCellDeclarationHelperParameterDescriptor(param_index)) + + if value_type == type(self).TypeLayer: + setattr(type(self), name + "_layer", + _PCellDeclarationHelperLayerDescriptor(len(self._layer_param_index))) + self._layer_param_index.append(param_index) + + # store the parameter declarations + pdecl = PCellParameterDeclaration(name, value_type, description) + self._param_decls.append(pdecl) + + # set additional attributes of the parameters + pdecl.hidden = hidden + pdecl.readonly = readonly + if not (default is None): + pdecl.default = default + if not (unit is None): + pdecl.unit = unit + if not (choices is None): + if not isinstance(choices, list) and not isinstance(choices, tuple): + raise "choices value must be an list/tuple of two-element arrays (description, value)" + for c in choices: + if (not isinstance(choices, list) and not isinstance(choices, tuple)) or len(c) != 2: + raise "choices value must be an list/tuple of two-element arrays (description, value)" + pdecl.add_choice(c[0], c[1]) + + # return the declaration object for further operations + return pdecl + + def display_text(self, parameters): + """ + implementation of display_text + """ + self._param_values = parameters + text = self.display_text_impl() + self._param_values = None + return text + + def get_parameters(self): + """ + gets the parameters + """ + return self._param_decls + + def get_values(self): + """ + gets the temporary parameter values + """ + v = self._param_values + self._param_values = None + return v + + def init_values(self, values=None, layers=None): + """ + initializes the temporary parameter values + "values" are the original values. If "None" is given, the + default values will be used. + "layers" are the layer indexes corresponding to the layer + parameters. + """ + if not values: + self._param_values = [] + for pd in self._param_decls: + self._param_values.append(pd.default) + else: + self._param_values = values + self._layers = layers + + def finish(self): + """ + Needs to be called at the end of produce() after init_values was used + """ + self._param_values = None + self._layers = None + + def get_layers(self, parameters): + """ + get the layer definitions + """ + layers = [] + for i in self._layer_param_index: + layers.append(parameters[i]) + return layers + + def coerce_parameters(self, layout, parameters): + """ + coerce parameters (make consistent) + """ + self.init_values(parameters) + self.layout = layout + self.coerce_parameters_impl() + self.layout = None + return self.get_values() + + def produce(self, layout, layers, parameters, cell): + """ + coerce parameters (make consistent) + """ + self.init_values(parameters, layers) + self.cell = cell + self.layout = layout + self.produce_impl() + self.cell = None + self.layout = None + self.finish() + + def can_create_from_shape(self, layout, shape, layer): + """ + produce a helper for can_create_from_shape + """ + self.layout = layout + self.shape = shape + self.layer = layer + ret = self.can_create_from_shape_impl() + self.layout = None + self.shape = None + self.layer = None + return ret + + def transformation_from_shape(self, layout, shape, layer): + """ + produce a helper for parameters_from_shape + """ + self.layout = layout + self.shape = shape + self.layer = layer + t = self.transformation_from_shape_impl() + self.layout = None + self.shape = None + self.layer = None + return t + + def parameters_from_shape(self, layout, shape, layer): + """ + produce a helper for parameters_from_shape + with this helper, the implementation can use the parameter setters + """ + self.init_values() + self.layout = layout + self.shape = shape + self.layer = layer + self.parameters_from_shape_impl() + param = self.get_values() + self.layout = None + self.shape = None + self.layer = None + return param + + def display_text_impl(self): + """ + default implementation + """ + return "" + + def coerce_parameters_impl(self): + """ + default implementation + """ + pass + + def produce_impl(self): + """ + default implementation + """ + pass + + def can_create_from_shape_impl(self): + """ + default implementation + """ + return False + + def parameters_from_shape_impl(self): + """ + default implementation + """ + pass + + def transformation_from_shape_impl(self): + """ + default implementation + """ + return Trans() + + +# import the Type... constants from PCellParameterDeclaration +for k in dir(PCellParameterDeclaration): + if k.startswith("Type"): + setattr(_PCellDeclarationHelper, k, getattr(PCellParameterDeclaration, k)) + +# Inject the PCellDeclarationHelper into pya module for consistency: +PCellDeclarationHelper = _PCellDeclarationHelper + +__all__ = ['PCellDeclarationHelper'] diff --git a/src/pymod/distutils_src/klayout/rdb.py b/src/pymod/distutils_src/klayout/rdb.py new file mode 100644 index 000000000..217207310 --- /dev/null +++ b/src/pymod/distutils_src/klayout/rdb.py @@ -0,0 +1 @@ +from klayout.rdbcore import * diff --git a/src/pymod/distutils_src/klayout/tl.py b/src/pymod/distutils_src/klayout/tl.py new file mode 100644 index 000000000..0645f506f --- /dev/null +++ b/src/pymod/distutils_src/klayout/tl.py @@ -0,0 +1 @@ +from klayout.tlcore import * diff --git a/src/pymod/distutils_src/rdb.py b/src/pymod/distutils_src/rdb.py deleted file mode 100644 index 6dd00e138..000000000 --- a/src/pymod/distutils_src/rdb.py +++ /dev/null @@ -1 +0,0 @@ -from rdbcore import * diff --git a/src/pymod/distutils_src/tl.py b/src/pymod/distutils_src/tl.py deleted file mode 100644 index cd1abfb00..000000000 --- a/src/pymod/distutils_src/tl.py +++ /dev/null @@ -1 +0,0 @@ -from tlcore import * diff --git a/src/pymod/rdb/rdbMain.cc b/src/pymod/rdb/rdbMain.cc index 0da6e19c6..ba085fe97 100644 --- a/src/pymod/rdb/rdbMain.cc +++ b/src/pymod/rdb/rdbMain.cc @@ -25,4 +25,4 @@ // to force linking of the rdb module #include "../../rdb/rdb/rdbForceLink.h" -DEFINE_PYMOD(rdbcore, "rdbcore", "KLayout core module 'rdbcore'") +DEFINE_PYMOD(rdbcore, "rdb", "KLayout core module 'rdb'") diff --git a/src/pymod/tl/tlMain.cc b/src/pymod/tl/tlMain.cc index cc75be08b..42c21c630 100644 --- a/src/pymod/tl/tlMain.cc +++ b/src/pymod/tl/tlMain.cc @@ -22,4 +22,4 @@ #include "../pymodHelper.h" -DEFINE_PYMOD(tlcore, "tlcore", "KLayout core module 'tlcore'") +DEFINE_PYMOD(tlcore, "tl", "KLayout core module 'tl'") From c3ab951c8a86e137f523305ffb35d44deb111442 Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Fri, 19 Oct 2018 19:02:38 -0400 Subject: [PATCH 06/20] passing python unit tests --- src/pymod/distutils_src/klayout/db/__init__.py | 3 +++ src/pymod/distutils_src/klayout/db/pcell_declaration_helper.py | 2 -- src/pymod/distutils_src/klayout/rdb.py | 3 +++ src/pymod/distutils_src/klayout/tl.py | 3 +++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/pymod/distutils_src/klayout/db/__init__.py b/src/pymod/distutils_src/klayout/db/__init__.py index c3270bfb8..ed86dcf86 100644 --- a/src/pymod/distutils_src/klayout/db/__init__.py +++ b/src/pymod/distutils_src/klayout/db/__init__.py @@ -1,3 +1,6 @@ +import klayout.dbcore from klayout.dbcore import * from klayout.db.pcell_declaration_helper import PCellDeclarationHelper + +__all__ = klayout.dbcore.__all__ + ['PCellDeclarationHelper'] diff --git a/src/pymod/distutils_src/klayout/db/pcell_declaration_helper.py b/src/pymod/distutils_src/klayout/db/pcell_declaration_helper.py index 9367f787f..e351a818b 100644 --- a/src/pymod/distutils_src/klayout/db/pcell_declaration_helper.py +++ b/src/pymod/distutils_src/klayout/db/pcell_declaration_helper.py @@ -276,5 +276,3 @@ for k in dir(PCellParameterDeclaration): # Inject the PCellDeclarationHelper into pya module for consistency: PCellDeclarationHelper = _PCellDeclarationHelper - -__all__ = ['PCellDeclarationHelper'] diff --git a/src/pymod/distutils_src/klayout/rdb.py b/src/pymod/distutils_src/klayout/rdb.py index 217207310..eb48ea888 100644 --- a/src/pymod/distutils_src/klayout/rdb.py +++ b/src/pymod/distutils_src/klayout/rdb.py @@ -1 +1,4 @@ +import klayout.rdbcore from klayout.rdbcore import * + +__all__ = klayout.rdbcore.__all__ diff --git a/src/pymod/distutils_src/klayout/tl.py b/src/pymod/distutils_src/klayout/tl.py index 0645f506f..a4c4287e9 100644 --- a/src/pymod/distutils_src/klayout/tl.py +++ b/src/pymod/distutils_src/klayout/tl.py @@ -1 +1,4 @@ +import klayout.tlcore from klayout.tlcore import * + +__all__ = klayout.tlcore.__all__ From c1dbb023ae8f70259e8e67991b9c0e5dc8ee1db1 Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Fri, 19 Oct 2018 19:09:20 -0400 Subject: [PATCH 07/20] fixing editable install 'python setup.py develop' --- src/pymod/distutils_src/klayout/.gitignore | 9 +++++++++ src/pymod/distutils_src/klayout/db_plugins/.keep | 0 2 files changed, 9 insertions(+) create mode 100644 src/pymod/distutils_src/klayout/.gitignore create mode 100644 src/pymod/distutils_src/klayout/db_plugins/.keep diff --git a/src/pymod/distutils_src/klayout/.gitignore b/src/pymod/distutils_src/klayout/.gitignore new file mode 100644 index 000000000..4b1a6f02b --- /dev/null +++ b/src/pymod/distutils_src/klayout/.gitignore @@ -0,0 +1,9 @@ +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so +*.dylib diff --git a/src/pymod/distutils_src/klayout/db_plugins/.keep b/src/pymod/distutils_src/klayout/db_plugins/.keep new file mode 100644 index 000000000..e69de29bb From 46116f4828d513c9caea425cd3eb45c1175ca9a3 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 29 Sep 2018 23:35:30 +0200 Subject: [PATCH 08/20] Basic performance improvement in the bitmap to image area Empty bitmaps are skipped now --- src/laybasic/laybasic/layBitmapsToImage.cc | 97 +++++++++++++--------- 1 file changed, 56 insertions(+), 41 deletions(-) diff --git a/src/laybasic/laybasic/layBitmapsToImage.cc b/src/laybasic/laybasic/layBitmapsToImage.cc index 57e547e4b..2c0ca533b 100644 --- a/src/laybasic/laybasic/layBitmapsToImage.cc +++ b/src/laybasic/laybasic/layBitmapsToImage.cc @@ -386,13 +386,18 @@ render_scanline_cross (const uint32_t *dp, unsigned int ds, const lay::Bitmap *p } } -static void create_precursor_bitmaps (const std::vector &view_ops_in, const std::vector &pbitmaps_in, const lay::LineStyles &ls, unsigned int width, unsigned int height, std::map &precursors, QMutex *mutex) +static void create_precursor_bitmaps (const std::vector &view_ops_in, const std::vector &vo_map, const std::vector &pbitmaps_in, const std::vector &bm_map, const lay::LineStyles &ls, unsigned int width, unsigned int height, std::map &precursors, QMutex *mutex) { + tl_assert (bm_map.size () == vo_map.size ()); + // Styled lines with width > 1 are not rendered directly, but through an intermediate step. // We prepare the necessary precursor bitmaps now - for (unsigned int i = 0; i < view_ops_in.size (); ++i) { + for (unsigned int i = 0; i < vo_map.size (); ++i) { - const ViewOp &op = view_ops_in [i]; + unsigned int vo_index = vo_map [i]; + unsigned int bm_index = bm_map [i]; + + const ViewOp &op = view_ops_in [vo_index]; if (op.width () > 1 && ls.style (op.line_style_index ()).width () > 0) { // lock bitmaps against change by the redraw thread @@ -400,12 +405,12 @@ static void create_precursor_bitmaps (const std::vector &view_ops_i mutex->lock (); } - lay::Bitmap &bp = precursors.insert (std::make_pair (i, lay::Bitmap (width, height, 1.0))).first->second; + lay::Bitmap &bp = precursors.insert (std::make_pair (bm_index, lay::Bitmap (width, height, 1.0))).first->second; LineStyleInfo ls_info = ls.style (op.line_style_index ()); ls_info.scale_pattern (op.width ()); for (unsigned int y = 0; y < height; y++) { - render_scanline_std_edge (ls_info.pattern (), ls_info.pattern_stride (), pbitmaps_in [i], y, width, height, bp.scanline (y)); + render_scanline_std_edge (ls_info.pattern (), ls_info.pattern_stride (), pbitmaps_in [bm_index], y, width, height, bp.scanline (y)); } if (mutex) { @@ -418,7 +423,7 @@ static void create_precursor_bitmaps (const std::vector &view_ops_i } static void -bitmaps_to_image_rgb (const std::vector &view_ops_in, +bitmaps_to_image_rgb (const std::vector &view_ops_in, const std::vector &pbitmaps_in, const lay::DitherPattern &dp, const lay::LineStyles &ls, @@ -427,29 +432,33 @@ bitmaps_to_image_rgb (const std::vector &view_ops_in, bool transparent, QMutex *mutex) { - unsigned int n_in = (unsigned int) view_ops_in.size (); - std::vector bm_map; std::vector vo_map; - vo_map.reserve (n_in); - for (unsigned int i = 0; i < n_in; ++i) { - vo_map.push_back (i); - } + vo_map.reserve (view_ops_in.size ()); + bm_map.reserve (view_ops_in.size ()); + unsigned int n_in = 0; - if (! use_bitmap_index) { - bm_map = vo_map; - } else { - bm_map.reserve (n_in); - for (unsigned int i = 0; i < n_in; ++i) { - bm_map.push_back (view_ops_in [i].bitmap_index () < 0 ? i : view_ops_in [i].bitmap_index ()); + // drop invisible and empty bitmaps, build bitmap mask + for (unsigned int i = 0; i < view_ops_in.size (); ++i) { + + const lay::ViewOp &vop = view_ops_in [i]; + + unsigned int bi = (use_bitmap_index && vop.bitmap_index () >= 0) ? (unsigned int) vop.bitmap_index () : i; + const lay::Bitmap *pb = bi < pbitmaps_in.size () ? pbitmaps_in [bi] : 0; + + if ((vop.ormask () | ~vop.andmask ()) != 0 && pb && ! pb->empty ()) { + vo_map.push_back (i); + bm_map.push_back (bi); + ++n_in; } + } // Styled lines with width > 1 are not rendered directly, but through an intermediate step. // We prepare the necessary precursor bitmaps now std::map precursors; - create_precursor_bitmaps (view_ops_in, pbitmaps_in, ls, width, height, precursors, mutex); + create_precursor_bitmaps (view_ops_in, vo_map, pbitmaps_in, bm_map, ls, width, height, precursors, mutex); std::vector view_ops; std::vector pbitmaps; @@ -489,18 +498,19 @@ bitmaps_to_image_rgb (const std::vector &view_ops_in, unsigned int w = vop.width (); const lay::Bitmap *pb = 0; + unsigned int bm_index = bm_map[i]; if (bm_map [i] < pbitmaps_in.size ()) { if (w > 1 && ls.style (vop.line_style_index ()).width () > 0) { - tl_assert (precursors.find (i) != precursors.end ()); - pb = &precursors [i]; + tl_assert (precursors.find (bm_index) != precursors.end ()); + pb = &precursors [bm_index]; } else { - pb = pbitmaps_in [bm_map[i]]; + pb = pbitmaps_in [bm_index]; } } if (pb != 0 && w > 0 - && ((pb->first_scanline () < y + slice && pb->last_scanline () > y) || w > 1) + && (pb->first_scanline () + w - 1 < y + slice && pb->last_scanline () > y + w - 1) && (vop.ormask () | ~vop.andmask ()) != 0) { uint32_t non_empty_sl = 0; @@ -660,29 +670,33 @@ bitmaps_to_image_mono (const std::vector &view_ops_in, bool use_bitmap_index, QMutex *mutex) { - unsigned int n_in = (unsigned int) view_ops_in.size (); - std::vector bm_map; std::vector vo_map; - vo_map.reserve (n_in); - for (unsigned int i = 0; i < n_in; ++i) { - vo_map.push_back (i); - } + vo_map.reserve (view_ops_in.size ()); + bm_map.reserve (view_ops_in.size ()); + unsigned int n_in = 0; - if (! use_bitmap_index) { - bm_map = vo_map; - } else { - bm_map.reserve (n_in); - for (unsigned int i = 0; i < n_in; ++i) { - bm_map.push_back (view_ops_in [i].bitmap_index () < 0 ? i : view_ops_in [i].bitmap_index ()); + // drop invisible and empty bitmaps, build bitmap mask + for (unsigned int i = 0; i < view_ops_in.size (); ++i) { + + const lay::ViewOp &vop = view_ops_in [i]; + + unsigned int bi = (use_bitmap_index && vop.bitmap_index () >= 0) ? (unsigned int) vop.bitmap_index () : i; + const lay::Bitmap *pb = bi < pbitmaps_in.size () ? pbitmaps_in [bi] : 0; + + if ((vop.ormask () | ~vop.andmask ()) != 0 && pb && ! pb->empty ()) { + vo_map.push_back (i); + bm_map.push_back (bi); + ++n_in; } + } // Styled lines with width > 1 are not rendered directly, but through an intermediate step. // We prepare the necessary precursor bitmaps now std::map precursors; - create_precursor_bitmaps (view_ops_in, pbitmaps_in, ls, width, height, precursors, mutex); + create_precursor_bitmaps (view_ops_in, vo_map, pbitmaps_in, bm_map, ls, width, height, precursors, mutex); std::vector view_ops; std::vector pbitmaps; @@ -722,18 +736,19 @@ bitmaps_to_image_mono (const std::vector &view_ops_in, unsigned int w = vop.width (); const lay::Bitmap *pb = 0; + unsigned int bm_index = bm_map[i]; if (bm_map [i] < pbitmaps_in.size ()) { if (w > 1 && ls.style (vop.line_style_index ()).width () > 0) { - tl_assert (precursors.find (i) != precursors.end ()); - pb = &precursors [i]; + tl_assert (precursors.find (bm_index) != precursors.end ()); + pb = &precursors [bm_index]; } else { - pb = pbitmaps_in [bm_map[i]]; + pb = pbitmaps_in [bm_index]; } } - if (pb != 0 + if (pb != 0 && w > 0 - && ((pb->first_scanline () < y + slice && pb->last_scanline () > y) || w > 1) + && (pb->first_scanline () + w - 1 < y + slice && pb->last_scanline () > y + w - 1) && (vop.ormask () | ~vop.andmask ()) != 0) { uint32_t non_empty_sl = 0; From dc9267d61e9d5734efb5b14f1b73cdc65113abc4 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 30 Sep 2018 00:16:19 +0200 Subject: [PATCH 09/20] WIP: updated solution * Reverted first solution partially because it lead to drawing errors. * Redraw thread will fire workers only for layers that really need to be drawn --- src/laybasic/laybasic/layBitmapsToImage.cc | 4 ++-- src/laybasic/laybasic/layRedrawLayerInfo.h | 15 ++++++++++++--- src/laybasic/laybasic/layRedrawThread.cc | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/laybasic/laybasic/layBitmapsToImage.cc b/src/laybasic/laybasic/layBitmapsToImage.cc index 2c0ca533b..dbd8bbc64 100644 --- a/src/laybasic/laybasic/layBitmapsToImage.cc +++ b/src/laybasic/laybasic/layBitmapsToImage.cc @@ -510,7 +510,7 @@ bitmaps_to_image_rgb (const std::vector &view_ops_in, if (pb != 0 && w > 0 - && (pb->first_scanline () + w - 1 < y + slice && pb->last_scanline () > y + w - 1) + && ((pb->first_scanline () < y + slice && pb->last_scanline () > y) || w > 1) && (vop.ormask () | ~vop.andmask ()) != 0) { uint32_t non_empty_sl = 0; @@ -748,7 +748,7 @@ bitmaps_to_image_mono (const std::vector &view_ops_in, if (pb != 0 && w > 0 - && (pb->first_scanline () + w - 1 < y + slice && pb->last_scanline () > y + w - 1) + && ((pb->first_scanline () < y + slice && pb->last_scanline () > y) || w > 1) && (vop.ormask () | ~vop.andmask ()) != 0) { uint32_t non_empty_sl = 0; diff --git a/src/laybasic/laybasic/layRedrawLayerInfo.h b/src/laybasic/laybasic/layRedrawLayerInfo.h index 3befe4c33..60865b241 100644 --- a/src/laybasic/laybasic/layRedrawLayerInfo.h +++ b/src/laybasic/laybasic/layRedrawLayerInfo.h @@ -74,9 +74,10 @@ struct RedrawLayerInfo /** * @brief The layer index * - * The logical layer to draw. If this member is <0 and the cellview_index is <0, it is an invalid layer, - * which is ignored. If the cellview_index is >=0, it denotes a "cell frame" pseudo - * layer. It is set by the constructor. + * The logical layer to draw. The layer index can be <0 which indicates a + * layer with not layout source (cell_frame may be true to indicate a + * pseudo layer then). + * This attribute is set by the constructor. */ int layer_index; @@ -115,6 +116,14 @@ struct RedrawLayerInfo * This member is set by the constructor. */ bool inverse_prop_sel; + + /** + * @brief Returns true, if the layer needs to be drawn + */ + bool needs_drawing () const + { + return visible && enabled && (cell_frame || layer_index >= 0) && cellview_index >= 0; + } }; } diff --git a/src/laybasic/laybasic/layRedrawThread.cc b/src/laybasic/laybasic/layRedrawThread.cc index f71f15e00..757692ada 100644 --- a/src/laybasic/laybasic/layRedrawThread.cc +++ b/src/laybasic/laybasic/layRedrawThread.cc @@ -307,7 +307,7 @@ RedrawThread::do_start (bool clear, const db::Vector *shift_vector, const std::v } for (int i = 0; i < m_nlayers; ++i) { - if (m_layers [i].visible && m_layers [i].enabled) { + if (m_layers [i].needs_drawing ()) { schedule (new RedrawThreadTask (i)); } } From d67a50bd1d8c280c5473dce7488164224ff2c873 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 30 Sep 2018 10:27:44 +0200 Subject: [PATCH 10/20] Fixed #176 by introducing a separate bitmap for text drawing optimization. --- .../laybasic/layRedrawThreadWorker.cc | 26 +++++++++++++------ src/laybasic/laybasic/layRedrawThreadWorker.h | 2 +- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/laybasic/laybasic/layRedrawThreadWorker.cc b/src/laybasic/laybasic/layRedrawThreadWorker.cc index a7d84268a..daabbdac3 100644 --- a/src/laybasic/laybasic/layRedrawThreadWorker.cc +++ b/src/laybasic/laybasic/layRedrawThreadWorker.cc @@ -1232,20 +1232,26 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c vertex = m_planes[3 + plane_group * (planes_per_layer / 3)]; // do not draw, if there is nothing to draw - if (mp_layout->cells () <= ci || vp.empty ()) { + if (mp_layout->cells () <= ci || vp.empty () || mp_layout->cell (ci).bbox (m_layer).empty ()) { return; } if (cell_var_cached (ci, trans)) { return; } + std::auto_ptr opt_bitmap; + lay::Bitmap *vertex_bitmap = dynamic_cast (vertex); + if (m_text_lazy_rendering && vertex_bitmap) { + opt_bitmap.reset (new lay::Bitmap (vertex_bitmap->width (), vertex_bitmap->height (), vertex_bitmap->resolution ())); + } + for (std::vector::const_iterator b = vp.begin (); b != vp.end (); ++b) { - draw_text_layer (drawing_context, ci, trans, *b, level, fill, frame, vertex, text); + draw_text_layer (drawing_context, ci, trans, *b, level, fill, frame, vertex, text, opt_bitmap.get ()); } } void -RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &vp, int level, CanvasPlane *fill, CanvasPlane *frame, CanvasPlane *vertex, CanvasPlane *text) +RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &vp, int level, CanvasPlane *fill, CanvasPlane *frame, CanvasPlane *vertex, CanvasPlane *text, lay::Bitmap *opt_bitmap) { test_snapshot (0); @@ -1283,6 +1289,9 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c // paint the simplified box if (anything) { r.draw (trans * bbox, 0, frame, vertex, 0); + if (opt_bitmap) { + r.draw (trans * bbox, 0, 0, opt_bitmap, 0); + } } // do not dive further into hierarchy @@ -1318,6 +1327,9 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c test_snapshot (0); r.draw (*shape, trans, fill, frame, vertex, text); + if (opt_bitmap) { + r.draw (*shape, trans, 0, 0, opt_bitmap, 0); + } ++shape; --ntexts; @@ -1355,8 +1367,6 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c // dive down into the hierarchy .. if (need_to_dive) { - const lay::Bitmap *vertex_bitmap = dynamic_cast (vertex); - // create a set of boxes to look into std::vector vv = search_regions (cell_bbox, vp, level); @@ -1377,7 +1387,7 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c bool skip = false; if (m_text_lazy_rendering && qid != current_quad_id) { current_quad_id = qid; - skip = vertex_bitmap && skip_quad (inst.quad_box () & bbox, vertex_bitmap, trans); + skip = opt_bitmap && skip_quad (inst.quad_box () & bbox, opt_bitmap, trans); } if (skip) { @@ -1448,7 +1458,7 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c db::ICplxTrans t (cell_inst.complex_trans (*p)); db::Box new_vp = db::Box (t.inverted () * *v); - draw_text_layer (drawing_context, new_ci, trans * t, new_vp, level + 1, fill, frame, vertex, text); + draw_text_layer (drawing_context, new_ci, trans * t, new_vp, level + 1, fill, frame, vertex, text, opt_bitmap); } @@ -1648,7 +1658,7 @@ RedrawThreadWorker::draw_layer_wo_cache (int from_level, int to_level, db::cell_ // skip this quad if we have drawn something here already size_t qid = inst.quad_id (); bool skip = false; - if (m_text_lazy_rendering && qid != current_quad_id) { + if (qid != current_quad_id) { current_quad_id = qid; skip = skip_quad (inst.quad_box () & bbox, vertex_bitmap, trans); } diff --git a/src/laybasic/laybasic/layRedrawThreadWorker.h b/src/laybasic/laybasic/layRedrawThreadWorker.h index 0b49a44d3..ea2a90a11 100644 --- a/src/laybasic/laybasic/layRedrawThreadWorker.h +++ b/src/laybasic/laybasic/layRedrawThreadWorker.h @@ -180,7 +180,7 @@ private: void draw_layer (int from_level, int to_level, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &redraw_box, int level, lay::CanvasPlane *fill, lay::CanvasPlane *frame, lay::CanvasPlane *vertex, lay::CanvasPlane *text, const UpdateSnapshotCallback *update_snapshot); void draw_layer_wo_cache (int from_level, int to_level, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &vv, int level, lay::CanvasPlane *fill, lay::CanvasPlane *frame, lay::CanvasPlane *vertex, lay::CanvasPlane *text, const UpdateSnapshotCallback *update_snapshot); void draw_text_layer (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &redraw_regions, int level); - void draw_text_layer (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &redraw_region, int level, lay::CanvasPlane *fill, lay::CanvasPlane *frame, lay::CanvasPlane *vertex, lay::CanvasPlane *text); + void draw_text_layer (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &redraw_region, int level, lay::CanvasPlane *fill, lay::CanvasPlane *frame, lay::CanvasPlane *vertex, lay::CanvasPlane *text, Bitmap *opt_bitmap); void draw_boxes (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &redraw_regions, int level); void draw_boxes (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &redraw_region, int level); void draw_box_properties (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &redraw_regions, int level); From d4636803e610827a7c9b71bdc65ee49277f36528 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 20 Oct 2018 09:56:45 +0200 Subject: [PATCH 11/20] Fixed typo in Changelog --- Changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 1f0dbe239..138367007 100644 --- a/Changelog +++ b/Changelog @@ -15,7 +15,7 @@ DEF reader did not pull vias from LEF * Bugfix: https://github.com/klayoutmatthias/klayout/issues/174 Performance issue with many layers with width >1 -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/175 +* Bugfix: https://github.com/klayoutmatthias/klayout/issues/176 Painting issue with texts * Bugfix: https://github.com/klayoutmatthias/klayout/issues/185 Hash values available as __hash__ standard method now From 79871f6bab032b052fdf90c60ae9156a5d18b4b2 Mon Sep 17 00:00:00 2001 From: klayoutmatthias Date: Sat, 20 Oct 2018 20:44:56 +0000 Subject: [PATCH 12/20] Fixed setup.py for Linux (and maybe for MacOS too) - Added "lib" prefix for libraries - Forced setuptools to produce shared objects for the libraries - otherwise it will produce static libs --- setup.py | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index 53beff5eb..f0fedbec3 100644 --- a/setup.py +++ b/setup.py @@ -62,6 +62,7 @@ import platform import distutils.sysconfig as sysconfig from distutils.errors import CompileError import distutils.command.build_ext +import setuptools.command.build_ext import multiprocessing N_cores = multiprocessing.cpu_count() @@ -122,6 +123,26 @@ def patched_get_ext_filename(self, ext_name): distutils.command.build_ext.build_ext.get_ext_filename = patched_get_ext_filename + +# despite it's name, setuptools.command.build_ext.link_shared_object won't +# link a shared object on Linux, but a static library and patches distutils +# for this ... We're patching this back now. + +def always_link_shared_object( + self, objects, output_libname, output_dir=None, libraries=None, + library_dirs=None, runtime_library_dirs=None, export_symbols=None, + debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, + target_lang=None): + self.link( + self.SHARED_LIBRARY, objects, output_libname, + output_dir, libraries, library_dirs, runtime_library_dirs, + export_symbols, debug, extra_preargs, extra_postargs, + build_temp, target_lang + ) + +setuptools.command.build_ext.libtype = "shared" +setuptools.command.build_ext.link_shared_object = always_link_shared_object + # ---------------------------------------------------------------------------------------- @@ -159,9 +180,17 @@ class Config(object): The library name is usually decorated (i.e. "tl" -> "tl.cpython-35m-x86_64-linux-gnu.so"). """ ext_suffix = self.ext_suffix - if platform.system() == "Darwin" and '_dbpi' in mod: - ext_suffix = ext_suffix.replace('.so', '.dylib') - return mod + ext_suffix + if platform.system() == "Windows": + return mod + ext_suffix + else: + if platform.system() == "Darwin" and '_dbpi' in mod: + ext_suffix = ext_suffix.replace('.so', '.dylib') + if mod[0] == '_': + # is a library, not an extension module and setuptools + # will add the "lib" suffix + return "lib" + mod + ext_suffix + else: + return mod + ext_suffix def path_of(self, mod, mod_src_path): """ @@ -203,7 +232,7 @@ class Config(object): return [ "libcurl", "expat", "pthreadVCE2", "zlib", "wsock32" ] else: if mod == "_tl": - ['curl', 'expat'], + return ['curl', 'expat'] return [] def link_args(self, mod): @@ -252,7 +281,7 @@ class Config(object): """ Gets the version string """ - return "0.26.0.dev5" + return "0.26.0.dev6" config = Config() From a0c3b095a2d923ac14bb2555deb33587866c79a5 Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Sat, 20 Oct 2018 17:21:00 -0400 Subject: [PATCH 13/20] fixing dbpi library names --- setup.py | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index f0fedbec3..45942e0cc 100644 --- a/setup.py +++ b/setup.py @@ -106,6 +106,8 @@ if sys.version_info[0] * 10 + sys.version_info[1] > 26: distutils.ccompiler.CCompiler.compile = parallelCCompile +# TODO: delete (Obsolete) +# patch get_ext_filename from distutils.command.build_ext import build_ext _old_get_ext_filename = build_ext.get_ext_filename @@ -124,8 +126,32 @@ def patched_get_ext_filename(self, ext_name): distutils.command.build_ext.build_ext.get_ext_filename = patched_get_ext_filename -# despite it's name, setuptools.command.build_ext.link_shared_object won't -# link a shared object on Linux, but a static library and patches distutils +# end patch get_ext_filename + + +# patch CCompiler's library_filename for _dbpi libraries (SOs) +# Its default is to have .so for shared objects, instead of dylib, +# hence the patch + +from distutils.ccompiler import CCompiler +old_library_filename = CCompiler.library_filename + + +def patched_library_filename(self, libname, lib_type='static', # or 'shared' + strip_dir=0, output_dir=''): + if platform.system() == "Darwin" and '_dbpi' in libname: + lib_type = 'dylib' + return old_library_filename(self, libname, lib_type=lib_type, + strip_dir=strip_dir, output_dir=output_dir) + + +distutils.ccompiler.CCompiler.library_filename = patched_library_filename + +# end patch CCompiler's library_filename for _dbpi libraries (SOs) + + +# despite its name, setuptools.command.build_ext.link_shared_object won't +# link a shared object on Linux, but a static library and patches distutils # for this ... We're patching this back now. def always_link_shared_object( From ecc90ab4db6dfef88947b5f463ef03cdd2dd60d2 Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Sat, 20 Oct 2018 23:46:12 -0400 Subject: [PATCH 14/20] attempt to solve the libname_of computation for all platforms --- setup.py | 54 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/setup.py b/setup.py index 45942e0cc..eebfebf74 100644 --- a/setup.py +++ b/setup.py @@ -193,30 +193,43 @@ class Config(object): else: self.build_temp = os.path.join(self.build_temp, "Release") - self.ext_suffix = sysconfig.get_config_var("EXT_SUFFIX") + build_ext_cmd = Distribution().get_command_obj('build_ext') - if self.ext_suffix is None: - self.ext_suffix = ".so" + build_ext_cmd.initialize_options() + build_ext_cmd.setup_shlib_compiler() + self.build_ext_cmd = build_ext_cmd self.root = "klayout" - def libname_of(self, mod): + def add_extension(self, ext): + self.build_ext_cmd.ext_map[ext.name] = ext + + def libname_of(self, mod, is_lib=None): """ Returns the library name for a given module The library name is usually decorated (i.e. "tl" -> "tl.cpython-35m-x86_64-linux-gnu.so"). + This code was extracted from the source in setuptools.command.build_ext.build_ext """ - ext_suffix = self.ext_suffix - if platform.system() == "Windows": - return mod + ext_suffix + libtype = setuptools.command.build_ext.libtype + full_mod = self.root + '.' + mod + if is_lib is True: + # Here we are guessing it is a library and that the filename + # is to be computed by shlib_compiler. + # See source code of setuptools.command.build_ext.build_ext.get_ext_filename + filename = self.build_ext_cmd.get_ext_filename(full_mod) + fn, ext = os.path.splitext(filename) + ext_path = self.build_ext_cmd.shlib_compiler.library_filename(fn, libtype) else: - if platform.system() == "Darwin" and '_dbpi' in mod: - ext_suffix = ext_suffix.replace('.so', '.dylib') - if mod[0] == '_': - # is a library, not an extension module and setuptools - # will add the "lib" suffix - return "lib" + mod + ext_suffix - else: - return mod + ext_suffix + # This assumes that the Extension/Library object was added to the + # ext_map dictionary via config.add_extension. + assert full_mod in self.build_ext_cmd.ext_map + ext_path = self.build_ext_cmd.get_ext_filename(full_mod) + ext_filename = os.path.basename(ext_path) + + # Exception for database plugins, which will always be dylib. + if platform.system() == "Darwin" and '_dbpi' in mod: + ext_filename = ext_filename.replace('.so', '.dylib') + return ext_filename def path_of(self, mod, mod_src_path): """ @@ -279,7 +292,7 @@ class Config(object): # We can only link against such, but the bundles produced otherwise. args = [] if mod[0] == "_": - args += ["-Wl,-dylib", '-Wl,-install_name,@rpath/%s' % self.libname_of(mod)] + args += ["-Wl,-dylib", '-Wl,-install_name,@rpath/%s' % self.libname_of(mod, is_lib=True)] args += ['-Wl,-rpath,@loader_path/'] return args else: @@ -289,7 +302,7 @@ class Config(object): # will look for the path-qualified library. But that's the # build path and the loader will fail. args = [] - args += ['-Wl,-soname,' + self.libname_of(mod)] + args += ['-Wl,-soname,' + self.libname_of(mod, is_lib=True)] if '_dbpi' not in mod: loader_path = '$ORIGIN' else: @@ -334,6 +347,8 @@ _tl = Library(config.root + '._tl', extra_compile_args=config.compile_args('_tl'), sources=list(_tl_sources)) +config.add_extension(_tl) + # ------------------------------------------------------------------ # _gsi dependency library @@ -348,6 +363,7 @@ _gsi = Library(config.root + '._gsi', extra_link_args=config.link_args('_gsi'), extra_compile_args=config.compile_args('_gsi'), sources=list(_gsi_sources)) +config.add_extension(_gsi) # ------------------------------------------------------------------ # _pya dependency library @@ -363,6 +379,7 @@ _pya = Library(config.root + '._pya', extra_link_args=config.link_args('_pya'), extra_compile_args=config.compile_args('_pya'), sources=list(_pya_sources)) +config.add_extension(_pya) # ------------------------------------------------------------------ # _db dependency library @@ -383,6 +400,7 @@ _db = Library(config.root + '._db', extra_link_args=config.link_args('_db'), extra_compile_args=config.compile_args('_db'), sources=list(_db_sources)) +config.add_extension(_db) # ------------------------------------------------------------------ # _rdb dependency library @@ -398,6 +416,7 @@ _rdb = Library(config.root + '._rdb', extra_link_args=config.link_args('_rdb'), extra_compile_args=config.compile_args('_rdb'), sources=list(_rdb_sources)) +config.add_extension(_rdb) # ------------------------------------------------------------------ # dependency libraries from db_plugins @@ -424,6 +443,7 @@ for pi in dbpi_dirs: sources=pi_sources) db_plugins.append(pi_ext) + config.add_extension(pi_ext) # ------------------------------------------------------------------ # tl extension library From b80ce12c12625eb9b4d133a8d39c2868db8ec1c7 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 22 Oct 2018 20:53:49 +0200 Subject: [PATCH 15/20] Some refactoring to fix qmake-based pymod builds - Unify structure of Python module sources so the pymod.pri can be used for all modules - switch to tlcore, dbcore and rdbcore + distutils_src wrapper modules --- src/pymod/db/db.pro | 3 ++- .../klayout/{rdb.py => rdb/__init__.py} | 0 .../klayout/{tl.py => tl/__init__.py} | 0 src/pymod/pymod.pri | 22 +++++++++++++++++++ src/pymod/rdb/rdb.pro | 3 ++- src/pymod/tl/tl.pro | 4 +++- 6 files changed, 29 insertions(+), 3 deletions(-) rename src/pymod/distutils_src/klayout/{rdb.py => rdb/__init__.py} (100%) rename src/pymod/distutils_src/klayout/{tl.py => tl/__init__.py} (100%) diff --git a/src/pymod/db/db.pro b/src/pymod/db/db.pro index 345123a4b..e40682d5c 100644 --- a/src/pymod/db/db.pro +++ b/src/pymod/db/db.pro @@ -1,5 +1,6 @@ -TARGET = db +TARGET = dbcore +REALMODULE = db include($$PWD/../pymod.pri) diff --git a/src/pymod/distutils_src/klayout/rdb.py b/src/pymod/distutils_src/klayout/rdb/__init__.py similarity index 100% rename from src/pymod/distutils_src/klayout/rdb.py rename to src/pymod/distutils_src/klayout/rdb/__init__.py diff --git a/src/pymod/distutils_src/klayout/tl.py b/src/pymod/distutils_src/klayout/tl/__init__.py similarity index 100% rename from src/pymod/distutils_src/klayout/tl.py rename to src/pymod/distutils_src/klayout/tl/__init__.py diff --git a/src/pymod/pymod.pri b/src/pymod/pymod.pri index 4715b50ce..f73ef6473 100644 --- a/src/pymod/pymod.pri +++ b/src/pymod/pymod.pri @@ -48,3 +48,25 @@ msvc { lib_target.extra = $(INSTALL_PROGRAM) $$DESTDIR_PYMOD/$${TARGET}$${PYTHONEXTSUFFIX} $(INSTALLROOT)$$PREFIX/pymod/klayout } INSTALLS = lib_target + +!equals(REALMODULE, "") { + + msvc { + QMAKE_POST_LINK += && $(MKDIR) $$shell_path($$DESTDIR_PYMOD/$$REALMODULE) && $(COPY) $$shell_path($$PWD/distutils_src/klayout/$$REALMODULE/*) $$shell_path($$DESTDIR_PYMOD/$$REALMODULE) + } else { + QMAKE_POST_LINK += && $(MKDIR) $$DESTDIR_PYMOD/$$REALMODULE && $(COPY) $$PWD/distutils_src/klayout/$$REALMODULE/* $$DESTDIR_PYMOD/$$REALMODULE + } + + # INSTALLS needs to be inside a lib or app templates. + modsrc_target.path = $$PREFIX/pymod/klayout/$$REALMODULE + # This would be nice: + # init_target.files += $$DESTDIR_PYMOD/$$REALMODULE/* + # but some Qt versions need this explicitly: + msvc { + modsrc_target.extra = $(INSTALL_PROGRAM) $$shell_path($$DESTDIR_PYMOD/$$REALMODULE/*) $$shell_path($(INSTALLROOT)$$PREFIX/pymod/klayout/$$REALMODULE) + } else { + modsrc_target.extra = $(INSTALL_PROGRAM) $$DESTDIR_PYMOD/* $(INSTALLROOT)$$PREFIX/pymod/klayout/$$REALMODULE + } + INSTALLS += modsrc_target + +} diff --git a/src/pymod/rdb/rdb.pro b/src/pymod/rdb/rdb.pro index 5a54aa383..f54b94059 100644 --- a/src/pymod/rdb/rdb.pro +++ b/src/pymod/rdb/rdb.pro @@ -1,5 +1,6 @@ -TARGET = rdb +TARGET = rdbcore +REALMODULE = rdb include($$PWD/../pymod.pri) diff --git a/src/pymod/tl/tl.pro b/src/pymod/tl/tl.pro index b4f161393..b3aa2e0c9 100644 --- a/src/pymod/tl/tl.pro +++ b/src/pymod/tl/tl.pro @@ -1,5 +1,6 @@ -TARGET = tl +TARGET = tlcore +REALMODULE = tl include($$PWD/../pymod.pri) @@ -41,3 +42,4 @@ msvc { init_target.extra = $(INSTALL_PROGRAM) $$DESTDIR_PYMOD/__init__.py $(INSTALLROOT)$$PREFIX/pymod/klayout } INSTALLS += init_target + From a25db860460a549d37eb1d0e37736067cd242794 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 22 Oct 2018 21:25:53 +0200 Subject: [PATCH 16/20] Fixed pymod.pri for Linux builds. --- src/pymod/pymod.pri | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pymod/pymod.pri b/src/pymod/pymod.pri index f73ef6473..180e245e2 100644 --- a/src/pymod/pymod.pri +++ b/src/pymod/pymod.pri @@ -63,9 +63,9 @@ INSTALLS = lib_target # init_target.files += $$DESTDIR_PYMOD/$$REALMODULE/* # but some Qt versions need this explicitly: msvc { - modsrc_target.extra = $(INSTALL_PROGRAM) $$shell_path($$DESTDIR_PYMOD/$$REALMODULE/*) $$shell_path($(INSTALLROOT)$$PREFIX/pymod/klayout/$$REALMODULE) + modsrc_target.extra = $(INSTALL_PROGRAM) $$shell_path($$DESTDIR_PYMOD/$$REALMODULE/*.py) $$shell_path($(INSTALLROOT)$$PREFIX/pymod/klayout/$$REALMODULE) } else { - modsrc_target.extra = $(INSTALL_PROGRAM) $$DESTDIR_PYMOD/* $(INSTALLROOT)$$PREFIX/pymod/klayout/$$REALMODULE + modsrc_target.extra = $(INSTALL_PROGRAM) $$DESTDIR_PYMOD/$$REALMODULE/*.py $(INSTALLROOT)$$PREFIX/pymod/klayout/$$REALMODULE } INSTALLS += modsrc_target From 802eb5ec7a482e209f2d70df2ac915cb4090e3cf Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 22 Oct 2018 21:58:56 +0200 Subject: [PATCH 17/20] Updated debian and RPM packager scripts for new pymod structure. --- scripts/makedeb.sh | 4 ++++ scripts/rpm-data/klayout.spec | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/scripts/makedeb.sh b/scripts/makedeb.sh index b58661e81..607b3212e 100755 --- a/scripts/makedeb.sh +++ b/scripts/makedeb.sh @@ -107,6 +107,10 @@ cp -pd $bininstdir/db_plugins/lib*so* makedeb-tmp/${libdir}/db_plugins cp -pd $bininstdir/lay_plugins/lib*so* makedeb-tmp/${libdir}/lay_plugins cp -pd $bininstdir/pymod/klayout/*so makedeb-tmp/${pylibdir} cp -pd $bininstdir/pymod/klayout/*py makedeb-tmp/${pylibdir} +for d in db tl rdb; do + mkdir -p makedeb-tmp/${pylibdir}/$d + cp -pd $bininstdir/pymod/klayout/$d/*py makedeb-tmp/${pylibdir}/$d +done cd makedeb-tmp diff --git a/scripts/rpm-data/klayout.spec b/scripts/rpm-data/klayout.spec index bf9826b85..3b8751085 100644 --- a/scripts/rpm-data/klayout.spec +++ b/scripts/rpm-data/klayout.spec @@ -137,6 +137,10 @@ mkdir -p %{buildroot}%{_libdir}/klayout/lay_plugins mkdir -p %{buildroot}%{_bindir} cp -pd %{_builddir}/bin.$TARGET/pymod/klayout/*.so %{buildroot}%{pylib}/klayout cp -pd %{_builddir}/bin.$TARGET/pymod/klayout/*.py %{buildroot}%{pylib}/klayout +for d in tl db rdb; do + mkdir -p %{buildroot}%{pylib}/klayout/$d + cp -pd %{_builddir}/bin.$TARGET/pymod/klayout/$d/*.py %{buildroot}%{pylib}/klayout/$d +done cp -pd %{_builddir}/bin.$TARGET/lib*.so* %{buildroot}%{_libdir}/klayout cp -pd %{_builddir}/bin.$TARGET/db_plugins/lib*.so* %{buildroot}%{_libdir}/klayout/db_plugins cp -pd %{_builddir}/bin.$TARGET/lay_plugins/lib*.so* %{buildroot}%{_libdir}/klayout/lay_plugins From 994ea47146b061358ee7bb72eec1712ceb484751 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 22 Oct 2018 22:45:26 +0200 Subject: [PATCH 18/20] Fixed RPM spec file --- scripts/rpm-data/klayout.spec | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/scripts/rpm-data/klayout.spec b/scripts/rpm-data/klayout.spec index 3b8751085..4cd9b3216 100644 --- a/scripts/rpm-data/klayout.spec +++ b/scripts/rpm-data/klayout.spec @@ -130,26 +130,34 @@ strip %{_builddir}/bin.$TARGET/strm* TARGET="linux-release" +# create and populate pylib mkdir -p %{buildroot}%{pylib}/klayout -mkdir -p %{buildroot}%{_libdir}/klayout -mkdir -p %{buildroot}%{_libdir}/klayout/db_plugins -mkdir -p %{buildroot}%{_libdir}/klayout/lay_plugins -mkdir -p %{buildroot}%{_bindir} cp -pd %{_builddir}/bin.$TARGET/pymod/klayout/*.so %{buildroot}%{pylib}/klayout cp -pd %{_builddir}/bin.$TARGET/pymod/klayout/*.py %{buildroot}%{pylib}/klayout +chmod 644 %{buildroot}%{pylib}/klayout/* for d in tl db rdb; do mkdir -p %{buildroot}%{pylib}/klayout/$d cp -pd %{_builddir}/bin.$TARGET/pymod/klayout/$d/*.py %{buildroot}%{pylib}/klayout/$d + chmod 644 %{buildroot}%{pylib}/klayout/$d/* done + +# create and populate libdir +mkdir -p %{buildroot}%{_libdir}/klayout +mkdir -p %{buildroot}%{_libdir}/klayout/db_plugins +mkdir -p %{buildroot}%{_libdir}/klayout/lay_plugins cp -pd %{_builddir}/bin.$TARGET/lib*.so* %{buildroot}%{_libdir}/klayout cp -pd %{_builddir}/bin.$TARGET/db_plugins/lib*.so* %{buildroot}%{_libdir}/klayout/db_plugins cp -pd %{_builddir}/bin.$TARGET/lay_plugins/lib*.so* %{buildroot}%{_libdir}/klayout/lay_plugins -chmod 644 %{buildroot}%{pylib}/klayout/* chmod 644 %{buildroot}%{_libdir}/klayout/*.so* chmod 644 %{buildroot}%{_libdir}/klayout/db_plugins/*.so* chmod 644 %{buildroot}%{_libdir}/klayout/lay_plugins/*.so* + +# create and populate bindir +mkdir -p %{buildroot}%{_bindir} cp -pd %{_builddir}/bin.$TARGET/klayout %{_builddir}/bin.$TARGET/strm* %{buildroot}%{_bindir} chmod 755 %{buildroot}%{_bindir}/* + +# other files install -Dm644 %{_sourcedir}/etc/%{name}.desktop %{buildroot}%{_datadir}/applications/%{name}.desktop install -Dm644 %{_sourcedir}/etc/logo.png %{buildroot}%{_datadir}/pixmaps/%{name}.png From 58239650aab19ea8af4d8e2b613caf12f390e33b Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 22 Oct 2018 23:28:55 +0200 Subject: [PATCH 19/20] Fixed pymod initialization for Python 2 Python 2 is a bit more picky with respect to the correct name of the module. If passing "db" to a module called dbcore, it will exit with a SystemError. --- src/pymod/db/dbMain.cc | 4 ++-- src/pymod/pymodHelper.h | 15 +++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/pymod/db/dbMain.cc b/src/pymod/db/dbMain.cc index 97c6388df..bdb15f7df 100644 --- a/src/pymod/db/dbMain.cc +++ b/src/pymod/db/dbMain.cc @@ -27,10 +27,10 @@ // to force linking of the db module #include "../../db/db/dbForceLink.h" -static PyObject *db_module_init (const char *mod_name, const char *mod_description) +static PyObject *db_module_init (const char *pymod_name, const char *mod_name, const char *mod_description) { db::init (); - return module_init (mod_name, mod_description); + return module_init (pymod_name, mod_name, mod_description); } DEFINE_PYMOD_WITH_INIT(dbcore, "db", "KLayout core module 'db'", db_module_init) diff --git a/src/pymod/pymodHelper.h b/src/pymod/pymodHelper.h index c9c41a6a8..ba2a69760 100644 --- a/src/pymod/pymodHelper.h +++ b/src/pymod/pymodHelper.h @@ -39,7 +39,7 @@ #include "gsiExpression.h" static PyObject * -module_init (const char *mod_name, const char *mod_description) +module_init (const char *pymod_name, const char *mod_name, const char *mod_description) { static pya::PythonModule module; @@ -50,7 +50,7 @@ module_init (const char *mod_name, const char *mod_description) // required for the tiling processor for example gsi::initialize_expressions (); - module.init (mod_name, mod_description); + module.init (pymod_name, mod_description); module.make_classes (mod_name); return module.take_module (); @@ -60,6 +60,9 @@ module_init (const char *mod_name, const char *mod_description) return 0; } +#define STRINGIFY(s) _STRINGIFY(s) +#define _STRINGIFY(s) #s + #if PY_MAJOR_VERSION < 3 #define DEFINE_PYMOD(__name__, __name_str__, __description__) \ @@ -67,7 +70,7 @@ module_init (const char *mod_name, const char *mod_description) DEF_INSIDE_PUBLIC \ void init##__name__ () \ { \ - module_init (__name_str__, __description__); \ + module_init (STRINGIFY(__name__), __name_str__, __description__); \ } \ #define DEFINE_PYMOD_WITH_INIT(__name__, __name_str__, __description__, __init__) \ @@ -75,7 +78,7 @@ module_init (const char *mod_name, const char *mod_description) DEF_INSIDE_PUBLIC \ void init##__name__ () \ { \ - __init__ (__name_str__, __description__); \ + __init__ (STRINGIFY(__name__), __name_str__, __description__); \ } \ #else @@ -85,7 +88,7 @@ module_init (const char *mod_name, const char *mod_description) DEF_INSIDE_PUBLIC \ PyObject *PyInit_##__name__ () \ { \ - return module_init (__name_str__, __description__); \ + return module_init (STRINGIFY(__name__), __name_str__, __description__); \ } \ #define DEFINE_PYMOD_WITH_INIT(__name__, __name_str__, __description__, __init__) \ @@ -93,7 +96,7 @@ module_init (const char *mod_name, const char *mod_description) DEF_INSIDE_PUBLIC \ PyObject *PyInit_##__name__ () \ { \ - return __init__ (__name_str__, __description__); \ + return __init__ (STRINGIFY(__name__), __name_str__, __description__); \ } \ #endif From 863144603c289785f3674a855c1ea09fee2d79a2 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 22 Oct 2018 23:48:15 +0200 Subject: [PATCH 20/20] Fixed MSVC builds ... --- src/pymod/pymod.pri | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pymod/pymod.pri b/src/pymod/pymod.pri index 180e245e2..544d594ff 100644 --- a/src/pymod/pymod.pri +++ b/src/pymod/pymod.pri @@ -52,9 +52,9 @@ INSTALLS = lib_target !equals(REALMODULE, "") { msvc { - QMAKE_POST_LINK += && $(MKDIR) $$shell_path($$DESTDIR_PYMOD/$$REALMODULE) && $(COPY) $$shell_path($$PWD/distutils_src/klayout/$$REALMODULE/*) $$shell_path($$DESTDIR_PYMOD/$$REALMODULE) + QMAKE_POST_LINK += && (if not exist $$shell_path($$DESTDIR_PYMOD/$$REALMODULE) $(MKDIR) $$shell_path($$DESTDIR_PYMOD/$$REALMODULE)) && $(COPY) $$shell_path($$PWD/distutils_src/klayout/$$REALMODULE/*.py) $$shell_path($$DESTDIR_PYMOD/$$REALMODULE) } else { - QMAKE_POST_LINK += && $(MKDIR) $$DESTDIR_PYMOD/$$REALMODULE && $(COPY) $$PWD/distutils_src/klayout/$$REALMODULE/* $$DESTDIR_PYMOD/$$REALMODULE + QMAKE_POST_LINK += && $(MKDIR) $$DESTDIR_PYMOD/$$REALMODULE && $(COPY) $$PWD/distutils_src/klayout/$$REALMODULE/*.py $$DESTDIR_PYMOD/$$REALMODULE } # INSTALLS needs to be inside a lib or app templates.