From bedb56c0f31184f99b09b0737b3bc3207e029688 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Wed, 22 May 2024 19:41:49 +0300 Subject: [PATCH] Install waf build system --- cl_dll/wscript | 47 ++ dlls/wscript | 53 ++ mainui/wscript | 44 ++ mod_options.txt | 4 + public/build.h | 253 ++++++++ scripts/waifulib/compiler_optimizations.py | 180 ++++++ scripts/waifulib/library_naming.py | 175 ++++++ scripts/waifulib/strip_on_install.py | 49 ++ scripts/waifulib/xcompile.py | 660 +++++++++++++++++++++ waf | 175 ++++++ wscript | 260 ++++++++ 11 files changed, 1900 insertions(+) create mode 100644 cl_dll/wscript create mode 100644 dlls/wscript create mode 100644 mainui/wscript create mode 100644 mod_options.txt create mode 100644 public/build.h create mode 100644 scripts/waifulib/compiler_optimizations.py create mode 100644 scripts/waifulib/library_naming.py create mode 100644 scripts/waifulib/strip_on_install.py create mode 100644 scripts/waifulib/xcompile.py create mode 100755 waf create mode 100644 wscript diff --git a/cl_dll/wscript b/cl_dll/wscript new file mode 100644 index 0000000..d8afc59 --- /dev/null +++ b/cl_dll/wscript @@ -0,0 +1,47 @@ +#! /usr/bin/env python +# encoding: utf-8 +# a1batross, mittorn, 2018 + +from waflib import Utils +import os + +def options(opt): + pass + +def configure(conf): + if conf.env.DEST_OS != 'win32': + conf.check(lib='dl') + +def build(bld): + libs = ['DL'] + defines = ['CLIENT_DLL'] + includes = ['.', + '../dlls', + '../common', + '../engine', + '../pm_shared', + '../game_shared', + '../public'] + + source = bld.path.ant_glob('**/*.cpp') + source += bld.path.parent.ant_glob('game_shared/*.cpp') + source += bld.path.parent.ant_glob('pm_shared/*.c') + + if bld.env.DEST_OS not in ['android', 'dos']: + install_path = os.path.join(bld.env.GAMEDIR, bld.env.CLIENT_INSTALL_DIR) + else: + install_path = bld.env.PREFIX + + bld.shlib( + source = source, + target = 'client' + bld.env.POSTFIX, + name = 'client', + features = 'c cxx', + includes = includes, + defines = defines, + use = libs, + install_path = install_path, + subsystem = bld.env.MSVC_SUBSYSTEM, + idx = bld.get_taskgen_count() + ) + diff --git a/dlls/wscript b/dlls/wscript new file mode 100644 index 0000000..c070862 --- /dev/null +++ b/dlls/wscript @@ -0,0 +1,53 @@ +#! /usr/bin/env python +# encoding: utf-8 +# a1batross, mittorn, 2018 + +from waflib import Utils +import os + +def options(opt): + return + +def configure(conf): + if conf.env.COMPILER_CC == 'msvc': + # progs.def removes MSVC function name decoration from GiveFnptrsToDll on Windows. + # Without this, the lookup for this function fails. + hlDefNode = conf.path.find_resource("./progs.def") + + if hlDefNode is not None: + conf.env.append_value('LINKFLAGS', '/def:%s' % hlDefNode.abspath()) + else: + conf.fatal("Could not find progs.def") + +def build(bld): + source = bld.path.ant_glob('**/*.cpp') + source += bld.path.parent.ant_glob('pm_shared/*.c') + source += bld.path.parent.ant_glob('game_shared/*.cpp') + + includes = [ + '.', + '../common', + '../engine', + '../pm_shared', + '../game_shared', + '../public' + ] + defines = [] + + if bld.env.DEST_OS not in ['android', 'dos']: + install_path = os.path.join(bld.env.GAMEDIR, bld.env.SERVER_INSTALL_DIR) + else: + install_path = bld.env.PREFIX + + bld.shlib( + source = source, + target = bld.env.SERVER_LIBRARY_NAME + bld.env.POSTFIX, + name = 'server', + features = 'c cxx', + includes = includes, + defines = defines, + install_path = install_path, + subsystem = bld.env.MSVC_SUBSYSTEM, + idx = bld.get_taskgen_count() + ) + diff --git a/mainui/wscript b/mainui/wscript new file mode 100644 index 0000000..3d342e1 --- /dev/null +++ b/mainui/wscript @@ -0,0 +1,44 @@ +#! /usr/bin/env python +# encoding: utf-8 +# a1batross, mittorn, 2018 + +from waflib import Utils +import os + +def options(opt): + return + +def configure(conf): + return + +def build(bld): + source = bld.path.ant_glob('**/*.cpp') + + includes = [ + '.', + '../common', + '../engine', + '../pm_shared', + '../game_shared', + '../public', + '../dlls' + ] + defines = [] + + if bld.env.DEST_OS not in ['android', 'dos']: + install_path = os.path.join(bld.env.GAMEDIR, bld.env.SERVER_INSTALL_DIR) + else: + install_path = bld.env.PREFIX + + bld.shlib( + source = source, + target = 'menu' + bld.env.POSTFIX, + name = 'menu', + features = 'c cxx', + includes = includes, + defines = defines, + install_path = install_path, + subsystem = bld.env.MSVC_SUBSYSTEM, + idx = bld.get_taskgen_count() + ) + diff --git a/mod_options.txt b/mod_options.txt new file mode 100644 index 0000000..0b7d8bd --- /dev/null +++ b/mod_options.txt @@ -0,0 +1,4 @@ +GAMEDIR=ID1 # Gamedir path +SERVER_INSTALL_DIR=bin # Where put server dll +CLIENT_INSTALL_DIR=bin # Where put client dll +SERVER_LIBRARY_NAME=progs # Library name for PC platforms diff --git a/public/build.h b/public/build.h new file mode 100644 index 0000000..851939b --- /dev/null +++ b/public/build.h @@ -0,0 +1,253 @@ +/* +build.h - compile-time build information + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +*/ +#pragma once +#ifndef BUILD_H +#define BUILD_H + +/* +All XASH_* macros set by this header are guaranteed to have positive value +otherwise not defined. + +Every macro is intended to be the unified interface for buildsystems that lack +platform & CPU detection, and a neat quick way for checks in platform code +For Q_build* macros, refer to buildenums.h + +Any new define must be undefined at first +You can generate #undef list below with this oneliner: + $ sed 's/\t//g' build.h | grep '^#define XASH' | awk '{ print $2 }' | \ + sort | uniq | awk '{ print "#undef " $1 }' + +Then you can use another oneliner to query all variables: + $ grep '^#undef XASH' build.h | awk '{ print $2 }' +*/ + +#undef XASH_64BIT +#undef XASH_AMD64 +#undef XASH_ANDROID +#undef XASH_APPLE +#undef XASH_ARM +#undef XASH_ARM_HARDFP +#undef XASH_ARM_SOFTFP +#undef XASH_ARMv4 +#undef XASH_ARMv5 +#undef XASH_ARMv6 +#undef XASH_ARMv7 +#undef XASH_ARMv8 +#undef XASH_BIG_ENDIAN +#undef XASH_DOS4GW +#undef XASH_E2K +#undef XASH_EMSCRIPTEN +#undef XASH_FREEBSD +#undef XASH_HAIKU +#undef XASH_IOS +#undef XASH_IRIX +#undef XASH_JS +#undef XASH_LINUX +#undef XASH_LITTLE_ENDIAN +#undef XASH_MIPS +#undef XASH_MOBILE_PLATFORM +#undef XASH_NETBSD +#undef XASH_OPENBSD +#undef XASH_POSIX +#undef XASH_PPC +#undef XASH_RISCV +#undef XASH_RISCV_DOUBLEFP +#undef XASH_RISCV_SINGLEFP +#undef XASH_RISCV_SOFTFP +#undef XASH_SERENITY +#undef XASH_WIN32 +#undef XASH_X86 +#undef XASH_NSWITCH +#undef XASH_PSVITA + +//================================================================ +// +// PLATFORM DETECTION CODE +// +//================================================================ +#if defined _WIN32 + #define XASH_WIN32 1 +#elif defined __EMSCRIPTEN__ + #define XASH_EMSCRIPTEN 1 +#elif defined __WATCOMC__ && defined __DOS__ + #define XASH_DOS4GW 1 +#else // POSIX compatible + #define XASH_POSIX 1 + #if defined __linux__ + #if defined __ANDROID__ + #define XASH_ANDROID 1 + #endif + #define XASH_LINUX 1 + #elif defined __FreeBSD__ + #define XASH_FREEBSD 1 + #elif defined __NetBSD__ + #define XASH_NETBSD 1 + #elif defined __OpenBSD__ + #define XASH_OPENBSD 1 + #elif defined __HAIKU__ + #define XASH_HAIKU 1 + #elif defined __serenity__ + #define XASH_SERENITY 1 + #elif defined __sgi + #define XASH_IRIX 1 + #elif defined __APPLE__ + #include + #define XASH_APPLE 1 + #if TARGET_OS_IOS + #define XASH_IOS 1 + #endif // TARGET_OS_IOS + #elif defined __SWITCH__ + #define XASH_NSWITCH 1 + #elif defined __vita__ + #define XASH_PSVITA 1 + #else + #error + #endif +#endif + +// XASH_SAILFISH is special: SailfishOS by itself is a normal GNU/Linux platform +// It doesn't make sense to split it to separate platform +// but we still need XASH_MOBILE_PLATFORM for the engine. +// So this macro is defined entirely in build-system: see main wscript +// HLSDK/PrimeXT/other SDKs users note: you may ignore this macro +#if XASH_ANDROID || XASH_IOS || XASH_NSWITCH || XASH_PSVITA || XASH_SAILFISH + #define XASH_MOBILE_PLATFORM 1 +#endif + +//================================================================ +// +// ENDIANNESS DEFINES +// +//================================================================ + +#if !defined XASH_ENDIANNESS + #if defined XASH_WIN32 || __LITTLE_ENDIAN__ + //!!! Probably all WinNT installations runs in little endian + #define XASH_LITTLE_ENDIAN 1 + #elif __BIG_ENDIAN__ + #define XASH_BIG_ENDIAN 1 + #elif defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__ && defined __ORDER_LITTLE_ENDIAN__ // some compilers define this + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + #define XASH_BIG_ENDIAN 1 + #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + #define XASH_LITTLE_ENDIAN 1 + #endif + #else + #include + #if __BYTE_ORDER == __BIG_ENDIAN + #define XASH_BIG_ENDIAN 1 + #elif __BYTE_ORDER == __LITTLE_ENDIAN + #define XASH_LITTLE_ENDIAN 1 + #endif + #endif // !XASH_WIN32 +#endif + +//================================================================ +// +// CPU ARCHITECTURE DEFINES +// +//================================================================ +#if defined __x86_64__ || defined _M_X64 + #define XASH_64BIT 1 + #define XASH_AMD64 1 +#elif defined __i386__ || defined _X86_ || defined _M_IX86 + #define XASH_X86 1 +#elif defined __aarch64__ || defined _M_ARM64 + #define XASH_64BIT 1 + #define XASH_ARM 8 +#elif defined __mips__ + #define XASH_MIPS 1 +#elif defined __EMSCRIPTEN__ + #define XASH_JS 1 +#elif defined __e2k__ + #define XASH_64BIT 1 + #define XASH_E2K 1 +#elif defined __PPC__ || defined __powerpc__ + #define XASH_PPC 1 + #if defined __PPC64__ || defined __powerpc64__ + #define XASH_64BIT 1 + #endif +#elif defined _M_ARM // msvc + #define XASH_ARM 7 + #define XASH_ARM_HARDFP 1 +#elif defined __arm__ + #if __ARM_ARCH == 8 || __ARM_ARCH_8__ + #define XASH_ARM 8 + #elif __ARM_ARCH == 7 || __ARM_ARCH_7__ + #define XASH_ARM 7 + #elif __ARM_ARCH == 6 || __ARM_ARCH_6__ || __ARM_ARCH_6J__ + #define XASH_ARM 6 + #elif __ARM_ARCH == 5 || __ARM_ARCH_5__ + #define XASH_ARM 5 + #elif __ARM_ARCH == 4 || __ARM_ARCH_4__ + #define XASH_ARM 4 + #else + #error "Unknown ARM" + #endif + + #if defined __SOFTFP__ || __ARM_PCS_VFP == 0 + #define XASH_ARM_SOFTFP 1 + #else // __SOFTFP__ + #define XASH_ARM_HARDFP 1 + #endif // __SOFTFP__ +#elif defined __riscv + #define XASH_RISCV 1 + + #if __riscv_xlen == 64 + #define XASH_64BIT 1 + #elif __riscv_xlen != 32 + #error "Unknown RISC-V ABI" + #endif + + #if defined __riscv_float_abi_soft + #define XASH_RISCV_SOFTFP 1 + #elif defined __riscv_float_abi_single + #define XASH_RISCV_SINGLEFP 1 + #elif defined __riscv_float_abi_double + #define XASH_RISCV_DOUBLEFP 1 + #else + #error "Unknown RISC-V float ABI" + #endif +#else + #error "Place your architecture name here! If this is a mistake, try to fix conditions above and report a bug" +#endif + +#if XASH_ARM == 8 + #define XASH_ARMv8 1 +#elif XASH_ARM == 7 + #define XASH_ARMv7 1 +#elif XASH_ARM == 6 + #define XASH_ARMv6 1 +#elif XASH_ARM == 5 + #define XASH_ARMv5 1 +#elif XASH_ARM == 4 + #define XASH_ARMv4 1 +#endif + +#endif // BUILD_H diff --git a/scripts/waifulib/compiler_optimizations.py b/scripts/waifulib/compiler_optimizations.py new file mode 100644 index 0000000..9cc81b7 --- /dev/null +++ b/scripts/waifulib/compiler_optimizations.py @@ -0,0 +1,180 @@ +# encoding: utf-8 +# compiler_optimizations.py -- main entry point for configuring C/C++ compilers +# Copyright (C) 2021 a1batross +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program 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 +# GNU General Public License for more details. + +try: from fwgslib import get_flags_by_type, get_flags_by_compiler +except: from waflib.extras.fwgslib import get_flags_by_type, get_flags_by_compiler +from waflib.Configure import conf +from waflib import Logs + +''' +Flags can be overriden and new types can be added +by importing this as normal Python module + +Example: +#!/usr/bin/env python +from waflib.extras import compiler_optimizations + +compiler_optimizations.VALID_BUILD_TYPES += 'gottagofast' +compiler_optimizations.CFLAGS['gottagofast'] = { + 'gcc': ['-Ogentoo'] +} +''' + +VALID_BUILD_TYPES = ['fastnative', 'fast', 'release', 'debug', 'sanitize', 'msan', 'none'] + +LINKFLAGS = { + 'common': { + 'msvc': ['/DEBUG'], # always create PDB, doesn't affect result binaries + 'gcc': ['-Wl,--no-undefined'], + 'owcc': ['-Wl,option stack=512k'] + }, + 'msan': { + 'clang': ['-fsanitize=memory', '-pthread'], + 'default': ['NO_MSAN_HERE'] + }, + 'sanitize': { + 'clang': ['-fsanitize=undefined', '-fsanitize=address', '-pthread'], + 'gcc': ['-fsanitize=undefined', '-fsanitize=address', '-pthread'], + 'msvc': ['/SAFESEH:NO'] + }, + 'debug': { + 'msvc': ['/INCREMENTAL', '/SAFESEH:NO'] + } +} + +CFLAGS = { + 'common': { + # disable thread-safe local static initialization for C++11 code, as it cause crashes on Windows XP + 'msvc': ['/D_USING_V110_SDK71_', '/FS', '/Zc:threadSafeInit-', '/MT', '/MP', '/Zc:__cplusplus'], + 'clang': ['-g', '-gdwarf-2', '-fvisibility=hidden', '-fno-threadsafe-statics'], + 'gcc': ['-g', '-fvisibility=hidden'], + 'owcc': ['-fno-short-enum', '-ffloat-store', '-g3'] + }, + 'fast': { + 'msvc': ['/O2', '/Oy', '/Zi'], + 'gcc': { + '3': ['-O3', '-fomit-frame-pointer'], + 'default': ['-Ofast', '-funsafe-math-optimizations', '-funsafe-loop-optimizations', '-fomit-frame-pointer'] + }, + 'clang': ['-Ofast'], + 'default': ['-O3'] + }, + 'fastnative': { + 'msvc': ['/O2', '/Oy', '/Zi'], + 'gcc': ['-Ofast', '-march=native', '-funsafe-math-optimizations', '-funsafe-loop-optimizations', '-fomit-frame-pointer'], + 'clang': ['-Ofast', '-march=native'], + 'default': ['-O3'] + }, + 'release': { + 'msvc': ['/O2', '/Zi'], + 'owcc': ['-O3', '-foptimize-sibling-calls', '-fomit-leaf-frame-pointer', '-fomit-frame-pointer', '-fschedule-insns', '-funsafe-math-optimizations', '-funroll-loops', '-frerun-optimizer', '-finline-functions', '-finline-limit=512', '-fguess-branch-probability', '-fno-strict-aliasing', '-floop-optimize'], + 'default': ['-O3'] + }, + 'debug': { + 'msvc': ['/Od', '/ZI'], + 'owcc': ['-O0', '-fno-omit-frame-pointer', '-funwind-tables', '-fno-omit-leaf-frame-pointer'], + 'default': ['-O0'] + }, + 'msan': { + 'clang': ['-O2', '-g', '-fno-omit-frame-pointer', '-fsanitize=memory', '-pthread'], + 'default': ['NO_MSAN_HERE'] + }, + 'sanitize': { + 'msvc': ['/Od', '/RTC1', '/Zi', '/fsanitize=address'], + 'gcc': ['-O0', '-fsanitize=undefined', '-fsanitize=address', '-pthread'], + 'clang': ['-O0', '-fsanitize=undefined', '-fsanitize=address', '-pthread'], + 'default': ['-O0'] + }, +} + +LTO_CFLAGS = { + 'msvc': ['/GL'], + 'gcc': ['-flto'], + 'clang': ['-flto'] +} + +LTO_LINKFLAGS = { + 'msvc': ['/LTCG'], + 'gcc': ['-flto'], + 'clang': ['-flto'] +} + +POLLY_CFLAGS = { + 'gcc': ['-fgraphite-identity'], + 'clang': ['-mllvm', '-polly'] + # msvc sosat :( +} + +def options(opt): + grp = opt.add_option_group('Compiler optimization options') + + grp.add_option('-T', '--build-type', action='store', dest='BUILD_TYPE', default='release', + help = 'build type: debug, release or none(custom flags)') + + grp.add_option('--enable-lto', action = 'store_true', dest = 'LTO', default = False, + help = 'enable Link Time Optimization if possible [default: %default]') + + grp.add_option('--enable-poly-opt', action = 'store_true', dest = 'POLLY', default = False, + help = 'enable polyhedral optimization if possible [default: %default]') + +def configure(conf): + conf.start_msg('Build type') + + if not conf.options.BUILD_TYPE in VALID_BUILD_TYPES: + conf.end_msg(conf.options.BUILD_TYPE, color='RED') + conf.fatal('Invalid build type. Valid are: %s' % ', '.join(VALID_BUILD_TYPES)) + + conf.end_msg(conf.options.BUILD_TYPE) + + conf.msg('LTO build', 'yes' if conf.options.LTO else 'no') + conf.msg('PolyOpt build', 'yes' if conf.options.POLLY else 'no') + + # -march=native should not be used + if conf.options.BUILD_TYPE.startswith('fast'): + Logs.warn('WARNING: \'%s\' build type should not be used in release builds', conf.options.BUILD_TYPE) + + try: + conf.env.CC_VERSION[0] + except IndexError: + conf.env.CC_VERSION = (0,) + +@conf +def get_optimization_flags(conf): + '''Returns a list of compile flags, + depending on build type and options set by user + + NOTE: it doesn't filter out unsupported flags + + :returns: tuple of cflags and linkflags + ''' + linkflags = conf.get_flags_by_type(LINKFLAGS, conf.options.BUILD_TYPE, conf.env.COMPILER_CC, conf.env.CC_VERSION[0]) + + cflags = conf.get_flags_by_type(CFLAGS, conf.options.BUILD_TYPE, conf.env.COMPILER_CC, conf.env.CC_VERSION[0]) + + if conf.options.LTO: + linkflags+= conf.get_flags_by_compiler(LTO_LINKFLAGS, conf.env.COMPILER_CC) + cflags += conf.get_flags_by_compiler(LTO_CFLAGS, conf.env.COMPILER_CC) + + if conf.options.POLLY: + cflags += conf.get_flags_by_compiler(POLLY_CFLAGS, conf.env.COMPILER_CC) + + if conf.env.DEST_OS == 'nswitch' and conf.options.BUILD_TYPE == 'debug': + # enable remote debugger + cflags.append('-DNSWITCH_DEBUG') + elif conf.env.DEST_OS == 'psvita': + # this optimization is broken in vitasdk + cflags.append('-fno-optimize-sibling-calls') + # remove fvisibility to allow everything to be exported by default + cflags.remove('-fvisibility=hidden') + + return cflags, linkflags diff --git a/scripts/waifulib/library_naming.py b/scripts/waifulib/library_naming.py new file mode 100644 index 0000000..ac2faf6 --- /dev/null +++ b/scripts/waifulib/library_naming.py @@ -0,0 +1,175 @@ +#! /usr/bin/env python +# Copyright 2019 (C) a1batross + +from waflib import Configure, Errors, Utils + +# TODO: make generic +CHECK_SYMBOL_EXISTS_FRAGMENT = ''' +#include "build.h" + +int main(int argc, char** argv) +{ + (void)argv; +#ifndef %s + return ((int*)(&%s))[argc]; +#else + (void)argc; + return 0; +#endif +} +''' + +# generated(see comments in public/build.h) +# cat build.h | grep '^#undef XASH' | awk '{ print "'\''" $2 "'\''," }' +DEFINES = [ +'XASH_64BIT', +'XASH_AMD64', +'XASH_ANDROID', +'XASH_APPLE', +'XASH_ARM', +'XASH_ARM_HARDFP', +'XASH_ARM_SOFTFP', +'XASH_ARMv4', +'XASH_ARMv5', +'XASH_ARMv6', +'XASH_ARMv7', +'XASH_ARMv8', +'XASH_BIG_ENDIAN', +'XASH_DOS4GW', +'XASH_E2K', +'XASH_EMSCRIPTEN', +'XASH_FREEBSD', +'XASH_HAIKU', +'XASH_IOS', +'XASH_IRIX', +'XASH_JS', +'XASH_LINUX', +'XASH_LITTLE_ENDIAN', +'XASH_MIPS', +'XASH_MOBILE_PLATFORM', +'XASH_NETBSD', +'XASH_OPENBSD', +'XASH_POSIX', +'XASH_PPC', +'XASH_RISCV', +'XASH_RISCV_DOUBLEFP', +'XASH_RISCV_SINGLEFP', +'XASH_RISCV_SOFTFP', +'XASH_SERENITY', +'XASH_WIN32', +'XASH_X86', +'XASH_NSWITCH', +'XASH_PSVITA', +] + +def configure(conf): + conf.env.stash() + conf.start_msg('Determining library postfix') + tests = map(lambda x: { + 'fragment': CHECK_SYMBOL_EXISTS_FRAGMENT % (x, x), + 'includes': [conf.path.find_node('public/').abspath()], + 'define_name': x }, DEFINES ) + + conf.multicheck(*tests, msg = '', mandatory = False, quiet = True) + + # engine/common/build.c + if conf.env.XASH_ANDROID: + buildos = "android" + elif conf.env.XASH_WIN32 or conf.env.XASH_LINUX or conf.env.XASH_APPLE: + buildos = "" # no prefix for default OS + elif conf.env.XASH_FREEBSD: + buildos = "freebsd" + elif conf.env.XASH_NETBSD: + buildos = "netbsd" + elif conf.env.XASH_OPENBSD: + buildos = "openbsd" + elif conf.env.XASH_EMSCRIPTEN: + buildos = "emscripten" + elif conf.env.XASH_DOS4GW: + buildos = "dos4gw" # unused, just in case + elif conf.env.XASH_HAIKU: + buildos = "haiku" + elif conf.env.XASH_SERENITY: + buildos = "serenityos" + elif conf.env.XASH_NSWITCH: + buildos = "nswitch" + elif conf.env.XASH_PSVITA: + buildos = "psvita" + elif conf.env.XASH_IRIX: + buildos = "irix" + else: + conf.fatal("Place your operating system name in build.h and library_naming.py!\n" + "If this is a mistake, try to fix conditions above and report a bug") + + if conf.env.XASH_AMD64: + buildarch = "amd64" + elif conf.env.XASH_X86: + if conf.env.XASH_WIN32 or conf.env.XASH_LINUX or conf.env.XASH_APPLE: + buildarch = "" + else: + buildarch = "i386" + elif conf.env.XASH_ARM and conf.env.XASH_64BIT: + buildarch = "arm64" + elif conf.env.XASH_ARM: + buildarch = "armv" + if conf.env.XASH_ARMv8: + buildarch += "8_32" + elif conf.env.XASH_ARMv7: + buildarch += "7" + elif conf.env.XASH_ARMv6: + buildarch += "6" + elif conf.env.XASH_ARMv5: + buildarch += "5" + elif conf.env.XASH_ARMv4: + buildarch += "4" + else: + raise conf.fatal('Unknown ARM') + + if conf.env.XASH_ARM_HARDFP: + buildarch += "hf" + else: + buildarch += "l" + elif conf.env.XASH_MIPS: + buildarch = "mips" + if conf.env.XASH_64BIT: + buildarch += "64" + if conf.env.XASH_LITTLE_ENDIAN: + buildarch += "el" + elif conf.env.XASH_RISCV: + buildarch = "riscv" + if conf.env.XASH_64BIT: + buildarch += "64" + else: + buildarch += "32" + + if conf.env.XASH_RISCV_DOUBLEFP: + buildarch += "d" + elif conf.env.XASH_RISCV_SINGLEFP: + buildarch += "f" + elif conf.env.XASH_JS: + buildarch = "javascript" + elif conf.env.XASH_E2K: + buildarch = "e2k" + elif conf.env.XASH_PPC: + buildarch = "ppc" + if conf.env.XASH_64BIT: + buildarch += "64" + if conf.env.XASH_LITTLE_ENDIAN: + buildarch += "el" + else: + raise conf.fatal("Place your architecture name in build.h and library_naming.py!\n" + "If this is a mistake, try to fix conditions above and report a bug") + + conf.env.revert() + + if buildos == 'android': + # force disable for Android, as Android ports aren't distributed in normal way and doesn't follow library naming + conf.env.POSTFIX = '' + elif buildos != '' and buildarch != '': + conf.env.POSTFIX = '_%s_%s' % (buildos,buildarch) + elif buildarch != '': + conf.env.POSTFIX = '_%s' % buildarch + else: + conf.env.POSTFIX = '' + + conf.end_msg(conf.env.POSTFIX) diff --git a/scripts/waifulib/strip_on_install.py b/scripts/waifulib/strip_on_install.py new file mode 100644 index 0000000..6522065 --- /dev/null +++ b/scripts/waifulib/strip_on_install.py @@ -0,0 +1,49 @@ +#! /usr/bin/env python +# Modified: Alibek Omarov +# Originally taken from Thomas Nagy's blogpost + +""" +Strip executables upon installation +""" + +import shutil, os +from waflib import Build, Utils, Context, Errors, Logs + +def options(opt): + grp = opt.option_groups['install/uninstall options'] + grp.add_option('--no-strip', dest='no_strip', action='store_true', default=False, + help='don\'t strip binaries. You must pass this flag to install command(default: False)') + +def configure(conf): + if conf.env.DEST_BINFMT in ['elf', 'mac-o']: + conf.find_program('strip', var='STRIP') + if not conf.env.STRIPFLAGS: + conf.env.STRIPFLAGS = os.environ['STRIPFLAGS'] if 'STRIPFLAGS' in os.environ else [] + +def copy_fun(self, src, tgt): + inst_copy_fun(self, src, tgt) + + if self.generator.bld.options.no_strip: + return + + if self.env.DEST_BINFMT not in ['elf', 'mac-o']: # don't strip unknown formats or PE + return + + if getattr(self.generator, 'link_task', None) and self.generator.link_task.outputs[0] in self.inputs: + cmd = self.env.STRIP + self.env.STRIPFLAGS + [tgt] + try: + self.generator.bld.cmd_and_log(cmd, output=Context.BOTH, quiet=Context.BOTH) + if not self.generator.bld.progress_bar: + c1 = Logs.colors.NORMAL + c2 = Logs.colors.CYAN + + f1 = os.path.getsize(src) + f2 = os.path.getsize(tgt) + + Logs.info('%s+ strip %s%s%s (%d bytes change)', c1, c2, tgt, c1, f2 - f1) + except Errors.WafError as e: + print(e.stdout, e.stderr) + +inst_copy_fun = Build.inst.copy_fun +Build.inst.copy_fun = copy_fun + diff --git a/scripts/waifulib/xcompile.py b/scripts/waifulib/xcompile.py new file mode 100644 index 0000000..08e9022 --- /dev/null +++ b/scripts/waifulib/xcompile.py @@ -0,0 +1,660 @@ +# encoding: utf-8 +# xcompile.py -- crosscompiling utils +# Copyright (C) 2018 a1batross +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program 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 +# GNU General Public License for more details. + +try: from fwgslib import get_flags_by_compiler +except: from waflib.extras.fwgslib import get_flags_by_compiler +from waflib import Logs, TaskGen +from waflib.Tools import c_config +from collections import OrderedDict +import os +import sys + +ANDROID_NDK_ENVVARS = ['ANDROID_NDK_HOME', 'ANDROID_NDK'] +ANDROID_NDK_SUPPORTED = [10, 19, 20, 23, 25] +ANDROID_NDK_HARDFP_MAX = 11 # latest version that supports hardfp +ANDROID_NDK_GCC_MAX = 17 # latest NDK that ships with GCC +ANDROID_NDK_UNIFIED_SYSROOT_MIN = 15 +ANDROID_NDK_SYSROOT_FLAG_MAX = 19 # latest NDK that need --sysroot flag +ANDROID_NDK_API_MIN = { 10: 3, 19: 16, 20: 16, 23: 16, 25: 19 } # minimal API level ndk revision supports + +ANDROID_STPCPY_API_MIN = 21 # stpcpy() introduced in SDK 21 +ANDROID_64BIT_API_MIN = 21 # minimal API level that supports 64-bit targets + +NSWITCH_ENVVARS = ['DEVKITPRO'] + +PSVITA_ENVVARS = ['VITASDK'] + +# This class does support ONLY r10e and r19c/r20 NDK +class Android: + ctx = None # waf context + arch = None + toolchain = None + api = None + ndk_home = None + ndk_rev = 0 + is_hardfloat = False + clang = False + + def __init__(self, ctx, arch, toolchain, api): + self.ctx = ctx + self.api = api + self.toolchain = toolchain + self.arch = arch + + for i in ANDROID_NDK_ENVVARS: + self.ndk_home = os.getenv(i) + if self.ndk_home != None: + break + else: + ctx.fatal('Set %s environment variable pointing to the root of Android NDK!' % + ' or '.join(ANDROID_NDK_ENVVARS)) + + # TODO: this were added at some point of NDK development + # but I don't know at which version + # r10e don't have it + source_prop = os.path.join(self.ndk_home, 'source.properties') + if os.path.exists(source_prop): + with open(source_prop) as ndk_props_file: + for line in ndk_props_file.readlines(): + tokens = line.split('=') + trimed_tokens = [token.strip() for token in tokens] + + if 'Pkg.Revision' in trimed_tokens: + self.ndk_rev = int(trimed_tokens[1].split('.')[0]) + + if self.ndk_rev not in ANDROID_NDK_SUPPORTED: + ctx.fatal('Unknown NDK revision: %d' % (self.ndk_rev)) + else: + self.ndk_rev = ANDROID_NDK_SUPPORTED[0] + + if 'clang' in self.toolchain or self.ndk_rev > ANDROID_NDK_GCC_MAX: + self.clang = True + + if self.arch == 'armeabi-v7a-hard': + if self.ndk_rev <= ANDROID_NDK_HARDFP_MAX: + self.arch = 'armeabi-v7a' # Only armeabi-v7a have hard float ABI + self.is_hardfloat = True + else: + ctx.fatal('NDK does not support hardfloat ABI') + + if self.api < ANDROID_NDK_API_MIN[self.ndk_rev]: + self.api = ANDROID_NDK_API_MIN[self.ndk_rev] + Logs.warn('API level automatically was set to %d due to NDK support' % self.api) + + if self.is_arm64() or self.is_amd64() and self.api < ANDROID_64BIT_API_MIN: + self.api = ANDROID_64BIT_API_MIN + Logs.warn('API level for 64-bit target automatically was set to %d' % self.api) + + def is_host(self): + ''' + Checks if we using host compiler(implies clang) + ''' + return self.toolchain == 'host' + + def is_arm(self): + ''' + Checks if selected architecture is **32-bit** ARM + ''' + return self.arch.startswith('armeabi') + + def is_x86(self): + ''' + Checks if selected architecture is **32-bit** or **64-bit** x86 + ''' + return self.arch == 'x86' + + def is_amd64(self): + ''' + Checks if selected architecture is **64-bit** x86 + ''' + return self.arch == 'x86_64' + + def is_arm64(self): + ''' + Checks if selected architecture is AArch64 + ''' + return self.arch == 'aarch64' + + def is_clang(self): + ''' + Checks if selected toolchain is Clang (TODO) + ''' + return self.clang + + def is_hardfp(self): + return self.is_hardfloat + + def ndk_triplet(self, llvm_toolchain = False, toolchain_folder = False): + if self.is_x86(): + if toolchain_folder: + return 'x86' + else: + return 'i686-linux-android' + elif self.is_arm(): + if llvm_toolchain: + return 'armv7a-linux-androideabi' + else: + return 'arm-linux-androideabi' + elif self.is_amd64() and toolchain_folder: + return 'x86_64' + else: + return self.arch + '-linux-android' + + def apk_arch(self): + if self.is_arm64(): + return 'arm64-v8a' + return self.arch + + def gen_host_toolchain(self): + # With host toolchain we don't care about OS + # so just download NDK for Linux x86_64 + if 'HOST_TOOLCHAIN' in self.ctx.environ: + return self.ctx.environ['HOST_TOOLCHAIN'] + if self.is_host(): + return 'linux-x86_64' + + if sys.platform.startswith('win32') or sys.platform.startswith('cygwin'): + osname = 'windows' + elif sys.platform.startswith('darwin'): + osname = 'darwin' + elif sys.platform.startswith('linux'): + osname = 'linux' + else: + self.ctx.fatal('Unsupported by NDK host platform') + + if sys.maxsize > 2**32: + arch = 'x86_64' + else: arch = 'x86' + + return '%s-%s' % (osname, arch) + + def gen_gcc_toolchain_path(self): + path = 'toolchains' + toolchain_host = self.gen_host_toolchain() + + if self.is_clang(): + toolchain_folder = 'llvm' + else: + if self.is_host(): + toolchain = '4.9' + else: + toolchain = self.toolchain + + toolchain_folder = '%s-%s' % (self.ndk_triplet(toolchain_folder = True), toolchain) + + return os.path.abspath(os.path.join(self.ndk_home, path, toolchain_folder, 'prebuilt', toolchain_host)) + + def gen_toolchain_path(self): + if self.is_clang(): + triplet = '%s%d-' % (self.ndk_triplet(llvm_toolchain = True), self.api) + else: + triplet = self.ndk_triplet() + '-' + return os.path.join(self.gen_gcc_toolchain_path(), 'bin', triplet) + + def gen_binutils_path(self): + if self.ndk_rev >= 23: + return os.path.join(self.gen_gcc_toolchain_path(), 'bin') + return os.path.join(self.gen_gcc_toolchain_path(), self.ndk_triplet(), 'bin') + + def cc(self): + if self.is_host(): + s = 'clang' + environ = getattr(self.ctx, 'environ', os.environ) + + if 'CC' in environ: + s = environ['CC'] + + return '%s --target=%s%d' % (s, self.ndk_triplet(), self.api) + return self.gen_toolchain_path() + ('clang' if self.is_clang() else 'gcc') + + def cxx(self): + if self.is_host(): + s = 'clang++' + environ = getattr(self.ctx, 'environ', os.environ) + + if 'CXX' in environ: + s = environ['CXX'] + + return '%s --target=%s%d' % (s, self.ndk_triplet(), self.api) + return self.gen_toolchain_path() + ('clang++' if self.is_clang() else 'g++') + + def strip(self): + if self.is_host(): + environ = getattr(self.ctx, 'environ', os.environ) + + if 'STRIP' in environ: + return environ['STRIP'] + return 'llvm-strip' + + if self.ndk_rev >= 23: + return os.path.join(self.gen_binutils_path(), 'llvm-strip') + return os.path.join(self.gen_binutils_path(), 'strip') + + def system_stl(self): + # TODO: proper STL support + return os.path.abspath(os.path.join(self.ndk_home, 'sources', 'cxx-stl', 'system', 'include')) + + def libsysroot(self): + arch = self.arch + if self.is_arm(): + arch = 'arm' + elif self.is_arm64(): + arch = 'arm64' + path = 'platforms/android-%s/arch-%s' % (self.api, arch) + + return os.path.abspath(os.path.join(self.ndk_home, path)) + + def sysroot(self): + if self.ndk_rev >= ANDROID_NDK_UNIFIED_SYSROOT_MIN: + return os.path.abspath(os.path.join(self.ndk_home, 'sysroot')) + else: + return self.libsysroot() + + def cflags(self, cxx = False): + cflags = [] + + if self.ndk_rev <= ANDROID_NDK_SYSROOT_FLAG_MAX: + cflags += ['--sysroot=%s' % (self.sysroot())] + else: + if self.is_host(): + cflags += [ + '--sysroot=%s/sysroot' % (self.gen_gcc_toolchain_path()), + '-isystem', '%s/usr/include/' % (self.sysroot()) + ] + + cflags += ['-I%s' % (self.system_stl())] + if not self.is_clang(): + cflags += ['-DANDROID', '-D__ANDROID__'] + + if cxx and not self.is_clang() and self.toolchain not in ['4.8','4.9']: + cflags += ['-fno-sized-deallocation'] + + if self.is_clang(): + # stpcpy() isn't available in early Android versions + # disable it here so Clang won't use it + if self.api < ANDROID_STPCPY_API_MIN: + cflags += ['-fno-builtin-stpcpy'] + + if self.is_arm(): + if self.arch == 'armeabi-v7a': + # ARMv7 support + cflags += ['-mthumb', '-mfpu=neon', '-mcpu=cortex-a9'] + + if self.is_hardfp(): + cflags += ['-D_NDK_MATH_NO_SOFTFP=1', '-mfloat-abi=hard', '-DLOAD_HARDFP', '-DSOFTFP_LINK'] + + if self.is_host(): + # Clang builtin redefine w/ different calling convention bug + # NOTE: I did not added complex.h functions here, despite + # that NDK devs forgot to put __NDK_FPABI_MATH__ for complex + # math functions + # I personally don't need complex numbers support, but if you want it + # just run sed to patch header + for f in ['strtod', 'strtof', 'strtold']: + cflags += ['-fno-builtin-%s' % f] + else: + cflags += ['-mfloat-abi=softfp'] + else: + # ARMv5 support + cflags += ['-march=armv5te', '-msoft-float'] + elif self.is_x86(): + cflags += ['-mtune=atom', '-march=atom', '-mssse3', '-mfpmath=sse'] + return cflags + + # they go before object list + def linkflags(self): + linkflags = [] + if self.is_host(): + linkflags += ['--gcc-toolchain=%s' % self.gen_gcc_toolchain_path()] + + if self.ndk_rev <= ANDROID_NDK_SYSROOT_FLAG_MAX: + linkflags += ['--sysroot=%s' % (self.sysroot())] + elif self.is_host(): + linkflags += ['--sysroot=%s/sysroot' % (self.gen_gcc_toolchain_path())] + + if self.is_clang() or self.is_host(): + linkflags += ['-fuse-ld=lld'] + else: linkflags += ['-no-canonical-prefixes'] + + linkflags += ['-Wl,--hash-style=sysv', '-Wl,--no-undefined'] + return linkflags + + def ldflags(self): + ldflags = [] + + if self.ndk_rev < 23: + ldflags += ['-lgcc'] + + if self.is_clang() or self.is_host(): + ldflags += ['-stdlib=libstdc++'] + else: ldflags += ['-no-canonical-prefixes'] + + if self.is_arm(): + if self.arch == 'armeabi-v7a': + ldflags += ['-march=armv7-a', '-mthumb'] + + if not self.is_clang() and not self.is_host(): # lld only + ldflags += ['-Wl,--fix-cortex-a8'] + + if self.is_hardfp(): + ldflags += ['-Wl,--no-warn-mismatch', '-lm_hard'] + else: + ldflags += ['-march=armv5te'] + return ldflags + +class NintendoSwitch: + ctx = None # waf context + arch = "arm64" + dkp_dir = None + portlibs_dir = None + dka64_dir = None + libnx_dir = None + + def __init__(self, ctx): + self.ctx = ctx + + for i in NSWITCH_ENVVARS: + self.dkp_dir = os.getenv(i) + if self.dkp_dir != None: + break + else: + ctx.fatal('Set %s environment variable pointing to the DEVKITPRO home!' % + ' or '.join(NSWITCH_ENVVARS)) + + self.dkp_dir = os.path.abspath(self.dkp_dir) + + self.dka64_dir = os.path.join(self.dkp_dir, 'devkitA64') + if not os.path.exists(self.dka64_dir): + ctx.fatal('devkitA64 not found in `%s`. Install devkitA64!' % self.dka64_dir) + + self.libnx_dir = os.path.join(self.dkp_dir, 'libnx') + if not os.path.exists(self.libnx_dir): + ctx.fatal('libnx not found in `%s`. Install libnx!' % self.libnx_dir) + + self.portlibs_dir = os.path.join(self.dkp_dir, 'portlibs', 'switch') + if not os.path.exists(self.portlibs_dir): + ctx.fatal('No Switch libraries found in `%s`!' % self.portlibs_dir) + + def gen_toolchain_prefix(self): + return 'aarch64-none-elf-' + + def gen_gcc_toolchain_path(self): + return os.path.join(self.dka64_dir, 'bin', self.gen_toolchain_prefix()) + + def cc(self): + return self.gen_gcc_toolchain_path() + 'gcc' + + def cxx(self): + return self.gen_gcc_toolchain_path() + 'g++' + + def strip(self): + return self.gen_gcc_toolchain_path() + 'strip' + + def pkgconfig(self): + # counter-intuitively, this motherfucker is in $DEVKITPRO/portlibs/switch/bin + return os.path.join(self.portlibs_dir, 'bin', self.gen_toolchain_prefix() + 'pkg-config') + + def cflags(self, cxx = False): + cflags = [] + # arch flags + cflags += ['-D__SWITCH__', '-march=armv8-a+crc+crypto', '-mtune=cortex-a57', '-mtp=soft', '-ftls-model=local-exec', '-fPIE'] + # help the linker out + cflags += ['-ffunction-sections', '-fdata-sections'] + # base include dirs + cflags += ['-isystem %s/include' % self.libnx_dir, '-I%s/include' % self.portlibs_dir] + # the game wants GNU extensions + if cxx: + cflags += ['-std=gnu++17', '-D_GNU_SOURCE'] + else: + cflags += ['-std=gnu11', '-D_GNU_SOURCE'] + return cflags + + # they go before object list + def linkflags(self): + linkflags = ['-fPIE', '-specs=%s/switch.specs' % self.libnx_dir] + # libsolder only supports sysv hashes and we need to build everything with -rdynamic + linkflags += ['-Wl,--hash-style=sysv', '-rdynamic'] + # avoid pulling in and exposing mesa's internals, that crashes it for some god forsaken reason + linkflags += ['-Wl,--exclude-libs=libglapi.a', '-Wl,--exclude-libs=libdrm_nouveau.a'] + return linkflags + + def ldflags(self): + # NOTE: shared libraries should be built without standard libs, so that they could import their contents from the NRO, + # but executables, including the SDL2 sanity check, will generally require libstdc++ and libm, which we will add manually + ldflags = [] # ['-lm', '-lstdc++'] + return ldflags + +class PSVita: + ctx = None # waf context + arch ='armeabi-v7a-hard' + vitasdk_dir = None + + def __init__(self, ctx): + self.ctx = ctx + + for i in PSVITA_ENVVARS: + self.vitasdk_dir = os.getenv(i) + if self.vitasdk_dir != None: + break + else: + ctx.fatal('Set %s environment variable pointing to the VitaSDK directory!' % + ' or '.join(PSVITA_ENVVARS)) + + def gen_toolchain_prefix(self): + return 'arm-vita-eabi-' + + def gen_gcc_toolchain_path(self): + return os.path.join(self.vitasdk_dir, 'bin', self.gen_toolchain_prefix()) + + def cc(self): + return self.gen_gcc_toolchain_path() + 'gcc' + + def cxx(self): + return self.gen_gcc_toolchain_path() + 'g++' + + def strip(self): + return self.gen_gcc_toolchain_path() + 'strip' + + def ar(self): + return self.gen_gcc_toolchain_path() + 'ar' + + def pkgconfig(self): + return self.gen_gcc_toolchain_path() + 'pkg-config' + + def cflags(self, cxx = False): + cflags = [] + # arch flags + cflags += ['-D__vita__', '-mtune=cortex-a9', '-mfpu=neon'] + # necessary linker flags + cflags += ['-Wl,-q', '-Wl,-z,nocopyreloc'] + # this optimization is broken in vitasdk + cflags += ['-fno-optimize-sibling-calls'] + # disable some ARM bullshit + cflags += ['-fno-short-enums', '-Wno-attributes'] + # base include dir + cflags += ['-isystem %s/arm-vita-eabi/include' % self.vitasdk_dir] + # SDL include dir + cflags += ['-I%s/arm-vita-eabi/include/SDL2' % self.vitasdk_dir] + return cflags + + # they go before object list + def linkflags(self): + linkflags = ['-Wl,--hash-style=sysv', '-Wl,-q', '-Wl,-z,nocopyreloc', '-mtune=cortex-a9', '-mfpu=neon'] + # enforce no-short-enums again + linkflags += ['-Wl,-no-enum-size-warning', '-fno-short-enums'] + return linkflags + + def ldflags(self): + ldflags = [] + return ldflags + +def options(opt): + xc = opt.add_option_group('Cross compile options') + xc.add_option('--android', action='store', dest='ANDROID_OPTS', default=None, + help='enable building for android, format: --android=,,, example: --android=armeabi-v7a-hard,4.9,9') + xc.add_option('--enable-magx', action='store_true', dest='MAGX', default=False, + help='enable building for Motorola MAGX [default: %default]') + xc.add_option('--enable-msvc-wine', action='store_true', dest='MSVC_WINE', default=False, + help='enable building with MSVC using Wine [default: %default]') + xc.add_option('--nswitch', action='store_true', dest='NSWITCH', default = False, + help ='enable building for Nintendo Switch [default: %default]') + xc.add_option('--psvita', action='store_true', dest='PSVITA', default = False, + help ='enable building for PlayStation Vita [default: %default]') + +def configure(conf): + if conf.options.ANDROID_OPTS: + values = conf.options.ANDROID_OPTS.split(',') + if len(values) != 3: + conf.fatal('Invalid --android paramater value!') + + valid_archs = ['x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'armeabi-v7a-hard', 'aarch64'] + + if values[0] not in valid_archs: + conf.fatal('Unknown arch: %s. Supported: %r' % (values[0], ', '.join(valid_archs))) + + conf.android = android = Android(conf, values[0], values[1], int(values[2])) + conf.environ['CC'] = android.cc() + conf.environ['CXX'] = android.cxx() + conf.environ['STRIP'] = android.strip() + conf.env.CFLAGS += android.cflags() + conf.env.CXXFLAGS += android.cflags(True) + conf.env.LINKFLAGS += android.linkflags() + conf.env.LDFLAGS += android.ldflags() + + conf.env.HAVE_M = True + if android.is_hardfp(): + conf.env.LIB_M = ['m_hard'] + else: conf.env.LIB_M = ['m'] + + conf.env.PREFIX = '/lib/%s' % android.apk_arch() + + conf.msg('Selected Android NDK', '%s, version: %d' % (android.ndk_home, android.ndk_rev)) + # no need to print C/C++ compiler, as it would be printed by compiler_c/cxx + conf.msg('... C/C++ flags', ' '.join(android.cflags()).replace(android.ndk_home, '$NDK/')) + conf.msg('... link flags', ' '.join(android.linkflags()).replace(android.ndk_home, '$NDK/')) + conf.msg('... ld flags', ' '.join(android.ldflags()).replace(android.ndk_home, '$NDK/')) + elif conf.options.MAGX: + # useless to change toolchain path, as toolchain meant to be placed in this path + toolchain_path = '/opt/toolchains/motomagx/arm-eabi2/lib/' + conf.env.INCLUDES_MAGX = [toolchain_path + i for i in ['ezx-z6/include', 'qt-2.3.8/include']] + conf.env.LIBPATH_MAGX = [toolchain_path + i for i in ['ezx-z6/lib', 'qt-2.3.8/lib']] + conf.env.LINKFLAGS_MAGX = ['-Wl,-rpath-link=' + i for i in conf.env.LIBPATH_MAGX] + elif conf.options.MSVC_WINE: + try: + toolchain_path = conf.environ['MSVC_WINE_PATH'] + except KeyError: + conf.fatal('Set MSVC_WINE_PATH environment variable to the MSVC toolchain root!') + + conf.environ['CC'] = conf.environ['CXX'] = os.path.join(toolchain_path, 'bin', conf.env.MSVC_TARGETS[0], 'cl') + conf.environ['LINK_CXX'] = os.path.join(toolchain_path, 'bin', conf.env.MSVC_TARGETS[0], 'link') + conf.environ['AR'] = os.path.join(toolchain_path, 'bin', conf.env.MSVC_TARGETS[0], 'lib') + conf.environ['WINRC'] = os.path.join(toolchain_path, 'bin', conf.env.MSVC_TARGETS[0], 'rc') + conf.env.DEST_OS = 'win32' + conf.env.DEST_CPU = conf.env.MSVC_TARGETS[0] + conf.env.COMPILER_CXX = conf.env.COMPILER_CC = 'msvc' + elif conf.options.NSWITCH: + conf.nswitch = nswitch = NintendoSwitch(conf) + conf.environ['CC'] = nswitch.cc() + conf.environ['CXX'] = nswitch.cxx() + conf.environ['STRIP'] = nswitch.strip() + conf.env.PKGCONFIG = nswitch.pkgconfig() + conf.env.CFLAGS += nswitch.cflags() + conf.env.CXXFLAGS += nswitch.cflags(True) + conf.env.LINKFLAGS += nswitch.linkflags() + conf.env.LDFLAGS += nswitch.ldflags() + conf.env.HAVE_M = True + conf.env.LIB_M = ['m'] + conf.env.DEST_OS = 'nswitch' + elif conf.options.PSVITA: + conf.psvita = psvita = PSVita(conf) + conf.environ['CC'] = psvita.cc() + conf.environ['CXX'] = psvita.cxx() + conf.environ['STRIP'] = psvita.strip() + conf.environ['AR'] = psvita.ar() + conf.env.PKGCONFIG = psvita.pkgconfig() + conf.env.CFLAGS += psvita.cflags() + conf.env.CXXFLAGS += psvita.cflags(True) + conf.env.LINKFLAGS += psvita.linkflags() + conf.env.LDFLAGS += psvita.ldflags() + conf.env.HAVE_M = True + conf.env.LIB_M = ['m'] + conf.env.VRTLD = ['vrtld'] + conf.env.DEST_OS = 'psvita' + + conf.env.MAGX = conf.options.MAGX + conf.env.MSVC_WINE = conf.options.MSVC_WINE + MACRO_TO_DESTOS = OrderedDict({ '__ANDROID__' : 'android', '__SWITCH__' : 'nswitch', '__vita__' : 'psvita' }) + for k in c_config.MACRO_TO_DESTOS: + MACRO_TO_DESTOS[k] = c_config.MACRO_TO_DESTOS[k] # ordering is important + c_config.MACRO_TO_DESTOS = MACRO_TO_DESTOS + +def post_compiler_cxx_configure(conf): + conf.msg('Target OS', conf.env.DEST_OS) + conf.msg('Target CPU', conf.env.DEST_CPU) + conf.msg('Target binfmt', conf.env.DEST_BINFMT) + + if conf.options.ANDROID_OPTS: + if conf.android.ndk_rev == 19: + conf.env.CXXFLAGS_cxxshlib += ['-static-libstdc++'] + conf.env.LDFLAGS_cxxshlib += ['-static-libstdc++'] + elif conf.options.MAGX: + for lib in ['qte-mt', 'ezxappbase', 'ezxpm', 'log_util']: + conf.check_cc(lib=lib, use='MAGX', uselib_store='MAGX') + + return + +def post_compiler_c_configure(conf): + conf.msg('Target OS', conf.env.DEST_OS) + conf.msg('Target CPU', conf.env.DEST_CPU) + conf.msg('Target binfmt', conf.env.DEST_BINFMT) + + return + +from waflib.Tools import compiler_cxx, compiler_c + +compiler_cxx_configure = getattr(compiler_cxx, 'configure') +compiler_c_configure = getattr(compiler_c, 'configure') + +def patch_compiler_cxx_configure(conf): + if not conf.env.MSVC_WINE: + compiler_cxx_configure(conf) + else: + conf.load('msvc', funs='no_autodetect') + post_compiler_cxx_configure(conf) + +def patch_compiler_c_configure(conf): + if not conf.env.MSVC_WINE: + compiler_c_configure(conf) + else: + conf.load('msvc', funs='no_autodetect') + post_compiler_c_configure(conf) + +setattr(compiler_cxx, 'configure', patch_compiler_cxx_configure) +setattr(compiler_c, 'configure', patch_compiler_c_configure) + +@TaskGen.feature('cshlib', 'cxxshlib', 'dshlib', 'fcshlib', 'vnum') +@TaskGen.after_method('apply_link', 'propagate_uselib_vars') +@TaskGen.before_method('apply_vnum') +def apply_android_soname(self): + """ + Enforce SONAME on Android + """ + if self.env.DEST_OS != 'android': + return + + setattr(self, 'vnum', None) # remove vnum, so SONAME would not be overwritten + link = self.link_task + node = link.outputs[0] + libname = node.name + v = self.env.SONAME_ST % libname + self.env.append_value('LINKFLAGS', v.split()) diff --git a/waf b/waf new file mode 100755 index 0000000..67f100a --- /dev/null +++ b/waf @@ -0,0 +1,175 @@ +#!/usr/bin/env python +# encoding: latin-1 +# Thomas Nagy, 2005-2018 +# +""" +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +""" + +import os, sys, inspect + +VERSION="2.0.27" +REVISION="7960a1ef00f01e312c17c65859d08920" +GIT="cd0c77725e40d970ae1ce215d51d8d59f0a46d41" +INSTALL='' +C1='#:' +C2='#8' +C3='#.' +cwd = os.getcwd() +join = os.path.join + + +WAF='waf' +def b(x): + return x +if sys.hexversion>0x300000f: + WAF='waf3' + def b(x): + return x.encode() + +def err(m): + print(('\033[91mError: %s\033[0m' % m)) + sys.exit(1) + +def unpack_wafdir(dir, src): + f = open(src,'rb') + c = 'corrupt archive (%d)' + while 1: + line = f.readline() + if not line: err('run waf-light from a folder containing waflib') + if line == b('#==>\n'): + txt = f.readline() + if not txt: err(c % 1) + if f.readline() != b('#<==\n'): err(c % 2) + break + if not txt: err(c % 3) + txt = txt[1:-1].replace(b(C1), b('\n')).replace(b(C2), b('\r')).replace(b(C3), b('\x00')) + + import shutil, tarfile + try: shutil.rmtree(dir) + except OSError: pass + try: + for x in ('Tools', 'extras'): + os.makedirs(join(dir, 'waflib', x)) + except OSError: + err("Cannot unpack waf lib into %s\nMove waf in a writable directory" % dir) + + os.chdir(dir) + tmp = 't.bz2' + t = open(tmp,'wb') + try: t.write(txt) + finally: t.close() + + try: + t = tarfile.open(tmp) + except: + try: + os.system('bunzip2 t.bz2') + t = tarfile.open('t') + tmp = 't' + except: + os.chdir(cwd) + try: shutil.rmtree(dir) + except OSError: pass + err("Waf cannot be unpacked, check that bzip2 support is present") + + try: + for x in t: t.extract(x) + finally: + t.close() + + for x in ('Tools', 'extras'): + os.chmod(join('waflib',x), 493) + + if sys.hexversion<0x300000f: + sys.path = [join(dir, 'waflib')] + sys.path + import fixpy2 + fixpy2.fixdir(dir) + + os.remove(tmp) + os.chdir(cwd) + + try: dir = unicode(dir, 'mbcs') + except: pass + try: + from ctypes import windll + windll.kernel32.SetFileAttributesW(dir, 2) + except: + pass + +def test(dir): + try: + os.stat(join(dir, 'waflib')) + return os.path.abspath(dir) + except OSError: + pass + +def find_lib(): + src = os.path.abspath(inspect.getfile(inspect.getmodule(err))) + base, name = os.path.split(src) + + #devs use $WAFDIR + w=test(os.environ.get('WAFDIR', '')) + if w: return w + + #waf-light + if name.endswith('waf-light'): + w = test(base) + if w: return w + for dir in sys.path: + if test(dir): + return dir + err('waf-light requires waflib -> export WAFDIR=/folder') + + dirname = '%s-%s-%s' % (WAF, VERSION, REVISION) + for i in (INSTALL,'/usr','/usr/local','/opt'): + w = test(i + '/lib/' + dirname) + if w: return w + + #waf-local + dir = join(base, (sys.platform != 'win32' and '.' or '') + dirname) + w = test(dir) + if w: return w + + #unpack + unpack_wafdir(dir, src) + return dir + +wafdir = find_lib() +sys.path.insert(0, wafdir) + +if __name__ == '__main__': + from waflib import Context + Context.WAFNAME='waifu' + Context.WAIFUVERSION='1.2.0' + sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), 'scripts', 'waifulib')) + from waflib import Scripting + Scripting.waf_entry_point(cwd, VERSION, wafdir) + +#==> +#BZh91AY&SY~Uhf$m~d@cܼ{޲t#.#.#.#.#.#.#.#.#.#.#.#.@#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.{Rtcg^]=GOnw^[u#:#8vѻtMl`^.íU#.#.*ŭKH]P*m,5Z-]uAUQ#:#:iQisuww$ mUYr<Ǿ:)gzs2)A/{<7S]zɒwLfǼrؾǯGMuynU%TU#.(!@JaBà:JDv +}}/wBY=v5>ݺ}J#:#8Oyp#.#.#.#.#.#.#8UO|/`#.Jh6tNӭ;٥h#.J9Vδtdt4V[w#.5ӐVpMboސAA!@$:#.ҀBhh wcX8POs+ﻰy۝#8U]kT60$̍RikQ{Ϯ9^{׶U#.j<#.jk}^L]u+ww\ 5o{}#8[uoo7wdTDT#8#:=6n;+kfXsvیf`1xzwεà;U2vګCg+۝vڼknkfWw;]0;͝uKW=}toOVc6hRnўWu˭}}ws}yݶ3ow;MC{9e6ek|{|+wz:JlYҪݧ֓ݱ6{oٍjԱ72\sNmn/7۟cǼZZ.r=h`{޹>_wɶNMo8[i:}rsjiپkPNS`Ib`\aN_>}:OON mj뾎֝fmwڵm4ٻrmy:zghiwf[UvF哫3tRԡ+j#.8T{v]^;5,#.#.Ry6#8k eM#:UJ=kV+bLks.+Q)J0+ pŴ7]^P#:/M_l[ۻ*E!*Le +vN}ۡCJ{ #.NViVv&G{ڝ!g=]jNY85#:ڽq벙]Bۻ:Pj#.vmI WԘmDj4 n9̇X_vk#.q)S1#.f#܉ͶO ]3VE흶sYwdbg*붏g4{cƠ7v=z;Slλe/bONZ^גt#.MF=޶4Փu^۱k4&CPH1#.6PCm㹓RmbS{>-#8m(:݁v9*dtd5lr%-#::`:*cRvɰv}YeVw76 Bph m+ֻwtbl pp:D;7-t㮷YQk: PeNk)kUnt#.jT(A>"nǐ=zA'CuB{.nΕ=>`i[dUۻ]#8vfdf湆IйEma$fvn΀z\Wo^TPYQ 3]#.l#.Sڪ6iBє{*#:paUfn>8 TrQd9v=QmDd3H aòlp6Z(Es/gg[Yul٫{{SvRxuxlݲ)RvS^xL&Z{o_o #.@4#.&@ LSLO2zjdɓhO6OSOLi=A)B 22?3 ?TQ#.#.#.#.#.#.#. !2  #&TSSyIOSlTS&Р#.#.#.#.#.#.zBzjS)ѨFP#.z#.#.zhmA#.#.#.#.#.#.#8)!#. &@LLFL)'4SƚS&h#.#.#.#.#.#.FC@&h#.#CL&TTޔGhz#.#.#.#.#.Я*{thծkyUoyV $BUYtm)#. H"~#d_.1ojX+BOO>,<VN.bەHϥ҈QL?#.( >f#:6cbSKE+=bYGdMdhw젚^Q*KKCi#:bPN1XEA#:y^FycH.KAIҴ m Ib YH#.P^Zʪb&\֫q2AW! @ L p*E/_pqb U#:U)H'"R0E1S RbQhP?TE#. :PTI`eQt@MKI%1.zpSmf"F|ҡF((#.|DP( #.%#:- *6[VI D$IA%2i1M$H L"&̣DfRi#0" @S2H"j F &*eE[f16""fL"%RajjZdhjj6*6jM2#84)14-YMmme%),cjJ56QQ2%bD2A#:R̔FIR %)%l$Bld4Ųj2bLQ36McLMhMd lcX%4fX"%ZaC#.Q6[ILjmijHҚ3maIfdL6,ء6M*K!ֶVlM%1b2H)fD2bm5SmS$3h2TĘRY)6 QPQ"FȖHLHQ"hEFPP2&̈*"#8Jb#8J 0I2Q#ILUbRjK J$ 3!#8I5fF$,-RcEF RB4ViK5RdSL%)dčdX1Y(ڍEfI )%ERB&)3`*I&25 $IF$2"KD$FM"DQ(%$I"E0eJ!ZRKb0I,bT()e,"RDi$fvJL6cE3IK11$E&ɋE&TH"6&JRJ1TBDHciMҖF ʙcDdYBjc0!TJ m$lA24Q#BA  l*hb͊ěSL& ) e55 Me4Ś!PBF#:*#8b#FlIdԑcb4͓LFmkDF32̓)cdjT,؉#8KdRѐ12X,E$$JmH$CLl$EM2C() J1BCa1bfi#:fVMa( ĕ$S&Ve4dJ†HC1"!&lfYdJ&FjVҁDB!Xee3R1 1SPY2DL6i,`Bl2LBdRlR#(4*E-%F(f)JP&F4SYi#"#: HReFF6efBIcjeeeaa&RD2T #:B13#86$EK%0#8ѓEb2(X"JI 4J#8$)DCb!#8 h4&ZS̨ML“c M6fٖefѦa4)QI5fi1JLf&5DLHIbȂ30Q#:ʚ(*&!%F1JP&33%"i5 % U-,5(0S4VJB"5HIS)YeԁHFjTe) TfID6*3hAb#h٤,iԭ65 #:4$)J1e4%]6[fh2EBXؚH3"cFc35&6*6,V2ciY (3XKI FfKC#IJ(4 ,ƈ3,*($RɈɄKI# JT4Ci&HL4M1e$Z@U&5$H̤S!&٘6S,ddfBѩMDhę#lJUؖX3QhcFb)L14II2d&6ɨ*5**-ZTk([Hm,R*Si2Mc2QU"e-4M$KII546J6QC Flh3TJmEb1 jMթZLk#:iK-hZX#8EHk(1hccZ6ŁF6#&ڤQXLQ$QBdd&FiZ 4m15RFŪ+HĄ5 HMKl$Ah6+fKRR52%VU,JjKf YM6cdɦXJk(4H6mM#A41$I`RDlIE($KbԕEe i-Edh&*F,K,ȚR2(h$l20jɍ M,̐2 0-MbB1 `A$2[&h3,2FE)F0 2}\hل6HME!#.bjR66e&Ld)#:eҕIL,m%,4jIhcTMP-5E!F22JTkHQ jDjffe%QPh2QB(bKd@R% BS+j K&lbL6i-2f`-FhňbI*LfCbHZ*-1[A#83!4fYĨH4Q%Q,YTF-F($тY4h-E+f%#.i, &634%TmIdB4iJ IJchمDZ#: *5A5ARh 3(VFDbM ,D[%&ciWhĦ*i+ƭ5l$j)6kfQD@*IJEjI! 62X[2ĔF"ɩ)R32jA 4m3"dR44FH2[@KT#:(J-&6%khM6$DcRQb$L2L&4Ԉġ%2j-IbJVɭ 2566[j-b%R-ңZ#6jbP40+McE&Z1d%Q$f#:ґ3USLmYccXֵMa"R&T*&$r1,EiSQ(f(mIIV-53VфF $X!Pjđ1RF2A1PHə*XQ$I)ɈDmLU4O?/wlrML{kzKjL%W=Q$D? @\t2:hH٘T/1QJwzpgKӯ;(ݜ'FSaF49fR{Xj#:~H؛3^{?-GIc0i&L6pq`}!|sc۳^ЯɇcO xg h#<"/ ^XA.$#8 {5W³\I(l9a7  smvsq:z&X9N9 ugs[jw|P|ܩX{~~~wURӟE;W\P೟kf"opȧ~L|屆2s.B#8oyx6? q+#n*Tbή}k\jkۓ}Hjװb3#:B"K{}KRqMt˷gT@Ha1_s'?BIRѿ/WtHƁ5_ݻ[-I1ji +"v?QMXa1T#8vܸw궓w&f?Mth_5J cG⇓0''D,M*P"r{f͈MjPRlC1OovSGj$4B@uOjPTL6 I}a#:#:,YwbCJ(:KHNLU ޖuL\tŇ=5UNV{URS# d3kx"3XAKH_h-vd1)=CɔOlFnlGGk)`iT2n{[qQ}wO;. d{MݥCo(?{|Rpx]tA4`u}[^(6C1NʒR=wfPw"TMGǻ81u"Ƞaw>h k[@됤WxrƑ~<5Gkԉ׍XWZ){2L~锍~lKKdt@n'f=6eԙ8vzwmy%|zΩ#8W]ĦkDD#8< F 7ԡwݮ:H8@-ԹTNd8;T҃M3.>?ud&+D]s<|eM|aDNE+!N*-]6+w&4)Fx} Y8ȏ8(F63}Nٶʌaw&[HƪB*V61o&#8NoS^?T:vccq(5Β-A3+ H&GtU9x#E  Vj6h]L!6P}(1Qq`? 7=sklD7e1aBdݖJW(9X~=s7DNcx{6S#8ǝpXL7eTg ږؾ?H0(Da913oq#:sriF" Wm}d]Va!H_ѱۯÐRPM?\?ZsHP0Ra&(thYl\4gQ;񟑣lwXDb[cnlk?/։L鹂#:Hϡi'#8|9CMKp6|Ə\g}vV^IiuRww(RbޒN$Fω%c:::)䅇|dipyIND Y7de5gq| =íd=ZsC>J|RrPvTnf#8~K#_YgpUgs:#8Z0P~H=!:%Ghq_qʷM&#:TKo_o~o3*u|w#8id ᙹ)'2'Ee΄bFRAi`BhN%8|:OoHyn~E~Ox3%덲7ʧxI2О+]Fz|Hz;"oVSU.Ιm}4Qp(U?Z:|*ԾkM>YjI(!#fboL|=N[~)1X~LO'9M l/BraM>)|ǞN0*{6/v/U^gH=at!#.Ǝf!Ƣ/p$uʬ\#:R/g)DJ6 os"g0vO׺]v~G#:ʩ S SQCG(Lq.iz_'^Iǐubw>~)+Hxk;ZHT4`Se7C -2:ǣ8)u05"l4)\6i-iE>tɒy>ɫZ?[ک(+cjԴ]V *" p"V~9ӂ5x-1]('AL7?<~9g t?ek$0ik=I7b.̇emԳߗW"=[}Ϟ(_r8e**ni;ǮdPQmgGÕT>m~޳kuorƪBl8(A-bq@$轒u1 B0S1'J~&0p}#4! s֠Ggwu"? :p(ܑk|ktF"IsҔvRW4n)yRcgT4SŅKچk#v#R% K e%{yV~;V}G=U_ƶ][D2j<$Ӽ'D=3Eu_JN-M*](sφa4hVӷ?c@g::p8(w`ͤa#8wDv5W˂L+1y0򚴍ɨ]#:GZh(^pK|}w:P##8nd|6khv7NaJj._2IT%?dBo~+:{-HB<+5}sБfBGJ#:J)Cil_C:1`pQ6lu_[F6Pddi0fN:lqә8#:)06x fs(~Fe.HR`6Ǒ+v"Q]Eq$OT/"=x7  ;aɜ.$K]r#85_1Pn"#8K g,.(z<1{ȉI^ UniRԴJwgI$EcΪb1x4CͼYFϬnYwM"MCEx?ѭiӬ'߂jXmnAG,5Z|'nOvUvǔxGO53hĉ-6~ۙ}39XzLO#.AH~4kɷAhr(8vΘ)Ύa#=s_sE'b{Gp(aOFZR.=;E23'<#:@[=|#:.|'!O!9h*nꁪzXh-v<y*-cp gFe 9fۭOkbTɽZ;;:Y W&r*((Erh(w(oZTg]XuniyƔ8>}"ZTUv7EZu\@uP?GXߩ($'ڞW宷; nR⊟nSI^\mѪ2C{}qM Ru-R&.+% c7EE8 S#:4eBUz~$h8@MZ#:#.&0eX Q_p xGRO1a;ّ_eƟ rq>#8#.4z K?(L#EZ+],CfKjr}ޔSͨR?AlMe2F"H9D,~KNݶ2=gYg߁}>;ˉ!.[1s+Epz2;#B.Q~#8n%+\i;2%&WIWke{#:f\ٙ,[#8 L1zXQ#8UҘFd- K'̦"#H:37u#::2HbυIHV`H~La$K$#l*ΫHS2Σi8$.$To5zyc8D5"7@4aW#:]bhM{Mi2#.<@W8NiCy7>Ruf.6ѭ7L] L,-!WnL"FRDjI;6lVt7z|2_ $I2}~g=μ5{x3߯"u-f>C[÷MZ<_ЬЄ'L7Qu9p?f߇#8t#.,q{"¡YPtj]"89]j9?V>zwλ9,a7m3a9Q3M"~C*f+3jT\*~n4UTlo/ ܓqXG Bg[2wo\Yiyج+VG+ R•fs#.QyFw߭(Ub.P vAz_puI&eA</#.zJ$Rz@R-̻ͫdh$͓Oh+L"glB̢R(}OOm.ȟtVK$mSV&'I;W٣?!:5wkޏYKFFtO{VCof9^V}ΐ%Xv#{ޤ:zv‚CEĵ69yA9.b<2uR?&޻QGH7Jt`n'&|}Y5^J|?hO/:_/LloƧɟ_hkx,R9O֫3]}N8o!l-#P: 2gu!qxrPp aNR2#:7=! s$w-2?Nbуo:ox^рfQ6[%cF\y{y2R'Yv;MGe'Jn}G=PZE}+őfh*}VepbׅMj_͸"]TV!MSr5i{VUso$kg{n.ߙW/;3VM,X+lِsauf6׭MZj*󧩖]U).\o+[{ki[_lr?7Բ%#:Ip]ݡˤbʔzδƚd;nqގ:T~Z g&w˗6AXO¨P]^O_Zq'T+bsI3>b֑āE"(0DKX#P\}6nPS&⠘(U l示P2#J~E"icZ keEdg\DD +(ޖ#:@7c -)AGӷ?S%xɒ/tƩp?)InCatU #8s2/d>męG@k*`ە|ݑs7>sh&>QjhR9 ʡ&}2쓆$* %gF`F1A M,GBZf_Y*GLq`#:'c& 39s/לk$as O|2̼*;,z<;ӭ*J=5<vA97%~+g#8ЌpUW#:#8܌Kۘ%x#:wr$9%$$)@W*#:*Z2|?ƦuY9G>9}q1ĺa^NgҕUԳ,A~2L#:#:Yʱa="3&5@ᓫ3n#7xr&iOTCeprN! zM ^ؐPLzߌةeUwEb>ap",dlUٔ3g4,+P32:}k"%!ަ.rȔqȘi)o/[FƭS^NQ2$bNG LZmkF&K?^ 2g;0I|5xVr4O ,k44Q4hLO靭XpKMgx 9R.P"R㏻#:VDULC'ֳE$9$P1b5jJ9Ihpӽ Ё_gd X_c:3-؏P\ #8YFر";7LVww\PDrPnȣs ̊vPֺ<rsj#8bn7AN]ZgaKb!RN&қHy?8Z,L(mt?qK#.ϷO_ۣjuPU@kGH/mO#g0D"{_뗡oJ&9 *R ')䋪v. W| $>19?e?O/:ij76xHӹ\ՃOgk Jhr]prЪ.0iY9(C+T9aTz=;H/IFl3nTyKUaj+xh޸]w[meH#"eGiJYZ 5U)a$du:,{M+|%QtL2#:xPy;Q%1q2Wj20/<_Л7;ЧYTys N'(ھ5&ShY#:vlpc颵(޻O0>y@~!! 9~q?Oz&EuR4P"¶+0#8s{#.~>t&4-#.PoW;](#6ݮxx+r8(;Wt}XH#.{9#:DЄ#oRmf̱+ZƱi OZ F/T}K{RNS-7]X]=B(q@#8bG?K5Ouw:WU@#.^8uMĪ4^ #8EXR#:-EƝ#8NאUњ^Z;%F58M5"78וuW^{Q\H?s~ 櫇++e[m4&mJn[bLF|#8>(pC˾;V>#8OU_J~Vgψ˹v 8,1G~ߋ9Q$0Yr۬t$MRM]-g"Ѳ}u` X4on#:pyq6m}u^i8EҨY!I(^#:F`θ/a[K].wN\{#:ՠ„t2TQW~p J (I$MV.`QurGh+Ɏw[KԚZ5lwD7aiF=.Fd`uur\1;LW_Y:`$73_%?LfB%P#.2=rskx`%q2f?Wns~P-&}+"DTGQ;XLFC#8^x2ǻ6R<-cIXo7n1g#:m O#.d'/9ȅJىc}`ϟ#G zJS3Qa#8e')<4>ᚔ&KVz3KU-38?E ԇ1!,,Iz0Q!G_'fnEz9G0)Bo6!zPOsSa85)-t%T_EH3t<#8RIh#8C?/Ģ7I0O`=39A'Lb'EM 7zrh:}~A$Y绫㏚XtC%㽣Abbh!GNo:~ssn҆8KΎ7Hvt< &<#8GknYK#25U ꛡx*~q|yZgJQGF08l{/2dH[m}9eF#8ӁSdhskFZǘ"5$"ȿVn<$cEO{ʩ8,U  fHagx^qGT\@5Bb D>$ǫzMǏ 6(>ͻNb^-\p`OH7"0X!\hJ%j2+p{~X~{#:p d.ye? !6ĕwb2CI,4Jd2P%gX?G4ҏ͆#81Rhd#{dj{jէζ o)[H:)hr|`V Aڼ zظ G+?Ᵹ| wWۆN]4#:]5QѮQ֭}9c+=p#.>` .T˂ц[5`"#8]tckXjoZI>}o# %|,#8.&MR~~.$ExqݦZmW7|:&gogG#8R0E2`4)4[0VEO{ΆJd ="GƹF陣ds|_=r[bL̤8b)73)ֽV3BЍAԖQ3\aq+niEw$"9oA1#.L@Ȑe,(cC-@h4deEa:}6#80 t癭ؿr4P X#8;Pـ

,QD]Է0#;X͛}8/^7lM;'Z D~oAuAuoEy(TKU p5YA eCB)@O +twOҢی|ز, /=4O8#:#.RB)A@Gxl/#:@#8_51#Ì<\O'_~6ZRkgr"t,O#. cyqZ#8#+բPO:.ۦidGagGþlZFMn[u09Wda،Uy|,]V64#8_DSUW[G}iaO/#t ñ>pH˄uwoOlFFOrhX^ډC:FZGif睉A5@~ef{ٻ*I[2|pY0;$7k?zG.% lcOi] NQ3TۙԶڂQ+>vX`j *`ޫJYK?͘ `轆p. g = uԏ#:\FG]||P $'8#.aRnՁi#:C_ۓ~EڭkzZi$ڿ0Qh')#:\׳!;X ,PlDHN|'~#.< n3ϑGl<#>ohU[|:I563rj2t c)#4Rfj{zHؓTϊC4{fP#?4/4V*uT{󑪠Qڳb8=gBbdP|-"zgrLg(eȁ , x_52Սz3/T8-8Y߻QH#:7-7iF}' p~ikjoM;:az!^z"B|r Q)#:RRl*;N(!Ɲ ioDH;-M{&>I.эUoaFB8wGkF^1ti\zqnǏ/^k˘Zqsof~ 32ΓƟ0=>YPp׬ȹ%z #.6#80zlY߫GT~x\7pKYDdv!/*P(Q7&7FH5'i $E-S|4 SnHbe8J2#8ynC.#:3#8+e#mU_ qhis(ᦍeXk4J6y7]"85# @;T$#:#_1#:,2{K7/JUpfkvB.ZQe撇<,%#:#.QQUM8;<tLŻҍ.@G(ܭaj.LIRb c@}0yyf?eA:ψv/\!Y`Yvlp= JtXC<0pń6it%5|c^ڸ uȆKwmISSt8+ND0pp%Ews yեT\jQrkfKMt۽ k#:ԫ"\S?keT#8h-.A8LVx8tsqe-̴c5-#N#'LoZD>~XQN$s^390$\>m]F&g<|N?ݾJZlgkiRw;b.j()i#.+n8@m#8FV 6Wf;9RCgX!G@3~h FF)l0NIU bLfHJI&>,$AS!bwtoោ!.dG%~7S#:0AF Aqp(,f$R+QLĹL行a@8w-#.xe#:?]R7f4 $Y\ =hp(΢Ku魀DNn+M8~6alAV3p=i&55UOR}5%>N9\#:=ߟ+>e4'_ Dh:-gQ-e#?iO=3ѱx,ϗƻ!kI]-r倓U(2뱣罹:G9\kkF|_Yo9{Um7a9sg." ^ͺ` X=b>HvoWtšlz q4F4)kr#.@ȹZE*@Ѭ`+i1xI3н`NN_4|/jG-S,\5oi g,xP73yiG7GtUfV$WE ]b!#Л6PT||#:ԨZŃ@.K@u".E®JWtݐ.nAl+#.YeBDm>+r-X :i,!SJb\/o0BPs9Np9Q@)`ATn${ř2$\v P =P4қWu\DS"S'Eg'(D!i#7 }d`kE mnd2Cu\#:]lz]ŃT-[:2 #.dGGSF^%aOfcn5@)m>q1]K&-zHw& kEmB40[u,&96MdGeΑT.(B@kp2TNbhk=AsyPPր^)$( g޺>9= ]S6iL%}X#8WkFqKKXDeEA9X߯~<\.1-sH 9,Ja#:ۯpҮ6>|B#.){T#.ܪ,j{»<[|OH q|1!(n<<+/;qQgoxIQsI"^w p{<|!^_ۛŞn l(Plv!:GUP(}4evw8:kwe?a# ^)8^JQо"7g9l^#8|18LQF*M&XPlO#:9χ ~ִT?3/phNnH ȁF6yjsXّ$s˃ ȁ+DŽ#8x _n 8n]<ɍ(0=@#. >ogvB̐#EQNXL =i?WH$Љs#8@BA!2#.Rc`~a6^|ggEb 6w`m͔OQxR טz5mI]wdϨ#8HO]]-[>7W[?XAR^~BB^p9;$bg 'THȏ63H#8hY nibNI"-&|Q>mׯ9De]^jVm})~M fgq/#:@A.I].qs&'o\&1#.xDHdĠ/Q)b-YRA!.KvN0vnLZ;)3ŒR7RC0j~o_;\Ӵ}2#$FЭ82V 5"1eLILY\zPw ?{OY=###.xߟby1X'>\$ޫ.@$m@.=Ue%Ʀ]a6 H^26LE,R8l[zu;\w6~&f`u"9S7H"S#:#:Ȣb9#&^3>_j\=І< DD2wW_ߗ-@M1shqûVc9cq"#E1[+/wi7U Aw2#.DQwY80d.W #.#.N~GL# Nji#:o#y'6 پPv(C85Pvel d׀nd˩YbLd)ݪT#nm_y_Lq#hԻ@>qjHS!-z6ODTiE5dzCD@BaX(SZ#: O9daciteȉdVZɐm,$Iȇ Li2ĈA$= !apSېnw  XC>0r@5&/R"ƜfpRp `6^hɷmpW9E l[$NƕكNt{&egSmGX/nѤ*]r^y[+sU=R̻K}MǓV&ҪVUa:ߍd҄if^I[g6^GJ`7j-#.sַqIMQQZ0`ָY9KbjԣD=\Et^pB2nC(#.1K.ھ`oP(KC5'DZ=-$quj]T|2(żw ި>4_6 y1)_xv<F@41?\~jkjxի_E xoc#s@L(Q f>_HuG(,;GKcNS<%#.lR/T5}4)5杠R#smM&'>&@┱Esx$~3sf盕U0@Nᒭ|Q0h0([nܻͲ(V;V{cESDv#>DL*W<5xɎãC:/L*_?Z 6 y_]ѐ3u㱱N#8Ŝ3 \uO~$#.qP7lGL/ ig>Eإsϱmx(-By)D^8?bY3o8JrC{vEj8؉NrH@K[deaQ;fMxRxŝEH"GZ]:y%i;˙ tHlQEqp(xpT"Կb|怾QЂ>h^v'UjZR.Nͽ]-ȦgTO$EK]muEqyl#.Q!Sc8i}sOU=x~A ^a\7.OdkS~HuGL/gq)6K8֕U0>Br>ѪOQp'2CscwABlVDjǷlsq "0l#@@RnB'1`Ok?# QT6O)/9 '9\@0p5>qh,%lI46kvQU0|;C$kGdKfmdA-b}cm9#.潸Fv[<˃xX~A)"˹s #y짷lr.!_͢WfjQ[ >W]pep""8b8(%*̺=q}D̐rm켮%I %Ṫ̹r#8R  Q[|,xY=f4Bb2#&NY{S/&- ml`y0O8G7BּP A-d#:'K[N7ߐRhGǝhkrqEITQ̪n+*Ձ~XG3㯖8 ۡCQe?bͱ'3/l۞Ưce9Pސݜ :{f0Lp&鞚ބZ?i w35V ?%_iq^#:;%˶.1jf-#.(Ԃ" g0{guLŷ'.l` pl/rIIr\2L%(Q;Nx<:zZ9\4\q-JJ̀#.kרXEP$ TSUHԌ p)ExY8j||bc117#:NKEr8RI'Y7^+Qc#:<;|E?tI733ϭo4t4D=xo]5؍#.S+t(+jQ/I Fm6?Rp{gSU_.&AsgӠb!ͪU|DxG~]ԏU)׾H VJ*/#:l~!D{6/kDo%ଌ^#tF`E*Ar#:#.֠tѲ/Q^lkK H$0.)iwK+9sNj ]+va#8Eڏ aآŜȍ䢷*9S!#.~{h"AI-O͵I.VsS#:dV(v0B!%G>WȵԷ < Z,#. PhVu$"3#8)8"{?Ujv9t4`\+ݬ2+P G3!3dLP2Z#:lvd #.h6EKߒ6w[Nd\n})NS0{[iH#:[?#3'Gu$MY)~KZ!ϔum]3=DrZ䓈w}}0o[c]bJM*I ]0KI$ k㏇6d҈|m<_]M\ľ{+!#,>giÚ4lcʺ˓')ryێq#8\C#8fH j$Q%S'QVLm,Ĕ ~Ŧk/) <ŶYBՉl0\FE@ONS-K\V ge̛cq ˌ}QJnn`BEUsr1kQ'K&4-UXGf'ba@0U `v<#:Cn5@uR%u}jo#:lBH[W_+|65>VصqD1ڵ` 8Z>Oٽ!a8>}BHE6u(1I[j\\'28-ͷ]_@xtFژ#:7ͯUhTalfi9ث/[#8Hd`ឱIەu8Z'bp|UHg7)llR "urn +|#:bKx%ZnCSj'\^nH jus߷H=}!fӑ#Boԫ!m,E(i= 0IÜ};'P!X` Nx!f#If J0{Ç;jeO<ܣspm: *>U2 6#:]_ɘ#_N=NsfJ>kmgGgCȹYsJ)s@_e L3#s2׍z]WRԸ[ tO÷:fU\- Ŋ>#8DD{X(3s;cY5?٢UUjT ̄~ESs |A8JU _ɵ#z¦aVqjۋ\ګz"Q#.&M_yi$i%h"w/>5㌩>{5@al#:j-OoԘݧG1ߎmH,/;cRZQt-i8\9>ܟh7FF6~b qMT =U,.--,\pI -\6I#:s"HbbBDxpk;7 |\XA̟Tyu_QRSQ3R:BGJj Kj$\)xd%^֜g |_Hݓ--E]+AKyHyN]Kb'H^ޚH8w]IvN[r~!?+oλO\ڃ2+L")>3H" rR6ʬ -#:uV#:>:cSP]5 E#TrM$#:nsꟽJeZ%O?8;cZɜ}'};%u2MT1ϕ_cL'ivϜ 'BmSœ=pDI=?#8h0\py1'!VRB%9u2S鳣%D/(7[x}00;|eBaw7ِRm(/4zN{wNhQ-Zٳ)XWlg)mE+aK/N.\Uj4p,eq]JP5֨[9Q(&4Z9FsrdA -j38FfpJqNfKN*]zu]& nƞW/`b叡i 27#:n'bV:\_r ;{h+[01đ ԏ۰+gGݣcY(Tow䫞||pM- N !Cm=~迱ӛ-sa,}`8:Q: ۳0a0&*am#8m(Qiby/䞼 E;,E`N\H]Q*=-fx)5w"C,+)HEO ]N`~U@HfOK[n%Em#tqvFgq^jD~p"+t#.#.%F @S".A Fb`3'ZnQd BAN@aJo:PEZ쾍y돝MX%NWAG:"#8v o%:al~Jɮ"q1ҷ6+Wv~T~X |لV9Gk#.Ԅ,Z#8)0i"&Ilt+!4ks0#8u)*ոyEr?1 wFA.e%XF_o#: 9 4!lpi ?x4g:6FfbN #GޖFB|~w>v)β77%#:,W#:']@]wJO% LCmV|jY7j~c72;.f<&P&~\a-m;`eX 9,rSgG/#80ͳxkd+M)_NRӖr/Bԛ<[_ڠH}gԎ=aKמ"tA :Fjuj\6ǣ2boqOGi=L3G=kZ {:zL\} {zuwL9^,~.M$k.رMC$#uˠxa!y NҒש-"d{)WsVzP]n9NHrL903`xΔatdv=;\E(Z(tcYLiMQr#.Xpݠ\1.t#.U2PnlAڢp_qVZ>{QK$"S3Iݍ5AN}f ˳ y% +GcؘG.p#:?`@_^nXK7~']9E:Lɉ@_!VRVX~okdg{6JƔpl0>|/8 u?M@0f]"Jy#4cԚ /̹BW1E|ZhZwΩ׊d[<:kmC P /|ҡa'Ou7GfkGK\ls&bOR2xw0=\h$=#:)\UpLa'ME ~Y?X0ԧR7hϟy d8z SBmv"0jZIr'eU#F[~c#:aM_W.Uʤ?QJSOT+,=-m:2P%į։ZxkMw~f]sDnmBrvUmeV/AwATCQ"KB08j=g/ϭ$XK̿zxwxVК#:;j<@^'#8SvA H.7ylXda>B)]1WدٵfuCsA[fiL+c4r$EtZLٜLCú<Zc~̃w2j`14cFiǥ-9n6RYPb13#:.M4bE3T.g/s0TsLCvFNߍxֿ^RUE^vFE:J@:s#8RcVs΅=&wΆ++q Q.% xPQ2[jAZP5mG\U0AYc ΄j+#:QܘnKs[#8@%ҵSGr3P ~l#:dobUQ>ڂJ5%ɩ"]#.3Rf+p{**2F'#kH*є|._>-~:*'F7&0j7SCِEu[GЍ|4W9ܐkί#8LPynQd`CzRc``<\MC8@U2ɂ>x=Oֱ4#:,!#:^2GEdWƟiR)*kVl{<бQ;:<l0h'&sEQv-Z'dzڣt5@stSb\oR7`" aC/J$ c#VOٟ07oz'liyQ'z2ŋ[j80^Fb=[/UhV7v8P]X"mzBv[k18„Kw^0(\S@(Tr@PdoS%g}eM**i`J02""~#.%v<:YvW*]-Z_K fx#WL ˽@?Em/g䶔錬+t7e:D uLBl*wKoUjU,1ksű-YAmpM,c8<0`_fx<`b#8;"{<+6\Yj#:\aq^}ƹ]ZrGj?L2-:l4>#:z%󦁳x^>*RX7 ,epRQM#:W_$ ̝A/d*:VT:vhrG:1E D:a+@0#86=v@ZʄE&ʸm/vM\U*ftbM@=-l#8Al? |#:K57!XV|ʒ6(`5#2Crg]!3.D[o7ιZ;>Xk+NA6aO 9z2!oEp#.)Z^lUv4@mضW"lVf6@ bĐ3b$ށrbZaaBmqfߚ~#.Eֽ ,܆K0LO1ўo^(r2O6MIWEC634ٲAXo.Ru[#8yIk{.qG-o̘6Dqm1Izk5Y U]n¾m{ ;F0Ƕ5Dj(B U`7u۶|p$s\PY]m&>A@t#"緟[xvqCКR'Uz$;&wu02mS Fb0ړp-^^ηiEnpXk%ԥjM1{#.%D4C=Et֗=ω%ɝXz湺!3?8X9Zg˳m\+OI6s.v[Ɲk pudgkU_"PA,"kzXb?)x :bz[#.rZQqWtt@qԚ^ p1 ܃OFl%X$L95t@6<Ά.FO|d8;Dy)ڪ/vn%XR/)E݂C" _.)XÛ7A#H+-mro#P_XOjyؖ3͐,5g$":]҈@ߧwBevioE6qzC߰[SzlmCiڱ L#U6.Tj#8+i]aeM,l&6:$h$cR7feyn/ő;%Q5~ҁ|Iܫ҈ꋀipk(z*O]XgR[8e`H&'Wp}u r "P$늪 c:>R%wk趭Y8,JV-%[ΣmnHl9#Aw#8#: }=eG7Gso.֛0[ऌ:fo[Jr~M='UưM4ć?Ǔ.3׷#5gq&]pu\=b0y!o[ʫHTceCJd%E0Orlyw2|x="?Oe)N<zY#:β,Og$0$ܝtv ZMF]v;ЩNɚ2B̏SiN"'Z6 cp#8I",9pIhګ'#.*}eJ`nQ:r_=n͝bae2*8Lht9"6#:afU&bcҒ6BYDlj0YyzPcV0ΦEm+HC"%'PT|׿~y{Pj䀞K-T2ij}-]mvyC1؎X:K 9y zmJ5X$G~ή#.oCƵ`DUTCCli@[`ϪQ_J#.h#.0ŮtYA'o8f9 Pp >ˈ"de(-%y#:5EQ3׋!!(J󲆼m#.K¢! #.g#8چ4(5I"#@00R#:W*I4ލ(*"@R+"x3Q0JԼl۳ߓmqye;hAsi,m9DǴ:^乤Lgx΍%4R3>7]#8o)Ȣ58NBg7Ya`x#..#8#8*oT:2ZI*XJ08$/T?׾ܨ+.^vq{^~q6ՇBWAaB,f,w5\d0y|?:lz>ԫ&S<&v&xA#:6zkڂۍ#:L*B2ka|4v\j?[`Yl#8 .q.!jlAuͣ`֙ȩ;,*ތ`>혟Kxh6,oR $DFx-q4Zwn=l@f%;kcd#įMԙ8ь&γ8ud  /vM8YI0LP/jLy[$q41.ȣBa:j(jzqi=Nl- h&Mwk{ٮ:@-3LTnIXǧ#QA1|!0h]N9!``tJI LZ#:1TiExxʲ꘻žL ƻ3m50=;F嚏9W"ו(((1ԱN9sg[ΒX8ȵrܓ{?#8.q2}avMpۉhs]b+6x 'ƜEMmk0cl}fg-S&.YR#P"X#83Vyb[щuf"! B(|T-EQ 6#:y$.x$m<ׇ:&H|{[VFrP}3t?; $d>w#>`/06;eξۤPF#.)KB >rLT߯SRf0[b2XǙp[&4FG |*`)YLIg;D$]L1CA#8S6_ 6R"T3#.PZWERJB0W$:puL8#:^xb_+㾣J3]zAKC#mٯT~w54$ϡju#:;4[ڛ&C~uvOKzS~XN >T#..X##8I>1aZ>%S &fMO #8$z36إ;P3cP#8$R|lU?k Ht!iƦnG<ʭyb+ x>Uc粗pFFobFج5Pŕ's zy8F߫S*T#:nVțD#:AT=F;S0/1OMhn.@H/~\(E+9T:_i\B#.$mWKrDJFҴQS\Di,M䦦# Y;ӫyyp&W/՞F7O9|t  iK+(SS+&:LO[#:[DDŽ(۱붎硃qc1!vۙ%39Ov G:ޏN4Xl'BL :ζ^׻ E slETU -g^7dЁ 4Î,ID"%LIJ#+=Q0|8>^(0S{rp>ga;@x' =Aa(gu)X='p[e,9'˽ `n.F4Bwy|30[#8dwlqh:)#}gL8hl{o7Cu M(ԩB)Mb,4-R\\Hy!i:w[ܛ)(x(RD󝮝vci6]ޭl`f'& Q<(^[v{<'F qF-i@9kWD=s4:pv= "qsRwIJuKdĜO\? up#e zQ-Cߓ̀Kz N\1Ctwq5?!V#:/oL.%4m~=as6.JYZR㋹\{=Yc,3`(75퇶v=q>l:$B#:=\}w#8)N`;F{c[m?,vv+Zj3oeWbt0dqw!RU{.T_8Bۧd6hdh&iaiז wnٔs;Xq՛Jɇl!>+xMy$=FvraiYv2OF#8J}m57\Ax-jsyPṇv%~':;ƫ(w;>ػ4e[ 3zD8[JԡAV`q3X%ԦdIIB澖:aPjeRRRBwj*Xm 0J\ԋֵ*Xy;N).sUf[0#`.Z:|c#:BB$$C"l"ڜ[Zvڱ}v2p{"pab|϶YK!"#pI/1uZjXd0/;<(&4-bV(ō|DHxҎE /nխη9#8˲Ҝxޔ"cb AICy1yN:n}'hsZ;buN<}Әo|\q;8UU+Z0(3j&aWXh"^+9rcK*O[N$=-I,iCgUul۹O|mU5f˧#9Œ#8bG͏⇎ɬ^wWxi9.c k1!#:mwBȖDǝm#VQ=,]ߐ7iqobs=^4UYyhK]mOH#:aNɎbW¬uSq8h\ƪQ4<3925 FCViu|\,sk;gY.`>< ۻԢBy#8($a-n(yhJ#:3CvR@*vۖ#:6%IB#.qWB<-[0}Y`$#:xA8J#A ]Y>>j?$I97m#:G3xQx gU0#0f"1)W *E ,X5Wu ŽǛ^8#.#84C%`=C}s1Š#8hdC-Fc&kJVȝ9:B"TΧz)'r]C hQ)tq'y:xTk7:w/> #8*=g!$<|]xd2Va07D$م7W:|/,Đc7-AWӿW2%r8iM-}U8C7(N [S9gIL6Wv3~<<7\&B[97qxoZo4ѽ}I"2gM,kdTJ#:Ȥda7Cfs]`h+(u 8Ŗ[= Jj#8ӟ%:цICG30Y.Õݨ0 D0Q iFvڭ3S!ef$y%-F;o(~+r\mH #8pFǿИ'd KLpafPaĄʝkrTI/s'MԼc|.~=f9x6_8Fs6é`>ph`+mط(z!3-lܿ&H1%1]vc)1ִ]=FO<* Nءq$eCn,k A-#.LR>H])d#8ta@b;Pǻl=#8uVO4⁣YiCqa%Ҭ7Kyl%ܨGmw8$y[ j#pXk}kbFh\YVqL %#.H$*#.;fWzlpt?.#8@Ũ#8#4XjZ8NϹ]wB3r@$?!Y I-*gjgNXZ((#87!'d?NL@zSD'jx*M 똱}7w#0//1c>OyJ̿(tc'h sOIwjGQ#8i>Ӷd= S60zo⛵W s, F/#UQtwɅi0] |jHHe0!4M{'k_ (*X9ܿ+͚AX7acwI#.gk|⫋ȎޥvyPsuRA}X6;lAx׳Ͷny;Q^%Y1_uzd2@hߚQHh9$z'@ 5Ȉ6qV/ pe$P63 "g_NNK$xK6/ne L6KsJ<ˣx8}o{x]O>=#.#._ a#FG(ѾC *Ҵayk]+(2 JW%\%N8m֩R<0X;x]`F\f+sS4?dt8#ၲ VeCzkYvO 33ê"AmP/L;9uM!itd#.<-qdLyd6{.ٟkU#`t{PxҾ3ͰC0 BVQ80ۙ#:!! !Xq+8y;Þx Iʩg9DD #.$#.<[C|?!5n`U\Cɇ Ozh5#gk7U\Ǚ#8j'ž>Ur_-=l5O)@>#.5X{%M]Z>;€rB"EC󓤢"z>-p#.r&#.8XI{}x߯^/i@#.p2]KJt>+P&sd'G<Khҝױ#:;6$DcmQl"7PY}̗_˓ݜtil'ќ0wuf}7㇓mF5:"@#.T>TCEC*S)2}Մ$Ï;T#:d"Xʡ y?eW#:HPD{2Ws&E&qGN_Z({rCxPC@d:3Au >ZՁ \ex}ߢiDm)1Db)5H,3M+E#}.%#:I_|Q?S#: sBZ0AdyIj*`L#8Ώo}[Xq|0h࿯#:x:Ϳ6_?!oh\.JGg<5@wNrNq/ef݊q붼ewmy<5Q}۵Wg=};Px#:D~0T/]I$E(9u\#:9aTI]hKDi#.AJ3+OGmB1mȑAmTRYJ5͙-&G 684dAWiMnol5hLeة.aQMd6g_/o=?!|xCĬR¦k#86:߰=p3v$޶c(ފHHi?tKpm)@4v4#:ii$0ێ!I1ZmO "ԭq3X8aYa0լ1֊F{@Xj놕iTQk ]i9-EIM* %Pmw;Sku;L#:B4j?]][MC;@%FZ)N([MiHVuhm*SI}Q*bÎ!I#.nO] #. A#8!(ȆxBT, o V&tBWOKwjՎP׭M?݋_BP o,ǁ>z~O |w }')5QJ*}NS6Mb6/J>IRK@~#:is pyIGAϪʄ=Z^vi{Tߺp C̀!Uo#:3~_ 1vc/h9h ?1>AU?Uqxߊ/`8L$Mx@QP!iukm-~s2_9uT1b|#:LT,:#:=4Q!9vdQGBZвX}#e hFwŸ~fo t ǎ<ۯSV̘=k;4Jr^ Q# e:rFx14xt윿Xu-̜zd|}~8ҰۦHnny}/g,5_1xhnr"%G"ޥS#:*zZE%IQiA;OT'^5xg[#Z_YXG'P!#.ٝbv'X((IՕ&)SV5Oobث&CBܡ.dDF #:4\ >O(@`T]:$}9~=_SyuFrNVE(IYeەlˣXdNnʸwG;$U_<,?v)J&'Di9[џ,#.!:95&Ϗd8nOOo eS3.'y|#tǓWfY:;1|9ӟ ]ovx6ٿg=Cz]/- %/|5x i pW? 8!mT,(9@2O97Nȧ F|vu|/מmO"Nݘyփ͗<2x2yoWoPn;oѾGeǯTi~]a#8hٝ"p){R{% :HYB!BIѦ&&D- YPBqey/?~6!>]p@G{Ll:}Z뱻@A|e?&Ixp;3`Y89rnm8t^=T>,~\Dx9(u`9>ky}qzyVq~V>LCx7N#8al,?#8<b~?+1)qAz7w4[[>Z<ޒo/_ÛApuw4n-ͣs]٤O!^#:?f/]&.t.|C-G=x8ziڟDn>'p{iz?M]j/3 .};Kv&ۤGғK u!lǕ|wr΀6xWa8<}l8I|^rꇃdž._'R %{|#:iqի.7F?~#Tlᗺ۹@F[mtRobٻ̿Lr'x?Fs}:~/&s<ڹytn-bf~짏~5'##._O\vϗ?$n.Yngv{vjf3YP9OըmC֞lMjH+G#:I z(! 6m̋5Y}{Y\t[ Ƅ08,XsW\GGM#8$mTX#8LV*K֞kfB7 ^m{o9qM1IOϳ?RTk79`q>k/*}])\%nЅzx_k>`e(p#8nsj?co+KjnݛKpODoPw3R=cȎ9F'e#.eh=]ȦUceՍE`8mQ!#:R|>ww͞>m97ޞqNѷ-ngdO#:r;yxts!ee{bqe_񼎘nt/Uu"…a]׏^R\N]}0l|,5aӖ#:ex#:y{K?;?ф#:}̄j+5}[efkh xN3=}Ou绛^SHTRNNiho&Xx^>c]tcsx]w|0wٽXAQgy$%[b7{ }~E;qϗzo!(%Guˆh>ZV:ؼoW?NQ5__#8|^ xCJl :jWrVgM/2UGln[')òGN, -_u;x/<v@?i#8w<Mno1ؕAs#.l@Gp).ݡŨ"@~؏3vDο8k=xwzF|GGBErtSORRv\Rxj)֨_x9\ȉsJ)8&"@*)r0&du:ʪQq|.Q`@+|c }|V<&lM0򔆺-X8FW 5["C#8ovȁI%McJe; <]!#:%lbLnMeDDR] g8zkRbttL&o7Y+z%L}Q=~qfԸϘ2oAQdМYNJUi7IڊX@R#'-sY6N#^t;:6NQ#:}FkA:5zJl;#7IKvDrSPB*c1t`4 {Kv8JJ.lO_(/=b#Y-8r!xIɫhCոd<-!'XEVxڬt1!Z) "T:$JRɏLp#8qC#8}jOGkh:m_yy8y:}'jW= .Х3M_N0d);IE51#8* VvrsE"?{aw<&}9U$o2Qd7 ߐYX lOoKXA|#86Zlgf}6GD5#iTP?d&Ε/0ؚYUPZD*k+39WnЭ#8v1VT9,hOQcITđ7KQ-w]E `(On\U io5uZZ5[֤8+B4cLyUaYm\8X6cZʠlcDj#85xD#:>lYF&g[d H5Lb8]'mn=h( ?s:ﱻ2N.2kQ68UcqB82XIb6uC1bR#8a5#8&%6g1OKo$lL;1Y#Xbu1"hubMi#:c(4Z)(##:X(*)%& @Ș#8#:Fc\J4dr U6tB87N=qMl Nz;su.G,J>(P (#0 WX~`zdaX,#. -YڗćTR }nS0$,MU%CC=^wy#8FWφ#8n)8bA[4/*s(?hn)Bn^;{\{JA!4-K%` lFCdr{|#8՚5&[1/bD1b \"YF&!5pNruSXO)#8 3nf\owFd4@hOLiPƔA:Y+51;c,TX("TNN:SAE5$!d2dR9h91ZpKV`-mяzh;u;1ePkjF=(nma#|^LLԐ)c?HW5;wP>HY8D2$F^&rƹ5u[5#.q#,bŅnwZ#8(liƈ4[N-#:(j376l26{k R!f۲Զ! [#:u#8agg=&ՒT +zGqQLXhT58A(0VY&iRȆ$u;]4_]uF}rw\~]]/}N}JM#PzPXcj+2㷽]ԽRzCEFZƼc8g/^4IedGN"ЋUTm#8%q'Fw$giL^ŰJw<·_$<$yC/U13u"*MvIGjM6juD`VsŇ<&v͊dH!*+V˕{iC_Ю?;o<8τ)r"ċChd*#:1VQ~x >m EN>"2S&ⷚR8{@4="EOvl'8/X0pOC~sO&(d4DM(#:A>Fo (qDc#:Qg qHA#.Z۳ -27+${#j]L7bq7 Иq 0!7C}+';?k4o4i(6u썓gBNHi<*$i[X1:dOr$[/XC:͗mW&C󉣶)XT_׭Wzk gwEL_T^ N /,AG \Új5Bcȥ6;dcDi7P>2(",mjT8r#8tB;)>j/dsC5!X֡Wߓ82#4|u&r(ALlsl4[Ki{(!Y8XA(a@cU8>$nLބ3%~CY9n:nB]N cYT9IMQd< &_o^Rm;jlUw[%<=́MC:=Ήf1r3W"%nE9l?>jCcUvgK4( "d@k"E7#.g{)}Ci/N"ZCRJS/s,'Pr3#:ɏm N.S*eE+sofJ~\kicq&bWDnj|\'Ngoec(BWeSBE>jiMIbҔ>30_vPutҏ9]wfPQyv $SlQ+J`t'Yq#8F!xICǝuqn ʋ|v:9 oT򙹬,<`CĶg\m ;6sqSR|nMkx\'mHYɮ1\#86g߻cM ۴|%^{kV'ztr53||0gs$n반2Ši(EkO4Zk{&[Ic?4va}Ȳwf2-S`dZ|}n[4.n)T/#8!m;XлhpP [hDOy>{sS/"WӒ%oK"#:mOMȑ;8l O8xf*[!H#6nfwpL8ȥZ,Jmm&s0ӥٳZ_$=$kZk |!kdɆ>aЗڍ1XAX36uJa*⢦7";6MAG%Rifn=2.g7M:mo1&Sh닺ѷp$t(=]w)5L({&$[or|̝ǚwBBxlm<3C&Q#8h&srj@Rp[TfFj QBojts3rԢg\qշ,AC\P|cg3y5T_ul"8nk-;:g` *!vJ[B[c",dw'ۜ%er Zǵ9o{}Vq~;\r6D;"9G_Bw(%Uų췵iRI""0|֍ 洵) ₩zx.mr#.XPbq ca[֩7{8UL:6~ _vז*F-Kk-ߟǘv c,bQў֜ի.K δ{"+riE/"tvU@([D{U/ub#:apf(G[mS$Pn!|^ͺ\.&E .ZS~MVUÄ/l\Im #:;8YSl[X>bؠҔspVݤ6tLM/aɏiؚ޹jS#:G> Xì:d-Oa+%UQх6IuM _.zRAsx>G#:|~(U0qQv5yVzkYn=#aywa%Nai^X~7*r/,]lVwͲ>?9gvjzMqTMd"L>xc`M=m8)3AOlra_t01;Hp) (Q1FQ^XV=}sh O=lM95%QeUt;h ~_K<-4E=YNXǙ5-H>qCLB^-⥖De@{X[HKh7#*#P?S]ȼSz-#YRB#:+*r}}R;5pYru_oڃ;d}u|u͜g(ghitV!8|L-V 6>/sqfmkL34 ^ fs1:B1l7S~Z5E#:!< X8u%CD#ud5ևpѡ@_Wj;*;@ %ZrYXDӑֽ`׺+o#Vklk\~[9kSdm}qg?,MFTի%ٽb~w#.Y( uuk<#ĥvAI6>ܕk*JnjJ6mrEK_%SUjVLeMV,q{Or y8 \I#m=k6\Ҥ:ӰG<xۢ=AŚLz#:#:4#:_/d<:QgNLq],z{{:'ڿ6[W), h4~˃]Gw0=>8Ppj4Dq!H?Laik$b6^XHG_29&[%YGS}-߼V֒]L6T70XUOer}ϙg/[X\b/+aTa'[g6Y8%,kZfүT%/d.ݟ9O9-b[["0Ys%\Ǫ70yH2YML8foGFQ7 H%w[=J'r(êP+?W}e>D?]`@i`.>,zCR"*7R(w:yj׺lG,i9ܹ GhN?<=-jh#:B5 TKyi . ;~#PBA#ەPb"tgd4oU-(ħx#.✮XiRSk*r? ÷+ʼn<ɝFXkhqnʦf(=v'0%4nzؼJZ#8sXPU욬Y#.اJ=`jKFm+Y*>8ï P1"piZ@`xKp:QEeԺZ[]k͢tkYl3ctZiθre=TDi(w(ModONAGXƤZW S9=CLĪNvI?zcm^;*pgnk0\7CM})8_+B%%koyE0.;gXثqg2tNqΚŲc믿$c#8{[PIҰlю{MxFc"q/ 3SEgQ2rP,(V.kV#y/aqn#ڸɽ v#%ty.HbDsYfV#8"-[(P>.4dB#8b>mtrs"{5VTPnKOvw>%)]5zql!֐DI.s;Gǟ?ZE̵܃Фcry^@aT u(*+lNpX6c;Vt\q'gYM?YwHտvڰ(}ߺ=js)/_{Lg@xVNԝNrBk}Fq!IDNaERGY~w< ~&EH/1 ϓK1eh2Mژ@@AT$kY#.r]\9VzF&[x,]coDa`E5ht\pÍ~GB#:3mw.+o:T(8k @fq{&N>wAm_>i={bKH65jRDdMdA>ϣp3l?m'?#:]ܛ8!SPćoz\nJ*Q3i17jI aP6ϧ={OQcQ;s'Y"a#8sW_WU#:KdʤV#8a M`Dy"C z^R;ByO#.suK($R$6h_V*lj$'/Mp泖36lCFV9C6 ;(HZU٥]ʾs,(P<)o+vFp#: $*0 Qs?U[|}6r ]  #.UķmH"IFُJ[@Kh^&"F~e1)mw?`C (PݵVgiÐ$'yײ#a:z]v9buƒ"5~ 3İr5lcH JGiUp7 ^V}N3v,Ͷ@bο,$śxtlK C1A1D|X>E p@@]0 ??Wj#8'?%>x2|2<'HoGm}^#.0H$oTb3C }g89b vbvHx#8vpw> C'/D#:5ɹF/!Ju>> uxf#:4{R֨bHmz__:{:0w2gLxhx7O랾=K}-I":2XV*H/%6ÅMAi#ony4(?Б+.56&g&L'^=ۓ%#:c؈_Υ4m#: l:d$s^ D(W\xd 0y({t] Q]}OEuir;<~nhCgq" q/lk4>–rEȪnwc7fSͽO>\x[0<ˠ섘o#.af\E|xR/:M)ц>f!o2B].8֦k|L& 0牚S4-~PI{JۧYp˗Ľl^Jns;&=j%niUh!5P#:&nLP96zhG՚z2e˖$\#8 T]{]#8-2rtwI}=Hp28HBH: )d<elB, *(uQ'vk?Bs7gZžEz7-'|vEWﳝ7tCf'zGB`$pzh6͖Nv S_OqOX98*15beVL@ Q}䰡e4~Α}܎IрL#:B0^t?jymPxd—C'%BMURٿIkC%UV?aѾo! -}ք$mMAѶb#.j9G1 Gd@YaukQhz'@ҵ=x?BQRxd6Ax~G୓ t30OWw˭=G[8l B%+h+3ӄA>z]~LCT%.,rc WWE3@.GtCM#.uh5Ԓt({,Kp[zE#8#8#:J:adۚ,7XR'ƷHɺ)L^;D F -fS[t:a8 ?C~ͯu˰cM}i{ߝao[#:ڞׯ5De8%/9߯hAPY(E#:#{#:Or O;Ib/e2@h[_]pmcxm.A!`lŰ&Y[V5(r?<%=#:cd:)^Hc1B+$)~x۹.Y" `P*j\׎Xe˟X@!+=%EBPl@=_/[ĐoS`9z &=\|rss:2D%FѲ}o $7}2Q3c鏪v}*Ŗ~YjlY^v|9¡,?J1)s_=NNr~7S5S4LU>n6;]@%08ݖS )X%L88L#՟Xq;1~W UtO~-e6\^"F=H:ce $!y0Xd]c5rMko߹ysy\6.j{!g,@*CQG"DN_#:uCEy6?[<;=l Ype*{k~_㫩clmS#:%/FJ|vv2h+d;%MrG:!܎ \L@MZR5dK7gb[YdL:#:&ʓ 4Pq 2Z(vV:]6L&,54+KpdI&O8UyiIn퓙T͒/@`Dd@)$ SQ)?"C|۞3TW0V އ]tim'&5Ex M#.oW׏~&w#8#:Qa<^S}l@w<:Bns_Y'?rF~#.J$4칁;* 6G1uw9ИȏHdڏ}CwY;h9ߔB?#8|{&.kQiڼ-;!2P-lBAxpߋݮ9<7/,|RnYָ#:fwqW+~K<92#ư pk騗7+%L-Yd1@OF7O'X~mY^&CL#:0#:m~ B(Q7jX`Px~w!7 Ρ2'u{;>}Hd%{#ɨ@{{mK׆#.׶m;D{!$a((JRݲI0SΖܘ9BOT\*'ZAB+'#DTg\M>C\]f.\וh"=g)#:o,r}@U"H_JX#ҸnG^с?ހP`z{"#T%~r*dL|h5{ JDE+ɿ5B+\Qyz_ah$g?O>@>ΡߧSH*@#8xNoL`Y"\khUg$!@ yYGeߨ"b^utAF0NpOczF濎Lv61r:r8?5p<|%5X3!=q8m#8$Ȱ8ďIᴚ271|#:ҫ{%P^]٪C~_Go#.1ˑ;C =jPXo-#!أ@Cx`6Nz_F,$N}l*BPwpnb|(#:[k0#:sȠD0WDa*$B`3Ss"ֽ<1]S>dfa'\gNÎNirc#[Z-!%u' 7C3[cO?\xOmx|v(_~^أb=Y9ZSE${j' qf2K& đlch2gali!.."u{ɂRZ2#:M%Kc8B5=/mf"+by>ji۝Ie,'EW ڢ)Z9l6~%ѝYl^%#:yz1fePLA|VRYQVKCOIUg[Lt[ +q0;6(AbF1 odFV3Q%p٣m4-}6.ȯ@ůNhDXNx?U";i#-b _E?>]{pPDg^ X0nk#ШEq|2)K keFuHlkUѺPh3QKzps&%vSEa3NƁ7l7s`Y0bo!cvYDIn֙o 3 ^`,6d$B `t=/}T>O:;=R0I{a?^%CٶsƜoO-yN֡ ĸ@|⠍Pq_?7kO7??qo=#o$g??;{OG#:_=__wO#.#._ _UTI/直x$stHfo_YvJ"<w#8#.4Biųn!\?Ξq01{u: M>x"UOSA#.dU:.O."1R9#80>nh9wZy={&!Jk#Gnn+ @XHPvt`F&"T#80)0]g=TwNNȐ2 \7q+<B@T&MhO|zns:=UE#:Av2l$#0t#::SHkh9WUӘ",ӤG[OُD;;P@{פz5yÌ|q8R|— kgCAĦ@`Z|:|1JG8k}#:9a4fJZtj]ۖZY=8wsŗdZ-;& ܇Kmq$tnoM>;(7;sW Ǝ98VB) iZ#8Yl.CL}ttKhMP2$`,LTׇ4L6K>^t>,W$>J_aZa1xv/f|MS86d m1Nݥ:4fSJJeCC#85P*?*1aaJm9\ɦ4KڌvVGK#|Nj_ il|C!%>'=geZu)R=PJ #j{|eڇ13DsE3v}4 @SWF Wu*LҩeYM#8xN6YTf@!z"EK2NtN:*Zv9QS$rs͎\'uN,x2#8X4$&(3kgHd;s$PKAZ1yS$-^r0$N#ȏǬï*RA2#"(]x*%~M3H"""2tqi;;I=LtP=EeIŰ9; &aɎ3vGj~~`{O׍nNnŠelj#.@W;rK,&s+syh0]U绶(,'yqJۦ۳%,aWu8(H!F&xl9|؈ 4fH#vC'=p'N2P$v1Ѭ$ p a@g]b]z/mx;Jy&̦\َ2Mdl]Ք5#8xU7NA`gL\A DH ;-F@y\Qbx7x.O6#s93IKɄUGReay^gwwtw5?8C="Tu'!1*Sҝ .#:m,\ 4:i6uaAK P(hV8a#.<5IK-a?E[1#:?#8^kk][1,T}0+A(Ǯ,E#8NX߯=[Ls4Ʒu-FL@ `?v-[>TQb TUL/Fp~##h7N'I-q?dv>F4l#8jZEےDD&RxܛCCSzʹw´c,bܘb#:#.kT5#.I )Г#.} ){3({"֚Hc܀ȗC"g3äfST9t15fa;ƞRfgy5+J5#KTi1m1@; \)+6C"JQJWE!#Y9|n_g''D6?3A@U%$<Ǜ0~,hu+uT#8>V]U=U |0;<Pv #:^XoAU*KwםݴXqGezBa`auSڸ3j~ԼHKw&zm0<y3,#.;'Wd11[h[Bӆ>?ͪ=hq*"тs3AD@J}y6o)2h9AIΫU Jl,);c@AiAej/#PfO&C\{naI_~=~F@#.&ş#VۂG=,,vtZK{/Ñ tN-"ѫ't`D Ӑ!vwVzG`.Ihp#.JIѴA~֥C.$ާ$/(?/^>Uɜ}C2O㦮mX}^kv[~l\p8B8];"H3w3j!>漦->j?C<<#8)$P(D g|U Σ#.qXYS4:#.'JU~!Z6o‡_Isu쳬$ =ϧ8tth?+)1ߏӧ4 iS~Ub)ӈ``P#.|??#BO'-p #.#.>Qlj0Q/o w:R?/N_TTNՋ hwQ@\V}-Y-%Q*9BmZW1tI  #:qx0UhBZW~,|N=6,#.. %E2EA6γ#I1KnItX#.t_gwfG ʷQn Ԯ0aybf,Q7!|7Ho'G$ ,A з$G'z᯽#.#. =@B䣩i]}/<;8$fͶn?=F7=ķ8h"0{"ox lY#U߷^8Fګٙ9wM]ڝ.$gc4m#.P7A#.0]<__U#.nQO_j$ϭk?㿣Vף5՘#.$Q5jz ;$GZ?by&\];jA1]z5X,pқyE*}姯tR:J Нr?_5Ơwdž9 |YhMg*CݟiT>>TrcԔrre֭XhG{[U#$ɞtQk]*er~u#:[#8*o "I##:/N5\X^x#.5PK^A>o ܮ ;#:EHi xZT*}牡m|ܮ[{:_KH"{}`kSIA$I9q_뎃58#. D̓kXr"75~#.hc]:{u/5X#]Jk\_(ff7qfc|#8'c~V4~>Ƹ]sL&~w6Fo7BO¥(O>J"\#.7@)"㸾߈Gzd-u7_i_!l}V_weٌy}B<::S@WfhW d1z~4$I 9Bq_6ߚP~SȈ#:X9ֱDͿz{9G 7zodϫ D@VQ^1iA`>Nxu(|Rw{;K!^n|Դޫcg%Mdمk4:;RI0OL!u Ri--{[ɶ:}lF8Q`1OʏgdB] e(@Ahv"G$-,)= E\9r-Do?G0K/O:YXCl8oy/}NMsPqfo>-PyK1^$&-[E}傌4֞>m`D~p HVv׬e1~BƶzGNS*˶Q[b>Go D:Ŀ,*#Lk*k&K:~? }~na|w:et_*qe0I8rUBkJNw+\7Hrbv|fb+oE\ks$l;4ZS/jsܘ{]\/ڲ%roDd)k#8+˂.Xd}A#'b8t=\B#::ٶVh:QD{=,:smQFI;?^fr92}Ƨsߟ UЯLYWG~֚ܽ!M2) HK $.Y=&qE3u%# #.xP</)H Epy$ab ec;%Y ;B=7"4eĥyR2MUʰ)6iEȱ{ww9P0CWxsd5t>q4җgu2fe.)f=1#:;;&5T}imϡi\~'fؿp:3ꜘK e#.0ymu/Ʉd-!_&m^ޢZ-BG=#8h OBH/(/Yzv~ud<}d4T#./*ue#85'3v?t3sQDc6vh#.wi93l &GژqǿlˆL6C!$B5`G!#8 F6>T>3>x~Wg./M \ea{iHA2u@պ|}?}fD#:`}>^=٬L-{& gu5gksS㓧dຕm#:p(!3) (/pbgd7@D`ٻL2lS (g&>&z;kE%.ZI*ч>w_ p$BoG$Wػ'R9#.(>z@'꜕ހH"Q@-#:j$P}"bwe$ !=/{A>IaC}g(XT#86($?dltL+SaH@7s NoH۸|w!_Z'dD5z/}g5wLfE!L=BΣC>dn|OGVgdOYAp#@#81EQ3#:haZ+K6faRf?:F~cȩHLx*bCIDKk7niMo]rw y)LkQgJ.Dnͳ4#8Jӑ&:Xqixɝآ+@ TpA R<k?t˹GjS%8Z\_uj N. P[`vJ"!ԳU˫}t~'OUjGy=.pdK>8 rX4Cݥ >l6Y17͇;~xiv@|(;sY#I3X"1ax\p,Ac`>M?[|մa3lf 3Fgⰹ#A esE@ d^9:l.{arx(3#:zwz/?}Fm4 c Gh:Oz%֛z5GOƩΤ?9e1r?52/7;2v]5#8m9cmJEdL#8A]tafnMt:#8Y ך+to>Kb0~#}0]s,x=ψn7#/Z*ˢ#:`JmTX^}ڟL^Wj l zioBcҔt5mU)+,kWp~{< b@ʆR8ȀdST"E`@lؚpZCjv < E-Bdv-Ѐ|X nAhY4QP9 @Y(qKGtӵ(ys{,ܼBؕ5DZgs)8@&jxgv7I14Os&њ8uAD%2a_`W$_(oZXU2`PXbSPkw ]4F!c p#8V^#ݏ$/t!Oz0Jהvd!v%4#8$D]t27$_Cٿ׎x l|!;/ ׈Mϛ|7چʣp\BJ<撑)ck4z@[?Z(8KWI#:gЏBraR0~_Xhrt (0XK?!)Q<6l#.eѤgC3YgsZr a0oL50Wo`W#:w_5OMAPߪd=StV1e6эVFcE#8%RkGŤFd-biTK/7[ѡxk9v" #:PMˇ =M&ŲL%j꛼m:7(7Q$W96~55_]}h0QF=4O~W|lQJ2kҰqDzָf,`dI%Z/tH !MT#: gRϯF%1hiSϯ'3?Ot(>d@&8_J{a:os9 g_kRGK'mT:9ק&kI俍wM#|4cZF&ցgzy淠c"sd(L5d?\MDpGQPS1j&6@0GH5YŖvB(h֙T?AEfdKBջU]wTi _fT>2.EƖ#8#͊l{;E q_ v@_fpcLX d?뱲<[8>ͱAmjGFNQ><=j6(O#:QP O"}#%t@6sz`S2#8$55Ajd#83b#m)uV7?Sl:ڟ8#:v9C#:{'eB,IYcIlF~8p͜;L8)ϥ֝|1txձC#:L*m2sh#8R%ߔIWX"d_f͑reH Bk{At>+hz,a - g X!`P|=ckM*}[|+t747F(#"I7#8^ H7d,28Z|xy*x0ɇhˍ~L}W=6m ʠPhR^|gO׳og_!4{-U[+ELzg ˋ>2y=C#. >[mơn7ѰP&ݙXx~zCFHDq$a!4#.\bX۰ 's^[cfn !@ds#.Bp? Z!cBB#:,OQK6ʘtl/EQpm Idu#8pcnd#/~>O3wP?=[UA؟ɀCf?p5NUT43"$ *J‡, i( 7WzɒsF!gWNz- Z+5VuO'H,X lrQdI$f'e֣sX6*+0&*d2RRbfMkBÌ -6̏w*̘eA)2V+3`OTH! ݧ:r&b1i˩DR$#.(>Y?$)`r?_?g`I@G#8?=|Xe58e3&T5\#:(૊G>o0){EtES4ۙu0=QknB/%CEQJjڣ^0Syp"3ԒsR\G@"ŃZ<7mP6aMCjpBiNdNYw50` I70ЍJ#86I&t]=ߧ3LX2 g~Sjƶ t0#.KF(@U: $pk1_hk< f ]#.߯an@Aپf)x_=@GXac8RCR&P%tw7K01 xiLUw P՚2FF*,^ÂȤ)v%#81P֊5JW_M0_!/WYL(-HrgmhTJ<-O˳O<`o`vAs'|hƿQee([BlC]+g6=vC]#.y@F.QD  1AQWGw}/ ~=;t[_(>D}<\"U?/ڡZ>묘%.>OwoU4m7]+^Q/HڠH|>8^#.55%Z5#8?{U#:6OLy#.͘`~u_!xu4:?S8/|n*BR8_[?{Js@#.#j(ކxBFz?ѯ7N+Cuu+gN! k:t6 Bn!9+9`fS}?1MQTAQ"}١@U͛:~0&}?? ؿWq:$ BI`{^LC2`[1zQGq>;AW voܖۏF!X,P7,7N {?"c\\$: LHr8PT~#8Gt@y{Ē}_bIJO>3;rD&~zˑt aS#Zig˚MebI&Vk&ͽu=$#.5dbx3 $L>zZЙ'(vx΂,0"D1㜟IUlq %#/\&^a䇷>Oe L //']^y!{';G|~Kat\XHOU5t57 #:8)UMD0NrT,?byF&lfX&Ev$wd6<@DA*Z:*FJ湰wtzlj;'g&j}!wKO;Ϡt E(EACWL|"#A<㢶P60o<4l.X(%áOl{$>|$t=a"I<}s!۹}3#.0R}{p>'oAAā0qMN`67`Z8M(%r#BILF#:D<>R`(G@\Nh DQzlĐ3ΈOo6?ֺn~^lN\}\r0A9䚡LݳH ZHFQOҠƘ}Fؐqv!HRPViIm&&UaveO<ۨ^C$!;<.B#:^%/N~46܇b3XnpgNO:Rtz7Nۚ];\tOa9>sG>/#8YwOkSOv)kMjXL%V8=IGΕ BA72>Lc`Bp:P>' Xo&KFįJ#.b#.iwg"o/7߆#8z|"MQm88I$#.6{43yw#.|EL}w\ =EƎA |r#U묄?d[#.~ #:dH0@Ӂmr:/̩# t=ZXX,P^>x& #.v#:R$4>}#:Ke2c?gZZs12]BB[un~Ceu!Yv.ԃD4lT ;A^~kG˘<ӲʺU4B#8/H=8;z`0XY#8'#.?ݧSuO̘'gxyJfasXר6? *Hjxy\=iNO`thz0q~g<ɌEP`$?D-3UT(=ĩq`.biG)DYU#8}6u>iɖtbCݟg`#8۸#:sAH@1sD#:?þ2IGa56*TA#.#::#:kٵ#8TYU {?T>,9MbpFNa7CsO=;W9E7~/ҞT7:4_b]9ސA؛;V?7;p<&~_teԢ ePExt8F 95J#٤p,LBؑ)\*'j?Kbt&=èCywbOT9Tu&U[J4~g6<"oAp!lOef$ЕQA-qYxq=~yEA *N~ǮԾwo`GP{*{M{vqIPAݘ6N<#.u)S :GӷFѯه(׈S @v:vi~۬C/%C:hq"SvzvJeSie" pF!wwg4'1mnzۢ#8q(@(0}NkoG"`!އlun'Ң׽=z㙟/ /2HĿVwh|=TY#:(J'Nu/#1D送hT\ \5l?#8%KRj̓ՙ2Q?^?r5I#. b\ 0jN^F-zԯ9_r@!$0bf4t^ZMH)3 m|P3$b,!ƔOSk[.#OR3W*yT{4^r`֋|v/_Otz3}xh* 2wbF3w^ @N[ ٣6+>nx`9]뒐N0o@} 5Qq~U VX:[f;6;ili$03WK/;h]^ߘK#:"4v2(qϺ;C`΄P#BX /yϛ5+0ķE HsOJHf}5o yf1*aNKO{E>Zqnh]_b7/T_'{T4}`}Zz|1Xa5HBMRTGA_.3#D:'Q ᨆs,90Lv~A0֗ HA4Yy/?Pє/(`]IJ:pi#81HjFJs#. VsBC5/ĮT#8"M1-Z=h#8#1R5AK}m0&)֝Hvb>`0?/o+%#:{FnIwsц\!\heHf(FRei G6\NbQ5P@YlѪla,JԩTB󽿌Wm㣙<IR}//]`W}g;$$:;< 1+, Ѱ)˕ʺK#.V?R* z#:zxr sP /a@?|j58z'Pk5`ՇT#.1@y߷7`|v'IgȶWgІS!7sNr!V`S\4ǒ9αhv̋,/Ὸb#:#.^|;fL~I=vI;u&3Ro8f,U+:0k$bì/A=O#:CHCF$~&d)f4GurdM;@e`c 9_u%  #8c#:?#:s=V̄pО6|g#.@Q1M(l|vǏrb#u`@߸55k#:;\tT랢dp7`'`][eXo?~*^_ǩAPxQUPD) Iڋo**55ZDykQ7yG8 ˍ ҥc1em*EC\OI~wCE !NưrbF#.sxV޿ԍ#:!{24gN6QEE*%;asPl! j|9fN-O`pv#O<,rk#:̙fZCSLblL̲0 *Zx,HEh;3qi`|~4`Xh|Tra+2V3B=m1_W% hE{-^\TF6׆)!T Mj*~H-`7q'$Wz=f@Mg3U>^G7s42(aCdcMhs`ءci#:R(kZh3{bzB!`qD?\(/o(o@Sb~264tA(0)L7܆ADi<"MEB%P{2x e$ {ECVH@i9acGobѶG c(!#.H]׈$!k h `)6ԩ,=6QR-ECJJx!#.ΧeA %OKq]G(85ʕed$P`1|N¼O?!=itG6pXiX8h<(@Â#:(AL!6}϶;-#:DA y+⓺]:JB`Bl)&UGEH`|T5G~~DMNEZy"8GG۟gqtz?iQN<#8~惼4dy2zIVd5sFR`#:lLEZeKmQ?W>C:nuu'A(1W`}! k[ p[28kC #.QA-z~Ө>"#An|6Q8s|(#8n,W5,Zjr#|#8X}"G'<:^uS>j5 ٴ?zK=q\D@(eN%$>#..#:`(P⧮GqSIT7l1عq}lO0х@DWㄳf#].%R" ݸ*(UR3aѝmtN݉]c99t/*- 88UKB<"T&l|ѕmW{t%J4*6uұD$#.%VCSqICsٝveLӓr!Bl [eq:Gto|MӉyX''KdU߷kB*4hk5`#:.pQڠ{MTbKAw@y{8xՅ"fZ"N.l+$8WsKUEQ*#.'0s7 !jXz`,?DXz?/>1#8fd%:oUH gߟGb7E|`띌<-+#":)<#:Y%>۵ZH$'QܪGx)Dх|'gt|+*=5 ,;N3܊@ 2}zC4R}&}~e^eh,@<#Qba?K{xddTm}~?1:hylo`Μy\x5!T(%+E8=1I"} m3vKLD;?1p}WcڵH 7^n#:9z>8tMQUL7lKw\ģ:ƞR" ^?ñƃ#8O4(ߞyF]p>ߓm#: [`H"()2ԨѧPÖTr`P{Py`XKQ?͊sXBSٱt!Y?mv/n?֕q HYr! p9s8;Ȇlxo#.hmۃ:z8xuבhȊa `?ru"'wCdGrK^a0[7,zgt~eA}X4} A@ϊvr6 ;?wqT7X!Ahh#.@no<4@5T#m/ۼtꛞG?5v-PuKltdgCim6N#.=!8CKgG3}((п#=S8xf3Xk<'|=ACHh?t0qd2f+Z5qW/S[Op'؁g$!E6[bZ5s`\%\*`AƓ .IANK,E 'Yħl4O2f }}tUTVe]G%nadCp#$Ù,?7`pB4U-1h(Y2wP epC|I9@*e s\C*(/?W*kv~#8%yWr2Fo.yi[>5XC\#.f#.' Qk$#m•i2*XIL~ߵR؃bj %v@٬2ō]VYFke=^gC>Rw$|!BUZwmv?>*l UUUZI#.GVF#:hwPmex?'/ r=DU~׸xT#8&m3@ FMfC9?(b m͈cFnw5۬!Ml۳B vbГfH,Eߑ [#80㒊 A3L(PT7&S_=̫ۯ9E٣z7 Tf,:Á\kr̙G.\e3ۚBpWWrCÈ:Mrln^:vɆ#8(ۅY$6ΊG!3P6(&L2&XlYV#85NEٙrg% [}&{Wr]1|)I5w2)2^42(#8ējr2B`,&1.맒?N3; sщuy#.a]_*m[VO˯rBSvDD=T}ZDF#Bcp~*&9ʶ v#6^flۂ/O)Q}CߑB/ZCzvwD0im#L„A 2)ّ4M*2nNah$;' =tNz~!s4DK_#.T'Z)6\YIqƭkdG<΢o-fyg\lgs0yTxK:v9.+;O#v̹r1hRh6ADg}2=S 0`CzyzgIv^̝s,i#8{׹Q],X>@w!F{`Qx^%j`9D;'dQ\y%'WA۴onb!!"xnT=AI/#"Bѧ4bsYЄdh<M^AEAޛ#8AKnC}/Ԑ<@"5"Ru pA^3;qb| t8YXJJ,͵sTUAJ4fl9#8|^Gj)#.C2m[}]b\!"s=JIT5:%#8 dc,Ʀ |:gy08r7#8f"Ey79,nuu5F*;U99a>&ۊx]#8u#8{ReE3,.XMnaBLlٙxhG ;dј4#Ie޶ǒS҈yp6ö#.Bzͪz[H|o}iBu;Z´^:MzB/I1ӶHzw1i0 ͫ9֮"ԭN\jTw6vj#.s "~`Mto|i8m|kaeH$x%`q426fB&"1zqáӍeY{9v nro،10F@d-n{fGTJ#:$Zۀyt9x#.RI3(ˁo 8I7@2I~[>[96.ɂ#.zq]`i+Fy &L2CÏglY 3n3#8k6{$fBZ[ üo=ΛJf:Bں Be4!fhw7xEv0:k5#:C\GHt|=fҝéܶB%w%dg~Ky5!.ӊw=P1rᕝ#.ΨH;4 b 9z0YlsLpjEՏJ=IH_nnnLwi5~9=PC02 !gD$dž73w#8#:FworQ7P4;#.@TF '&vufu*#.>at<|1zga#8A>:К^x!4(.7ZŠ̨;mnKAs; p=HSԎGP{/?s3 ,#yyaXMFQfx9}NxwArec?x9ױ]c-3.YJIʎ|wGzI7CTy tbi Rc"Nhϊa% x8oˌ_3#87ٌ$}kppSH#."|#8+44ALymrLgPHDam]AZ}|ÝM#EEhKj=ӈ !۸#.gPFj`!Cz\@HCП޽DUO3J#:Vnr@0Z^~88YNRy><ACGwFNCz|(i'0Gn8K>[10=f2aP(졝$MBh6EZ٪6I6Rgӵ؆e:f2L*6VMLJ#.&aP᠆i, VI6)v`M"zKf,(k7dYrg˱?фm9^xye^i#:Pt#/?ONHBpUf)%~T9Rg#.jvC˗ ~mH0y47O+9Jq)e![QMNo)x=)R]>߆H¦={s]c)νa}K@,ot ߄rr"`K I+/ 2bՀ%g8BN#ENˆHA#.9Aݻ5\x['-1,>an{!V&j vzDVEzy;/!ߝq/3Ƴ#8o-IXo<|E W#/9l|.<@W^>4m3i|?^(PH\΁\绌S+F êu1=@?(aI0f|Wѡ2C ol#8p&8~ĞMLR3ӏD#8dß'bJyGxHMLBj?Fg?e~0#:?#8X#.QHE7m\UHT#:BsQEg <1<zŷ6P>*L70ȶƵ>^NL[yJ[{^Wz z{'P#:Ox5Kϓm#$!#R2l;w`blT8!z@K~F& ?6~6[TY R-z%v$_4I!ThPu#:Ϥ> :NŘ(Y?/~t>CTǕAdOo$9!_?b 1h:0xr験,hKFPl*͵LZR3w/C0L\O#pǙ/sHG\1Il+|UbV,Y UQj6ϵ4:b.QDUr2Th084`8zVě޺#.7bߥ=}˧RPς/1_ԣD,4 @0PIWG>p1'FG%5Fp[Ύ ~2/$4;?ZӖZiyͨkKQc')o}IAroK#81Fȋ0N*(ڈ6?>R'yyɁCaYh`OgSG=[iq"#R"5(#:GjPl&`ĕc$!Bڒ/]j7w7yw%#.H"TI=|| `o=3yhR dc!H0FL,P*pe(Kudɲ״zƚ `d {‡G`*$n32jDbyG f #8t~J+UDv3#8R/Ȑq^C,u'`Ϳb@~#.c#Ϟ۰؞'"׻/ʌEvVB) ܩKhJBFh.n]ݓWڞJXPe /,{Crt*ӓ3f&/7<1.r^: }Uɹ:]ӎ~ejg0fl CXwk[2=1}8f(jjdn#8E.>W?};ۻnb#DߟpǠHPB#.Д.ys} (&РJ(th!)RaW~08ۨcsSW6J #:5h-L$q%ĕU|m\T1#.QdU T$`p+?"#.|㐋8 >}9fQ9i2+b "ydVȴˆVbk+yD*g3"E)m]л`L!]`EQKhYcY2 l乪i &5Lg\ q!P Ij /`ſ&z@))JBf!I0P4*d4J&CFE#:$H%=sw dhA*Rö#.#8A9!0 N#"$!O!{%!G&Iݞ.&#8OB(b>CA& ϵďs#8r50ixn#.LB R8АIG^:h&g].Cts#: "v#PDbU@p[SF{zj{u=o{GuL(#:Ui#cV@dKڏ)AXA0C˩'#.'@gO#8jAp҅G]g;?Q ӈ2q`M$LՆλpXu=$<[Ø/o.Nkgsa{I9Ɇ" (<9.Fɇ:VC-e#.2$/ FȢLĨhHbBU#./?iyz'EWJH?4Y${7kn1bJ`i7m{bO]ovd>zE!~c1U0 a'k#:j> +h6NFʕ"uM mdpG*@MdgVT^~_`:'TTiP_;|py2H|' /jK&􃷟$_ߝK eEG4qq%DɯރO9lbmP8G[Gt_w{i@?9Ihpn 71km AmK28mP8X"@|GpME#:tWJ0lg >8N")@^IaL#:p}BuppF:'b?>#:rM^)@M-Y>1MɊ6sܜI6ucc-\;ǂ!c3P`9`,#8`"]ۧ3*n4V5N6jtff\F2MjgCB+ClG;0c-֧@4ՃS!p9Cυ]QUWR$$PP!XeUCS@#:y/Ѽ3ٌ͝Zwf/V>䭹 ;d%ɮzkm*ꬂ.J6a*ZJ\]J#816 \d#{s#:q.D@j4'Q0نBl d',XePDXvS@A~Xϫ#8]N T#.!5zlp͖ࠞ0 $2Q߿XWM& )dFiBd4DHK)rR(f#8*X#8&Ggz 85#.pܔ=~4(-s&#8ڥ5IDS@Zjm#.!'hCndK' {?i@#.'>T#8kNd 8ju) uo9"|b&}?9#8Q#.3QCsNL#Q5>uzt0_YTDDSbJ/U#7M~45r,)PTZXfF9!O[-q z/TPAv^(c`f_D! fQPA#.% ֪S#8f(? 2702 {p'=VY #.z#.5Bwu򭿈'?Re0ם-)|?Ο`}I.W׉rJBbzϚ3}Yӂ1'GbP-!ުZp?B{z;'eT=!ڕ/c$^ch9ҭt#:x,jA?}R4~_Z޽*Uy3 ̟Q#8qsXٰ֦pTB4H~d1ho~}OCpvpǔbxB}>!IĀ#8Za#:~v& `m#:bZ0W=Ox- R}a#: OV#:30ͤO3^ovgH#W6%l#8TF!\'тC[1yCQ{OИ/#:l2%#:ћ5#8RW 'ᵹMJQ@2QZI-TˎAP­|FHUK*rN.1%LSZq6MF1wtX, te(8n PDP@H`}dyly9jC2ok6uS"q;_0nfr2UAx#8)ACY/V}#:31o^}N5Ú8t.DbbKvd2xEr:<ڎ:v޺}epgf,8Ԟs[Sy߮6ZÞ]l@i7ѴsDs߯*O;*s&.s=r{Kdg\i#863#a/Zƻf|1Y̼of.vv;ElP1-6<ˍFp$J{T*ءrzCϝx/լU5f}+2p6Yy#8Y>Gg672?ہUBIߩ̨t"E폕βH<}wC]GJ0=RBT$CJ;RɦBnx#:!]57lT9Õ1|}ZomBwŏsFT@}o`3-7I%%6@1B1Dfz9`]C~@ײ1C<#8FvtG.p#:DUT#:T*vI"P c$k0|6q1 $1%d7Qv2珖pq҅#8Ȍ&K& &9u,9YA~$AȥUX(7xuxAb_'h06&d& 2L_ U(&\ɂDO]ϛhzQ@lqްhfN & Չ):)#:Aӳrj됩((.a<>M.ȇjKRU*RJ#83vѺ/i#:ݻONN?S.#)b*"`N=>qS픎?vCq`VL̨ C:;Ouw6fٻmn] W+ˬyA(F L끄k1PAXB)dhfmtK&TdK@–;ZY9[*U`&ıhdfD*ִ㳥(yxIpxG&!p@3 @E$u kdTeG3&F&M3*+3RlYb@T+++FwgN_bG_Ci[`,Gy DD)&t#8fv#8455':#=60UFV2ҫ+j4Z.j<o+%V'(ۤ^fR{f.ڌB<1#8ف#.QÚLued(T$}|n0D?"Z}UΎ9QU*W#: >ό,2A9nM="b5#:SΪ@>&H(a]Q"p}ǧ#.x#.#8*/ͳMNYLos׫[ەuәȥ.y A"BR(ƂDQƦKB)!HQ,eU#.*BUkeG4.ߨFU4pb_N"A/оfo!/ϬPc`s=qBUgWZ/ͮѩݫ&.nWW/\^,x8 mԉD[ͰF)KAMG:~\bTAB80ɶI}a*&tNYO!ãKܑx"F<Ll)_q 㚮f'|ͤ6ѲjQ2kRx΁|5Q#:x>l+Z'KEDR[֑/N!SX`A&F50˞#BdӨ~W[Y61FTN!f~ۉD]"b"zDk~_wTahL ;QzCs%}jXdSA*EC!Ɉ7Z[9Ypjs.|k~KfPv6 ,]ʒ"h?I#2BJ@r>AϛJ^%;]vajȄR#:܏n-jFº3p p6. VckAebw'(}a# y56*& 4ew U`u=aH ~lj+;; RKݝT\#81l騵b41X[r#.r@ݦ@t mpP Bc8#8"H'@@s1bhOoqՅs8%mfJ=J!lV#nݢ#"̵: L')?׿vi!`/)J@"h}_.D%aA$26We5ICB` O3ZíEGAtIf#.P"d4D~%{dԭ#5LLqI.Ѧ(8(HP9D!0UGLƊ(%ЁHof [PDO5<7h8gNTK0p:G㰺A*-`'PcVKD#.ݽA&Ti$ݹH'áx\b糋cFl/,t4"D֠ထ9;%'sT $za$b!# Xq\8Ԧ>!SciM&Ň'(g?`W9,rz֊E^AƒsƻJ@a;,+VIz6v`h8)[O~ߟRwÔܮQӧ۸#Z2KHs`DOòIBN':0IQLRByAF#:;|#8n$'vءHY';_W-[ead!ݐPI zܐsۇưÁRgR%M`T*(T#:jY=Р4UivB}C䈓ZRT6Pe!#._^U^[v5*b Q]II* &V5abf3?fbo dU43#b`ma- $-4;;`[EtuHt ({udPkvHICSW\һtM*3?g#8Ap.ktHF0H< 6L(.J4PICv=3>^(2MDLb,IBB&41A]D(P"1!ޞ?|6ÐtuatRj-D厵ܧ΅M#:t@DA#8i#8]Cd6q#:{M;q73"M,d3dҋsvfkpSP+WJF5^\X%DhMPQ%bs ̙F[1qS~L~ڥ-fZdHRnlF09\QgJ38mv) ܡ++0Ck fɣF5Y[C#8"ӨY0rMFz5A*aY̅jfW[v1]!cIFFO͹$m<"l'L7Xc\Ӛ24-wYɛ ol4;pR$P#8ƞ9KmiF#84O24QHTԜ^ #:vD/@1SB#`Ptm$c:#8Lp1l#8@pA+P)܄7 ]"H-̯1Kq_󪺓qee" t&OZW%#6^jґmR8X)zF!I۰ѥ|Æ mwd@ o\ih(YeBĒ}px&)%騁hlR,]&As+zu%G-U#DVʹe5"h߱ѻ#.lh:kpo3n*Cd%QFd1fQx4#:4 }(#.}g?AA#Ԛ`/p4$yf(cSvO-H#:#:8p =)'n5*(Wu@Ӛד8[PZaJL(gi5Ȭ&(39[J2>1-X9·|灃#8D3m ¦A1TW9cipxM!$€E|P0a3q9kcp4 XFx#.C^8wZ#: }iB@>#:\##8, ( "BZG%o%`p 43nq9MD0kGEbFY[jhhIy@St]lqZi=8'=LIG̀ym~9t+c#8%P0o0zOd`5FUs]+Qgp̐[.w@{>Wْe>(En_uklrwQ1f̵/o&j4&*R*l{[ЕJy*i~^~ee(9dsҚPԪdP`dWWixf)52tuκDmnj.CnnI]uO]E),6kckshG$HQ#.#8#.ͱP$P)RU&hfr-K%kuIJ@Jv$~SG-J4_2r+WF|D'x0&#.? }swnP]ĦUV f8ƫ .-dR3[ClG^p A2PD'v,ɒfLJ}II#bW:e5HbiR-)&TU ɭ3IF%6Vcf$fDQCKwQE#:#:$:Y3f%!S41 (S#.e%2K#:RA6Li)34DGnb凯0:NGKJ m(gi_ ᰜhc{wT)uCdDCE0%Ӓ&nCtX^oE-'L̺'girr4Pfh/a18HQ0z%fU938}6:wpoy;ǂa@r8|B4 x1vڦ gCcԎs(Gƚe'4$6ddk*L:*1 o~.L`$M#./~Hmu|-*3kQHի0X5cci4,m1k  hzPOy#:1PKU<((|)b$E&]wvS5(EcPI6#YR6E"M{>h1L|i`:1{?yXjҥrU}Ŝ3ԧq|DNt"PfڧRvȕ HOp2Onj";#8#=@>jstk/^܉mU {#( QX/rP9':IJ p?mgQӤggaXhh'ɘam2E`t/D(b.0މBL^@Th4&#.9Cʻ!G/SnzupқoXDmʾ60%͚[A\b)_c$#L9g`U>+YS5:#J&PN$D֗ WATf#:Ӈ0t5&q3<$ D٩va)=89N8a?4? ýBs߶vu Mڇ&E/TQ#:mCT܃?^_H5ȑ#8x~:ZzK(2:XV޹)RoEx:7VfDFӵFee{#:m6y>\3[X-_Fڗh|ő>#dtUh8,|EQ6bZ#:#IԋYEҥQ !k|V'}3%T<(j6cD>6*ldQmpUoq :)r7{ްy0rQthyd騛a;;R#8MxbM3Dɢ?6M3ՕFȥimRil#8^Z0 )xC&񻳦^OVC//[qh֔jtJ(tf>.e;;jugx+#8rbx7,sX(k!]l!#8P e{5+S\u*M7+WeF`wyɳEK*=^a6L]4 AeVCwKh7zъaÏZOCU]ܳtm[>3h%H<>eTb,4ItUڝ7IB6R&J:9%w},XJjAځp/h}+$v+i;B#;-T4%Zq-(fﮒz8Ý>kl1xpۂ@:l#bg.ԥ;NB=:i2GX\LHfm{~C#8CR2f[#8W#8l8OF0޷KMB6xt#83zowD1~)#8,ӲӐ1,w.l"ǽsc<]4@`eȈ)TDCRLkXCr"!7)SPy;Xö͗MZDys/sDlOC8J/`ېw;k@Nit4aXh7gvb#58*U8ss~;Cg&+J_ =p@FVS8~#țnx}7يbFcO#:!fL]ۊ̬XJJ3n(lY32#:Q#hEœ7X^OHD6ݞ5蝺uw3jMMف7l):h/2:aB7`u)"1hSwB#U!lj8\+[j qeZ6 <1ݮ}㓮u*)x~U2DXkn.Nbnpڥ멍K єh|#×xzT*L M@mo#:n?^8H m-ЖZ@a 0]@vp@S4#8H`\EH㤊*fѩR 隩HiZg 2Du˳a^AأLCe<0vv'FV{5KjimE`1gҗi1K1\j#:j0+7b#8Lh}#WespIo 6ߎ'n#7AhJH1ق&S6n3v0oVo.#áoZ#8lYwT8Iga"zGLC>"';o| mCK>,tp AK;q!\4wiB@#8s~6W{#8 BArg.ZCk*)]1f`pŒcۅ~3۵]2Rk#tSa;+x|<f-"4c Ж]z^M\#"2 a-#p 5ƭq4Dc6PtHz:3*p)#.|̇6(xJÓS.Fam+zU=ÌAP}\ITdөfnh<^=R5#H8i fF#:-gn$WG:Tr1%oj8(#8:#.IFA d؛st.\-pxSl&H:oQȁ=Fju4i=10֣6kՀ[0BLVvZa;;g@m}0bIO#.5!8 qf4l6P|#.m))!t1n,;t6["Ƃ[OCx1]wkp ͼƋ ,TeR}[Sf)|ق,PYRtDy+h4>ao7dC1B-86)%J/+BSI٭CcT`c$9nR_~ eI^ɶMNqvt\hg`i7WM8{ivV]}E%Fs-Jx@1h8bU&޵Yzg#N\XgXv2ɢg 69B+EBSČEͻfjhɜL\i&k#: {;Geh$7~lspV7VY=ӡsT8]8jq;ݞwc*dp՘  ϊ16FI!XV1,挲rM& 'Uvblؽ39# I΀t7K=V+rыC=MeTC_eEBKm WH#ml%Fzf6Nfaid8g4ޜ<[nR2;D2]F@c>xaOW{~T;ns8u(hע[#:5Fq„>PIoS A8zTΧ^mT ӪHl\#8`As)axȐǍ4AkF>sY#.؈ :0%@06c9qְ j b}2~PaZZEn/XRTN2Up[nqڜNKlL$LɒL!e>#8WG X1ɬ='adߔJ]F!O6:1 %*1M=%R<t@$;oAG-jkdk7/am[f%"7L:F'[b䦽e9͜f@H& ד#CX#8μcwCVò4lG6vNRG&Vf5 |L·G(*Dw1oM Ldh2ΰ8$$㥪vs?EmƞIpʚV[ɨxoZE) gj/ެ)CQ4㔜t`b4wYtLκ5ʟluLٳGTfU)l ˊOS-KQ61=l;,ܶL5;3V62z5lP'j( %&Iu(.#mm5e:exōR* (ܶ˄QGQ#8u deykXq2.x³ $b,XujܘمRȓt+vz)#8t]_fzǻy9eVUFZN:pebVgZmN&08,Mr%U"X#:AH9!ﬔӉjC#:č#1SV"ՙ6LUwD!(KMDi L1%|Շ@a.6M,Et!j#:$Mï f vvR#.j0-JR.pۼFfԴ)އZ.҇*]jH#u)&Q 7JzEi,%wdcXL键%\S7KR=Ibo4̂+n5iq>gF_SQRkK0yb 9܊Nilu5g[Wtj#.01#.`^K#.gJ)P'bmSŐKG33"FMW3´ (eRj^S- <$D-Z5t@XR6a8Zl6M(oRJYNӴ'#C݇}7C) >XPypi-&`4&<֤"3Ș[w)Mޝ8Ql^6$Ί|2aa⛆3YeX-UL]gLhmyG8tD ˇzB&v}"lTy̓犁C̼>y+[F67,&qꡩ2H7I /tA;2RtQHm/,^$QH5T!('&h 2e 2#.3ΰqi\^g[#v4,;ۏvj[0ML6`HhI6 2 ldt&w\w@!_y, }U0H{!S 2'6}U!Dz*#"|R!MA|8Mux@JZ)J |$a#: T LXь1KѴ9 iMRBb€@V{#:nsNJAw.D9#.r7-ܗ@&׻qn_9=svVg͌nj`89ƔKC> [3/pv5#8I%Kil R(&naP֒B9C6N}FVP {B=[f,9~Ip|p0 XLq3a #:ʩYwQ&Nf^#8L;sPƓ!s_'^/nI-s1ltz" ]L ENdyVgݏ1m3O3{$b\1!Zvck/],k{;#ƛ'&}LO[s3)'NqNmn,m۸ #82a3}U1</YI˞ ׵3G$$/{Ҕa3]MsΈI:EBeuy]+#8|)d츪f 5nߞeV#Zs'%43[7cȷ)<ۉ6NEkO6#8%;:Q2xYRŮv^y%%,me̓,ɳdWE#:D>1 IXZx*e޼a/X#`&"!]@NC@#`Cl8鬝d3*@'$*air gϚ^O ц~@vgsbw𩖊(5w')ܘݢ2|~V|7=fGՠ̌ 5F`u'"L9`dÎRFdM&DE L#:#.DR'N^0:8hTcHU#:N ]ayh r#.0@Ρ9Hd1PE`??zT)(wB*1i64~8;w5•J]bDCv(t)c4l]Mk캍IC$NbvGNҔ7|8==ູ'#.0#.E?~JA?m adJc%St뛮#8G6J{UN 6OJ_i|~s#.7UM/ŀO;>}؇=TOG f[z#8ڋl45:&Z˥0UD_-i6 I.E-;OcNM[;h(M$%I 2#.VI-i\كFSS6ù0Mc(}sXW7I˶.:pvx}S r.*hv۟aau#8[ #:P#.^iCt `\B* vC>7`w4 ;SmiI)Z5FѬV-bLZ,LѱI$̤#8"D0Tsmdr%GcwSʐ0Na`h(|`@#.;sm.~P5 PNF! =DёUh/R#:^`ya#8 J1T~Uh y<تUd,D<#8carƮRͳ2D`e391#:Iksl!T성|2 x2s]ԂB 5Mģm;'w$Ӵg>W#:)7E'?zt@DT#Vgi<$ڢ3X 4#8@n{'Z-gT(&h`Ĥd4M,.PdfCxZYE@p(~]Tc(>"*xyCԘ%<~ײ GG[*f(fz2S.Du L. MKk>u5^o<գV^[W;-5}O|.:VemN\"Eoao-+BM#:Cwc9=gt&XvF@i}-;:Ƈa!+uz^2h\2#8{&EM(1 1<:qF̛K bZ"ufltN|IPACF?)yřL>_#.}m6D\Itmq^b**,02##:E(h5J[0E@q(lT9!#.Sԓb<;J#.{t#8m=/2gys`KksZ&-U~KqґVDYT1CbrpEpUY\>9lѦ݇9x~hrqSg,a]UnnMM;Kp 1zHvF0*KF:o򔦽")<'_gj]#Y㶬i;Hb^7c~}<,81Vz7똝>5m9QݑXa,rb*sjXۜFs#=n;R%)rݙ#~9Dm @`BoX:~`UW7k5}vKZ|1iłrbH\杵6}?[s^I{D.f4qfݣ+O\eΖQ*cꟛ 64bw~ "ȈA2CCnXqLWM6<* л\]ѸDqţ&s^=ZrF3.:4Dw4E94Tk;ݡlU3pSb&tNeLz8mz⮎[Z0ilg gm]# 4qֺC6IA#L0R=W5qsJjiԜ>[T,&@iUm;㨩kH]o0AqPc.]Թ4sJ47Ħ+s%z>O\-yLҞwuf8ۉn}y6Y]{wvA/[Jtѳ\ZFj̝؏:d"!ᖜRvw{Zn_rZLZq*H&tSW0ͽ94Nٳpѧ&GNQ0B8WOMd-sCk"&c~#.@~#81fMi!]{(Dx$Cv Sy(Pբ .L KC j!i%a! e@7A+'X 8å Ob8>$HT&Ͷ^h2FtA&dA6iǔO$jEDƐiq#.K$'& ~'#:v]!`Fd#.`B3i<`[\#F1C@C:omA#))Id,5lg#*d:k.)#:q#YJ&.M\%6$14 +;puڒ+fewvk.mnA!r@j)iU$#cdmXQc!b$hlbXĹIhI#)WF4f %T"VtyHhjHXp8ۊ|TTfUVljf$3#:C ($/P|ݾ3F1#.0X֙EXJTX"?) ~LG4*uN)66b(sJ\#:J J#:}?$8{5 b1sAI?GP(!sۄ4JAP.d& "4H#FQEX"(RE/ml$LA„RczьIJ0]< N~u|Cත١YcoK1J#.#81E0ʀTfLD @pe̟ŚLҁ g@ mPLrY^]N327Dv#Jbn0Mkxhl\Pu#:wmRC"M=M쉈Ce.b9$+ԎGzn|aeuy6뚒dQ@ r(>#)y (@ WBt2M0zJ5"gZ?ktID5ĩ*'dڄWe"G*VWNB>_.3' D:A*Q?` `F- :YZX5GD/$糺0.hf hk݌ŒBIdu=BC$#8`{}gAQ x%i@g-TXG>^X!]AAQD6 AM#8롤p~ 2,L& B/>.ֶ..3P8FmVadaCj*+X#NG24VgApmA7Ioɤ6'W!LfGGôm#:9R߆k|Z~h ]QA.THKkF2܍a[`bAA$]#:}jst#:R!p#.@lV&#:,h 4 D?d%(PJJ9aOxhS\קb &+931L3ٶ|2L%Z"L?43+L30Z ~utAH#89^< ġT4b[dK~Nv8K8g ~).>#.8n=~W:ИB{K9@-#:q+ԉCֽf-6Sp~@bҦ0} Dx:i u#.:< ZV`#:lvbX%&xt 2J@Bs )d.3w x&KA0pm^\}iyz2S\c 6H#.# ʔEJPVή#8!,qe&ZɷwmSh l!FTBDR"81=1ng\>r(//Yo~*yIArwWkvtﻞ/JWaIfW#:UCLYc#.T p5ٜs,<2BIQP0,-#:- o HNCDڍӐp~,<`D-#.}ӥN$gBb +T&l`,l)S^y}iK*h>4|2$<.O`ۻl$25>4: ;X&N<ԎN #8rksfUeJ"jح CP#.n:[gmx~!% gP< #.#:3( {#.fZXR(#:a3ra~q#56MuncUwm,r!!>%#8 UCf|\65av#.> F#.킞vĀY$̮ gY>rD aEf u3RRqV##8J7t!F<$GjRRKjCCpTn@.b5Cŷ;lV#8](;hVkf"iO&3U#8vm:^*y9W +텶Zk,W򌻺2 xe:슅L#5/Q3u_nd1}mFE#3gv) hF_nU(^oD/ jͱ?:o@NΆ{.0E+ʠ*cZxhi1Ad։hK5M_c29,pFs"|!6ѐFr/7MUdR:E1r12S TP٭\չj f6s]m}+hgde;#.eLbR:v#8&-FSCJLTQz$u$Cր c)=X'**Yg?N@yޑ/y!^xT!"sSf#O8@/N{HRlVhjZJebJU)Rd2($0X'3P2\JuӿٝXԿF\Nrmލ9w9a,]ș{15^^B̆l)!f#8%;7 09&,0mùH<_^s*jѸ*X%hgb%K7Q}ť" &-U6i4m49t+QV*kVI^kDj5"mD7H\#:k;$u@tȣ#aaFi< mf -|fv0AI#.~aw۶"썌M<ʪnO#X{/vȺ0<R!:AҊn1 3E覿Mb#@u`;#.*uR!%QӪ oLL@&WH@#H1*Tp x;6%9lkvg3LTo.cinnWeE  BR9@4TE\hTmmhh+ZKDRh-TncrƨjjcXk9K4tpۑtwmWsXWkdM[ƎnQV#:ՋbTk%cƢ%G-ʢ665hlmI6*$*VI5%InlVZ#:SEPYb#8P(zOݏy\v(5_6fB 2c&.Q_$ngI ZT6XbSZ?ԆQ@?'>tS}ɱOk0=,OHgZ_!@rp?9RdEP(.Fʈhp MD;#.Nۯeuy]Һm5߶LLp8h<ò/oZ0R]'nnU[[X׬"vF) H41!&$Le")YclDhKm9,p(_C(9#8#.#.U74RZ>H;qs@kGRN|nol+:^_wKj3@"$ F|AoA?Rz0R=Pctwp;\v-IL0[{6*(%PGT@;ƥɵ9\C:/d:jHPɇ҇3l~vZc~|7BQU#fYQ +\.Dhꨨy!H$`(g^WCдցOf wO+ #:`Fnh^'!  A#8VL #8/l>6?tOh(6TȌ[>x)O_Hё祱'A&.#B匢\6/tBɣXHAVW[0z}u().hQQatbd9C6:H{hrj?fC,4HRD1igU?,y#:E&MJVfE:.LTF5#8a\B[^GmpƛI$h#:v|?^ &'!7aNY V-D,>t!#.7`#T?,]Ga%U($JB>vJyNH#:fiR%J1E- N#鬣DF%]xS@4DBO!>x#8i4,b K"ۀB m&jSiDTRc}P6=Sp""X$#:B0b2^U^7D[Iv8µ`nwbFbHU}snhAW coU*?_lC J)J#8wj%G0RW'zj'.|L+#8^gv&ypD߮k|bš#8q%$#8']Q[t7>Ž#8'9d)(Zf\?s1Cڿav#.8#8o#eoPRjb!28?370i#:3Uœekyn*Fd0KJU)(Z?C`LM1iU4TR+LXMtZ3 (6eNݷs;>4}8.~c` k U=bm*@,byf~zr,}\`H#:/ưCK㣍~vk*a/2DA4%rKR! fVC2bI#f@LFn" hEHWZR4n#.ԏgx"zJ>EdqUI'pwݣC`LAR Z 9~;ϴ±:xc>t#:SݒȮD{JPZhu8kf<J@rC!ͅ;8V2n#8(Jr`vYjL)"ԙeA1ƑlqQ/5@ġtʼn7D'4M]k?Mxe<+姬DS[P/]ih[[;ab8`-Dwl2uࢄ#.gvPz==J.)遆wb#D봙 ;@ƕ]HA1FՄON)?h~TM@#8asO9A4BahÓ6Y^{mKt?oϱ-TiOQ3?t蝽qE(0!(jJj16 (&16V`j*JKl!IIdF"hf2IAhl15lZ6$+Qƍ&DiДJPYjJQ6&cJkv#BfiiiSJBT?ݐY#:ZKeLAK6fV4#8&&a!kD2J$0 ( Pi2$[e2aɘf&f4ɀ5Y"([4QMR&QJdEhMM1yywMۿWe}W[7sr lXRm c#.EJP{O,#:,60#.S#.0͍F46*>Q(Rh! #.)J&!B=W~s*l't!%&_l#NMܑ5Ҥܹ%bJYNmeڛMDyshj~ɻa*fэK6DLd+L@QJF8p]cL(M! ө)Wu3_wourϥt:ɨX30=f øsyS1PP쀉|?jAH@$^r7#8'_D?ȼ4#D+I2D RTF5%H-F֢K~*aW:5H M <#.|DogԘoA:B"\wH1Q#z~IǕW/Oٙ7f<_ւwD{#8Y6 K7\; 7G #:N7Pl ev.}SLᏎ%HֹŸyRLɸt3.}a6c; 'qMlBΪ+>;y|uaLlaDy]*x!]QgTG'N*"2m#:5svR}9}-_ϝV"P=NuDZ9V8Ɏ zwIt$uaU4PlIJJ`G#"aH.a:1€1O@xяPk8v@ޥi"Q m6yNu#:Gb(#8h>\߇wNRj#8WC#:Hb3&-mJuzԥeM)!$IC4w0 eQRQ!#8g w",Q_ݳ"0QM !ޒ"r pukbBƐ'Dː!546 g^SAaYP [inK׳2ce612*!#C6;zOqXRݍ-ZͰ3%o-&190_pљ4⑉cO,xzp>6>Y\0QN8†\d?j$F6P t RH=k M=TKp3fԄ"cKxr5j,ԥEوc!wl))nF1ÅqThh-:C *51 %2 Tc#8 c<1[6{h7TwhftD &8`ILmD?0?nƊdN%^o =>-^o PTZ |B9Ճ'w@>jڃF÷&7À8Oxlzi@"Ct M|S`4A!67 4$@^pXv UPb'0 Q]xye!@$P`o#!6\ڻ{.1 ``AtFA#85yw dLā6x۵_BRD@#.3")B TŇV@M ͬj.gK]#8(N3?lH6 X$AD˺#ׅ \Cei!lB<|1%5gECkc>3oCw?A ߋ~?squM$4P{+E޽esyJd#.dBm.H@;b,y1!%aiZ+CXҒcZDrqAppTѧwZ9[(+QTTF 1LVYJ3@ .X[3lFʇeG9#8F#.4Gcѽi7#~L!Kh1ȓV[J6&!"MZ<4ɡj\0DJ[Jmpq-r|ʊD6dkݵ(S\Z6Qf:SڳQ,LF#.eP$ۋ>iXh&!a6pᷖ܈hd`Ddlce ƌ&d@c8zwĨ&`&{68+ڑFa}9%uv!il0cXƐ^k0L ݍSC!֣^qfddAr0!=L) &sҢebZ[<0EP[{: $gN\կx?&|ϔ6r.EBgú:^MMiHGAAy(HyJ|cPҵ[JfE-H5&BJD2瘅FϮ\5ޒWٺbύo|r-鼷yk,mbEF.nIˎi2^w;}uUY]u-ƵŠ hiJW0$PilՉC݅4kbi Hÿ6ta0|aP9WwG#8J֥B<GNE$* {xc,κ8m|8V$>PX}ӧ-g.MSj~c92TaQPcg&z=o߿#܈iM`Oyɖ^v@8zng)'c[:<|S8ȱłL1Nrz(9:^@~\/WW풀,gzp|8..ިS x=:02wLN%4]jQ;ll ߹޿Sa#.nktؤN 8kz`r-ER+rQP$&J#.PPHJ," ?lȞpHB~a>61iP"HZ4-+˭s]YQGH=IvxjQjRzBxG0T<~6Su ӳa!!TEH#dp2&"c7׻cv!m^aF}ZWn`KZ.,E#!z^zmw[W=^ `6 `D#8M0OH!vT58hLN- q#.w#!) @7m\J={̛!Zm1\<$C}=wdziHAj H4~$S#.`3#>\|'YEX\#8_kH5h7Aո1lelC#8׉C .`ヂa)+SA"6I"`I,D@#:#.4%Qz*T$EP%#:(#:Cd(ኀ|#8M'ǪI{U 5j˜c5\H&Tq H^zƷv}b@*;>d|wvS-Hk3*3gdNgv`YC #8H$X3#8;-t?wq3撑纸Ttvƪ8k`]C~?L0~kI$fBa^[𬲆0Ɋ.8<ÚŢ#:(r 1F1JyX1"jaҀ)([)DH\`dh aD@; 8aVSM#o\wTY3 sh&@Rqd#:Wh%$5ju#)#0b0f ,7CI.,7VM)0*ZAcB0.{H;~'aG2Q5?7߅?&"ۼ:B֗* 37cM|GHTD^Yl3C1 `Z168 џQu`Bm`H347ĻV-M&ma plX4|RS#:mH}k*#:dX pA?P/um97c4S!t$"@0o8'0wHw+G4pm4۩~BC,/ @`8ǽӄ ,?q:~##.DN=Oxn۳ó.\բN#:&d0POdPTd7#.M$03a0P_3)E=!@9q˗EӾe Ϡ| }j"c`9Mb<(w#:o<3wx-6x'D!ʾ.!ʇ-{"NmB5:eE 0#8bDǻ$#8=W"O^zSmT)k#:aH9 =>sϏ#.#. l0PTPp>$q/4ݲ[Z*j-5kr lѪ'41a DhjZC$rFb3*Tk6W5h(hڊŭr֨Uk_]i+cf iV_b D(1'94&D*@1M KSnB1qM:GAO"D2ڥ0[Z4k9ݻ|幸(3XhHT:TGCW.XYD. rAI̍ ؀`PqU#.R $Hz^a?yݎLa9c,݈o2{Ů4P |X}A&R}Q #8ɒTo;hɒkHQJ>耤@(<w=WH$@<>p=#r9vFS,&/}Yѥjr8a,>B0,YH݄iyi8~;ð#8U{C#.4pi!IEc#8(|R,L#.a3#:?E͡tRyhD:OxN2>]x4#.&g&`#)<)>VU}(W\eAHh; s٧]x-&vm MBvPRqrit`G)# ;iDAʏa2iIKB(D&)EAVE4ahM=".ߍD8nڱll#8H{ٽAkP;^'=]ٽHz#?qi V`"+Q#:G3CT ZBK?+ 16,h5GS]~xl$r }bʤՖbP"#8GC( ^r&2d-m/R6|'čpg',)2.h۬};`̨йs{91d;>"] \)ht#:dU/vfG#8ק^^9hOޠ˞o#.>ac&?+w%:+yw#:hi]}\wa͌|^.2 np ar!Xai,PLa#84g8$ޕjڨϐgsP> ŗ|BD5>O{1^ZEcbNnճ^ݻ=޽r+;/O2\y#8}H`Dډ"`\R(=Y$(ԞRRl1HEi.T~ v{IqWX {lF.#.]*a,p˲`}FnFk@D`9K@hb;X#80fae\j *SHQգUU6 zY㨱<)4MLBv&%A$6f=Mlx"`J H+I[BI )Q4#8< B#!d+c0ab 3f ֫+Li' ѓQC;],ܫ,#8 EB)0mnG" =X8ԅhXV ']Lmc+i6QcG0:=RjF "YA~hMln+z$hּ3⚘"ٲCn(<#8:blBU`A$A#:Ezd, &5(FT4`APu )\RnL呕DB leLC 7ĸ0Fކ$u6 DcBjDȌ#:j Ei0U,i(Ii&j\2Ŏk$@Dx&d!`-j#7- $ŔIi#86FFSSBSbъI%m6&YJ&)u#:`JEm!ct#849#94$$R,o*#:[Iq5QY5HACdpU]TiH*&8Z_=\Mw 868c!ud7MToMbmc\0-FVB]@RD&-Syq4XȌwѨщq2:b48&TpM4{6Z[iPm6 ,#8lbLlz*6#8t\QaO1+Mclxeec5,S5ce4CC;>_N֮%N:AZ֓f$#8/Ө(8?o`8#.Gq 8x&;e)MҭƮO[O[il\3J]4@YikLE6[:wZ=ozK*W{׼w28Č0cC449 #\b x %#8FQ#e,@&oלּ\ܻ*g=7k (=Ha-b˪Ei'}޽jN~˾;&LSӍ6\責hmϯ[{E`I4D#:yQ^vگ2S%yPyS!I~Ve0a;ij 5#MHNۇz1\ozzM3&^\2Q&F{FMmy2޳-ٛ$)@qSUAܬ13K$>#8FBF!o(W^Uߞsٴ2s!zɶlduoXBFK:#=hn-EG]sԼ邴jWsY17NAoCJ]qv8i5Hz<|#:X1`L]4_a/P5'Vtu71#.,*T~!27:D}:].6B#BWbvNΛtܢ׭eu|a#:Ҕj6Ѵ1i@,PMQѬA2%6U]Z&Ek.SJY(iIbت6((5hՍb2%IDҌEj#:0!AZP/i`A;tQL"rAb`{LN.B'g1>CR$6Xlm$)bAiBV%#8_}/T׉wu*Y$*wHe+(w#:$_=tÉD^HPRUaA_P@vCU $#:D4I˖#:2ҔJ!Y9R)dD&4#:S[FdڤuuQE[w36W6Ʋm% Qx2F !#:HfҺp/gZND\ث+#$QkO;bʰĀtF6:'#84U!L|AL( HKw/.N'$DEIe5i҄tO=du~3%64ݙĜrW e)CF>ҽ`w"/.ȋ6\>G%"V 1 Q _ȣL_ KD(ihE 0O ك)dHw#:E9"M#:zBq >R嶍[Sm:FH۾.[uq].cժ8AZ)I8'cb&1.#8G^nCX.LR<ׅf?Owr-.lHw;ÖDe#pCF:FsgFe,zB,2WY@6fU.g6`v}BKAYf q>VSmfO{12ocP?51};Zqt!;I|6򍀽A)T#:UC?OBϑ87{,WfaЕtvdkI(ba1j0#ŔViV 1mT̑6Q&a2b(5r;ͪJ5]R[ZL0m%Gh\iCRHHlBRCP ?A1hm286Lfl`cxakWHi6u b$ XPBd!X"1bZ-dYnkV +liź)G6_~ܦ/'Ο'\||[ͽVimkL%&Ja`*c1kx\YWo_򹣘h#.f4#.R̋ r12-iԴP]v5|{[v!S#:(qAS#.48ZF:gH4F;ArEPpB`M;iMF&R#8@! j#8p "KM/?{Y=89#.Ѧ V?K-]\f 1 /]0tOnpLau(OM#hBrSO6oqFty oYĚ݁ 8aQ#8nN3s74ܝZDǀ%W*x(#.TPQ4AZxSJ;)¤qb#ynH؁K}uvb;n)JRCU#.-zm#:S[V(֨Ii0!#:LϼKk> ls_F#=٘!LXJޣ} 6Е}I)6%rh6&q=#:s+f[Ax%xV SCX4Q9.@dai`30@""S#:>L#.O8`4F$"J(TK+I 26DZHR4p]溚E͵:[]wbe嫚t]׽s1wm7t켯=wjeu\e2Sa0QdRyV-I/Kا;Esss66[;unsq^ks^Fϖ|Q\U3cXu绯m $@ Řb\[%jM)b˓T^owcjjq;yy]ӫ-nU ^|Zf@j_EӲB!@ާ)'bQ#.9 J@##.:$D2J_>tP:#:.@ #:`ّ#8LH |q#8T>`»ML" #.C:->Au?:;,(_s/aa@yBHX@QT/#:ًt RiSt;~4} E@9 f?;a#8x~vUwH(B)J$*s#8=,>2@PѨ bblZܯ+{jz| +#:),WOl^]cd{JPhB NϛzPHIhT[Q KJ!H#ѣYMc"5FuF#8b~>>iBXD׆ɵBH*@F0LYftPa rdwf]u#8k# $%^,FDe.QwkQ<m"dI@:}vIH pDIdpFR-#8.̖$ x % Rx L*Kzm,F3">u `=v6PN*C)$Ȓo/#*sdEbE6C"C#.#.4Bl1O ^y-Y0!T%ѴG#.;@`bA剄Ȥ#8&ۆʟCq}HIH#.#. bfv[Xhuf1&Ѕ!*eD1(*,()X(JLFD& Q]B,س@MXMcKk`,"ciY;BTflS ^xHJD0 }fWPI,wYD(GݡV"1R@Ơʜkm LN~lvBHJ8#8Ե2X:4G:@BhJ ˢԂQ6'Pb6,%HU}B7~cIP#IB-&h%$@IHIs ƳmӤ!DY@D%oVIXaXFV B_vn2zd#ӯP1 M6Eh!ZYxFMcnRb'lHO#:ڍI$ЮJ""#87\ 6C35C#.6#:w#8ECbl}#.nz悅H&}a}2`U@}^g3aӭIɋDB#:XiҚe" 6m -@&jl:֫Z*R`10Ge<\M g)1;meuc^_ ?.@z)!!HA3E{@zWStr4'.v뻓keh( ^XA:vO":R%%2aAfFN˓PHa9 y-Hw޽F%PA)Zۭ B#: 3pCuu']@!!!O8|b旊JZ+31#84H}ãfћSN]0APv OY٫Λ822G#.߷K2zֱr*)sl^R_:xmFAF gD4!͈ʔ:_*X.aQ)u\D;mփyS6H)~A*#:~ULGa)%@2#8@#@ CF$Нd,|H5L#.;("Y'`rC 9&_-^=c#:V`cAY5$DUMr;Cb?`5$.6#.zMBRt##:#.2b$aR#:vhZT~L!C)w@_XC0b=a % #8hF/\،?r-2>ϴkc&6[4XwdIJM=k?I4܍&?;506)?H#81Jç%f#:1i踩ó-Q9RhOlQBgG=.C'`wC̟1V jg2#,Fm"x֍H#.y|BC}dŒe#"<3ݾ0]/!oY>91Zþp-#8w]~ S9EdQ0Oߓ1>q ID'1a4#8Q=: !lb))b Ҷ9Aj Aۮ&9/>:0mQQ M$1$)Z~=䌠\BCjIV8"f'gළ>*].Oٝ!3INMw>y^ !|`2yI[$[֫>Yp##D6()"ۋP41[k e50q,Ƨ7᮱d\/wuUDݷR[w$Б "k+RڡFs8T*oQ}rb5#.w+#.F f2 D"#.@^A)$&"FR>/"M~r%bCs?ePP"0I-ETYmM\>Χ%ŶP}!kc#Ѿ?W#:|%#:c=mM3Ft 4Da=y'$8吲/ZϬA#8~+DӁ4}mM8I!Y=@q<46zvΆɤ}' ()4aI A>BDDAcԝ<g/aAߜV"*O%8*w#:8|%(5` I ~mhSQkP,ۺ6#8/d|x#'_ #8 M`5 iP"a}hhaw( @)2D#:hʦBD$ɥ  BCs;5bLH4T#:R2Z{0:/W9(|}eCz!sM`r>^FjrVb1,dTe`#15hSQKV-gY0@&exl~olbQTD¢B5!Ĥ)RP0T: h<G91HdId:9oE&=#:\aK#::&+FM\֤iq([PB%DQ6AvРp7v#81$ =_"Zth_9GCh#p1_Pj__2i|:@Ϸ!(2QQ~=@'BA7ĉ#8$9U) $#88"C(C([gqj X,|qfQq1SٔtS#D/bևq`aܗP?WnRF}(N=x4P{ǂke4W-LZ0DkZ#: o'rR"#:_̭s\ɴK.]0Ͻ MtS">0[n)4v #AyIBIETkpw01FNm 6Z2~Ɖgn 6!$y#8`'t30ߗ_QXaʪ#.Ҩ33sqO]O1CuFebtDjcCO Es32n(8D4FBB#׶BD:Ps#8$`1ma(fb"HCԄϳ fFhC`=I|_T~tɜ'aעbsp;枝(k/&9&(PeaI%%!B`7=ۏ=}U-NrjvE}XzZ/ɟ,f%r( ɒw .II_jWo{ji^N(L"˙EkQ`mM@0JPe6DE&!C)2LHɢXh$l*)Kۊgp#.4SEC@f&TdȨČc? HGoh A~:2.V])GF6-""$tn#: Zkm`?t3^NǷ#.hq+ެj#8WbJnc v6#~si^a2f H sZ(ܨlD"Mͤ4`1ZT`ZqcV2{~XLrf,Q0ӛA0ǚԋim+X:6d(Ǻn7#:c|sQbֹM6̍/晡 nl%JH-e#81#PS6tL(h! {v]tkݼtXFRhe11C`ʤn<ӱd"x"<84-?B%XǵAAa1 ">&QXich& s#\H!urr}.JgLLKj~7#8:O<)5s2rFffX>-\+IDlXґ(j~k -o:"Bm {8F15r4Va@؋bnbiFvC-R$&H*JTۯ>/{l_%[rJ;s9q96n\L#H@o]Cp91j*wwt٤fPjTC-f;nFR#:W7l64(N#.@hi!Z[o^9hb@DRQH#86ة#.P28QFMg\R*#.)L%*AרOվ:F7ʔ# 'IhI4G^]{jR^Q1((;"*B&K M"B+ݺ`6һ1SQWJ74ąQ"0N]ƣu6X$d=LCrr;ݞ$dұqN8$NeЛ7HHqi0cc t0+chZg3(FM36CDӜkbg0!zj>%hh 6%40^ma#:+rImMC璾t;v {Y^2Lu~>ݽysNLPhiVZ001C䦘Em0cB8D#8ZRCm5wFE=xj8? ) "Q0WQ؊(c͋@0=x6(֯QZnW.U]-~JY#:#.JH&g=)osBKڿ##8JC̊1"T`VIilf.FBD  E(*fړVDm-&Ṕ H sA 3w͓{OT#:`OI4'7]>6;c)PL'EPۘSL,RC'QD~9x%G".t` neFA{ h(5P,"6݆:4LL@WuyN[WH(C2 !(Fib$2 m,T&X861x|Ԧcxym:OF6X3944MoWkU;z.A\6'kQ&9q6̉إMg}jv5C輙r4ʞppu5ԃdKbG@݃# iv;Fлhka~&3haZa&-#:LG#&67vdއBq+Q%TbAƖ_zۻbŚzm#:pATY+  u>z'B/OŁ?ECMM%AmY"fRQby{yx&" DKiaFq_JCW:#8:OoZP4)Hڪ\}_T5S1cӑ#GiѡnF.JhS%չ#8 lڜzMiώsICf*ipgnZֱyH[,=EL}oFv{'ϑT^ (~ǃW\K|׫`|a>0Yic8)a)IF$$jج']ܝH̄B! q3ɿҜ;xmybpAMALU:`dp8=:f)J%=Л2bVB}FۿmG5r* >GyZoHh ̣2]Ll#*!IG[!2n!Iq*YD0Êaj,#*dP:y[@3jSg4ԦrBUrEcyjPiG'm/$g5rwmƘjB%6Ȁ\ MW-o*{o.9 hZZ2S HrV!$;#.PِZ#8܀s3evM4~= 8 ֳ@;#:K{^86[c g}dtCHIsc*#80C@;g}a B?`9rp1)"LK8{,'Un\w34I$NhwvPB*`rZ%HEKɠS@"QL%R0HP.ޜuЂ#. 7PϷ.wzOkݞ kMp#:G?(*mh!$ި14qwz$2#:q:*6#:_q79rQ8Д, ?yx#.u7ªF#:F{|ӜQֈB8R9F@_7q#. *-P#.kS8T)H~H dP55gKEjQ DVHPh>#8Uo62.ZȡP(\R?(3 VZѶd˖Z/`^4ֈ&TsvRq?6Lt 7J>=2^ mI=JJğˀtv_aB_V#8_O'>J0k 2*pҐ.Ɲڷ "@v2E>V0 rw7i]urNv#ei5DjqFXkf|u- &S &2ztFDLZ-E3f.(c`t%7s_K?h_j#8/a]M^_k(vf .FcQx5[T4;2I/}Ğ=*Dm+kI̚y&HAI'CJɓyɔ:6Lj̠~0_%֔NR`nvq\JI'w6  ih\zSLn#:r*&UsrM^{TMR<-2Rn=kKuq1&qf6i IChóՆT:7Ǯg/I;yzzq=[][Mn%FϬ^/w!79yY˾3n-^ÏvcLm^Wna6Z6Q1*#:!QzJ>&^e˳z[Kǟ[#8#:\o QHswIsYABnRcx6>Jrc8;{UΜ6D.xVְ`QIBtCjyzϰrݸ*q>-% tq~K\g#2!C̽eUߵofͅ*TpdBIu֑H#8!A=&Bݦ SI".98CD&u"(ðJPQBNPVZj=DwYt&Hc.ӇnT`a66%x~VrQ፶8өSkS0185$pfc[Dwq.-Ls88o$y#"$lSr_qWLOS*rS|u4Mn;:f]Jl8er,]1a#̘^z^w'He։cGcu\:|6=;mҔB[E]y)ym LD+#8WE v;\H͆pX/|9aTAI=)Ai2 چ/h2LCoj7jCB Y!Xh%^.si"a1.C`X/w;Vq\w~[zX0؇n^s$#8: &́Xo3eRKf뚮$8Ђ:BlPC \5ް'Dxq6j}.2'{@h4܌76Bge#.#8Dye6>MJMekEж|桩W.{֫\ȝ\I6#S}bI]X֖dTHЩ.I,Z#hHytA ʁO.vvONuIgv/zo>;nYUibfa=Ց%#8滣Au*T0 I2m6S!tLU#c܏_/I1WYۂɘ9W1TW1'̍U=6#8yƍ/\"Rn>|l6/3i8} wE׈zvgBJrm$rcln^ڔ^3=TN|>RGNviŅ=`{Ir/Jq})5AfABdig#6f39X܅ !,iX84Ƭ"ZRG8̭{T,S'od1;y@, u69e]/<YD5QQYp2~M(@ ˓;eA" #:)#8,[UI{k鞯(`Jcb6sp sKmkƣc'Z^@ۆ(/jD+ +xp/XDYXf%NN|#lN ;`N30'~=x:6C܏IEg]` %S_^亡f[gGv5w>7;wOś"sB3S^X8*EDnU-m5˻I6KrЯ绍.Et#:i@ZR>%Aqӂ*cbnD1åAyIWO72p&Kπt<0M448:L#8Ab|^αļa 0[ebeHEaC)k_zk@|4* 0`O!6@ 5#.rIc;Ǧfhs,M7v1$D%0buC;r2 2Hݷ0iY9Jzi9e<ɀqAMXȪ_Y ƥn3(;z/;<ԍ>*y\B1#TP4$QYHM@D$\Jܑƙ-<7V#8YZX.,ח(wў=1=ޏ_vo?3*#:T(Fd I$Os#8{bI:$H!YݣSU3HS¾7!H)ǰ?uq#:@f"Û~#84ˆ} gD oA;Oow֏pǦSYpýnSX~y=|DU|7A0Hctm*m63DȒOmb$~Jmb;^xǗYw1P2$r<7#8<969M1`JrZȞBi/lX,"%v&'_ =={ۿw)"H*u'F4PUnDI.n)]u緬aI#ۍ6\̰ !lM:b&qKcb6s;YKSD1i#8:ad15ٙ\m;4V&D}#:-Fޭ)[ߓ׶*Zw\.hۊ/置Wd{)26˕ԓ$Dc$HZ2эF4n}|让F!"FMC>Pro'vX0 )3d4;l Ġw{oؘUPpd76bruwZ'bЕۉBO0=!O9&x|a@OzEUSQxb^TM|Djr"nŒy;YQma .^ ӱ5QDw*"tcg!g}zGeYbmU+%os8FSYTdÖ4Vi_8)~`='c_aU!L%y';<&S*.3 '" q0(gh2 6Ƥ'yd=Tr`sy_&n5XEOW^ɸIѷ4䢆ymJṋb#m-naFmiI4[j%$zVgM*SjQ&;ޖ5t'۝5ۤ݋:AuuW]ۖ*6l %S6LJi&`]:gޞ?#.87=GrNsiIw{~CG/U0"1e>:|Quꮛ~=s;"̇>dd>!—u9"dAC..~;%x+--#ēwƎL!_QO}Φ#:Mclq(#:XזlC2cDטK}'#ce+F#:ْ%54f]IE~ÍTQC)?rdu+Q3\|3gx^gzc#:LT h1fA#.LDr#: zv>`b"(4@?9;,b2@s]i!w#.$'߿ISu djEşd#t۾"Hr /E4 "$b@=3q+M2RKKN5Y]6t-sUıi6P3Yhj12QlZi54gw4˩+j&cC)0U2E,#.JB2bj+1?rrUۂ̌d@0ځlveب}5ZPK܏R#86+XXW iϾLo5K\xSAHd̄L&@>S}#87x ZrD_9 s8)8C`ˏJeF#zfDch1ya2M0Ot@V!r +umՅWyq#8ClǨ DžW7ih~bǦViJqmXKQȎ#:H6ˁ#.1V,I/մVmuR͆L>mF@D1,mHPbnu7L(r64\Z@d\H$1D$Px=x8rJC)SZ޵^웷sVn"h#8:h6KtC)܈"1IRw)&vz`VOf`DK1 wK`^[OdUlIpC/oPIonxp#.^.Ɂ@5,tMn>~-Pb_O2Chɼ T뇭1_bnUF#8|'>DE<üA-k(%3.)\PqE}U#: E(JM2"&!J`ZXL]Qv#8acgނTv&.R/5vּ!y)9Tݟ=g/5lOw>1>XDlnNuכGQ̳ }l=f!ӱ;#ʨEl/*{-`#.:gFOݗyWrD)4Qs6 _¦BSK;{=*{W*$ͽi}?@O@9:GCBPÖqeS)%Pӟ7Uc/|fbeJ3+MTd5~obF#8ʰۏnԻwVL߇K$(a$2JbRzbg[#FT0l8rā0Pp=ll)%?z(vԤA#.DAac~h9nvB)X\AxtL %x/?ҏl wQ ſ_$jH9!n|0C·$}Ǧ9>vSٶ)U'b?)(CtN7M܎cLc^ٕRMxtZ#Š>#.3}C'g0;R8ݣSzu˶jƗ-tfΫ+9ƀr:d~9,M~kkiL;zÒ76Ck&~ߪv͚u8.$F^H:ظdLeuN$o2u{tX;mI0;b4/xv9&WMIy"͎u> owB"=,؋SOx}6qcfܭ߁~JN{[L,AQ+S<*1(IiMvSOu;sTo+]8}[6ɪF9[/yΈl'XgȅΜ4Ӎ hGK8NiiŒUn!Ƣ[㩧(EKjYqfV:;YWjݒ]*BHi#88kZLYғ}Ǝ[DU :At带Jú"3ot:fh14!SU݁hCx#fm~pfk&q qK!X+$+E۞1Yv*;v#IAj2s#8c^R6 Fne#8N{0٣CoqPKCyXL$ )X\k ˆ=ji wަ>/k#8[ ZolU8H(E:Lkkstdpdl@@ 7ɀvJtq#M;iC a;aԱ,I9v\ΧFk;.#H}68eh.[6D\o c;fC˴P&痚PP;bbi8FF4>arhK5GJܦ3+ΧXqɢ{D,[:#L`6#.e}Ӥ&[ELNF `W?2j)XCo%+\toHÌ͎$;3-{L IKwE\k[pKv4Q,;TbD֓ѻo1Ánhyi[ bfM)X$[ịm1i4m]m-5.z;#Qø̰j&9axD1_%)~3!\johvR'U\l5#EwwbRITۙXTd b#:g#./fk#9I~QC;\q۲~o'h8n|>6Rv>伦LyxIM,#: ep`o'PA"ԔRPfL#:.RF\UTݳRu1>ڌ&}h;fӮ~"Ps\K1,3n]mIR$رa#:P%@ɛ`9p@G B6#KFVU) "un1Kn2J1`*wmъUuAP(-\ DtExDbGi#:q`ʂ\V:7 \ij8\ʺ[5}r.b !8Ynd!HC;$Vk58s,l̰S&.3hvyQ֑#:Z1d2oN>Bse1#8nZiO\;1 o]ht4;60T6UKL#`%6*yĖ;&v=F:Îchr-ecωYDaIBj-[ >ómtVƒa9&#/2H.,L"ӪJ?3e#:;mkaӪCKj*s1 Ο((V駎v96ɓ}c Jz2RX14fM JMH 걺gv(Xr` "K3 kFoGIt4qޘ(08CٹK͞s0P_c7pˮ8WJ#:_8Phsfb8m5>n#8l5hzLIoN#j(3hӻhF#8ֹ#.8x$a!qA+:}^v&HyLtd&]33H32LcSt1f5,RӳB e͜7L8%AfGh j li8HƹUY,qQϖq:>bBvjzOxk^&tqKoLΗ[:,.\NSt F36+CYv$F0B6} ۘp=Uao~^\q5dQM5"~imOڠ(8 睻My8fzu=3R;J6GlzmgHdFA1DIͷ/y>uK'ιwfnT;W̺eKz=o+K{]fd$%ެ;/a cݶ#8IUu<{tt|#8*.Jht8Bb&I!W4Idzh*"`/jMIb™852xmWwRqB0sQhg9-9t}0NnM2N4jk$"y}xN@onKaZjZN)#.y*#: haO@Q IM(r#:B"̀89>NR^h/q<!1诗c@"YWqҞg\ݮ\s2n9L#O&ЮhhhKzsB㊷#gc3G"U:FFhl+oB:#8!3&0aGݔ0#NmT<T00*_Y#:c/sF\mMI62JhL>'l9n}|]ݔ[Nz43:ޘ3*^\a@BHF܍kBX^|HROf^¯asl #8&SXaYr2pLCeA@*eÛ087x(>V8v%U no>]w}з8xqizMF!(iCmۊc:cԢ]q=I/~|/ Q?&pK}{L4?4g![qڦƈ [#(D:a \)XR EaRNh3(\P>#.!@`C0>Pe>Ԫi$]6)'02hhhhi hMUj$#.HA4J|6B B@" ; "*d*DdD @+R2I 2J$βNAPD#:LEJAiE$PaЩJ4j#.G#.*y#8J#. #8{{ko 8эK blX1+#B]XA%aOC#23(#́N!9#$OP#:n'0FgC^{T}2"[G"P7TF|-#.z}(JY%"B(ϴ #oϸ<#.>*|bxCo˰j< wo&#:d"!@B#:Q(0&@ר0QDkSuVdqm܆fj#.#:*HM!1|Fk꒙9y`#o]3E0<G !" 8r^yK>.VBj'h[&jatW!С1-8#8'J&T-C#:gIcmaxPc#dLhR\3 AJOC*LPM㹴[L+uvr[U5H{cz˜C}sr)Vv,\Хh"$9m}Nؚò9eO-gg 71f:m$ndf;Yg,b̎#:a|,X'0<2d:lO1dZV\@Fw]+r"N=ߍu1-mZRv4y3 `łˌ PJa06[,.9oHqq ׍A *"a*B@)ߍ!ݰ *2.XoLf#4r#8RE*АG=Zs~>0a,h(O/y8cD33' =3%e Z&#J{##8_4܁=gG~3^C*nmC t*P4#.Hz)sICHQfJ#:G.`dJ1˿.J4z]ȝ$3ouݷ+ݮl c"m,=TȐF!F,Fj5GYbkt[JTئQb_iW(V-4k`Ww^jɨԚ 0Ll9#8zl&DME# #AhyRs|rZ6}!MXn{ $?ihu6)tHU3!H BR,JB(YkS*ESjkh,k`s`CFj[AUI$U-AHE%5eMc!b2#:IԚ1E,R/d?"MFبƊE#8ͤfmvDrCaP5R)y#T*!'&L¾DRR-6[,ɯ/ŃWI(ْֈزe+%64%{ZX RA?JРy{]eUsq/WsNJt#:D&pǶMj]]#8(;&!5}!'MVOJUNFh8uk2Z^`҃ѵzB|ܠG!7!bX#QF3#:E F&\=-IqM-}Nגa0FB<@Od5!ဤ!%Hg`"ȁ`j렂#_2 X %#:d]*#.xD)^ʺo.kv/^n^\(.^LkjV#8,ʲv+רbڬ i% JM@n#.@P H'~THUpWy/~rI!64z1H #8B&9èPa)W-+DێQxY!yԜx#.Ԯ_9,Z8fp ӵAY0;v4NT=Bf|?29#:=`5ꝗ.붉anWFloú&#:BFD#:i(d [YB%k`)QHy|x<jǰ7 td~jWE e® mj}xH-"S9_i#8AJ@%3Rck?93T#:C(D|2b]u4#8X DUФ3D Lʩ-ϩ Z1ׯe:ZfIdl(qTΔ?%& b6 kUF`nA&!Aj ­]kJc͑nK]O&-NS#."2qJq2ݫdZ:P6)Q4Tu]uiu2]WHh1Nc|R @J9d2L#.J!ݹ֖2.5]N/r<`"#.JB|?.eEP4^*)QHcgpl$D7g@V]ϞX >rhN~&Mpx XR0V#:4rÒ!kI3n(U4)0khpblW xY>\ȅ,UxUoRd5xCL?sw1CrBiJpQHv#&'Ոn*z%lֿ4 s#8&S8^^ࢋEQA& O5/orI>RY140>YCmd*b 'j쎔QH8/W#. 34qo1&B;L 988#8.G\:AprP$$Xx{yfI5|7\wtwPe BG$$X $=KJ6ْYLM#8s$iJl*,2҉A栴$@Cl%,@C,tK*û}FHT&&L^o7ZCS'g> }w0"#ֳ`҂m[xiZsL(2G1L?M(b#8֞d<pQEKO5H6rz:ly׌מ#:sh5#8 R{ZJP-n,Mьn(ܑ]"N#:Oq%[YC=ͨ;`|(Y,h+(Hl3ȎXYt)8ECCDֶVYB)@̙'q",!F~J=o'<&ש9$X$i4piŗ(*RH=LQKd{lRWoIJS):H퇗qA71CEJLnf ۟].(s8Qلc"tqvKXڤw?38tRQHŘLD'#:l*8-fu æO#8!)@ɤE.GL BHՂ8&^A(|>ld"+PCl09rXKQ^BC#.f:p0و1!M#*%eBO8B0QwmR%u#:~#C>:91"!d%2C#85HR9_jѥl3cdMhAp7>J#.J! _}D*yw"<9> n0 Nyfn?q!Ϡ#8!G!#.ehkI!&@qF?0! ydshU^rrϵD9f%SD@(PY܁r.مd=f#8< MȍB#8#;N=/"`E(" !ߏa-!&rpgZ]@Ryߋq^pP2Fc^ߝ1F$im1d痂&OQ#:չW&Rb8'=_U D,+޲)~ytd,Uf1U7D4(#:!d;"R =CŸ]~*y()lcJlvæAMF\cjnbTɚֱ#8x'&((m)A@5J,N8Nk?δ]r`9Զ)F;?NaGSkQbPj.)N/8q~_P4yU{xaVn(7ѷI?t2`z%@FE5U:ҭX@AQb\E#Y6ֆ3x˪"mjArʚV9{˥1#86hqǾBQRgHkRRUxɥNi4嘲H(q#8i0D\Өt8#FL֯2!Bl#:1#:QihLDDe6#.zʓ bm#8FRO#8zf7E,% DTut,[@zh VPRT"0yo<^H>pL&SJd+zX8vs]3 a (of ۂa' l#.τD%q (ˎDQT!fiñsy<י)4#8q1WAvF*J#.OZt(Ԉ0H4MTDE(#.#.E#nè˨iCȫ)gs9 0AOIMv/(_|24kgW3P(FD$"^|m{u۱kOa@f*T[^nkRiRQU,!|n!2jkS$2H+3J@Ab#:˖T>0rSa!H|HM2vT L Z(}cZ=g#.fz>ߛ֬Wk|F}1!FgK2b>`2;~IE$tgg>5:;ArQ0DuCM?zIOgIcBbPZHE=rjB%;7uNU#M3oXVp +L„<.ӯFq"xfͷ#QN,3I*v,9}Y3e*;jQ9'ڇt%#:wyCC OǍmqg}E֕j|#8 ˌ ƢٙF=9彶t 有>~c*%Cn8B(w2i7H6-%;drv,3nC$*xs#8 mc0aC$K@UBY$˒cH3é!#:޳xv䱸+PbmE޶fzSTUjS-ŵC0I!ou:C8إ p#d8>X.9~z ^' l6,1^WϷ&Z`t% iO&ڈԸA,{ LJkLܐjNV)aw6$U:m .υ\#8C_D%06J4*X;&<>|̤!%]P]|b*7[m|jvhך`~msGZMbJDH*pvT48NgPfY(2{h0z%>6OpCIPy ENm{#.ظ4TțX;zL|9Y<2p9Uj0w BO0쐅klAT4n ?oI[>̬zWg=As>jdp" hGw (/BP;N0|jG3R5[\ٵZfi6җ0)#.ie$g~/۩OsDwdreFTXMIWkzr)43izOϔ;ad?_GF g&?'vڃwgN=C¶=01W Mi)O?zØkʑۧShx"0>$&_ݤ#0z)HʹBC_TzrO1nk)D<杽?˗(]Iw A1QaY{acPl؝jqeo>@_R{ d %&6_ʜkek,*S]--6t_):0-[vPVJbH!^ LttJi=B:!P=6e=_6+?N#8&ڔiWsYwiӶg>ւV2rf[󉸔UIڣeDGtiPtnm=lght[AiyJu\sŀkSV5?ѴxvOq]a-q(9EȺq*Y29AxQJ"'5#_?G*܉e.` e-_|?r[|eKN2GS]H'Ȝ0Qgxid$A*#8F5]B@bV_ +#<== diff --git a/wscript b/wscript new file mode 100644 index 0000000..0f4c3f8 --- /dev/null +++ b/wscript @@ -0,0 +1,260 @@ +#! /usr/bin/env python +# encoding: utf-8 +# a1batross, mittorn, 2018 + +from waflib import Build, Configure, Context, Logs +import sys +import os +import re + +VERSION = '2.4' +APPNAME = 'hlsdk-portable' +top = '.' +default_prefix = '/' + +Context.Context.line_just = 60 # should fit for everything on 80x26 + +@Configure.conf +def get_taskgen_count(self): + try: idx = self.tg_idx_count + except: idx = 0 # don't set tg_idx_count to not increase counter + return idx + +def options(opt): + opt.load('reconfigure compiler_optimizations xcompile compiler_cxx compiler_c clang_compilation_database strip_on_install msdev msvs msvc subproject') + + grp = opt.add_option_group('Common options') + + grp.add_option('-8', '--64bits', action = 'store_true', dest = 'ALLOW64', default = False, + help = 'allow targetting 64-bit engine(Linux/Windows/OSX x86 only) [default: %default]') + grp.add_option('--disable-werror', action = 'store_true', dest = 'DISABLE_WERROR', default = False, + help = 'disable compilation abort on warning') + + opt.add_subproject('dlls') + opt.add_subproject('cl_dll') + opt.add_subproject('mainui') + +def configure(conf): + conf.load('fwgslib reconfigure compiler_optimizations') + conf.env.MSVC_TARGETS = ['x86' if not conf.options.ALLOW64 else 'x64'] + + # Force XP compatibility, all build targets should add subsystem=bld.env.MSVC_SUBSYSTEM + if conf.env.MSVC_TARGETS[0] == 'x86': + conf.env.MSVC_SUBSYSTEM = 'WINDOWS,5.01' + else: + conf.env.MSVC_SUBSYSTEM = 'WINDOWS' + + # Load compilers early + conf.load('xcompile compiler_c compiler_cxx') + + # HACKHACK: override msvc DEST_CPU value by something that we understand + if conf.env.DEST_CPU == 'amd64': + conf.env.DEST_CPU = 'x86_64' + + if conf.env.COMPILER_CC == 'msvc': + conf.load('msvc_pdb') + + conf.load('msvs msdev subproject clang_compilation_database strip_on_install enforce_pic gitversion') + if conf.env.GIT_VERSION: + conf.define('XASH_BUILD_COMMIT', conf.env.GIT_VERSION) + if conf.env.GIT_BRANCH: + conf.define('XASH_BUILD_BRANCH', conf.env.GIT_BRANCH) + + enforce_pic = True # modern defaults + conf.check_pic(enforce_pic) + + # We restrict 64-bit builds ONLY for Win/Linux/OSX running on Intel architecture + # Because compatibility with original GoldSrc + if conf.env.DEST_OS in ['win32', 'linux', 'darwin'] and conf.env.DEST_CPU == 'x86_64': + conf.env.BIT32_MANDATORY = not conf.options.ALLOW64 + if conf.env.BIT32_MANDATORY: + Logs.info('WARNING: will build game for 32-bit target') + else: + conf.env.BIT32_MANDATORY = False + + conf.load('force_32bit') + + cflags, linkflags = conf.get_optimization_flags() + cxxflags = list(cflags) # optimization flags are common between C and C++ but we need a copy + + # on the Switch, allow undefined symbols by default, which is needed for libsolder to work + # we'll specifically disallow them for the engine executable + # additionally, shared libs are linked without standard libs, we'll add those back in the engine wscript + if conf.env.DEST_OS == 'nswitch': + linkflags.remove('-Wl,--no-undefined') + conf.env.append_unique('LINKFLAGS_cshlib', ['-nostdlib', '-nostartfiles']) + conf.env.append_unique('LINKFLAGS_cxxshlib', ['-nostdlib', '-nostartfiles']) + # same on the vita + elif conf.env.DEST_OS == 'psvita': + conf.env.append_unique('CFLAGS_cshlib', ['-fPIC']) + conf.env.append_unique('CXXFLAGS_cxxshlib', ['-fPIC', '-fno-use-cxa-atexit']) + conf.env.append_unique('LINKFLAGS_cshlib', ['-nostdlib', '-Wl,--unresolved-symbols=ignore-all']) + conf.env.append_unique('LINKFLAGS_cxxshlib', ['-nostdlib', '-Wl,--unresolved-symbols=ignore-all']) + # check if we need to use irix linkflags + elif conf.env.DEST_OS == 'irix' and conf.env.COMPILER_CC == 'gcc': + linkflags.remove('-Wl,--no-undefined') + linkflags.append('-Wl,--unresolved-symbols=ignore-all') + # check if we're in a sgug environment + if 'sgug' in os.environ['LD_LIBRARYN32_PATH']: + linkflags.append('-lc') + + conf.check_cc(cflags=cflags, linkflags=linkflags, msg='Checking for required C flags') + conf.check_cxx(cxxflags=cxxflags, linkflags=linkflags, msg='Checking for required C++ flags') + + conf.env.append_unique('CFLAGS', cflags) + conf.env.append_unique('CXXFLAGS', cxxflags) + conf.env.append_unique('LINKFLAGS', linkflags) + + if conf.env.COMPILER_CC != 'msvc' and not conf.options.DISABLE_WERROR: + opt_flags = [ + # '-Wall', '-Wextra', '-Wpedantic', + '-fdiagnostics-color=always', + + # stable diagnostics, forced to error, sorted + '-Werror=bool-compare', + '-Werror=bool-operation', + '-Werror=cast-align=strict', + '-Werror=duplicated-cond', + # '-Werror=format=2', + '-Werror=implicit-fallthrough=2', + # '-Werror=logical-op', + '-Werror=packed', + '-Werror=packed-not-aligned', + '-Werror=parentheses', + '-Werror=return-type', + '-Werror=sequence-point', + '-Werror=sizeof-pointer-memaccess', + '-Werror=sizeof-array-div', + '-Werror=sizeof-pointer-div', + # '-Werror=strict-aliasing', + '-Werror=string-compare', + '-Werror=tautological-compare', + '-Werror=use-after-free=3', + '-Werror=vla', + # '-Werror=write-strings', + '-Wno-write-strings', + + # unstable diagnostics, may cause false positives + '-Winit-self', + '-Wmisleading-indentation', + '-Wunintialized', + + # disabled, flood + # '-Wdouble-promotion', + ] + + opt_cflags = [ + '-Werror=declaration-after-statement', + '-Werror=enum-conversion', + '-Werror=implicit-int', + '-Werror=implicit-function-declaration', + '-Werror=incompatible-pointer-types', + '-Werror=int-conversion', + '-Werror=jump-misses-init', + # '-Werror=old-style-declaration', + # '-Werror=old-style-definition', + # '-Werror=strict-prototypes', + '-fnonconst-initializers' # owcc + ] + + opt_cxxflags = [] # TODO: + + cflags = conf.filter_cflags(opt_flags + opt_cflags, cflags) + cxxflags = conf.filter_cxxflags(opt_flags + opt_cxxflags, cxxflags) + + conf.env.append_unique('CFLAGS', cflags) + conf.env.append_unique('CXXFLAGS', cxxflags) + + if conf.env.DEST_OS == 'android': + # LIB_M added in xcompile! + pass + elif conf.env.DEST_OS == 'win32': + a = [ 'user32', 'winmm' ] + if conf.env.COMPILER_CC == 'msvc': + for i in a: + conf.start_msg('Checking for MSVC library') + conf.check_lib_msvc(i) + conf.end_msg(i) + else: + for i in a: + conf.check_cc(lib = i) + else: + conf.check_cc(lib='m') + + # check if we can use C99 tgmath + if conf.check_cc(header_name='tgmath.h', mandatory=False): + if conf.env.COMPILER_CC == 'msvc': + conf.define('_CRT_SILENCE_NONCONFORMING_TGMATH_H', 1) + tgmath_usable = conf.check_cc(fragment='''#include + const float val = 2, val2 = 3; + int main(void){ return (int)(-asin(val) + cos(val2)); }''', + msg='Checking if tgmath.h is usable', mandatory=False, use='M') + conf.define_cond('HAVE_TGMATH_H', tgmath_usable) + else: + conf.undefine('HAVE_TGMATH_H') + cmath_usable = conf.check_cxx(fragment='''#include + int main(void){ return (int)sqrt(2.0f); }''', + msg='Checking if cmath is usable', mandatory = False) + conf.define_cond('HAVE_CMATH', cmath_usable) + + if conf.env.COMPILER_CC == 'msvc': + conf.define('_CRT_SECURE_NO_WARNINGS', True) + conf.define('_CRT_NONSTDC_NO_DEPRECATE', True) + elif conf.env.COMPILER_CC == 'owcc': + pass + else: + conf.env.append_unique('CXXFLAGS', ['-Wno-invalid-offsetof', '-fno-exceptions']) + conf.define('stricmp', 'strcasecmp', quote=False) + conf.define('strnicmp', 'strncasecmp', quote=False) + conf.define('_snprintf', 'snprintf', quote=False) + conf.define('_vsnprintf', 'vsnprintf', quote=False) + conf.define('_LINUX', True) + conf.define('LINUX', True) + + conf.msg(msg='-> processing mod options', result='...', color='BLUE') + regex = re.compile('^([A-Za-z0-9_-]+)=([A-Za-z0-9_-]+)\ \#\ (.*)$') + with open(str(conf.path.make_node('mod_options.txt'))) as fd: + lines = fd.readlines() + for line in lines: + m = regex.match(line.strip()) + if m: + p = m.groups() + conf.start_msg("* " + p[2]) + if p[1] == 'ON': + conf.env[p[0]] = True + conf.define(p[0], 1) + elif p[1] == 'OFF': + conf.env[p[0]] = False + conf.undefine(p[0]) + else: + conf.env[p[0]] = p[1] + conf.end_msg(p[1]) + if conf.env.HLDEMO_BUILD and conf.env.OEM_BUILD: + conf.fatal('Don\'t mix Demo and OEM builds!') + + # force to use server library name + if conf.env.DEST_OS == 'android': + conf.env.SERVER_LIBRARY_NAME = 'server' # can't be any other name, until specified + + # strip lib from pattern + if conf.env.DEST_OS not in ['android']: + if conf.env.cxxshlib_PATTERN.startswith('lib'): + conf.env.cxxshlib_PATTERN = conf.env.cxxshlib_PATTERN[3:] + + conf.load('library_naming') + conf.add_subproject('dlls') + conf.add_subproject('cl_dll') + conf.add_subproject('mainui') + +def build(bld): + if bld.is_install and not bld.options.destdir: + bld.fatal('Set the install destination directory using --destdir option') + + # don't clean QtCreator files and reconfigure saved options + bld.clean_files = bld.bldnode.ant_glob('**', + excl='*.user configuration.py .lock* *conf_check_*/** config.log %s/*' % Build.CACHE_DIR, + quiet=True, generator=True) + + bld.add_subproject('dlls') + bld.add_subproject('cl_dll') + bld.add_subproject('mainui')