2016-09-10 13:09:50 +02:00
#!/usr/bin/python
###############################################################################
# #
# This file is part of IfcOpenShell. #
# #
# IfcOpenShell is free software: you can redistribute it and/or modify #
# it under the terms of the Lesser GNU General Public License as published by #
# the Free Software Foundation, either version 3.0 of the License, or #
# (at your option) any later version. #
# #
# IfcOpenShell is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# Lesser GNU General Public License for more details. #
# #
# You should have received a copy of the Lesser GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
###############################################################################
###############################################################################
# #
# This script builds IfcOpenShell and its dependencies #
# #
# Prerequisites for this script to function correctly: #
2022-10-01 11:29:27 +02:00
# * cmake * git * bzip2 * tar * c(++) compilers * autoconf #
2017-08-13 13:13:26 +02:00
# #
# if building with USE_OCCT additionally: #
2022-11-25 13:16:36 +01:00
# * glx.h #
2017-08-13 13:13:26 +02:00
# #
2019-11-06 14:05:05 +01:00
# if building with OCCT 7.4.0 additionally: #
# * libfontconfig1-dev #
# #
2019-05-10 12:04:32 +02:00
# if building with -shared #
# * libgl1-mesa-dev libxext-dev libxmu-dev libxmu-headers libxi-dev #
# #
2019-05-21 13:30:58 +02:00
# for python37 to install correctly additionally: #
2019-05-21 12:53:54 +02:00
# * libffi(-dev[el]) #
# #
2016-09-10 13:09:50 +02:00
# on debian 7.8 these can be obtained with: #
2020-12-24 20:46:42 +00:00
# $ apt-get install git gcc g++ autoconf bison bzip2 cmake #
2022-11-25 13:16:36 +01:00
# mesa-common-dev libffi-dev libfontconfig1-dev #
2017-08-13 13:13:26 +02:00
# #
2016-09-10 13:09:50 +02:00
# on ubuntu 14.04: #
2020-12-24 20:46:42 +00:00
# $ apt-get install git gcc g++ autoconf bison make cmake #
2022-11-25 13:16:36 +01:00
# mesa-common-dev libffi-dev libfontconfig1-dev #
2017-08-13 13:13:26 +02:00
# #
2016-09-10 13:09:50 +02:00
# on OS X El Capitan with homebrew: #
2022-11-25 13:16:36 +01:00
# $ brew install git bison autoconf automake libffi cmake #
2016-09-10 13:09:50 +02:00
# #
###############################################################################
import logging
import os
import sys
import subprocess as sp
import shutil
import tarfile
2016-11-06 19:07:03 +01:00
import multiprocessing
2021-10-05 10:22:01 +02:00
import platform
2021-10-06 15:52:55 +02:00
import sysconfig
2019-06-23 19:23:38 +02:00
2023-04-11 08:47:46 +02:00
# @todo temporary for expired mpfr.org certificate on 2023-04-08
import ssl
ssl . _create_default_https_context = ssl . _create_unverified_context
2021-10-05 10:22:01 +02:00
from urllib . request import urlretrieve
2019-06-23 19:23:38 +02:00
2016-09-10 13:09:50 +02:00
logger = logging . getLogger ( __name__ )
logger . setLevel ( logging . INFO )
ch = logging . StreamHandler ( )
ch . setLevel ( logging . INFO )
logger . addHandler ( ch )
2021-10-05 18:32:12 +02:00
PROJECT_NAME = " IfcOpenShell "
2021-10-06 15:52:55 +02:00
USE_CURRENT_PYTHON_VERSION = os . getenv ( " USE_CURRENT_PYTHON_VERSION " )
2022-01-16 13:16:44 +01:00
ADD_COMMIT_SHA = os . getenv ( " ADD_COMMIT_SHA " )
2021-10-08 15:23:27 +02:00
2024-03-20 14:58:06 +01:00
PYTHON_VERSIONS = [ " 3.9.11 " , " 3.10.3 " , " 3.11.8 " , " 3.12.1 " ]
2021-10-05 18:32:12 +02:00
JSON_VERSION = " v3.6.1 "
2021-10-06 12:07:08 +02:00
OCE_VERSION = " 0.18.3 "
2021-10-05 18:32:12 +02:00
OCCT_VERSION = " 7.5.3 "
2022-11-25 13:16:36 +01:00
BOOST_VERSION = " 1.80.0 "
2021-10-19 08:49:46 +02:00
PCRE_VERSION = " 8.41 "
2021-10-06 12:07:08 +02:00
LIBXML2_VERSION = " 2.9.11 "
SWIG_VERSION = " 4.0.2 "
2021-10-05 18:32:12 +02:00
OPENCOLLADA_VERSION = " v1.6.68 "
2021-10-06 12:07:08 +02:00
HDF5_VERSION = " 1.12.1 "
2021-10-05 18:32:12 +02:00
2022-09-14 10:56:16 +02:00
GMP_VERSION = " 6.2.1 "
MPFR_VERSION = " 3.1.6 " # latest is 4.1.0
2021-10-06 12:07:08 +02:00
CGAL_VERSION = " 5.3 "
2021-08-10 19:02:52 +00:00
2016-09-10 13:09:50 +02:00
# binaries
2021-10-05 18:32:12 +02:00
cp = " cp "
bash = " bash "
git = " git "
bunzip2 = " bunzip2 "
tar = " tar "
cc = " cc "
cplusplus = " c++ "
autoconf = " autoconf "
automake = " automake "
make = " make "
2021-10-05 18:45:27 +02:00
date = " date "
2021-10-05 18:32:12 +02:00
curl = " curl "
wget = " wget "
strip = " strip "
2016-09-10 13:09:50 +02:00
2022-11-25 13:16:36 +01:00
explicit_targets = [ s for s in sys . argv [ 1 : ] if not s . startswith ( " - " ) ]
flags = set ( s . lstrip ( ' - ' ) for s in sys . argv [ 1 : ] if s . startswith ( " - " ) )
2016-09-10 13:09:50 +02:00
# Helper function for coloured printing
2021-10-05 18:32:12 +02:00
NO_COLOR = " \033 [0m " # <ref>http://stackoverflow.com/questions/5947742/how-to-change-the-output-color-of-echo-in-linux</ref>
BLACK_ON_WHITE = " \033 [0;30;107m "
RED = " \033 [31m "
GREEN = " \033 [32m "
YELLOW = " \033 [33m "
MAGENTA = " \033 [35m "
2016-09-10 13:09:50 +02:00
def cecho ( message , color = NO_COLOR ) :
""" Logs message `message` in color `color`. """
2021-10-05 14:24:59 +02:00
logger . info ( f " { color } { message } \033 [0m " )
2016-09-10 13:09:50 +02:00
def which ( cmd ) :
2021-10-05 14:24:59 +02:00
for path in os . getenv ( " PATH " ) . split ( " : " ) :
2016-09-10 13:09:50 +02:00
if os . path . exists ( path ) and cmd in os . listdir ( path ) :
return cmd
return None
2019-06-23 19:23:38 +02:00
2016-09-10 13:09:50 +02:00
# Set defaults for missing empty environment variables
2017-10-02 10:22:57 +02:00
USE_OCCT = os . environ . get ( " USE_OCCT " , " true " ) . lower ( ) == " true "
TOOLSET = None
2021-10-06 15:52:55 +02:00
if platform . system ( ) == " Darwin " :
2017-10-02 10:22:57 +02:00
# C++11 features used in OCCT 7+ need a more recent stdlib
TOOLSET = " 10.9 " if USE_OCCT else " 10.6 "
2020-12-29 07:59:52 -05:00
2016-09-10 13:09:50 +02:00
2021-10-05 14:24:59 +02:00
IFCOS_NUM_BUILD_PROCS = os . getenv ( " IFCOS_NUM_BUILD_PROCS " , multiprocessing . cpu_count ( ) + 1 )
2016-09-10 13:09:50 +02:00
2022-11-25 13:16:36 +01:00
CMAKE_DIR = os . path . realpath ( os . path . join ( os . path . dirname ( __file__ ) , " .. " , " cmake " ) )
build_dir = os . environ . get ( " BUILD_DIR " , os . path . join ( os . path . dirname ( __file__ ) , " .. " , " build " ) )
2016-09-10 13:09:50 +02:00
2022-11-25 13:16:36 +01:00
path = [ build_dir , platform . system ( ) , " wasm " if " wasm " in flags else platform . machine ( ) ]
2021-10-05 18:32:12 +02:00
if TOOLSET :
path . append ( TOOLSET )
DEFAULT_DEPS_DIR = os . path . realpath ( os . path . join ( * path ) )
DEPS_DIR = os . getenv ( " DEPS_DIR " , DEFAULT_DEPS_DIR )
2018-09-08 13:23:36 +02:00
if not os . path . exists ( DEPS_DIR ) :
os . makedirs ( DEPS_DIR )
2016-09-10 13:09:50 +02:00
2021-10-05 18:32:12 +02:00
BUILD_CFG = os . getenv ( " BUILD_CFG " , " RelWithDebInfo " )
2016-09-10 13:09:50 +02:00
# Print build configuration information
2021-10-05 14:24:59 +02:00
cecho ( f """ This script fetches and builds { PROJECT_NAME } and its dependencies
" " " , BLACK_ON_WHITE)
2016-09-10 13:09:50 +02:00
cecho( """ Script configuration :
""" , GREEN)
2021-10-05 14:24:59 +02:00
cecho(f """ * USE_OCCT = { USE_OCCT } """ , MAGENTA)
2017-08-13 13:13:26 +02:00
if USE_OCCT:
cecho( " - Compiling against official Open Cascade " )
else:
cecho( " - Compiling against Open Cascade Community Edition " )
2021-10-05 14:24:59 +02:00
cecho(f " * Dependency Directory = {DEPS_DIR} " , MAGENTA)
cecho(f " - The directory where {PROJECT_NAME} dependencies are installed. " )
cecho(f " * Build Config Type = {BUILD_CFG} " , MAGENTA)
2016-09-10 13:09:50 +02:00
cecho( """ - The used build configuration type for the dependencies .
Defaults to RelWithDebInfo if not specified . """ )
if BUILD_CFG == " MinSizeRel " :
cecho( " WARNING: MinSizeRel build can suffer from a significant performance loss. " , RED)
2021-10-05 14:24:59 +02:00
cecho(f " * IFCOS_NUM_BUILD_PROCS = {IFCOS_NUM_BUILD_PROCS} " , MAGENTA)
2016-09-10 13:09:50 +02:00
cecho( """ - How many compiler processes may be run in parallel .
""" )
2018-09-08 13:23:36 +02:00
dependency_tree = {
2021-10-05 18:32:12 +02:00
' IfcParse ' : ( ' boost ' , ' libxml2 ' , ' hdf5 ' ),
' IfcGeom ' : ( ' IfcParse ' , ' occ ' , ' json ' , ' cgal ' ),
' IfcConvert ' : ( ' IfcGeom ' ,),
' OpenCOLLADA ' : ( ' libxml2 ' , ' pcre ' ),
2018-09-08 13:23:36 +02:00
' IfcGeomServer ' : ( ' IfcGeom ' ,),
2021-10-05 18:32:12 +02:00
' IfcOpenShell-Python ' : ( ' python ' , ' swig ' , ' IfcGeom ' ),
2018-09-08 13:23:36 +02:00
' swig ' : ( ' pcre ' ,),
' boost ' : (),
' libxml2 ' : (),
' python ' : (),
2022-11-25 13:16:36 +01:00
' occ ' : ( ' freetype ' ,),
2019-05-21 13:31:43 +02:00
' pcre ' : (),
2021-07-11 19:15:20 +00:00
' json ' : (),
2021-08-10 19:02:52 +00:00
' hdf5 ' : (),
2022-11-25 13:16:36 +01:00
' cgal ' : (),
' freetype ' : (),
2018-09-08 13:23:36 +02:00
}
def v(dep):
yield dep
for d in dependency_tree[dep]:
for x in v(d):
yield x
2022-11-25 13:16:36 +01:00
if " v " in flags:
logger.setLevel(logging.DEBUG)
else:
logger.setLevel(logging.INFO)
2019-05-10 12:04:32 +02:00
2022-11-25 13:16:36 +01:00
BUILD_STATIC = " shared " not in flags
2019-05-10 12:04:32 +02:00
ENABLE_FLAG = " --enable-static " if BUILD_STATIC else " --enable-shared "
DISABLE_FLAG = " --disable-shared " if BUILD_STATIC else " --disable-static "
LINK_TYPE = " static " if BUILD_STATIC else " shared "
LINK_TYPE_UCFIRST = LINK_TYPE[0].upper() + LINK_TYPE[1:]
LIBRARY_EXT = " a " if BUILD_STATIC else " so "
PIC = " -fPIC " if BUILD_STATIC else " "
2022-11-25 13:16:36 +01:00
if any(f.startswith( " py- " ) for f in flags):
PYTHON_VERSIONS = [pyv for pyv in PYTHON_VERSIONS if " py- %s " % " " .join(pyv.split( ' . ' )[0:2]) in flags]
if len(explicit_targets):
targets = set(sum((list(v(target)) for target in explicit_targets), []))
2018-09-08 13:23:36 +02:00
else:
targets = set(dependency_tree.keys())
2022-11-25 13:16:36 +01:00
targets = set(t for t in targets if ' without- %s ' % t.lower() not in flags)
2018-09-08 13:23:36 +02:00
print( " Building: " , *sorted(targets, key=lambda t: len(list(v(t)))))
2016-09-10 13:09:50 +02:00
# Check that required tools are in PATH
2022-10-01 11:29:27 +02:00
for cmd in [git, bunzip2, tar, cc, cplusplus, autoconf, automake, make, " patch " , " cmake " ]:
2016-09-10 13:09:50 +02:00
if which(cmd) is None:
2021-10-05 10:22:01 +02:00
raise ValueError(f " Required tool ' {cmd} ' not installed or not added to PATH " )
2016-09-10 13:09:50 +02:00
# identifiers for the download tool (could be less memory consuming as ints, but are more verbose as strings)
2019-06-30 09:44:40 +02:00
download_tool_default = download_tool_py = " py "
2016-09-10 13:09:50 +02:00
download_tool_git = " git "
2017-09-18 14:51:58 +02:00
2016-09-10 13:09:50 +02:00
# Create log directory and file
log_dir = os.path.join(DEPS_DIR, " logs " )
if not os.path.exists(log_dir):
os.makedirs(log_dir)
2021-10-05 10:22:01 +02:00
LOG_FILE = os.path.join(log_dir, sp.check_output([date, " + % Y % m %d " ], encoding= " utf-8 " ).strip()) + " .log "
2016-09-10 13:09:50 +02:00
if not os.path.exists(LOG_FILE):
open(LOG_FILE, " w " ).close()
2021-10-05 10:22:01 +02:00
logger.info(f " using command log file ' {LOG_FILE} ' " )
2016-09-10 13:09:50 +02:00
2024-03-20 06:22:33 -04:00
# Causing havoc in python 3.11 build
try:
del os.environ[ ' __PYVENV_LAUNCHER__ ' ]
except: pass
2022-11-25 13:16:36 +01:00
def run(cmds, cwd=None, can_fail=False):
2018-09-08 13:23:36 +02:00
"""
Wraps ` subprocess . Popen . communicate ( ) ` and logs the command being executed ,
sets up logging ` stderr ` to ` LOG_FILE ` ( in append mode ) and returns stdout
with leading and trailing whitespace removed .
"""
2021-10-05 10:22:01 +02:00
logger.debug(f " running command { ' ' .join(cmds)} in directory {cwd} " )
log_file_handle = open(LOG_FILE, " a " )
proc = sp.Popen(cmds, cwd=cwd, stdout=sp.PIPE, stderr=sp.PIPE, encoding= " utf-8 " )
2018-09-08 13:23:36 +02:00
stdout, stderr = proc.communicate()
log_file_handle.write(stdout)
2016-11-06 19:07:03 +01:00
log_file_handle.write(stderr)
2016-09-10 13:09:50 +02:00
log_file_handle.close()
2021-10-05 10:22:01 +02:00
logger.debug(f " command returned {proc.returncode} " )
2016-09-10 13:09:50 +02:00
2022-11-25 13:16:36 +01:00
if proc.returncode != 0 and not can_fail:
2018-09-08 13:23:36 +02:00
print( " - " * 70)
print(stderr)
print( " - " * 70)
2021-10-24 14:56:50 +02:00
raise RuntimeError(f " Command ` { ' ' .join(cmds)}` returned exit code {proc.returncode} " )
2016-11-06 19:07:03 +01:00
2018-09-08 13:23:36 +02:00
return stdout.strip()
2016-09-10 13:09:50 +02:00
2022-09-14 10:56:52 +02:00
if platform.system() == " Darwin " :
if run([ " sw_vers " , " -productVersion " ]) >= " 11. " :
# Apparently not supported
PYTHON_VERSIONS = [pv for pv in PYTHON_VERSIONS if tuple(map(int, pv.split( " . " ))) >= (3, 7)]
2022-11-09 10:57:42 +01:00
if run([ " sw_vers " , " -productVersion " ]) < " 10.16 " :
2024-03-20 06:22:33 -04:00
# This is now solved with the ' __PYVENV_LAUNCHER__ ' hack
# PYTHON_VERSIONS = [pv for pv in PYTHON_VERSIONS if tuple(map(int, pv.split( " . " ))) < (3, 11)]
pass
2022-09-14 10:56:52 +02:00
2021-10-05 10:22:01 +02:00
BOOST_VERSION_UNDERSCORE = BOOST_VERSION.replace( " . " , " _ " )
2016-09-10 13:09:50 +02:00
2021-10-05 10:22:01 +02:00
OCE_LOCATION = f " https://github.com/tpaviot/oce/archive/OCE- {OCE_VERSION} .tar.gz "
BOOST_LOCATION = f " https://boostorg.jfrog.io/artifactory/main/release/ {BOOST_VERSION} /source/ "
2016-09-10 13:09:50 +02:00
# Helper functions
2021-10-05 18:45:27 +02:00
2016-09-10 13:09:50 +02:00
def run_autoconf(arg1, configure_args, cwd):
configure_path = os.path.realpath(os.path.join(cwd, " .. " , " configure " ))
if not os.path.exists(configure_path):
2018-09-08 13:23:36 +02:00
run([bash, " ./autogen.sh " ], cwd=os.path.realpath(os.path.join(cwd, " .. " ))) # only run autogen.sh in the directory it is located and use cwd to achieve that in order to not mess up things
2016-11-06 19:07:03 +01:00
# Using `sh` over `bash` fixes issues with building swig
2021-10-05 14:24:59 +02:00
prefix = os.path.realpath(f " {DEPS_DIR} /install/ {arg1} " )
2022-11-25 13:16:36 +01:00
wasm = []
if " wasm " in flags:
wasm.append( " emconfigure " )
run([*wasm, " /bin/sh " , " ../configure " ] + configure_args + [f " --prefix= {prefix} " ], cwd=cwd)
2016-09-10 13:09:50 +02:00
2021-10-05 18:45:27 +02:00
2016-09-10 13:09:50 +02:00
def run_cmake(arg1, cmake_args, cmake_dir=None, cwd=None):
if cmake_dir is None:
2021-10-05 10:22:01 +02:00
P = " .. "
2016-09-10 13:09:50 +02:00
else:
2021-10-05 10:22:01 +02:00
P = cmake_dir
2022-11-25 13:16:36 +01:00
wasm = []
if " wasm " in flags:
wasm.append( " emcmake " )
run([*wasm, " cmake " , P, *cmake_args, f " -DCMAKE_BUILD_TYPE= {BUILD_CFG} " ], cwd=cwd)
2016-09-10 13:09:50 +02:00
2021-10-05 18:45:27 +02:00
2019-06-23 05:07:46 +02:00
def git_clone_or_pull_repository(clone_url, target_dir, revision=None):
2016-09-10 13:09:50 +02:00
""" Lazily clones the ` git ` repository denoted by ` clone_url ` into
2019-06-23 05:07:46 +02:00
the ` target_dir ` or pulls latest changes if the ` target_dir ` exists ( naively assumes
2016-09-10 13:09:50 +02:00
that a working clone exists there ) and optionally checks out a revision
` revision ` after cloning or in the existing clone if ` revision ` is not
` None ` . """
if not os.path.exists(target_dir):
2021-10-05 10:22:01 +02:00
logger.info(f " cloning ' {clone_url} ' into ' {target_dir} ' " )
2021-03-14 09:32:38 +01:00
run([git, " clone " , " --recursive " , clone_url, target_dir])
2016-09-10 13:09:50 +02:00
else:
2021-10-05 10:22:01 +02:00
logger.info(f " directory ' {target_dir} ' already cloned. Pulling latest changes. " )
2019-08-03 14:48:01 +02:00
# detect whether we are on a branch and pull
if run([git, " rev-parse " , " --abbrev-ref " , " HEAD " ], cwd=target_dir) != " HEAD " :
run([git, " pull " , clone_url], cwd=target_dir)
2016-09-10 13:09:50 +02:00
if revision != None:
2018-09-08 13:23:36 +02:00
run([git, " checkout " , revision], cwd=target_dir)
2016-09-10 13:09:50 +02:00
2019-08-03 14:48:01 +02:00
2021-07-11 19:15:20 +00:00
def build_dependency(name, mode, build_tool_args, download_url, download_name, download_tool=download_tool_default, revision=None, patch=None, additional_files= {} , no_append_name=False, **kwargs):
2016-09-10 13:09:50 +02:00
""" Handles building of dependencies with different tools ( which are
distinguished with the ` mode ` argument . ` build_tool_args ` is expected to be
a list which is necessary in order to not mess up quoting of compiler and
linker flags . """
check_dir = os.path.join(DEPS_DIR, " install " , name)
if os.path.exists(check_dir):
2021-10-05 10:22:01 +02:00
logger.info(f " Found existing {name} , skipping " )
2016-09-10 13:09:50 +02:00
return
build_dir = os.path.join(DEPS_DIR, " build " )
if not os.path.exists(build_dir):
os.makedirs(build_dir)
2019-06-30 09:44:40 +02:00
2021-10-05 10:22:01 +02:00
logger.info(f " \r Fetching {name} ... " )
2016-09-10 13:09:50 +02:00
2019-06-30 09:44:40 +02:00
if download_tool == download_tool_py:
2017-09-18 14:51:58 +02:00
if no_append_name:
url = download_url
else:
url = os.path.join(download_url, download_name)
2019-06-30 09:44:40 +02:00
2016-09-10 13:09:50 +02:00
download_path = os.path.join(build_dir, download_name)
if not os.path.exists(download_path):
2019-06-30 09:44:40 +02:00
urlretrieve(url, os.path.join(build_dir, download_path))
2016-09-10 13:09:50 +02:00
else:
2021-10-05 10:22:01 +02:00
logger.info(f " Download ' {download_path} ' already exists, assuming it ' s an undamaged download and that it has been extracted if possible, skipping " )
2016-09-10 13:09:50 +02:00
elif download_tool == download_tool_git:
2021-10-05 10:22:01 +02:00
logger.info(f " \r Checking {name} ... " )
2019-06-23 05:07:46 +02:00
git_clone_or_pull_repository(download_url, target_dir=os.path.join(build_dir, download_name), revision=revision)
2016-09-10 13:09:50 +02:00
else:
2021-10-05 10:22:01 +02:00
raise ValueError(f " download tool ' {download_tool} ' is not supported " )
2016-09-10 13:09:50 +02:00
download_dir = os.path.join(build_dir, download_name)
2017-08-13 13:13:26 +02:00
2016-09-10 13:09:50 +02:00
if os.path.isdir(download_dir):
2021-10-05 14:24:59 +02:00
extract_dir_name = download_name
2016-09-10 13:09:50 +02:00
extract_dir = os.path.join(build_dir, extract_dir_name)
else:
download_tarfile_path = os.path.join(build_dir, download_name)
if download_name.endswith( " .tar.gz " ) or download_name.endswith( " .tgz " ):
compr = " gz "
elif download_name.endswith( " .tar.bz2 " ):
compr = " bz2 "
else:
raise RuntimeError( " fix source for new download type " )
2021-10-05 10:22:01 +02:00
download_tarfile = tarfile.open(name=download_tarfile_path, mode=f " r: {compr} " )
2021-07-11 19:15:20 +00:00
# tarfile seriously doesn ' t have a function to retrieve the root directory more easily
2021-10-05 14:24:59 +02:00
extract_dir_name = os.path.commonprefix([x for x in download_tarfile.getnames() if x != " . " ])
2018-09-08 13:23:36 +02:00
#run([tar, " --exclude= \" */* \" " , " -tf " , download_name], cwd=build_dir).strip() no longer works
2016-09-10 13:09:50 +02:00
if extract_dir_name is None:
2021-10-05 14:24:59 +02:00
extract_dir_name = run([bash, " -c " , f " tar -tf {download_name} 2> /dev/null | head -n 1 | cut -f1 -d / " ], cwd=build_dir)
2016-09-10 13:09:50 +02:00
extract_dir = os.path.join(build_dir, extract_dir_name)
if not os.path.exists(extract_dir):
2018-09-08 13:23:36 +02:00
run([tar, " -xf " , download_name], cwd=build_dir)
2016-09-10 13:09:50 +02:00
2017-08-13 13:13:26 +02:00
for path, url in additional_files.items():
if not os.path.exists(path):
2019-06-23 19:23:38 +02:00
urlretrieve(url, os.path.join(extract_dir, path))
2017-08-13 13:13:26 +02:00
2018-04-15 14:01:37 +02:00
if patch is not None:
2022-11-25 13:16:36 +01:00
if isinstance(patch, str):
patch = [patch]
for p in patch:
patch_abs = os.path.abspath(os.path.join(os.path.dirname(__file__), p))
if os.path.exists(patch_abs):
try: run([ " patch " , " -p1 " , " --batch " , " --forward " , " -i " , patch_abs], cwd=extract_dir)
except Exception as e:
# Assert that the patch has already been applied
run([ " patch " , " -p1 " , " --batch " , " --reverse " , " --dry-run " , " -i " , patch_abs], cwd=extract_dir)
2021-07-11 19:15:20 +00:00
if mode == " ctest " :
run([ " ctest " , " -S " , " HDF5config.cmake,BUILD_GENERATOR=Unix " , " -C " , BUILD_CFG, " -V " , " -O " , " hdf5.log " ], cwd=extract_dir)
run([tar, " -xf " , kwargs[ " ctest_result " ] + " .tar.gz " ], cwd=os.path.join(extract_dir, ' build ' ))
shutil.copytree(
os.path.join(extract_dir, " build " , kwargs[ " ctest_result " ], kwargs[ " ctest_result_path " ]),
os.path.join(DEPS_DIR, " install " , name)
)
elif mode != " bjam " :
2016-09-10 13:09:50 +02:00
extract_build_dir = os.path.join(extract_dir, " build " )
if os.path.exists(extract_build_dir):
shutil.rmtree(extract_build_dir)
os.makedirs(extract_build_dir)
2021-10-05 10:22:01 +02:00
logger.info(f " \r Configuring {name} ... " )
2019-05-10 11:59:00 +02:00
if mode == " autoconf " :
2016-09-10 13:09:50 +02:00
run_autoconf(name, build_tool_args, cwd=extract_build_dir)
elif mode == " cmake " :
run_cmake(name, build_tool_args, cwd=extract_build_dir)
else:
raise ValueError()
2021-10-05 10:22:01 +02:00
logger.info(f " \r Building {name} ... " )
run([make, f " -j {IFCOS_NUM_BUILD_PROCS} " , " VERBOSE=1 " ], cwd=extract_build_dir)
logger.info(f " \r Installing {name} ... " )
2018-09-08 13:23:36 +02:00
run([make, " install " ], cwd=extract_build_dir)
2021-10-05 10:22:01 +02:00
logger.info(f " \r Installed {name} \n " )
2016-09-10 13:09:50 +02:00
else:
2021-10-05 10:22:01 +02:00
logger.info(f " \r Configuring {name} ... " )
2018-09-08 13:23:36 +02:00
run([bash, " ./bootstrap.sh " ], cwd=extract_dir)
2021-10-05 10:22:01 +02:00
logger.info(f " \r Building {name} ... " )
2022-11-25 13:16:36 +01:00
run([ " ./b2 " , f " -j {IFCOS_NUM_BUILD_PROCS} " ] + build_tool_args, cwd=extract_dir, can_fail= " wasm " in flags)
2021-10-05 10:22:01 +02:00
logger.info(f " \r Installing {name} ... " )
shutil.copytree(os.path.join(extract_dir, " boost " ), os.path.join(DEPS_DIR, " install " , f " boost- {BOOST_VERSION} " , " boost " ))
logger.info(f " \r Installed {name} \n " )
2016-09-10 13:09:50 +02:00
cecho( " Collecting dependencies: " , GREEN)
# Set compiler flags for 32bit builds on 64bit system
# TODO: This is untested
2021-10-05 14:24:59 +02:00
ADDITIONAL_ARGS = []
2016-09-10 13:09:50 +02:00
2021-10-06 15:52:55 +02:00
if platform.system() == " Darwin " :
2021-10-05 14:24:59 +02:00
ADDITIONAL_ARGS = [f " -mmacosx-version-min= {TOOLSET} " ] + ADDITIONAL_ARGS
2016-09-10 13:09:50 +02:00
2022-11-25 13:16:36 +01:00
if " wasm " in flags:
ADDITIONAL_ARGS.extend(( " -sWASM_BIGINT " , " -fexceptions " ))
2016-09-10 13:09:50 +02:00
# If the linker supports GC sections, set it up to reduce binary file size
# -fPIC is required for the shared libraries to work
2021-10-05 18:32:12 +02:00
CXXFLAGS = os.environ.get( " CXXFLAGS " , " " )
CFLAGS = os.environ.get( " CFLAGS " , " " )
LDFLAGS = os.environ.get( " LDFLAGS " , " " )
2017-11-18 16:51:59 +01:00
2021-10-05 14:24:59 +02:00
ADDITIONAL_ARGS_STR = " " .join(ADDITIONAL_ARGS)
2022-11-25 13:16:36 +01:00
if " wasm " not in flags and sp.call([bash, " -c " , " ld --gc-sections 2>&1 | grep -- --gc-sections &> /dev/null " ]) != 0:
2021-10-05 14:24:59 +02:00
CXXFLAGS_MINIMAL = f " {CXXFLAGS} {PIC} {ADDITIONAL_ARGS_STR} "
CFLAGS_MINIMAL = f " {CFLAGS} {PIC} {ADDITIONAL_ARGS_STR} "
2019-05-10 12:04:32 +02:00
if BUILD_STATIC:
2021-10-05 14:24:59 +02:00
CXXFLAGS = f " {CXXFLAGS} {PIC} -fdata-sections -ffunction-sections -fvisibility=hidden -fvisibility-inlines-hidden {ADDITIONAL_ARGS_STR} "
CFLAGS = f " {CFLAGS} {PIC} -fdata-sections -ffunction-sections -fvisibility=hidden {ADDITIONAL_ARGS_STR} "
2019-05-10 12:04:32 +02:00
else:
2021-10-05 14:24:59 +02:00
CXXFLAGS = CXXFLAGS_MINIMAL
CFLAGS = CFLAGS_MINIMAL
LDFLAGS = f " {LDFLAGS} -Wl,--gc-sections {ADDITIONAL_ARGS_STR} "
2016-09-10 13:09:50 +02:00
else:
2021-10-05 14:24:59 +02:00
CXXFLAGS_MINIMAL = f " {CXXFLAGS} {PIC} {ADDITIONAL_ARGS_STR} "
CFLAGS_MINIMAL = f " {CFLAGS} {PIC} {ADDITIONAL_ARGS_STR} "
2019-05-10 12:04:32 +02:00
if BUILD_STATIC:
2021-10-05 14:24:59 +02:00
CXXFLAGS = f " {CXXFLAGS} {PIC} -fvisibility=hidden -fvisibility-inlines-hidden {ADDITIONAL_ARGS_STR} "
CFLAGS = f " {CFLAGS} {PIC} -fvisibility=hidden -fvisibility-inlines-hidden {ADDITIONAL_ARGS_STR} "
2019-05-10 12:04:32 +02:00
else:
CXXFLAGS=CXXFLAGS_MINIMAL
CFLAGS=CFLAGS_MINIMAL
2021-10-05 14:24:59 +02:00
LDFLAGS = f " {LDFLAGS} {ADDITIONAL_ARGS_STR} "
2019-05-10 12:04:32 +02:00
os.environ[ " CXXFLAGS " ] = CXXFLAGS
os.environ[ " CFLAGS " ] = CFLAGS
os.environ[ " LDFLAGS " ] = LDFLAGS
2016-09-10 13:09:50 +02:00
# Some dependencies need a more recent CMake version than most distros provide
2020-12-24 20:46:42 +00:00
# @tfk: this is no longer needed
# build_dependency(name= " cmake- %s " % (CMAKE_VERSION,), mode= " autoconf " , build_tool_args=[], download_url= " https://cmake.org/files/v %s " % (CMAKE_VERSION_2,), download_name= " cmake- %s .tar.gz " % (CMAKE_VERSION,))
2016-09-10 13:09:50 +02:00
2021-07-11 19:15:20 +00:00
if ' hdf5 ' in targets:
2021-10-05 10:22:01 +02:00
HDF5_MAJOR = " . " .join(HDF5_VERSION.split( " . " )[:-1])
2021-07-11 19:15:20 +00:00
build_dependency(
2021-10-05 10:22:01 +02:00
name=f " hdf5- {HDF5_VERSION} " ,
2021-07-11 19:15:20 +00:00
mode= " ctest " ,
build_tool_args=[],
2021-10-05 10:22:01 +02:00
download_url=f " https://support.hdfgroup.org/ftp/HDF5/releases/hdf5- {HDF5_MAJOR} /hdf5- {HDF5_VERSION} /src/ " ,
download_name=f " CMake-hdf5- {HDF5_VERSION} .tar.gz " ,
2021-10-06 15:52:55 +02:00
ctest_result=f " HDF5- {HDF5_VERSION} - { platform.system()} " ,
2021-10-05 10:22:01 +02:00
ctest_result_path=f " HDF_Group/HDF5/ {HDF5_VERSION} "
2021-07-11 19:15:20 +00:00
)
2019-05-21 13:31:43 +02:00
if " json " in targets:
2021-10-05 10:22:01 +02:00
json_url = f " https://github.com/nlohmann/json/releases/download/ {JSON_VERSION} /json.hpp "
json_install_path = f " {DEPS_DIR} /install/json/nlohmann/json.hpp "
2019-06-28 08:38:24 +02:00
if not os.path.exists(os.path.dirname(json_install_path)):
2019-05-21 13:31:43 +02:00
os.makedirs(os.path.dirname(json_install_path))
2019-06-28 08:38:24 +02:00
if not os.path.exists(json_install_path):
2019-06-23 19:23:38 +02:00
urlretrieve(json_url, json_install_path)
2019-05-21 13:31:43 +02:00
2018-09-08 13:23:36 +02:00
if " pcre " in targets:
build_dependency(
2021-10-05 10:22:01 +02:00
name=f " pcre- {PCRE_VERSION} " ,
2018-09-08 13:23:36 +02:00
mode= " autoconf " ,
2019-05-10 12:04:32 +02:00
build_tool_args=[DISABLE_FLAG],
2021-10-05 10:22:01 +02:00
download_url=f " https://downloads.sourceforge.net/project/pcre/pcre/ {PCRE_VERSION} / " ,
download_name=f " pcre- {PCRE_VERSION} .tar.bz2 "
2018-09-08 13:23:36 +02:00
)
2016-09-10 13:09:50 +02:00
# An issue exists with swig-1.3 and python >= 3.2
# Therefore, build a recent copy from source
2018-09-08 13:23:36 +02:00
if " swig " in targets:
build_dependency(
name= " swig " ,
mode= " autoconf " ,
2021-10-05 10:22:01 +02:00
build_tool_args=[ " --disable-ccache " , f " --with-pcre-prefix= {DEPS_DIR} /install/pcre- {PCRE_VERSION} " ],
2018-09-08 13:23:36 +02:00
download_url= " https://github.com/swig/swig.git " ,
download_name= " swig " ,
download_tool=download_tool_git,
2021-10-05 10:22:01 +02:00
revision=f " rel- {SWIG_VERSION} "
2018-09-08 13:23:36 +02:00
)
2022-11-25 13:16:36 +01:00
if " freetype " in targets:
build_dependency(
name=f " freetype " ,
mode= " cmake " ,
build_tool_args=[
f " -DCMAKE_INSTALL_PREFIX= {DEPS_DIR} /install/freetype "
],
download_url = " https://github.com/freetype/freetype " ,
download_name = " freetype2 " ,
download_tool=download_tool_git,
)
2016-09-10 13:09:50 +02:00
2018-09-08 13:23:36 +02:00
if USE_OCCT and " occ " in targets:
2022-11-25 13:16:36 +01:00
patches = []
if OCCT_VERSION < " 7.4 " :
patches.append( " ./patches/occt/enable-exception-handling.patch " )
if " wasm " in flags:
patches.append( " ./patches/occt/no_em_js.patch " )
2017-08-13 13:13:26 +02:00
build_dependency(
2021-10-05 10:22:01 +02:00
name=f " occt- {OCCT_VERSION} " ,
2017-08-13 13:13:26 +02:00
mode= " cmake " ,
build_tool_args=[
2021-10-05 10:22:01 +02:00
f " -DINSTALL_DIR= {DEPS_DIR} /install/occt- {OCCT_VERSION} " ,
f " -DBUILD_LIBRARY_TYPE= {LINK_TYPE_UCFIRST} " ,
2017-08-13 13:13:26 +02:00
" -DBUILD_MODULE_Draw=0 " ,
2022-11-25 13:16:36 +01:00
" -DBUILD_RELEASE_DISABLE_EXCEPTIONS=Off " ,
f " -D3RDPARTY_FREETYPE_DIR= {DEPS_DIR} /install/freetype "
2017-08-13 13:13:26 +02:00
],
2022-06-08 13:37:48 +02:00
download_url = " https://github.com/Open-Cascade-SAS/OCCT " ,
2018-08-19 10:29:01 +02:00
download_name = " occt " ,
download_tool=download_tool_git,
2022-11-25 13:16:36 +01:00
patch=patches,
2018-09-08 13:23:36 +02:00
revision= " V " + OCCT_VERSION.replace( ' . ' , ' _ ' )
)
elif " occ " in targets:
build_dependency(
2021-10-05 10:22:01 +02:00
name=f " oce- {OCE_VERSION} " ,
2018-09-08 13:23:36 +02:00
mode= " cmake " ,
build_tool_args=[
" -DOCE_DISABLE_TKSERVICE_FONT=ON " ,
" -DOCE_TESTING=OFF " ,
" -DOCE_BUILD_SHARED_LIB=OFF " ,
" -DOCE_DISABLE_X11=ON " ,
" -DOCE_VISUALISATION=OFF " ,
" -DOCE_OCAF=OFF " ,
2021-10-05 10:22:01 +02:00
f " -DOCE_INSTALL_PREFIX= {DEPS_DIR} /install/oce- {OCE_VERSION} "
2018-09-08 13:23:36 +02:00
],
download_url= " https://github.com/tpaviot/oce/archive/ " ,
2021-10-05 10:22:01 +02:00
download_name=f " OCE- {OCE_VERSION} .tar.gz "
2018-09-08 13:23:36 +02:00
)
2017-08-13 13:13:26 +02:00
2018-09-08 13:23:36 +02:00
if " libxml2 " in targets:
build_dependency(
2021-10-05 10:22:01 +02:00
f " libxml2- {LIBXML2_VERSION} " ,
2018-09-08 13:23:36 +02:00
" autoconf " ,
build_tool_args=[
" --without-python " ,
2019-05-10 12:04:32 +02:00
ENABLE_FLAG,
DISABLE_FLAG,
2018-09-08 13:23:36 +02:00
" --without-zlib " ,
" --without-iconv " ,
" --without-lzma "
],
download_url= " ftp://xmlsoft.org/libxml2/ " ,
2021-10-05 10:22:01 +02:00
download_name=f " libxml2- {LIBXML2_VERSION} .tar.gz "
2018-09-08 13:23:36 +02:00
)
2017-07-03 20:42:18 +02:00
2018-09-08 13:23:36 +02:00
if " OpenCOLLADA " in targets:
2022-12-28 13:33:16 +01:00
patches = [ " ./patches/opencollada/pr622_and_disable_subdirs.patch " ]
if " wasm " in flags:
# This is necessary for the WASM build, because recent versions of
# clang don ' t have the tr1:: namespace anymore. However, it breaks
# some versions of gcc (9.4.0 at least) due to specializing std::hash
# outside of the std:: namespace.
patches.append( " ./patches/opencollada/remove_tr1.patch " )
2018-09-08 13:23:36 +02:00
build_dependency(
" OpenCOLLADA " ,
" cmake " ,
build_tool_args=[
2021-10-05 10:22:01 +02:00
f " -DLIBXML2_INCLUDE_DIR= {DEPS_DIR} /install/libxml2- {LIBXML2_VERSION} /include/libxml2 " ,
f " -DLIBXML2_LIBRARIES= {DEPS_DIR} /install/libxml2- {LIBXML2_VERSION} /lib/libxml2. {LIBRARY_EXT} " ,
f " -DPCRE_INCLUDE_DIR= {DEPS_DIR} /install/pcre- {PCRE_VERSION} /include " ,
f " -DPCRE_PCREPOSIX_LIBRARY= {DEPS_DIR} /install/pcre- {PCRE_VERSION} /lib/libpcreposix. {LIBRARY_EXT} " ,
f " -DPCRE_PCRE_LIBRARY= {DEPS_DIR} /install/pcre- {PCRE_VERSION} /lib/libpcre. {LIBRARY_EXT} " ,
f " -DCMAKE_INSTALL_PREFIX= {DEPS_DIR} /install/OpenCOLLADA/ "
2018-09-08 13:23:36 +02:00
],
download_url= " https://github.com/KhronosGroup/OpenCOLLADA.git " ,
download_name= " OpenCOLLADA " ,
download_tool=download_tool_git,
2022-12-28 13:33:16 +01:00
patch=patches,
2019-06-23 05:07:46 +02:00
revision=OPENCOLLADA_VERSION
2018-09-08 13:23:36 +02:00
)
2022-11-25 13:16:36 +01:00
if " python " in targets and not USE_CURRENT_PYTHON_VERSION and " wasm " not in flags:
2018-09-08 13:23:36 +02:00
# Python should not be built with -fvisibility=hidden, from experience that introduces segfaults
2021-10-05 18:32:12 +02:00
OLD_CXX_FLAGS = os.environ[ " CXXFLAGS " ]
OLD_C_FLAGS = os.environ[ " CFLAGS " ]
os.environ[ " CXXFLAGS " ] = CXXFLAGS_MINIMAL
os.environ[ " CFLAGS " ] = CFLAGS_MINIMAL
2018-09-08 13:23:36 +02:00
# On OSX a dynamic python library is built or it would not be compatible
# with the system python because of some threading initialization
2021-10-05 18:32:12 +02:00
PYTHON_CONFIGURE_ARGS = []
2021-10-06 15:52:55 +02:00
if platform.system() == " Darwin " :
2022-09-14 10:57:08 +02:00
PYTHON_CONFIGURE_ARGS = [ " --enable-shared " ]
2021-10-05 18:32:12 +02:00
for PYTHON_VERSION in PYTHON_VERSIONS:
2021-10-24 14:56:50 +02:00
try:
build_dependency(
f " python- {PYTHON_VERSION} " ,
" autoconf " ,
PYTHON_CONFIGURE_ARGS,
f " http://www.python.org/ftp/python/ {PYTHON_VERSION} / " ,
f " Python- {PYTHON_VERSION} .tgz "
)
except RuntimeError as e:
# Sometimes setting up modules such as pip/lzma can cause
# the python installer script to return a non zero exit
# code where actually the headers and dynamic libraries
# are installed correctly. This is all we need so we catch
2021-10-28 17:56:02 -04:00
# the exception and only reraise if a partially successful
2021-10-24 14:56:50 +02:00
# install is not detected.
if not os.path.exists(
os.path.join(DEPS_DIR, " install " , f " python- {PYTHON_VERSION} " )
):
raise e
2021-10-05 18:32:12 +02:00
os.environ[ " CXXFLAGS " ] = OLD_CXX_FLAGS
os.environ[ " CFLAGS " ] = OLD_C_FLAGS
2018-09-08 13:23:36 +02:00
if " boost " in targets:
str_concat = lambda prefix: lambda postfix: " " if postfix.strip() == " " else " = " .join((prefix, postfix.strip()))
2022-11-25 13:16:36 +01:00
toolset = []
if " wasm " in flags:
toolset.append( " toolset=emscripten " )
2018-09-08 13:23:36 +02:00
build_dependency(
2021-10-05 10:22:01 +02:00
f " boost- {BOOST_VERSION} " ,
2018-09-08 13:23:36 +02:00
mode= " bjam " ,
build_tool_args=[
2021-10-05 10:22:01 +02:00
f " --stagedir= {DEPS_DIR} /install/boost- {BOOST_VERSION} " ,
2018-09-08 13:23:36 +02:00
" --with-system " ,
" --with-program_options " ,
" --with-regex " ,
" --with-thread " ,
" --with-date_time " ,
" --with-iostreams " ,
2022-11-25 13:16:36 +01:00
f " link= {LINK_TYPE} " ,
*toolset,
*map(str_concat( " cxxflags " ), CXXFLAGS.strip().split( ' ' )),
*map(str_concat( " linkflags " ), LDFLAGS.strip().split( ' ' )),
" stage " , " -s " , " NO_BZIP2=1 " ],
2020-12-29 07:59:52 -05:00
download_url=BOOST_LOCATION,
2022-11-25 13:16:36 +01:00
patch= " ./patches/boost/boostorg_regex_62.patch " ,
2021-10-05 10:22:01 +02:00
download_name=f " boost_ {BOOST_VERSION_UNDERSCORE} .tar.bz2 "
2018-09-08 13:23:36 +02:00
)
2022-11-25 13:16:36 +01:00
if " wasm " in flags:
# only supported on nix for now
run(( " find " , " . " , " -name " , " *.bc " , " -exec " , " bash " , " -c " , " emar q $ { 1 % .bc}.a $1 " , " bash " , " {} " , " ; " ), cwd=f " {DEPS_DIR} /install/boost- {BOOST_VERSION} /lib " )
2017-07-03 20:42:18 +02:00
2021-08-10 19:02:52 +00:00
if " cgal " in targets:
2022-11-25 13:16:36 +01:00
gmp_args = []
mpfr_args = []
if " wasm " in flags:
gmp_args.extend(( " --disable-assembly " , " --host " , " none " , " --enable-cxx " ))
mpfr_args.extend(( " --host " , " none " ))
2021-08-10 19:02:52 +00:00
build_dependency(
2021-10-05 10:22:01 +02:00
name=f " gmp- {GMP_VERSION} " ,
2021-08-10 19:02:52 +00:00
mode= " autoconf " ,
2022-11-25 13:16:36 +01:00
build_tool_args=[ENABLE_FLAG, DISABLE_FLAG, " --with-pic " , *gmp_args],
2021-08-10 19:02:52 +00:00
download_url= " https://ftp.gnu.org/gnu/gmp/ " ,
2021-10-05 10:22:01 +02:00
download_name=f " gmp- {GMP_VERSION} .tar.bz2 "
2021-08-10 19:02:52 +00:00
)
build_dependency(
2021-10-05 18:32:12 +02:00
name=f " mpfr- {MPFR_VERSION} " ,
2021-08-10 19:02:52 +00:00
mode= " autoconf " ,
2022-11-25 13:16:36 +01:00
build_tool_args=[ENABLE_FLAG, DISABLE_FLAG, *mpfr_args, f " --with-gmp= {DEPS_DIR} /install/gmp- {GMP_VERSION} " ],
2021-10-05 10:22:01 +02:00
download_url=f " http://www.mpfr.org/mpfr- {MPFR_VERSION} / " ,
download_name=f " mpfr- {MPFR_VERSION} .tar.bz2 "
2021-08-10 19:02:52 +00:00
)
build_dependency(
2021-10-05 18:32:12 +02:00
name=f " cgal- {CGAL_VERSION} " ,
2021-08-10 19:02:52 +00:00
mode= " cmake " ,
build_tool_args=[
2022-10-13 09:52:22 +02:00
f " -DGMP_LIBRARIES= {DEPS_DIR} /install/gmp- {GMP_VERSION} /lib/libgmp. {LIBRARY_EXT} " ,
2021-10-05 10:22:01 +02:00
f " -DGMP_INCLUDE_DIR= {DEPS_DIR} /install/gmp- {GMP_VERSION} /include " ,
2022-10-13 09:52:22 +02:00
f " -DMPFR_LIBRARIES= {DEPS_DIR} /install/mpfr- {MPFR_VERSION} /lib/libmpfr. {LIBRARY_EXT} " ,
2021-10-05 10:22:01 +02:00
f " -DMPFR_INCLUDE_DIR= {DEPS_DIR} /install/mpfr- {MPFR_VERSION} /include " ,
f " -DBoost_INCLUDE_DIR= {DEPS_DIR} /install/boost- {BOOST_VERSION} " ,
f " -DCMAKE_INSTALL_PREFIX= {DEPS_DIR} /install/cgal- {CGAL_VERSION} / " ,
2021-08-10 19:02:52 +00:00
" -DCGAL_HEADER_ONLY=On " ,
" -DBUILD_SHARED_LIBS=Off "
],
download_url= " https://github.com/CGAL/cgal.git " ,
download_name= " cgal " ,
download_tool=download_tool_git,
2021-10-05 10:22:01 +02:00
revision=f " v {CGAL_VERSION} "
2021-08-10 19:02:52 +00:00
)
2023-05-24 15:16:48 +02:00
2016-09-10 13:09:50 +02:00
cecho( " Building IfcOpenShell: " , GREEN)
2021-10-08 15:23:27 +02:00
IFCOS_DIR = os.path.join(DEPS_DIR, " build " , " ifcopenshell " )
2021-11-28 14:07:11 +00:00
if os.environ.get( " NO_CLEAN " , " " ).lower() not in { " 1 " , " on " , " true " }:
if os.path.exists(IFCOS_DIR):
shutil.rmtree(IFCOS_DIR)
os.makedirs(IFCOS_DIR, exist_ok=True)
2016-09-10 13:09:50 +02:00
executables_dir = os.path.join(IFCOS_DIR, " executables " )
2021-11-28 14:07:11 +00:00
os.makedirs(executables_dir, exist_ok=True)
2016-09-10 13:09:50 +02:00
2018-09-08 13:23:36 +02:00
OFF_ON = [ " OFF " , " ON " ]
2021-10-05 18:32:12 +02:00
cmake_args = [
2021-07-11 19:15:20 +00:00
" -DUSE_MMAP= " " OFF " ,
" -DBUILD_EXAMPLES= " " OFF " ,
2021-10-05 18:32:12 +02:00
" -DBUILD_SHARED_LIBS= " +OFF_ON[not BUILD_STATIC],
2021-10-05 10:22:01 +02:00
" -DBOOST_ROOT= " f " {DEPS_DIR} /install/boost- {BOOST_VERSION} " ,
2019-05-21 13:31:43 +02:00
" -DGLTF_SUPPORT= " " ON " ,
2021-10-05 10:22:01 +02:00
" -DJSON_INCLUDE_DIR= " f " {DEPS_DIR} /install/json " ,
2021-08-10 14:34:01 +00:00
" -DBoost_NO_BOOST_CMAKE= " " On " ,
2022-01-16 13:59:19 +01:00
" -DADD_COMMIT_SHA= " +( " On " if ADD_COMMIT_SHA else " Off " )
2018-09-08 13:23:36 +02:00
]
2022-11-25 13:16:36 +01:00
if " wasm " in flags:
# Boost is built by the build script so should not be found
# inside of the sysroot set by the emscriptem toolchain
cmake_args.append( " -DWASM_BUILD=On " )
2021-08-10 19:02:52 +00:00
if " cgal " in targets:
cmake_args.extend([
2021-10-05 10:22:01 +02:00
" -DCGAL_INCLUDE_DIR= " f " {DEPS_DIR} /install/cgal- {CGAL_VERSION} /include " ,
" -DGMP_INCLUDE_DIR= " f " {DEPS_DIR} /install/gmp- {GMP_VERSION} /include " ,
" -DGMP_LIBRARY_DIR= " f " {DEPS_DIR} /install/gmp- {GMP_VERSION} /lib " ,
" -DMPFR_INCLUDE_DIR= " f " {DEPS_DIR} /install/mpfr- {MPFR_VERSION} /include " ,
" -DMPFR_LIBRARY_DIR= " f " {DEPS_DIR} /install/mpfr- {MPFR_VERSION} /lib " ,
2021-08-10 19:02:52 +00:00
])
2018-09-08 13:23:36 +02:00
if " occ " in targets and USE_OCCT:
2021-10-05 10:22:01 +02:00
occ_include_dir = f " {DEPS_DIR} /install/occt- {OCCT_VERSION} /include/opencascade "
occ_library_dir = f " {DEPS_DIR} /install/occt- {OCCT_VERSION} /lib "
2018-09-08 13:23:36 +02:00
cmake_args.extend([
2018-09-18 19:42:01 +02:00
" -DOCC_INCLUDE_DIR= " +occ_include_dir,
" -DOCC_LIBRARY_DIR= " +occ_library_dir
2018-09-08 13:23:36 +02:00
])
2021-10-05 18:32:12 +02:00
2018-09-08 13:23:36 +02:00
elif " occ " in targets:
2021-10-05 10:22:01 +02:00
occ_include_dir = f " {DEPS_DIR} /install/oce- {OCE_VERSION} /include/oce "
occ_library_dir = f " {DEPS_DIR} /install/oce- {OCE_VERSION} /lib "
2018-09-08 13:23:36 +02:00
cmake_args.extend([
2018-09-18 19:42:01 +02:00
" -DOCC_INCLUDE_DIR= " +occ_include_dir,
" -DOCC_LIBRARY_DIR= " +occ_library_dir
2018-09-08 13:23:36 +02:00
])
if " OpenCOLLADA " in targets:
cmake_args.extend([
2021-10-05 10:22:01 +02:00
" -DOPENCOLLADA_INCLUDE_DIR= " f " {DEPS_DIR} /install/OpenCOLLADA/include/opencollada " ,
" -DOPENCOLLADA_LIBRARY_DIR= " f " {DEPS_DIR} /install/OpenCOLLADA/lib/opencollada "
2018-09-08 13:23:36 +02:00
])
2021-10-05 18:32:12 +02:00
else:
cmake_args.extend([
" -DCOLLADA_SUPPORT= " " Off " ,
])
2018-09-08 13:23:36 +02:00
if " pcre " in targets:
cmake_args.append(
2021-10-05 10:22:01 +02:00
" -DPCRE_LIBRARY_DIR= " f " {DEPS_DIR} /install/pcre- {PCRE_VERSION} /lib "
2018-09-08 13:23:36 +02:00
)
if " libxml2 " in targets:
cmake_args.extend([
2021-10-05 10:22:01 +02:00
" -DLIBXML2_INCLUDE_DIR= " f " {DEPS_DIR} /install/libxml2- {LIBXML2_VERSION} /include/libxml2 " ,
" -DLIBXML2_LIBRARIES= " f " {DEPS_DIR} /install/libxml2- {LIBXML2_VERSION} /lib/libxml2. {LIBRARY_EXT} "
2018-09-08 13:23:36 +02:00
])
2021-07-11 19:15:20 +00:00
if " hdf5 " in targets:
cmake_args.extend([
2021-10-05 10:22:01 +02:00
" -DHDF5_INCLUDE_DIR= " f " {DEPS_DIR} /install/hdf5- {HDF5_VERSION} /include " ,
" -DHDF5_LIBRARY_DIR= " f " {DEPS_DIR} /install/hdf5- {HDF5_VERSION} /lib "
2021-07-11 19:15:20 +00:00
])
2022-11-25 13:16:36 +01:00
else:
cmake_args.append( " -DHDF5_SUPPORT=Off " )
if not explicit_targets or { " IfcGeom " , " IfcConvert " , " IfcGeomServer " } & set(explicit_targets):
logger.info( " \r Configuring executables... " )
exec_args = [
" -DBUILD_IFCGEOM= " +OFF_ON[ " IfcGeom " in targets],
" -DBUILD_GEOMSERVER= " +OFF_ON[ " IfcGeomServer " in targets],
" -DBUILD_CONVERT= " +OFF_ON[ " IfcConvert " in targets],
" -DBUILD_IFCPYTHON= " " OFF " ,
" -DCMAKE_INSTALL_PREFIX= " f " {DEPS_DIR} /install/ifcopenshell " ,
]
run_cmake( " " , exec_args + cmake_args, cmake_dir=CMAKE_DIR, cwd=executables_dir)
2021-07-11 19:15:20 +00:00
2022-11-25 13:16:36 +01:00
logger.info( " \r Building executables... " )
2016-09-10 13:09:50 +02:00
2022-11-25 13:16:36 +01:00
run([make, f " -j {IFCOS_NUM_BUILD_PROCS} " ], cwd=executables_dir)
run([make, " install/strip " if BUILD_CFG == " Release " else " install " ], cwd=executables_dir)
2018-09-08 13:23:36 +02:00
if " IfcOpenShell-Python " in targets:
# On OSX the actual Python library is not linked against.
2021-10-05 10:22:01 +02:00
ADDITIONAL_ARGS = " "
2021-10-06 15:52:55 +02:00
if platform.system() == " Darwin " :
2021-10-05 18:32:12 +02:00
ADDITIONAL_ARGS = " -Wl,-flat_namespace,-undefined,suppress "
2022-11-25 13:16:36 +01:00
if " wasm " in flags:
ADDITIONAL_ARGS = f " -Wl,-undefined,suppress -sSIDE_MODULE=2 -sEXPORTED_FUNCTIONS=_PyInit__ifcopenshell_wrapper "
2021-10-05 10:22:01 +02:00
os.environ[ " CXXFLAGS " ] = f " {CXXFLAGS_MINIMAL} {ADDITIONAL_ARGS} "
os.environ[ " CFLAGS " ] = f " {CFLAGS_MINIMAL} {ADDITIONAL_ARGS} "
os.environ[ " LDFLAGS " ] = f " {LDFLAGS} {ADDITIONAL_ARGS} "
2018-09-08 13:23:36 +02:00
2021-10-08 15:23:27 +02:00
python_dir = os.path.join(IFCOS_DIR, " pythonwrapper " )
os.makedirs(python_dir, exist_ok=True)
2018-09-08 13:23:36 +02:00
2021-10-08 15:23:27 +02:00
def compile_python_wrapper(python_version, python_library, python_include, python_executable):
logger.info(f " \r Configuring python {python_version} wrapper... " )
2018-09-08 13:23:36 +02:00
2020-08-01 19:32:50 +02:00
cache_path = os.path.join(python_dir, " CMakeCache.txt " )
if os.path.exists(cache_path):
2021-10-08 15:23:27 +02:00
os.remove(cache_path)
2020-08-01 19:32:50 +02:00
2021-10-24 10:08:06 +02:00
os.environ[ " PYTHON_LIBRARY_BASENAME " ] = os.path.basename(python_library)
2018-09-08 13:23:36 +02:00
2022-11-25 13:16:36 +01:00
swig_when_built = []
if " swig " in targets:
swig_when_built.append(f " -DSWIG_EXECUTABLE= {DEPS_DIR} /install/swig/bin/swig " )
2018-09-08 13:23:36 +02:00
run_cmake( " " ,
2021-07-11 19:15:20 +00:00
cmake_args + [
2021-10-24 10:08:06 +02:00
" -DPYTHON_LIBRARY= " +python_library,
2022-11-25 13:16:36 +01:00
*([f " -DPYTHON_EXECUTABLE= {python_executable} " ] if python_executable else []),
# *([f " -DPYTHON_MODULE_INSTALL_DIR= {os.environ['PYTHONPATH']} /ifcopenshell " ] if " wasm " in flags else []),
*([ " -DPYTHON_MODULE_INSTALL_DIR= " +os.path.abspath(os.path.join(os.path.dirname(__file__), " .. " , " package " ))] if " wasm " in flags else []),
2021-10-24 10:08:06 +02:00
" -DPYTHON_INCLUDE_DIR= " +python_include,
2021-10-05 10:22:01 +02:00
" -DCMAKE_INSTALL_PREFIX= " f " {DEPS_DIR} /install/ifcopenshell/tmp " ,
2022-11-25 13:16:36 +01:00
" -DUSERSPACE_PYTHON_PREFIX= " +[ " Off " , " On " ][os.environ.get( " PYTHON_USER_SITE " , " " ).lower() in { " 1 " , " on " , " true " }],
*swig_when_built],
cmake_dir=CMAKE_DIR, cwd=python_dir)
2021-10-06 12:07:08 +02:00
2021-10-08 15:23:27 +02:00
logger.info(f " \r Building python {python_version} wrapper... " )
2016-09-10 13:09:50 +02:00
2021-10-05 10:22:01 +02:00
run([make, f " -j {IFCOS_NUM_BUILD_PROCS} " , " _ifcopenshell_wrapper " ], cwd=python_dir)
2018-09-08 13:23:36 +02:00
run([make, " install/local " ], cwd=os.path.join(python_dir, " ifcwrap " ))
2016-09-10 13:09:50 +02:00
2022-11-25 13:16:36 +01:00
if python_executable:
module_dir = os.path.dirname(run([python_executable, " -c " , " import inspect, ifcopenshell; print(inspect.getfile(ifcopenshell)) " ]))
2016-09-10 13:09:50 +02:00
2022-11-25 13:16:36 +01:00
if platform.system() != " Darwin " :
2023-12-17 13:18:34 +01:00
if BUILD_CFG == " Release " :
# TODO: This symbol name depends on the Python version?
run([strip, " -s " , " -K " , " PyInit__ifcopenshell_wrapper " , " _ifcopenshell_wrapper.so " ], cwd=module_dir)
2018-09-08 13:23:36 +02:00
2022-11-25 13:16:36 +01:00
return module_dir
2021-10-06 15:52:55 +02:00
2022-11-25 13:16:36 +01:00
if " wasm " in flags:
compile_python_wrapper(
f " {os.environ['PYMAJOR']} . {os.environ['PYMINOR']} . {os.environ['PYMICRO']} " ,
f " {os.environ['TARGETINSTALLDIR']} /lib/libpython {os.environ['PYMAJOR']} . {os.environ['PYMINOR']} .a " ,
os.environ[ ' PYTHONINCLUDE ' ],
None
)
elif USE_CURRENT_PYTHON_VERSION:
2021-10-08 15:23:27 +02:00
python_info = sysconfig.get_paths()
2022-11-25 13:16:36 +01:00
py_path_components = [
sysconfig.get_config_var( ' LIBDIR ' ),
2021-11-28 14:08:03 +00:00
sysconfig.get_config_var( " INSTSONAME " )
2022-11-25 13:16:36 +01:00
]
if sysconfig.get_config_var( ' multiarchsubdir ' ):
py_path_components.insert(1, sysconfig.get_config_var( ' multiarchsubdir ' ).replace( " / " , " " ))
python_lib = os.path.join(*py_path_components)
2021-11-28 14:08:03 +00:00
compile_python_wrapper(platform.python_version(), python_lib, python_info[ " include " ], sys.executable)
2021-10-08 15:23:27 +02:00
else:
for python_version in PYTHON_VERSIONS:
python_library = run([bash, " -c " , f " ls {DEPS_DIR} /install/python- {python_version} /lib/libpython*.* " ])
python_include = run([bash, " -c " , f " ls -d {DEPS_DIR} /install/python- {python_version} /include/python* " ])
python_executable = os.path.join(DEPS_DIR, " install " , f " python- {python_version} " , " bin " , f " python {python_version[0]} " )
2021-10-06 12:07:08 +02:00
2021-10-08 15:23:27 +02:00
module_dir = compile_python_wrapper(python_version, python_library, python_include, python_executable)
run([cp, " -R " , module_dir, os.path.join(DEPS_DIR, " install " , " ifcopenshell " , f " python- {python_version} " )])
2016-09-10 13:09:50 +02:00
logger.info( " \r Built IfcOpenShell... \n \n " )