Skip to content

Commit

Permalink
pymod build system was updated to include libpng
Browse files Browse the repository at this point in the history
This refs #49
  • Loading branch information
Kazzz-S committed Feb 14, 2023
2 parents 8a5cb1d + 0a6d058 commit 5950501
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 52 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
HOST_CCACHE_DIR="$(ccache -k cache_dir)"
mkdir -p $HOST_CCACHE_DIR
- name: Build wheels # check https://cibuildwheel.readthedocs.io/en/stable/setup/#github-actions
uses: pypa/cibuildwheel@v2.11.3
uses: pypa/cibuildwheel@v2.12.0
# to supply options, put them in 'env', like:
# env:
# CIBW_SOME_OPTION: value
Expand Down Expand Up @@ -77,7 +77,7 @@ jobs:
- uses: actions/upload-artifact@v2
with:
path: dist/*.tar.gz

upload_to_test_pypy:
needs: [build, make_sdist]
runs-on: ubuntu-latest
Expand Down
8 changes: 6 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,9 @@ before-build = "ccache -s"
environment-pass = ["HOST_CCACHE_DIR"]

[tool.cibuildwheel.macos]
# Don't repair macOS wheels
repair-wheel-command = ""
before-all = [
"brew install libpng",
"brew deps --tree --installed",
]
# Repair macOS wheels (include libpng with the wheel, for example)
repair-wheel-command = "delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v --ignore-missing-dependencies {wheel}"
136 changes: 88 additions & 48 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
from distutils.errors import CompileError
import distutils.command.build_ext
import setuptools.command.build_ext
from setuptools.command.build_ext import build_ext as _build_ext
import multiprocessing

# for Jenkins we do not want to be greedy
Expand Down Expand Up @@ -137,6 +138,24 @@ def quote_path(path):
else:
return path

import subprocess

def check_libpng():
""" Check if libpng is available (Linux & Macos only)"""
try:
subprocess.check_call(["libpng-config", "--version"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return True
except FileNotFoundError as e:
# libpng is not present.
if True: # change to False to enable installation without libpng
raise RuntimeError("libpng missing. libpng-config is not available") from e
return False

def libpng_cflags():
return subprocess.check_output(["libpng-config", "--cflags"]).decode().split()

def libpng_ldflags():
return subprocess.check_output(["libpng-config", "--ldflags"]).decode().split()

# TODO: delete (Obsolete)
# patch get_ext_filename
Expand All @@ -161,6 +180,12 @@ def patched_get_ext_filename(self, ext_name):

# end patch get_ext_filename

# TODO: customize this object instead of introspecting and patching distutils (if possible)
class klayout_build_ext(_build_ext):
""" Customize build extension class to check for dependencies before installing."""
def finalize_options(self) -> None:
ret = super().finalize_options()
return ret

# patch CCompiler's library_filename for _dbpi libraries (SOs)
# Its default is to have .so for shared objects, instead of dylib,
Expand Down Expand Up @@ -222,7 +247,6 @@ def always_link_shared_object(
target_lang,
)


setuptools.command.build_ext.libtype = "shared"
setuptools.command.build_ext.link_shared_object = always_link_shared_object

Expand Down Expand Up @@ -321,6 +345,9 @@ def compile_args(self, mod):
"-Wno-strict-aliasing", # Avoids many "type-punned pointer" warnings
"-std=c++11", # because we use unordered_map/unordered_set
]
if platform.system() == "Darwin" and mod == "_tl":
if check_libpng():
args += libpng_cflags()
return args

def libraries(self, mod):
Expand All @@ -330,9 +357,14 @@ def libraries(self, mod):
if platform.system() == "Windows":
if mod == "_tl":
return ["libcurl", "expat", "pthreadVCE2", "zlib", "wsock32", "libpng16"]
elif platform.system() == "Darwin":
if mod == "_tl":
libs = ["curl", "expat"] # libpng is included by libpng_ldflags
return libs
else:
if mod == "_tl":
return ["curl", "expat", "png"]
libs = ["curl", "expat", "png"]
return libs
return []

def link_args(self, mod):
Expand Down Expand Up @@ -361,6 +393,8 @@ def link_args(self, mod):
"-Wl,-install_name,@rpath/%s" % self.libname_of(mod, is_lib=True),
]
args += ["-Wl,-rpath,@loader_path/"]
if mod == "_tl" and check_libpng():
args += libpng_ldflags()
return args
else:
# this makes the libraries suitable for linking with a path -
Expand All @@ -385,15 +419,20 @@ def macros(self):
"""
Returns the macros to use for building
"""
return [
("HAVE_PNG", 1),
macros = [
("HAVE_CURL", 1),
("HAVE_EXPAT", 1),
("KLAYOUT_MAJOR_VERSION", self.major_version()),
("KLAYOUT_MINOR_VERSION", self.minor_version()),
("GSI_ALIAS_INSPECT", 1),
]

if platform.system() == "Darwin" and check_libpng():
macros += [("HAVE_PNG", 1)]
else:
macros += [("HAVE_PNG", 1)]
return macros

def minor_version(self):
"""
Gets the version string
Expand Down Expand Up @@ -611,9 +650,9 @@ def version(self):
define_macros=config.macros() + [('MAKE_LAYBASIC_LIBRARY', 1)],
include_dirs=[_rdb_path, _db_path, _tl_path, _gsi_path],
extra_objects=[
config.path_of('_rdb', _rdb_path),
config.path_of('_tl', _tl_path),
config.path_of('_gsi', _gsi_path),
config.path_of('_rdb', _rdb_path),
config.path_of('_tl', _tl_path),
config.path_of('_gsi', _gsi_path),
config.path_of('_db', _db_path)
],
language='c++',
Expand All @@ -635,10 +674,10 @@ def version(self):
define_macros=config.macros() + [('MAKE_LAYVIEW_LIBRARY', 1)],
include_dirs=[_laybasic_path, _rdb_path, _db_path, _tl_path, _gsi_path],
extra_objects=[
config.path_of('_laybasic', _laybasic_path),
config.path_of('_rdb', _rdb_path),
config.path_of('_tl', _tl_path),
config.path_of('_gsi', _gsi_path),
config.path_of('_laybasic', _laybasic_path),
config.path_of('_rdb', _rdb_path),
config.path_of('_tl', _tl_path),
config.path_of('_gsi', _gsi_path),
config.path_of('_db', _db_path)
],
language='c++',
Expand All @@ -660,9 +699,9 @@ def version(self):
define_macros=config.macros() + [('MAKE_LYM_LIBRARY', 1)],
include_dirs=[_pya_path, _rba_path, _tl_path, _gsi_path],
extra_objects=[
config.path_of('_rba', _rba_path),
config.path_of('_pya', _pya_path),
config.path_of('_tl', _tl_path),
config.path_of('_rba', _rba_path),
config.path_of('_pya', _pya_path),
config.path_of('_tl', _tl_path),
config.path_of('_gsi', _gsi_path)
],
language='c++',
Expand All @@ -684,11 +723,11 @@ def version(self):
define_macros=config.macros() + [('MAKE_ANT_LIBRARY', 1)],
include_dirs=[_laybasic_path, _layview_path, _rdb_path, _db_path, _tl_path, _gsi_path],
extra_objects=[
config.path_of('_laybasic', _laybasic_path),
config.path_of('_layview', _layview_path),
config.path_of('_rdb', _rdb_path),
config.path_of('_tl', _tl_path),
config.path_of('_gsi', _gsi_path),
config.path_of('_laybasic', _laybasic_path),
config.path_of('_layview', _layview_path),
config.path_of('_rdb', _rdb_path),
config.path_of('_tl', _tl_path),
config.path_of('_gsi', _gsi_path),
config.path_of('_db', _db_path)
],
language='c++',
Expand All @@ -710,11 +749,11 @@ def version(self):
define_macros=config.macros() + [('MAKE_IMG_LIBRARY', 1)],
include_dirs=[_laybasic_path, _layview_path, _rdb_path, _db_path, _tl_path, _gsi_path],
extra_objects=[
config.path_of('_laybasic', _laybasic_path),
config.path_of('_layview', _layview_path),
config.path_of('_rdb', _rdb_path),
config.path_of('_tl', _tl_path),
config.path_of('_gsi', _gsi_path),
config.path_of('_laybasic', _laybasic_path),
config.path_of('_layview', _layview_path),
config.path_of('_rdb', _rdb_path),
config.path_of('_tl', _tl_path),
config.path_of('_gsi', _gsi_path),
config.path_of('_db', _db_path)
],
language='c++',
Expand All @@ -736,11 +775,11 @@ def version(self):
define_macros=config.macros() + [('MAKE_EDT_LIBRARY', 1)],
include_dirs=[_laybasic_path, _layview_path, _rdb_path, _db_path, _tl_path, _gsi_path],
extra_objects=[
config.path_of('_laybasic', _laybasic_path),
config.path_of('_layview', _layview_path),
config.path_of('_rdb', _rdb_path),
config.path_of('_tl', _tl_path),
config.path_of('_gsi', _gsi_path),
config.path_of('_laybasic', _laybasic_path),
config.path_of('_layview', _layview_path),
config.path_of('_rdb', _rdb_path),
config.path_of('_tl', _tl_path),
config.path_of('_gsi', _gsi_path),
config.path_of('_db', _db_path)
],
language='c++',
Expand Down Expand Up @@ -879,23 +918,23 @@ def version(self):

lay = Extension(config.root + '.laycore',
define_macros=config.macros(),
include_dirs=[_laybasic_path,
_layview_path,
_img_path,
_ant_path,
_edt_path,
_lym_path,
_tl_path,
_gsi_path,
include_dirs=[_laybasic_path,
_layview_path,
_img_path,
_ant_path,
_edt_path,
_lym_path,
_tl_path,
_gsi_path,
_pya_path],
extra_objects=[config.path_of('_laybasic', _laybasic_path),
config.path_of('_layview', _layview_path),
config.path_of('_img', _img_path),
config.path_of('_ant', _ant_path),
config.path_of('_edt', _edt_path),
config.path_of('_lym', _lym_path),
config.path_of('_tl', _tl_path),
config.path_of('_gsi', _gsi_path),
extra_objects=[config.path_of('_laybasic', _laybasic_path),
config.path_of('_layview', _layview_path),
config.path_of('_img', _img_path),
config.path_of('_ant', _ant_path),
config.path_of('_edt', _edt_path),
config.path_of('_lym', _lym_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('laycore'),
extra_compile_args=config.compile_args('laycore'),
Expand Down Expand Up @@ -935,7 +974,8 @@ def version(self):
package_data={config.root: ["src/pymod/distutils_src/klayout/*.pyi"]},
data_files=[(config.root, ["src/pymod/distutils_src/klayout/py.typed"])],
include_package_data=True,
ext_modules=[_tl, _gsi, _pya, _rba, _db, _lib, _rdb, _lym, _laybasic, _layview, _ant, _edt, _img]
+ db_plugins
+ [tl, db, lib, rdb, lay]
ext_modules=[_tl, _gsi, _pya, _rba, _db, _lib, _rdb, _lym, _laybasic, _layview, _ant, _edt, _img]
+ db_plugins
+ [tl, db, lib, rdb, lay],
cmdclass={'build_ext': klayout_build_ext}
)

0 comments on commit 5950501

Please sign in to comment.