# -*- mode: python -*- # # Copyright (C) 2006, 2007, 2008 Imendio AB # Copyright 2009, 2010, 2011 John Ralls, Fremont, CA # # Default setup for building GTK+ on Mac OS X. Note that you should # normally never need to edit this file. Any custom settings should be # done in ~/.jhbuildrc-custom. # # Specific builds can be set up by creating files named # ~/.jhbuildrc-. When setting the environment variable JHB to # such a name, the corresponding rc file will be read (e.g.: # JHB=mybuild jhbuild shell). # # Use .jhbuildrc-custom to override the moduleset, modules to build, # the source checkout location, installation prefix, or svn usernames # etc. # # Please email richard@imendio.com if you have suggestions for # improving this setup, or have any patches that you would like to get # included. import sys import errno import re #some variables we'll need defined later _default_arch = "" _osx_version = 0.0 _target = '10.11' def _popen(cmd_arg): from subprocess import Popen, PIPE devnull = open('/dev/null') cmd = Popen(cmd_arg, stdout=PIPE, stderr=devnull, shell=True) retval = cmd.stdout.read().strip() err = cmd.wait() cmd.stdout.close() devnull.close() if err: raise RuntimeError("Failed to close %s stream" % cmd_arg) return retval.decode('utf-8') # Register an extra command to get the checkout dir for a module. # import jhbuild class _cmd_get_srcdir(jhbuild.commands.Command): doc = 'Display information about one or more modules' from jhbuild.errors import FatalError name = 'gtk-osx-get-srcdir' usage_args = 'module' def run(self, config, options, args, help=None): module_set = jhbuild.moduleset.load(config) if args: modname = args[0] try: module = module_set.get_module(modname, ignore_case = True) except KeyError: raise RuntimeError(_('unknown module %s') % modname) print(module.get_srcdir(None)) else: raise FatalError('no module specified') jhbuild.commands.register_command(_cmd_get_srcdir) class _cmd_bootstrap_gtk_osx(jhbuild.commands.base.cmd_build): doc = 'Build buildsystem tools not provided by MacOS.' name = 'bootstrap-gtk-osx' def run(self, config, options, args, help=None): global use_local_modulesets moduleset="bootstrap" modulesets_dir = os.path.dirname(config.moduleset) if (use_local_modulesets and os.path.exists(os.path.join(modulesets_dir, moduleset + '.modules'))): config.modulesets_dir = modulesets_dir config.moduleset = moduleset elif (use_local_modulesets and config.modulesets_dir and os.path.exists(os.path.join(config.modulesets_dir, moduleset + '.modules'))): config.moduleset = moduleset else: config.moduleset = 'https://raw.githubusercontent.com/dehesselle/jhb/master/etc/modulesets/jhb/bootstrap.modules' args = ['meta-bootstrap'] for item in options.skip: config.skip += item.split(',') options.skip = [] rc = jhbuild.commands.base.cmd_build.run(self, config, options, args) return rc jhbuild.commands.register_command(_cmd_bootstrap_gtk_osx) class _getenv(jhbuild.commands.Command): doc = "Retrieve an environment variable set within jhbuild" name = "gtk-osx-getenv" usage_args = 'envvar' def run(self, config, options, args): # module_set = jhbuild.moduleset.load(config) if not args: raise FatalError("No environment variable") var = args[0] if var not in os.environ: raise FatalError("variable " + var + " not defined in jhbuild environment") print(os.environ[var]) jhbuild.commands.register_command(_getenv) # Determine the native system: def osx_ver(): global _default_arch, _osx_version, _target vstring = _popen("uname -r") mstring = _popen("machine") exp = re.compile(r'(\d+\.\d+)\.\d+') vernum = exp.match(vstring) _osx_version = float(vernum.group(1)) - 4.0 if _osx_version < 16: _target = '10.%d' % int(_osx_version) else: _target = '%d' % (_osx_version - 5) _default_arch = _popen("uname -m") # Determine the XCode Version: def xcode_ver(): global conditions devdir = _popen("xcode-select -p") if devdir != "/Library/Developer/CommandLineTools": ver = _popen("xcodebuild -version") exp = re.compile(r'Xcode (\d+\.\d+)') vernum = exp.match(ver) if vernum: _xcode_ver = float(vernum.group(1)) if _xcode_ver < 5.0: raise EnvironmentError("Xcode Version %f is not supported; if you want to build with Xcode versions earlier than 5.0 checkout tag Last-Lion." % _xcode_ver) if _xcode_ver < 10.0: conditions.add('pre-Mavericks') return _xcode_ver else: raise EnvironmentError("No suitable Xcode found. Xcode 5.0 or later is required.") else: #Command-Line Tools instead of Xcode ver_str = _popen("pkgutil --pkg-info=com.apple.pkg.CLTools_Executables | grep version*") print("Found Command Line Tools '%s'" % ver_str) exp = re.compile(r'version: (\d+\.\d+)') vernum = exp.match(ver_str) if vernum: print("Command Line Tools version %f" % float(vernum.group(1))) return float(vernum.group(1)) else: return 8.0 # Some utitily functions used here and in custom files: # def environ_append(key, value, separator=' '): old_value = os.environ.get(key) if old_value is not None: value = old_value + separator + value os.environ[key] = value def environ_prepend(key, value, separator=' '): old_value = os.environ.get(key) if old_value is not None: value = value + separator + old_value os.environ[key] = value def environ_remove(key, value, separator=':'): old_value = os.environ.get(key) if old_value is not None: old_value_split = old_value.split(separator) value_split = [x for x in old_value_split if x != value] value = separator.join(value_split) os.environ[key] = value def parse_custom_argument(key): for i, arg in enumerate(sys.argv[:-1]): if arg == key: return sys.argv[i+1] return None def append_autogenargs(module, args): old_value = module_autogenargs.get(module, autogenargs) module_autogenargs[module] = old_value + " " + args def remove_autogenargs(module, args): arg_string = module_autogenargs.get(module, autogenargs) module_autogenargs[module] = arg_string.replace(args, "") # Call either setup_debug or setup_release in your .jhbuildrc-custom # or other customization file to get the compilation flags. def setup_debug(): global autogenargs # The enable-debug option generally turns on ASSERTS, which can slow # down code and in the case of WebKit, breaks it on OSX because of # threading problems. It's better to set it for individual packages # with append_autogenargs(). # autogenargs = autogenargs + " --enable-debug=yes" # Gtk+ crashes in gdk_window_quartz_raise() -- in a call to [NSWindow # orderFront:] if gcc is passed -O0 for 64-bit compilation. The old # stabs+ debug format also doesn't work. See Snow Leopard in the Wiki # for more information about debugging. environ_prepend('CFLAGS', "-O0 -g") environ_prepend('CXXFLAGS', "-O0 -g") environ_prepend('OBJCFLAGS', "-O0 -g") def setup_release(): environ_prepend('CFLAGS', "-O2") environ_prepend('CXXFLAGS', "-O2") environ_prepend('OBJCFLAGS', "-O2") # Set up the environment for building against particular SDK. # #We call osx_ver() here so that we can set up _default_arch for setup_sdk osx_ver() # # This is the workhorse of the setup. Call this function from # .jhbuildrc-custom to configure compile and link flags. Optionally # specify a minimum MacOS version (10.11, 10.12, 10.13, etc.) and a list # of architectures. # # The sdk_version does nothing, as since Xcode 5 it is preferred to # build with the SDK that goes with the selected Xcode or command-line # tools, which we retrieve via xcrun. sdk_version remains in the # setup_sdk signature to prevent breaking existing jhbuildrc-customs. # # For most users accepting the defaults is the right course. def setup_sdk(target=_target, sdk_version=None, architectures=[_default_arch]): global use_local_modulesets, conditions os.environ["MACOSX_DEPLOYMENT_TARGET"] = target sdkdir = None xcodepath = None xcodeversion = xcode_ver() sdkdir = _popen("xcrun --show-sdk-path") if sdkdir: environ_prepend("LDFLAGS", "-L" + sdkdir + "/usr/lib") environ_prepend("CFLAGS", "-I" + sdkdir + "/usr/include") environ_prepend("CXXFLAGS", "-I" + sdkdir + "/usr/include") environ_prepend("OBJCFLAGS", "-I" + sdkdir + "/usr/include") environ_prepend("CPPFLAGS", "-I" + sdkdir + "/usr/include") environ_prepend("CMAKE_PREFIX_PATH", os.path.join(sdkdir, 'usr'), ':') environ_prepend("LIBRARY_PATH", sdkdir + "/usr/lib", ':') # It's often necessary to look for things in the SDK when # developing, and it takes a lot of typing, so define a # convenience environment variable: environ_append('SDKDIR', sdkdir) os.environ["SDKROOT"] = sdkdir # Apple Documentation says that "-syslibroot" is the arg to pass to the # linker, but we are using the compiler to control the linker, and # everything seems to be working correctly. environ_append("CFLAGS", "-isysroot " + sdkdir) environ_append("CPPFLAGS", "-isysroot " + sdkdir) environ_append("CXXFLAGS", "-isysroot " + sdkdir) environ_append("OBJCFLAGS", "-isysroot " + sdkdir) environ_append("LDFLAGS", "-isysroot " + sdkdir) # To pick up cups-config from the right place. os.environ["CUPS_CONFIG"] = os.path.join(sdkdir, "usr/bin/cups-config") if architectures == ["i386"]: # The '#' on openssl is to stop jhbuild from appending any more autogen # arguments such as --disable-Werror; they cause openssl to error out append_autogenargs("openssl", "darwin-i386-cc #") elif architectures == ["x86_64"]: conditions.add('64-bit') append_autogenargs("glib", "ac_cv_c_bigendian=no") append_autogenargs("openssl", "darwin64-x86_64-cc #") elif architectures == ["arm64"]: conditions.add('64-bit') conditions.add('arm64') append_autogenargs("glib", "ac_cv_c_bigendian=no") append_autogenargs("openssl", "darwin64-arm64-cc #") # Not a legal value elif len(set(architectures) - {"i386", "x86_64", 'arm64'}) > 0: raise EnvironmentError("Only architectures i386, x86_64, and arm64 are supported.") if len(set(architectures)) > 1: print("WARNING: Universal builds are neither prohibited nor supported. It might work, but if it doesn't you're on your own.") # For unknown reasons, iconv is not picked up correctly without this # gcc = _popen("xcrun -f gcc") gpp = _popen("xcrun -f g++") ld = _popen("xcrun -f ld") os.environ["CC"] = gcc os.environ["OBJC"] = gcc os.environ["CXX"] = gpp os.environ['LD'] = ld # Set the -arch flags for everything we're building. # for arch in architectures: environ_prepend("CFLAGS", "-arch " + arch) environ_prepend("CXXFLAGS", "-arch " + arch) environ_prepend("CPPFLAGS", "-arch " + arch) environ_prepend("OBJCFLAGS", "-arch " + arch) environ_prepend("LDFLAGS", "-arch " + arch) # For intel, set glib's build parameter so that it builds the # correct atomic asm functions # if architectures == ["i386"]: append_autogenargs("glib", "--build=i486-apple-darwin") append_autogenargs("gmp", "ABI=32") append_autogenargs("liboil", "--host=i486-apple-darwin") append_autogenargs("gnutls", "--host=i486-apple-darwin") elif architectures == ["x86_64"]: append_autogenargs("glib", "--build=x86_64-apple-darwin") append_autogenargs("gmp", "--host=x86_64-apple-darwin ABI=64") append_autogenargs("liboil", "--host=x86_64-apple-darwin") append_autogenargs("gnutls", "--host=x86_64-apple-darwin") elif architectures == ["arm64"]: append_autogenargs("glib", "--build=aarch64-apple-darwin") append_autogenargs("gmp", "--host=aarch64-apple-darwin ABI=64") append_autogenargs("liboil", "--host=aarch64-apple-darwin") append_autogenargs("libffi", "--host=aarch64-apple-darwin") # El Capitan needs bash to work around SIP. If you're using a # common bootstrap directory (e.g. $HOME/.local) then override # CONFIG_SHELL in .jhbuildrc-custom after calling setup_sdk(). config_shell = os.path.join(prefix, 'bin', 'bash') if _osx_version < 11.0: skip.append('bash') elif os.path.exists(config_shell): os.environ['CONFIG_SHELL'] = config_shell if not sdkdir: sdkdir = '/' if os.path.exists(os.path.join(sdkdir, "usr", "include", "openssl")): skip.append('openssl') # openssl removed in El Capitan # gettext-fw rebuilds gettext with an in-tree libiconv to get # around the Apple-provided one not defining _libiconv_init for # x86_64 append_autogenargs("gettext-fw", "--with-libiconv-prefix=" + prefix) environ_append("CFLAGS", "-mmacosx-version-min=" + target) environ_append("CXXFLAGS", "-mmacosx-version-min=" + target) environ_append("OBJCFLAGS", "-mmacosx-version-min=" + target) environ_append("LDFLAGS", "-mmacosx-version-min=" + target) #Overcome Python's obnoxious misconfiguration of portable builds if len(architectures) == 1: os.environ["BUILDCFLAGS"] = os.environ["CFLAGS"] append_autogenargs("gnutls", "--disable-guile") append_autogenargs("guile", 'CFLAGS="$CFLAGS -O1"') #Some packages require special arguments or flags to compile with Clang: module_extra_env["pkg-config"] = {'CFLAGS': os.environ['CFLAGS'] + ' -std=gnu89'} append_autogenargs('libgcrypt', 'CFLAGS="$CFLAGS -fheinous-gnu-extensions"') module_makeargs['liboil'] = 'CFLAGS="$CFLAGS -DHAVE_SYMBOL_UNDERSCORE -fheinous-gnu-extensions"' # openssl doesn't understand DESTDIR, but luckily it has its own mechanism. module_extra_env['openssl'] = {'INSTALL_PREFIX': os.path.join(prefix, '_jhbuild', 'root-openssl')} # GMP deliberately attempts to use CC_FOR_BUILD with no separate # cflags so we need to force it: module_extra_env['gmp'] = {'CC_FOR_BUILD':os.environ['CC'] + ' ' + os.environ['CFLAGS']} # Kill a couple of noisy warnings for webkit1: module_extra_env["webkit"] = {'CPPFLAGS':os.environ['CPPFLAGS'] + " -Wno-unused-local-typedef -Wno-missing-field-initializsers"} module_extra_env["webkit1gtk3"] = {'CPPFLAGS':os.environ['CPPFLAGS'] + " -Wno-unused-local-typedef -Wno-missing-field-initializsers -Wno-undefined-bool-conversion"} module_extra_env["webkit"] = {'CXXFLAGS':os.environ['CXXFLAGS'] + ' -Wno-inconsistent-missing-override'} module_extra_env["webkit1gtk3"] = {'CXXFLAGS':os.environ['CXXFLAGS'] + ' -Wno-inconsistent-missing-override'} # Finally when building normally we need to force CFLAGS_FOR_BUILD # to our current CFLAGS so that everything will link with other # build products. Note that this will generally break # cross-compilation, not that it works anyway. os.environ['CFLAGS_FOR_BUILD'] = os.environ['CFLAGS'] # Make sure we don't link against XQuartz whose freetype-config is on PATH # when XQuartz is installed by removing it from PATH environ_remove('PATH', '/opt/X11/bin') return sdkdir ###### End Function Definitions ####### ##### The following configuration can be overridden in custom files ###### # Moduleset to use. You can override this in .jhbuildrc-custom or on # the command line. # moduleset = "" use_local_modulesets = False modulesets_dir = "" # A list of the modules to build. You can override this in # .jhbuildrc-custom or on the command line. # modules = [ 'meta-gtk-osx-bootstrap', 'meta-gtk-osx-gtk3' ] # A list of modules to skip. # # Source and installation locations. # _root = os.path.expanduser("~/gtk") checkoutroot = os.path.join(_root, "source") prefix = os.path.join(_root, "inst") _exec_prefix = None tarballdir = None # Extra arguments to pass to all autogen.sh scripts. # autogenargs='' # Extra meson args. --wrapmode=nofallback prevents meson projects from # building dependencies on their own. We generally want failed # dependencies to error out so that we know to add them to the # appropriate modules. mesonargs='--wrap-mode=nofallback' # Use the included install-check program if available. It won't update # timestamps if the header hasn't changed, which speeds up builds. # _path = os.path.expanduser('~/.local/bin/install-check') if os.path.exists(_path): os.environ['INSTALL'] = _path _gtk_osx_prompt_prefix = "JH" _gtk_osx_default_build = "" #print "Default Architecture %s\n" % _default_arch if _osx_version < 11.0: print("Error: Mac OS X 10.11 or newer is required, exiting.") raise SystemExit ###### Import Customizations ###### # Import optional user RC for further customization. You can override # the prefix or default build setup for example, or CFLAGS or # module_autogenargs, etc. # _this_dir = os.path.dirname(__file__); _home = os.path.expanduser('~') _user_config_dir = os.environ.get('XDG_CONFIG_HOME', os.path.join(_home, '.config')) _user_rc = '' if ('JHBUILDRC_CUSTOM' in os.environ and os.environ['JHBUILDRC_CUSTOM']): _user_rc = os.environ['JHBUILDRC_CUSTOM'] if not os.path.exists(_user_rc): _user_rc = os.path.join(_this_dir, 'jhbuildrc-custom'); if not os.path.exists(_user_rc): _user_rc = os.path.join(_this_dir, '.jhbuildrc-custom') if not os.path.exists(_user_rc): _user_rc = os.path.join(_user_config_dir, 'jhbuildrc-custom') if not os.path.exists(_user_rc): _user_rc = os.path.join(_user_config_dir, '.jhbuildrc-custom') if not os.path.exists(_user_rc): _user_rc = os.path.join(_home, 'jhbuildrc-custom') if not os.path.exists(_user_rc): _user_rc = os.path.join(_home, '.jhbuildrc-custom') if os.path.exists(_user_rc): exec(compile(open(_user_rc, "rb").read(), _user_rc, 'exec')) # Allow including different variants depending on the environment # variable JHB. This can be used to have different setups for SDK # builds, for example. # _build = os.environ.get('JHB', _gtk_osx_default_build) disable_Werror = False ###### Everything Below Uses (and Overrides) customizations! ####### # jhbuild turns on 'nice' by default ut that messes up some of the # custom autogen-templates Gtk-OSX needs to use:" nice_build = False # Harfbuzz needs to be built twice, once before cairo and again after # gobject-introspection because cairo needs harfbuzz and # gobject-introspection needs cairo. The only way to get jhbuild to # run the configuration for harfbuzz the second time is to set # alwaysautogen to true. alwaysautogen = True # Freetype2 if left to itself will create an install name without the # path so none of the libraries that depend on it can link. Require # the install name to be an absolute path. module_cmakeargs["freetype"] = '-DCMAKE_INSTALL_NAME_DIR="' + os.path.join(prefix, 'lib') + '"' module_cmakeargs["freetype-no-harfbuzz"] = '-DCMAKE_INSTALL_NAME_DIR="' + os.path.join(prefix, 'lib') + '"' module_cmakeargs["webkit2gtk3"] = '-DCMAKE_INSTALL_NAME_DIR="' + os.path.join(prefix, 'lib') + '"' module_cmakeargs["zlib"] = '-DCMAKE_INSTALL_NAME_DIR="' + os.path.join(prefix, 'lib') + '"' # Check and warn if jhbuild is started from within jhbuild, since that # will mess up environment variables, especially if different build # setups are used. # _old_prefix = os.environ.get('JHBUILD_PREFIX', "") _old_build = os.environ.get('JHBUILD_CONFIG', "") _ran_recursively = _old_prefix != "" if _ran_recursively: if _old_build != _build: print("Error: jhbuild is already running with a different build setup, exiting.") raise SystemExit print("Warning: jhbuild is started from within a jhbuild session.") if _build != "": try: exec(compile(open(os.path.join(os.environ['HOME'], '.jhbuildrc-' + _build), "rb").read(), os.path.join(os.environ['HOME'], '.jhbuildrc-' + _build), 'exec')) except EnvironmentError as e: print("Couldn't find the file '.jhbuildrc-" + _build + "', exiting.") raise SystemExit # The following parameters were set to None at the top of the file; # they're set here to their default values after processing the # customizations, but tested to make sure that if they've been # customized, it will stick. # Default location for tarball download is into checkoutroot/pkgs. If # you do multiple builds with different checkoutroots, you'll want to # override this to somewhere common (~/.local/pkgs is one alternative) if tarballdir == None: tarballdir = os.path.join(checkoutroot, 'pkgs') # _exec_prefix is used to set $M4 and $LIBTOOLIZE. We set it here to # prefix if it wasn't over-ridden in .jhbuildrc-custom if _exec_prefix == None: _exec_prefix = prefix os.environ['PREFIX'] = prefix # Deprecated, please move to JHBUILD_PREFIX. os.environ['JHBUILD_PREFIX'] = prefix os.environ['JHBUILD_SOURCE'] = checkoutroot # Some packages go off and find /usr/lib/gm4, which is broken Note the # use of _exec_prefix here. By default it's prefix, but you can # override it to somewhere else in jhbuildrc-custom if you like. #os.environ["M4"] = _exec_prefix + "/bin/m4" #os.environ['LIBTOOLIZE'] = _exec_prefix + '/bin/libtoolize' #Some autogens detect that it's a Mac and use glibtoolize if it's #available. Override this behavior. if not ("LIBTOOLIZE" in os.environ and os.environ["LIBTOOLIZE"]): environ_append('LIBTOOLIZE', os.path.join(prefix, "bin", "libtoolize")) # The option "headerpad_max_install_names" is there to leave some room for # changing the library locations with install_name_tool. Note that GNU # libtool seems to drop the option if we don't use -W here. # environ_append('LDFLAGS', '-Wl,-headerpad_max_install_names') #environ_append('LDFLAGS', '-Wl,-no_weak_imports') # Make sure we find our installed modules, and before other versions. environ_prepend('LDFLAGS', '-L' + prefix + '/lib') environ_prepend('CPPFLAGS', '-I' + prefix + '/include') # Make sure that ltdl can find our libraries addpath("LTDL_LIBRARY_PATH", prefix + "/lib") # Add additional Perl paths so that our modules can be found. prependpath('PERL5LIB', prefix + '/lib/perl5/vendor_perl') prependpath('PERL5LIB', prefix + '/lib/perl5/site_perl') # Point gtk-doc and other xsltproc users to our XML catalog. # _pfx_cat_file = os.path.join(prefix, 'share', 'xml', 'catalog') if not os.path.exists(_pfx_cat_file): os.makedirs(os.path.dirname(_pfx_cat_file)) open(_pfx_cat_file, "w").close() if 'XML_CATALOG_FILES' in os.environ: # os.environ['XML_CATALOG_FILES'] += ':' + _pfx_cat_file pass else: os.environ['XML_CATALOG_FILES'] = _pfx_cat_file #GConf needs to be built static, overriding the generic autogenargs, #but including it in the module puts it in front of where autogenargs #puts --disable-static, so we need the override here. # append_autogenargs("gconf", "--enable-static") if _build: if "shell" in sys.argv: print("Build setup: %s, prefix: %s" % (_build, prefix)) os.environ["JHBUILD_CONFIG"] = _build else: if "shell" in sys.argv: print("Prefix: %s" % (prefix)) if not _ran_recursively and _gtk_osx_prompt_prefix: os.environ["JHBUILD_PROMPT"] = "[" + _gtk_osx_prompt_prefix + "] " os.environ["PYTHON"] = os.path.join(prefix, 'bin', 'python3') module_extra_env['pkg-config'] = {'PYTHON':sys.executable} module_extra_env["spidermonkey"] = {'AUTOCONF':'autoconf'} # Unset this so we don't mess with the check for not starting # recursively. os.unsetenv("JHB") if "shell" in sys.argv: print("Entered jhbuild shell, type 'exit' to return.")