mirror of https://github.com/KLayout/klayout.git
933 lines
37 KiB
Python
Executable File
933 lines
37 KiB
Python
Executable File
#! /usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
#===============================================================================
|
|
# File: "macbuild/build4mac.py"
|
|
#
|
|
# The top Python script for building KLayout (http://www.klayout.de/index.php)
|
|
# version 0.25 or later on different Apple Mac OSX platforms.
|
|
#===============================================================================
|
|
from __future__ import print_function # to use print() of Python 3 in Python >= 2.7
|
|
import sys
|
|
import os
|
|
import shutil
|
|
import glob
|
|
import platform
|
|
import optparse
|
|
import subprocess
|
|
|
|
#-------------------------------------------------------------------------------
|
|
## To import global dictionaries of different modules and utility functions
|
|
#-------------------------------------------------------------------------------
|
|
mydir = os.path.dirname(os.path.abspath(__file__))
|
|
sys.path.append( mydir + "/macbuild" )
|
|
from build4mac_env import *
|
|
from build4mac_util import *
|
|
|
|
#-------------------------------------------------------------------------------
|
|
## To set global variables including present directory and platform info.
|
|
#-------------------------------------------------------------------------------
|
|
def SetGlobals():
|
|
global ProjectDir # project directory where "build.sh" exists
|
|
global Usage # string on usage
|
|
global BuildBash # the main build Bash script
|
|
global Platform # platform
|
|
global ModuleQt # Qt module to be used
|
|
global ModuleRuby # Ruby module to be used
|
|
global ModulePython # Python module to be used
|
|
global NonOSStdLang # True if non-OS-standard language is chosen
|
|
global NoQtBindings # True if not creating Qt bindings for Ruby scripts
|
|
global MakeOptions # options passed to `make`
|
|
global DebugMode # True if debug mode build
|
|
global CheckComOnly # True if only for checking the command line parameters to "build.sh"
|
|
global DeploymentF # True if fully (including Qt's Frameworks) deploy the binaries for bundles
|
|
global DeploymentP # True if partially deploy the binaries excluding Qt's Frameworks
|
|
global DeployVerbose # -verbose=<0-3> level passed to 'macdeployqt' tool
|
|
global Version # KLayout's version
|
|
# auxiliary variables on platform
|
|
global System # 6-tuple from platform.uname()
|
|
global Node # - do -
|
|
global Release # - do -
|
|
global Version # - do -
|
|
global Machine # - do -
|
|
global Processor # - do -
|
|
global Bit # machine bit-size
|
|
|
|
Usage = "\n"
|
|
Usage += "--------------------------------------------------------------------------------------------------------\n"
|
|
Usage += "<< Usage of 'build4mac.py' >>\n"
|
|
Usage += " for building KLayout 0.25 or later on different Apple Mac OSX platforms.\n"
|
|
Usage += "\n"
|
|
Usage += "$ [python] ./build4mac.py \n"
|
|
Usage += " option & argument : descriptions | default value\n"
|
|
Usage += " ----------------------------------------------------------------------------------+---------------\n"
|
|
Usage += " : * key type names below are case insensitive * | \n"
|
|
Usage += " : 'nil' = not to support the script language | \n"
|
|
Usage += " : 'Sys' = using the OS standard script language | \n"
|
|
Usage += " : Refer to 'macbuild/build4mac_env.py' for details | \n"
|
|
Usage += " [-q|--qt <type>] : type=['Qt4MacPorts', 'Qt5MacPorts', 'Qt5Custom'] | qt5macports \n"
|
|
Usage += " [-r|--ruby <type>] : type=['nil', 'Sys', 'Src24', 'MP24', 'B25'] | sys \n"
|
|
Usage += " [-p|--python <type>] : type=['nil', 'Sys', 'Ana27', 'Ana36', 'MP36', 'B36'] | sys \n"
|
|
Usage += " [-n|--noqtbinding] : don't create Qt bindings for ruby scripts | disabled \n"
|
|
Usage += " [-m|--make <option>] : option passed to 'make' | -j4 \n"
|
|
Usage += " [-d|--debug] : enable debug mode build | disabled \n"
|
|
Usage += " [-c|--checkcom] : check command line and exit without building | disabled \n"
|
|
Usage += " [-y|--deploy] : deploy executables and dylibs including Qt's Frameworks | disabled \n"
|
|
Usage += " [-Y|--DEPLOY] : deploy executables and dylibs for those who built KLayout | disabled \n"
|
|
Usage += " : from the source code and use the tools in the same machine | \n"
|
|
Usage += " : ! After confirmation of successful build of | \n"
|
|
Usage += " : KLayout, rerun this script with BOTH: | \n"
|
|
Usage += " : 1) the same options used for building AND | \n"
|
|
Usage += " : 2) <-y|--deploy> OR <-Y|--DEPLOY> | \n"
|
|
Usage += " : optionally with [-v|--verbose <0-3>] | \n"
|
|
Usage += " [-v|--verbose <0-3>] : verbose level of `macdeployqt' (effective with -y only) | 1 \n"
|
|
Usage += " : 0 = no output, 1 = error/warning (default), | \n"
|
|
Usage += " : 2 = normal, 3 = debug | \n"
|
|
Usage += " [-?|--?] : print this usage and exit | disabled \n"
|
|
Usage += "--------------------------------------------------------------------------------------------------------\n"
|
|
|
|
ProjectDir = os.getcwd()
|
|
BuildBash = "./build.sh"
|
|
(System, Node, Release, Version, Machine, Processor) = platform.uname()
|
|
|
|
if not System == "Darwin":
|
|
print("")
|
|
print( "!!! Sorry. Your system <%s> looks like non-Mac" % System, file=sys.stderr )
|
|
print(Usage)
|
|
quit()
|
|
|
|
release = int( Release.split(".")[0] ) # take the first of ['14', '5', '0']
|
|
if release == 14:
|
|
Platform = "Yosemite"
|
|
elif release == 15:
|
|
Platform = "ElCapitan"
|
|
elif release == 16:
|
|
Platform = "Sierra"
|
|
elif release == 17:
|
|
Platform = "HighSierra"
|
|
else:
|
|
Platform = ""
|
|
print("")
|
|
print( "!!! Sorry. Unsupported major OS release <%d>" % release, file=sys.stderr )
|
|
print(Usage)
|
|
quit()
|
|
|
|
if not Machine == "x86_64":
|
|
print("")
|
|
print( "!!! Sorry. Only x86_64 architecture machine is supported but found <%s>" % Machine, file=sys.stderr )
|
|
print(Usage)
|
|
quit()
|
|
|
|
# default modules
|
|
ModuleQt = "Qt5MacPorts"
|
|
if Platform == "Yosemite":
|
|
ModuleRuby = "RubyYosemite"
|
|
ModulePython = "PythonYosemite"
|
|
elif Platform == "ElCapitan":
|
|
ModuleRuby = "RubyElCapitan"
|
|
ModulePytyon = "PythonElCapitan"
|
|
elif Platform == "Sierra":
|
|
ModuleRuby = "RubySierra"
|
|
ModulePython = "PythonSierra"
|
|
elif Platform == "HighSierra":
|
|
ModuleRuby = "RubyHighSierra"
|
|
ModulePython = "PythonHighSierra"
|
|
else:
|
|
ModuleRuby = "nil"
|
|
ModulePython = "nil"
|
|
|
|
NonOSStdLang = False
|
|
NoQtBindings = False
|
|
MakeOptions = "-j4"
|
|
DebugMode = False
|
|
CheckComOnly = False
|
|
DeploymentF = False
|
|
DeploymentP = False
|
|
DeployVerbose = 1
|
|
Version = GetKLayoutVersionFrom( "./version.sh" )
|
|
|
|
#------------------------------------------------------------------------------
|
|
## To get command line parameters
|
|
#------------------------------------------------------------------------------
|
|
def ParseCommandLineArguments():
|
|
global Usage
|
|
global Platform
|
|
global ModuleQt
|
|
global ModuleRuby
|
|
global ModulePython
|
|
global NonOSStdLang
|
|
global NoQtBindings
|
|
global MakeOptions
|
|
global DebugMode
|
|
global CheckComOnly
|
|
global DeploymentF
|
|
global DeploymentP
|
|
global DeployVerbose
|
|
|
|
p = optparse.OptionParser( usage=Usage )
|
|
p.add_option( '-q', '--qt',
|
|
dest='type_qt',
|
|
help="Qt type=['Qt4MacPorts', 'Qt5MacPorts']" )
|
|
|
|
p.add_option( '-r', '--ruby',
|
|
dest='type_ruby',
|
|
help="Ruby type=['nil', 'Sys', 'Src24', 'MP24']" )
|
|
|
|
p.add_option( '-p', '--python',
|
|
dest='type_python',
|
|
help="Python type=['nil', 'Sys', 'Ana27', 'Ana36', 'MP36']" )
|
|
|
|
p.add_option( '-n', '--noqtbinding',
|
|
action='store_true',
|
|
dest='no_qt_binding',
|
|
default=False,
|
|
help="do not create Qt bindings for Ruby scripts" )
|
|
|
|
p.add_option( '-m', '--make',
|
|
dest='make_option',
|
|
help="options passed to `make`" )
|
|
|
|
p.add_option( '-d', '--debug',
|
|
action='store_true',
|
|
dest='debug_build',
|
|
default=False,
|
|
help="enable debug mode build" )
|
|
|
|
p.add_option( '-c', '--checkcom',
|
|
action='store_true',
|
|
dest='check_command',
|
|
default=False,
|
|
help="check command line and exit without building" )
|
|
|
|
p.add_option( '-y', '--deploy',
|
|
action='store_true',
|
|
dest='deploy_full',
|
|
default=False,
|
|
help="fully deploy built binaries" )
|
|
|
|
p.add_option( '-Y', '--DEPLOY',
|
|
action='store_true',
|
|
dest='deploy_partial',
|
|
default=False,
|
|
help="deploy built binaries when non-OS-standard script language is chosen" )
|
|
|
|
p.add_option( '-v', '--verbose',
|
|
dest='deploy_verbose',
|
|
help="verbose level of `macdeployqt` tool" )
|
|
|
|
p.add_option( '-?', '--??',
|
|
action='store_true',
|
|
dest='checkusage',
|
|
default=False,
|
|
help='check usage' )
|
|
|
|
p.set_defaults( type_qt = "qt5macports",
|
|
type_ruby = "sys",
|
|
type_python = "sys",
|
|
no_qt_binding = False,
|
|
make_option = "-j4",
|
|
debug_build = False,
|
|
check_command = False,
|
|
deploy_full = False,
|
|
deploy_partial = False,
|
|
deploy_verbose = "1",
|
|
checkusage = False )
|
|
|
|
opt, args = p.parse_args()
|
|
if (opt.checkusage):
|
|
print(Usage)
|
|
quit()
|
|
|
|
# Determine Qt type
|
|
candidates = [ i.upper() for i in ['Qt4MacPorts', 'Qt5MacPorts', 'Qt5Custom'] ]
|
|
ModuleQt = ""
|
|
index = 0
|
|
for item in candidates:
|
|
if opt.type_qt.upper() == item:
|
|
if index == 0:
|
|
ModuleQt = 'Qt4MacPorts'
|
|
break
|
|
elif index == 1:
|
|
ModuleQt = 'Qt5MacPorts'
|
|
break
|
|
elif index == 2:
|
|
ModuleQt = 'Qt5Custom'
|
|
break
|
|
else:
|
|
index += 1
|
|
if ModuleQt == "":
|
|
print("")
|
|
print( "!!! Unknown Qt type", file=sys.stderr )
|
|
print(Usage)
|
|
quit()
|
|
|
|
# By default, OS-standard script languages (Ruby and Python) are used
|
|
NonOSStdLang = False
|
|
|
|
# Determine Ruby type
|
|
candidates = [ i.upper() for i in ['nil', 'Sys', 'Src24', 'MP24', 'B25'] ]
|
|
ModuleRuby = ""
|
|
index = 0
|
|
for item in candidates:
|
|
if opt.type_ruby.upper() == item:
|
|
if index == 0:
|
|
ModuleRuby = 'nil'
|
|
break
|
|
elif index == 1:
|
|
if Platform == "Yosemite":
|
|
ModuleRuby = 'RubyYosemite'
|
|
elif Platform == "ElCapitan":
|
|
ModuleRuby = 'RubyElCapitan'
|
|
elif Platform == "Sierra":
|
|
ModuleRuby = 'RubySierra'
|
|
elif Platform == "HighSierra":
|
|
ModuleRuby = 'RubyHighSierra'
|
|
else:
|
|
ModuleRuby = ''
|
|
break
|
|
elif index == 2:
|
|
ModuleRuby = 'Ruby24SrcBuild'
|
|
NonOSStdLang = True
|
|
elif index == 3:
|
|
ModuleRuby = 'Ruby24MacPorts'
|
|
NonOSStdLang = True
|
|
elif index == 4:
|
|
ModuleRuby = 'Ruby25Brew'
|
|
NonOSStdLang = True
|
|
else:
|
|
index += 1
|
|
if ModuleRuby == "":
|
|
print("")
|
|
print( "!!! Unknown Ruby type", file=sys.stderr )
|
|
print(Usage)
|
|
quit()
|
|
|
|
# Determine Python type
|
|
candidates = [ i.upper() for i in ['nil', 'Sys', 'Ana27', 'Ana36', 'MP36', 'B36'] ]
|
|
ModulePython = ""
|
|
index = 0
|
|
for item in candidates:
|
|
if opt.type_python.upper() == item:
|
|
if index == 0:
|
|
ModulePython = 'nil'
|
|
break
|
|
elif index == 1:
|
|
if Platform == "Yosemite":
|
|
ModulePython = 'PythonYosemite'
|
|
elif Platform == "ElCapitan":
|
|
ModulePython = 'PythonElCapitan'
|
|
elif Platform == "Sierra":
|
|
ModulePython = 'PythonSierra'
|
|
elif Platform == "HighSierra":
|
|
ModulePython = 'PythonHighSierra'
|
|
else:
|
|
ModulePython = ''
|
|
break
|
|
elif index == 2:
|
|
ModulePython = 'Anaconda27'
|
|
NonOSStdLang = True
|
|
elif index == 3:
|
|
ModulePython = 'Anaconda36'
|
|
NonOSStdLang = True
|
|
elif index == 4:
|
|
ModulePython = 'Python36MacPorts'
|
|
NonOSStdLang = True
|
|
elif index == 5:
|
|
ModulePython = 'Python36Brew'
|
|
NonOSStdLang = True
|
|
else:
|
|
index += 1
|
|
if ModulePython == "":
|
|
print("")
|
|
print( "!!! Unknown Python type", file=sys.stderr )
|
|
print(Usage)
|
|
quit()
|
|
|
|
NoQtBindings = opt.no_qt_binding
|
|
MakeOptions = opt.make_option
|
|
DebugMode = opt.debug_build
|
|
CheckComOnly = opt.check_command
|
|
DeploymentF = opt.deploy_full
|
|
DeploymentP = opt.deploy_partial
|
|
|
|
if DeploymentF and DeploymentP:
|
|
print("")
|
|
print( "!!! Choose either [-y|--deploy] or [-Y|--DEPLOY]", file=sys.stderr )
|
|
print(Usage)
|
|
quit()
|
|
|
|
DeployVerbose = int(opt.deploy_verbose)
|
|
if not DeployVerbose in [0, 1, 2, 3]:
|
|
print("")
|
|
print( "!!! Unsupported verbose level passed to `macdeployqt` tool", file=sys.stderr )
|
|
print(Usage)
|
|
quit()
|
|
|
|
if not DeploymentF and not DeploymentP:
|
|
target = "%s %s %s" % (Platform, Release, Machine)
|
|
modules = "Qt=%s, Ruby=%s, Python=%s" % (ModuleQt, ModuleRuby, ModulePython)
|
|
message = "### You are going to build KLayout\n for <%s>\n with <%s>...\n"
|
|
print("")
|
|
print( message % (target, modules) )
|
|
|
|
#------------------------------------------------------------------------------
|
|
## To run the main Bash script "build.sh" with appropriate options
|
|
#
|
|
# @return 0 on success; non-zero on failure
|
|
#------------------------------------------------------------------------------
|
|
def RunMainBuildBash():
|
|
global ProjectDir
|
|
global Platform
|
|
global BuildBash
|
|
global ModuleQt
|
|
global ModuleRuby
|
|
global ModulePython
|
|
global NoQtBindings
|
|
global MakeOptions
|
|
global DebugMode
|
|
global CheckComOnly
|
|
global DeploymentF
|
|
global MacPkgDir # relative path to package directory
|
|
global MacBinDir # relative path to binary directory
|
|
global MacBuildDir # relative path to build directory
|
|
global MacBuildLog # relative path to build log file
|
|
global AbsMacPkgDir # absolute path to package directory
|
|
global AbsMacBinDir # absolute path to binary directory
|
|
global AbsMacBuildDir # absolute path to build directory
|
|
global AbsMacBuildLog # absolute path to build log file
|
|
|
|
#-----------------------------------------------------
|
|
# [1] Set parameters passed to the main Bash script
|
|
#-----------------------------------------------------
|
|
parameters = ""
|
|
|
|
# (A) debug or release
|
|
if DebugMode:
|
|
mode = "debug"
|
|
parameters += " -debug"
|
|
else:
|
|
mode = "release"
|
|
parameters += " -release"
|
|
|
|
# (B) Qt4 or Qt5
|
|
if ModuleQt == 'Qt4MacPorts':
|
|
parameters += " \\\n -qt4"
|
|
parameters += " \\\n -qmake %s" % Qt4MacPorts['qmake']
|
|
MacPkgDir = "./qt4.pkg.macos-%s-%s" % (Platform, mode)
|
|
MacBinDir = "./qt4.bin.macos-%s-%s" % (Platform, mode)
|
|
MacBuildDir = "./qt4.build.macos-%s-%s" % (Platform, mode)
|
|
MacBuildLog = "./qt4.build.macos-%s-%s.log" % (Platform, mode)
|
|
AbsMacPkgDir = "%s/qt4.pkg.macos-%s-%s" % (ProjectDir, Platform, mode)
|
|
AbsMacBinDir = "%s/qt4.bin.macos-%s-%s" % (ProjectDir, Platform, mode)
|
|
AbsMacBuildDir = "%s/qt4.build.macos-%s-%s" % (ProjectDir, Platform, mode)
|
|
AbsMacBuildLog = "%s/qt4.build.macos-%s-%s.log" % (ProjectDir, Platform, mode)
|
|
parameters += " \\\n -bin %s" % MacBinDir
|
|
parameters += " \\\n -build %s" % MacBuildDir
|
|
elif ModuleQt == 'Qt5MacPorts':
|
|
parameters += " \\\n -qt5"
|
|
parameters += " \\\n -qmake %s" % Qt5MacPorts['qmake']
|
|
MacPkgDir = "./qt5.pkg.macos-%s-%s" % (Platform, mode)
|
|
MacBinDir = "./qt5.bin.macos-%s-%s" % (Platform, mode)
|
|
MacBuildDir = "./qt5.build.macos-%s-%s" % (Platform, mode)
|
|
MacBuildLog = "./qt5.build.macos-%s-%s.log" % (Platform, mode)
|
|
AbsMacPkgDir = "%s/qt5.pkg.macos-%s-%s" % (ProjectDir, Platform, mode)
|
|
AbsMacBinDir = "%s/qt5.bin.macos-%s-%s" % (ProjectDir, Platform, mode)
|
|
AbsMacBuildDir = "%s/qt5.build.macos-%s-%s" % (ProjectDir, Platform, mode)
|
|
AbsMacBuildLog = "%s/qt5.build.macos-%s-%s.log" % (ProjectDir, Platform, mode)
|
|
parameters += " \\\n -bin %s" % MacBinDir
|
|
parameters += " \\\n -build %s" % MacBuildDir
|
|
elif ModuleQt == 'Qt5Custom':
|
|
parameters += " \\\n -qt5"
|
|
parameters += " \\\n -qmake %s" % Qt5Custom['qmake']
|
|
MacPkgDir = "./qt5.pkg.macos-%s-%s" % (Platform, mode)
|
|
MacBinDir = "./qt5.bin.macos-%s-%s" % (Platform, mode)
|
|
MacBuildDir = "./qt5.build.macos-%s-%s" % (Platform, mode)
|
|
MacBuildLog = "./qt5.build.macos-%s-%s.log" % (Platform, mode)
|
|
AbsMacPkgDir = "%s/qt5.pkg.macos-%s-%s" % (ProjectDir, Platform, mode)
|
|
AbsMacBinDir = "%s/qt5.bin.macos-%s-%s" % (ProjectDir, Platform, mode)
|
|
AbsMacBuildDir = "%s/qt5.build.macos-%s-%s" % (ProjectDir, Platform, mode)
|
|
AbsMacBuildLog = "%s/qt5.build.macos-%s-%s.log" % (ProjectDir, Platform, mode)
|
|
parameters += " \\\n -bin %s" % MacBinDir
|
|
parameters += " \\\n -build %s" % MacBuildDir
|
|
parameters += " \\\n -rpath %s" % "@executable_path/../Frameworks"
|
|
|
|
# (C) want Qt bindings with Ruby scripts?
|
|
if NoQtBindings:
|
|
parameters += " \\\n -without-qtbinding"
|
|
else:
|
|
parameters += " \\\n -with-qtbinding"
|
|
|
|
# (D) options to `make` tool
|
|
if not MakeOptions == "":
|
|
parameters += " \\\n -option %s" % MakeOptions
|
|
|
|
# (E) about Ruby
|
|
if ModuleRuby == "nil":
|
|
parameters += " \\\n -noruby"
|
|
else:
|
|
parameters += " \\\n -ruby %s" % RubyDictionary[ModuleRuby]['exe']
|
|
parameters += " \\\n -rbinc %s" % RubyDictionary[ModuleRuby]['inc']
|
|
parameters += " \\\n -rblib %s" % RubyDictionary[ModuleRuby]['lib']
|
|
|
|
# (F) about Python
|
|
if ModulePython == "nil":
|
|
parameters += " \\\n -nopython"
|
|
else:
|
|
parameters += " \\\n -python %s" % PythonDictionary[ModulePython]['exe']
|
|
parameters += " \\\n -pyinc %s" % PythonDictionary[ModulePython]['inc']
|
|
parameters += " \\\n -pylib %s" % PythonDictionary[ModulePython]['lib']
|
|
|
|
#-----------------------------------------------------
|
|
# [2] Make the consolidated command line
|
|
#-----------------------------------------------------
|
|
command = "time"
|
|
command += " \\\n %s" % BuildBash
|
|
command += parameters
|
|
command += " 2>&1 | tee %s" % MacBuildLog
|
|
if CheckComOnly:
|
|
print(command)
|
|
quit()
|
|
|
|
#-----------------------------------------------------
|
|
# [3] Invoke the main Bash script; takes time:-)
|
|
#-----------------------------------------------------
|
|
if DeploymentF:
|
|
return 0
|
|
elif DeploymentP:
|
|
return 0
|
|
else:
|
|
myscript = "build4mac.py"
|
|
if subprocess.call( command, shell=True ) != 0:
|
|
print( "", file=sys.stderr )
|
|
print( "-------------------------------------------------------------", file=sys.stderr )
|
|
print( "!!! <%s>: failed to build KLayout" % myscript, file=sys.stderr )
|
|
print( "-------------------------------------------------------------", file=sys.stderr )
|
|
print( "", file=sys.stderr )
|
|
return 1
|
|
else:
|
|
print( "", file=sys.stderr )
|
|
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
|
|
print( "### <%s>: successfully built KLayout" % myscript, file=sys.stderr )
|
|
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
|
|
print( "", file=sys.stderr )
|
|
return 0
|
|
|
|
#------------------------------------------------------------------------------
|
|
## For making a bundle (klayout.app), deploy built binaries and libraries
|
|
# on which those binaries depend.
|
|
#
|
|
# Reference: "Deploying an Application on Mac OS X" of Qt Assistant.
|
|
#
|
|
# @return 0 on success; non-zero on failure
|
|
#------------------------------------------------------------------------------
|
|
def DeployBinariesForBundle():
|
|
global ProjectDir
|
|
global ModuleQt
|
|
global NonOSStdLang
|
|
global DeploymentF
|
|
global DeploymentP
|
|
global MacPkgDir
|
|
global MacBinDir
|
|
global MacBuildDir
|
|
global MacBuildLog
|
|
global AbsMacPkgDir
|
|
global AbsMacBinDir
|
|
global AbsMacBuildDir
|
|
global AbsMacBuildLog
|
|
global Version
|
|
global DeployVerbose
|
|
|
|
print("")
|
|
print( "##### Started deploying libraries and executables for <klayout.app> #####" )
|
|
print( " [1] Checking the status of working directory ..." )
|
|
#-------------------------------------------------------------
|
|
# [1] Check the status of working directory
|
|
#-------------------------------------------------------------
|
|
os.chdir(ProjectDir)
|
|
if not DeploymentF and not DeploymentP:
|
|
return 1
|
|
if DeploymentF and NonOSStdLang:
|
|
print( "WARNING!!! You chose <-y|--deploy> while using non-OS-standard script language.", file=sys.stderr )
|
|
print( " Use <-Y|--DEPLOY> instead", file=sys.stderr )
|
|
#return 1
|
|
if not os.path.isfile(MacBuildLog):
|
|
print( "!!! Build log file <%s> does not present !!!" % MacBuildLog, file=sys.stderr )
|
|
return 1
|
|
if not os.path.isdir(MacBuildDir):
|
|
print( "!!! Build directory <%s> does not present !!!" % MacBuildDir, file=sys.stderr )
|
|
return 1
|
|
if not os.path.isdir(MacBinDir):
|
|
print( "!!! Binary directory <%s> does not present !!!" % MacBinDir, file=sys.stderr )
|
|
return 1
|
|
|
|
|
|
print( " [2] Creating a new empty directory <%s> for deployment ..." % MacPkgDir )
|
|
#-------------------------------------------------------------
|
|
# [2] Create a new empty directory for deploying binaries
|
|
#-------------------------------------------------------------
|
|
os.chdir(ProjectDir)
|
|
if os.path.isfile(MacPkgDir):
|
|
os.remove(MacPkgDir)
|
|
if os.path.isdir(MacPkgDir):
|
|
shutil.rmtree(MacPkgDir)
|
|
os.mkdir(MacPkgDir)
|
|
|
|
|
|
print( " [3] Creating the standard directory structure for 'klayout.app' bundle ..." )
|
|
#-----------------------------------------------------------------
|
|
# [3] Create the directory skeleton for "klayout.app" bundle
|
|
# and command line buddy tools such as "strm2cif".
|
|
# They are stored in the directory structure below.
|
|
#
|
|
# klayout.app/+
|
|
# +-- Contents/+
|
|
# +-- Info.plist
|
|
# +-- PkgInfo
|
|
# +-- Resources/+
|
|
# | +-- 'klayout.icns'
|
|
# +-- Frameworks/+
|
|
# | +-- '*.framework'
|
|
# | +-- '*.dylib'
|
|
# +-- MacOS/+
|
|
# | +-- 'klayout'
|
|
# +-- Buddy/+
|
|
# +-- 'strm2cif'
|
|
# +-- 'strm2dxf'
|
|
# :
|
|
# +-- 'strmxor'
|
|
#-----------------------------------------------------------------
|
|
targetDir0 = "%s/klayout.app/Contents" % AbsMacPkgDir
|
|
targetDirR = targetDir0 + "/Resources"
|
|
targetDirF = targetDir0 + "/Frameworks"
|
|
targetDirM = targetDir0 + "/MacOS"
|
|
targetDirB = targetDir0 + "/Buddy"
|
|
os.makedirs(targetDirR)
|
|
os.makedirs(targetDirF)
|
|
os.makedirs(targetDirM)
|
|
os.makedirs(targetDirB)
|
|
|
|
|
|
print( " [4] Copying KLayout's dynamic link libraries to 'Frameworks' ..." )
|
|
#-------------------------------------------------------------------------------
|
|
# [4] Copy KLayout's dynamic link libraries to "Frameworks/" and create
|
|
# the library dependency dictionary.
|
|
# <<< Do this job in "Frameworks/" >>>
|
|
#
|
|
# Note:
|
|
# KLayout's dynamic link library is built as below:
|
|
# (1) libklayout_lay.0.25.0.dylib
|
|
# (2) libklayout_lay.0.25.dylib -> libklayout_lay.0.25.0.dylib
|
|
# (3) libklayout_lay.0.dylib -> libklayout_lay.0.25.0.dylib
|
|
# (4) libklayout_lay.dylib -> libklayout_lay.0.25.0.dylib
|
|
# where,
|
|
# (1) is an ordinary file with full version number 'major.minor.teeny'
|
|
# between "library_name."='libklayout_lay.' and '.dylib'
|
|
# (2) is a symbolic link with 'major.minor' version number
|
|
# (3) is a symbolic link with 'major' version number
|
|
# (4) is a symbolic link without version number number
|
|
#
|
|
# The dynamic linker tries to find a library name in style (3) as shown
|
|
# in the example below.
|
|
#
|
|
# Example:
|
|
# MacBookPro(1)$ otool -L klayout
|
|
# klayout:
|
|
# :
|
|
# :
|
|
# libklayout_tl.0.dylib (compatibility version 0.25.0, current version 0.25.0)
|
|
# libklayout_gsi.0.dylib (compatibility version 0.25.0, current version 0.25.0)
|
|
# libklayout_db.0.dylib (compatibility version 0.25.0, current version 0.25.0)
|
|
# :
|
|
#-------------------------------------------------------------------------------
|
|
os.chdir( targetDirF )
|
|
dynamicLinkLibs = glob.glob( AbsMacBinDir + "/*.dylib" )
|
|
depDicOrdinary = {} # inter-library dependency dictionary
|
|
for item in dynamicLinkLibs:
|
|
if os.path.isfile(item) and not os.path.islink(item):
|
|
#-------------------------------------------------------------------
|
|
# (A) Copy an ordinary *.dylib file here by changing the name
|
|
# to style (3) and set its mode to 0755 (sanity check).
|
|
#-------------------------------------------------------------------
|
|
fullName = os.path.basename(item).split('.')
|
|
# e.g. [ 'libklayout_lay', '0', '25', '0', 'dylib' ]
|
|
nameStyle3 = fullName[0] + "." + fullName[1] + ".dylib"
|
|
shutil.copy2( item, nameStyle3 )
|
|
os.chmod( nameStyle3, 0o0755 )
|
|
#-------------------------------------------------------------------
|
|
# (B) Then get inter-library dependencies
|
|
#-------------------------------------------------------------------
|
|
otoolCm = "otool -L %s | grep libklayout" % nameStyle3
|
|
otoolOut = os.popen( otoolCm ).read()
|
|
dependDic = DecomposeLibraryDependency(otoolOut)
|
|
depDicOrdinary.update(dependDic)
|
|
'''
|
|
PrintLibraryDependencyDictionary( depDicOrdinary, "Style (3)" )
|
|
quit()
|
|
'''
|
|
|
|
print( " [5] Setting and changing the identification names among KLayout's libraries ..." )
|
|
#-------------------------------------------------------------
|
|
# [5] Set the identification names for KLayout's libraries
|
|
# and make the library aware of the locations of libraries
|
|
# on which it depends; that is, inter-library dependency
|
|
#-------------------------------------------------------------
|
|
ret = SetChangeIdentificationNameOfDyLib( depDicOrdinary )
|
|
if not ret == 0:
|
|
msg = "!!! Failed to set and change to new identification names !!!"
|
|
print(msg)
|
|
return 1
|
|
|
|
|
|
print( " [6] Copying built executables and resource files ..." )
|
|
#-------------------------------------------------------------
|
|
# [6] Copy some known files in source directories to
|
|
# relevant target directories
|
|
#-------------------------------------------------------------
|
|
os.chdir(ProjectDir)
|
|
sourceDir0 = "%s/klayout.app/Contents" % MacBinDir
|
|
sourceDir1 = sourceDir0 + "/MacOS"
|
|
sourceDir2 = "%s/macbuild/Resources" % ProjectDir
|
|
sourceDir3 = "%s" % MacBinDir
|
|
|
|
tmpfileM = ProjectDir + "/macbuild/Resources/Info.plist.template"
|
|
keydicM = { 'exe': 'klayout', 'icon': 'klayout.icns', 'bname': 'klayout', 'ver': Version }
|
|
plistM = GenerateInfoPlist( keydicM, tmpfileM )
|
|
file = open( targetDir0 + "/Info.plist", "w" )
|
|
file.write(plistM)
|
|
file.close()
|
|
|
|
shutil.copy2( sourceDir0 + "/PkgInfo", targetDir0 ) # this file is not mandatory
|
|
shutil.copy2( sourceDir1 + "/klayout", targetDirM )
|
|
shutil.copy2( sourceDir2 + "/klayout.icns", targetDirR )
|
|
shutil.copy2( sourceDir2 + "/qt.conf", targetDirM )
|
|
|
|
|
|
os.chmod( targetDir0 + "/PkgInfo", 0o0644 )
|
|
os.chmod( targetDir0 + "/Info.plist", 0o0644 )
|
|
os.chmod( targetDirM + "/klayout", 0o0755 )
|
|
os.chmod( targetDirM + "/qt.conf", 0o0644 )
|
|
os.chmod( targetDirR + "/klayout.icns", 0o0644 )
|
|
|
|
buddies = glob.glob( sourceDir3 + "/strm*" )
|
|
for item in buddies:
|
|
shutil.copy2( item, targetDirB )
|
|
buddy = os.path.basename(item)
|
|
os.chmod( targetDirB + "/" + buddy, 0o0755 )
|
|
|
|
|
|
print( " [7] Setting and changing the identification names of KLayout's libraries in each executable ..." )
|
|
#-------------------------------------------------------------
|
|
# [7] Set and change the library identification name(s) of
|
|
# different executables
|
|
#-------------------------------------------------------------
|
|
os.chdir(ProjectDir)
|
|
os.chdir(MacPkgDir)
|
|
klayoutexec = "klayout.app/Contents/MacOS/klayout"
|
|
ret = SetChangeLibIdentificationName( klayoutexec, "../Frameworks" )
|
|
if not ret == 0:
|
|
os.chdir(ProjectDir)
|
|
msg = "!!! Failed to set/change library identification name for <%s> !!!"
|
|
print( msg % klayoutexec, file=sys.stderr )
|
|
return 1
|
|
|
|
buddies = glob.glob( "klayout.app/Contents/Buddy/strm*" )
|
|
macdepQtOpt = ""
|
|
for buddy in buddies:
|
|
macdepQtOpt += "-executable=%s " % buddy
|
|
ret = SetChangeLibIdentificationName( buddy, "../Frameworks" )
|
|
if not ret == 0:
|
|
os.chdir(ProjectDir)
|
|
msg = "!!! Failed to set/change library identification name for <%s> !!!"
|
|
print( msg % buddy, file=sys.stderr )
|
|
return 1
|
|
|
|
if DeploymentF:
|
|
print( " [8] Finally, deploying Qt's Frameworks ..." )
|
|
#-------------------------------------------------------------
|
|
# [8] Deploy Qt Frameworks
|
|
#-------------------------------------------------------------
|
|
verbose = " -verbose=%d" % DeployVerbose
|
|
if ModuleQt == 'Qt4MacPorts':
|
|
deploytool = Qt4MacPorts['deploy']
|
|
app_bundle = "klayout.app"
|
|
options = macdepQtOpt + verbose
|
|
elif ModuleQt == 'Qt5MacPorts':
|
|
deploytool = Qt5MacPorts['deploy']
|
|
app_bundle = "klayout.app"
|
|
options = macdepQtOpt + verbose
|
|
elif ModuleQt == 'Qt5Custom':
|
|
deploytool = Qt5Custom['deploy']
|
|
app_bundle = "klayout.app"
|
|
options = macdepQtOpt + verbose
|
|
|
|
os.chdir(ProjectDir)
|
|
os.chdir(MacPkgDir)
|
|
command = "%s %s %s" % ( deploytool, app_bundle, options )
|
|
print(command)
|
|
if subprocess.call( command, shell=True ) != 0:
|
|
msg = "!!! Failed to deploy applications on OSX !!!"
|
|
print( msg, file=sys.stderr )
|
|
print("")
|
|
os.chdir(ProjectDir)
|
|
return 1
|
|
else:
|
|
print( "##### Finished deploying libraries and executables for <klayout.app> #####" )
|
|
print("")
|
|
os.chdir(ProjectDir)
|
|
return 0
|
|
else:
|
|
print( " [8] Skipped deploying Qt's Frameworks ..." )
|
|
print( "##### Finished deploying libraries and executables for <klayout.app> #####" )
|
|
print("")
|
|
os.chdir(ProjectDir)
|
|
return 0
|
|
|
|
#------------------------------------------------------------------------------
|
|
## To deploy script bundles that invoke the main bundle (klayout.app) in
|
|
# editor mode or viewer mode
|
|
#
|
|
# @return 0 on success; non-zero on failure
|
|
#------------------------------------------------------------------------------
|
|
def DeployScriptBundles():
|
|
global ProjectDir
|
|
global MacPkgDir
|
|
global AbsMacPkgDir
|
|
|
|
print("")
|
|
print( "##### Started deploying files for <KLayoutEditor.app> and <KLayoutViewer.app> #####" )
|
|
print( " [1] Checking the status of working directory ..." )
|
|
#-------------------------------------------------------------
|
|
# [1] Check the status of working directory
|
|
#-------------------------------------------------------------
|
|
os.chdir(ProjectDir)
|
|
if not os.path.isdir(MacPkgDir):
|
|
print( "!!! Package directory <%s> does not present !!!" % MacPkgDir, file=sys.stderr )
|
|
return 1
|
|
|
|
|
|
print( " [2] Creating a new empty directory <%s> for deployment ..." % (MacPkgDir + "/klayout.scripts") )
|
|
#-------------------------------------------------------------
|
|
# [2] Create a new empty directory for deploying binaries
|
|
#-------------------------------------------------------------
|
|
os.chdir(MacPkgDir)
|
|
scriptDir = "klayout.scripts"
|
|
if os.path.isfile(scriptDir):
|
|
os.remove(scriptDir)
|
|
if os.path.isdir(scriptDir):
|
|
shutil.rmtree(scriptDir)
|
|
os.mkdir(scriptDir)
|
|
|
|
|
|
print( " [3] Creating the standard directory structure for the script bundles ..." )
|
|
#--------------------------------------------------------------------------------------------
|
|
# [3] Create the directory skeleton for the two script bundles.
|
|
#
|
|
# klayout.scripts/+
|
|
# +-- KLayoutEditor.app/+
|
|
# | +-- Contents/+
|
|
# | +-- Info.plist
|
|
# | +-- Resources/+
|
|
# | | +-- 'klayout-red.icns'
|
|
# | +-- MacOS/+
|
|
# | +-- 'KLayoutEditor.sh'
|
|
# +-- KLayoutViewer.app/+
|
|
# +-- Contents/+
|
|
# +-- Info.plist
|
|
# +-- Resources/+
|
|
# | +-- 'klayout-blue.icns'
|
|
# +-- MacOS/+
|
|
# +-- 'KLayoutViewer.sh'
|
|
#--------------------------------------------------------------------------------------------
|
|
os.chdir(ProjectDir)
|
|
targetDir0E = "%s/%s/KLayoutEditor.app/Contents" % ( AbsMacPkgDir, scriptDir )
|
|
targetDir0V = "%s/%s/KLayoutViewer.app/Contents" % ( AbsMacPkgDir, scriptDir )
|
|
|
|
targetDirME = targetDir0E + "/MacOS"
|
|
targetDirMV = targetDir0V + "/MacOS"
|
|
targetDirRE = targetDir0E + "/Resources"
|
|
targetDirRV = targetDir0V + "/Resources"
|
|
|
|
os.makedirs(targetDirME)
|
|
os.makedirs(targetDirMV)
|
|
os.makedirs(targetDirRE)
|
|
os.makedirs(targetDirRV)
|
|
|
|
|
|
print( " [4] Copying script files and icon files ..." )
|
|
#-------------------------------------------------------------------------------
|
|
# [4] Copy different script files icon files
|
|
#-------------------------------------------------------------------------------
|
|
os.chdir(ProjectDir)
|
|
resourceDir = "macbuild/Resources"
|
|
|
|
shutil.copy2( resourceDir + "/KLayoutEditor.sh", targetDirME )
|
|
shutil.copy2( resourceDir + "/KLayoutViewer.sh", targetDirMV )
|
|
shutil.copy2( resourceDir + "/klayout-red.icns", targetDirRE )
|
|
shutil.copy2( resourceDir + "/klayout-blue.icns", targetDirRV )
|
|
|
|
os.chmod( targetDirME + "/KLayoutEditor.sh", 0o0755 )
|
|
os.chmod( targetDirMV + "/KLayoutViewer.sh", 0o0755 )
|
|
os.chmod( targetDirRE + "/klayout-red.icns", 0o0644 )
|
|
os.chmod( targetDirRV + "/klayout-blue.icns", 0o0644 )
|
|
|
|
tmpfileE = ProjectDir + "/macbuild/Resources/Info.plist.template"
|
|
keydicE = { 'exe': 'KLayoutEditor.sh', 'icon': 'klayout-red.icns', 'bname': 'klayout', 'ver': Version }
|
|
plistE = GenerateInfoPlist( keydicE, tmpfileE )
|
|
fileE = open( targetDir0E + "/Info.plist", "w" )
|
|
fileE.write(plistE)
|
|
fileE.close()
|
|
|
|
tmpfileV = ProjectDir + "/macbuild/Resources/Info.plist.template"
|
|
keydicV = { 'exe': 'KLayoutViewer.sh', 'icon': 'klayout-blue.icns', 'bname': 'klayout', 'ver': Version }
|
|
plistV = GenerateInfoPlist( keydicV, tmpfileV )
|
|
fileV = open( targetDir0V + "/Info.plist", "w" )
|
|
fileV.write(plistV)
|
|
fileV.close()
|
|
print( "##### Finished deploying files for <KLayoutEditor.app> and <KLayoutViewer.app> #####" )
|
|
print("")
|
|
os.chdir(ProjectDir)
|
|
return 0
|
|
|
|
#------------------------------------------------------------------------------
|
|
## The main function
|
|
#------------------------------------------------------------------------------
|
|
def main():
|
|
SetGlobals()
|
|
ParseCommandLineArguments()
|
|
#----------------------------------------------------------
|
|
# [The main build stage]
|
|
#----------------------------------------------------------
|
|
ret = RunMainBuildBash()
|
|
if not DeploymentF and not DeploymentP:
|
|
if ret == 0:
|
|
sys.exit(0)
|
|
else:
|
|
sys.exit(1)
|
|
else:
|
|
#----------------------------------------------------------
|
|
# [Deployment stage-1]
|
|
# Deployment of dynamic link libraries, executables and
|
|
# resources to make the main "klayout.app" bundle
|
|
#----------------------------------------------------------
|
|
ret1 = DeployBinariesForBundle()
|
|
if not ret1 == 0:
|
|
sys.exit(1)
|
|
#----------------------------------------------------------
|
|
# [Deployment stage-2]
|
|
# Deployment of wrapper Bash scripts and resources
|
|
# to make "KLayoutEditor.app" and "KLayoutViewer.app"
|
|
#----------------------------------------------------------
|
|
ret2 = DeployScriptBundles()
|
|
if ret2 == 0:
|
|
sys.exit(1)
|
|
else:
|
|
sys.exit(0)
|
|
|
|
#===================================================================================
|
|
if __name__ == "__main__":
|
|
main()
|
|
|
|
#---------------
|
|
# End of file
|
|
#---------------
|