Waf macosx fixestags/v1.9.11-RC1
| @@ -1,9 +1,34 @@ | |||
| sudo: false | |||
| os: | |||
| - osx | |||
| - linux | |||
| language: | |||
| - cpp | |||
| - cpp | |||
| compiler: | |||
| - gcc | |||
| install: | |||
| - sudo apt-get install libsamplerate-dev libsndfile-dev libasound2-dev | |||
| - gcc | |||
| - clang | |||
| addons: | |||
| apt: | |||
| packages: | |||
| - libsamplerate-dev | |||
| - libsndfile-dev | |||
| - libasound2-dev | |||
| before_install: | |||
| - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update; fi | |||
| - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew outdated pkg-config || brew upgrade pkg-config; fi | |||
| - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install aften; fi | |||
| - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install libsamplerate; fi | |||
| - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install libsndfile; fi | |||
| - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install opus; fi | |||
| - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install readline; fi | |||
| script: | |||
| - ./waf configure --alsa | |||
| - ./waf build | |||
| - if [ "$TRAVIS_OS_NAME" == "linux" ]; then ./waf configure --alsa; fi | |||
| - if [ "$TRAVIS_OS_NAME" == "osx" ]; then ./waf configure --opus=no --readline=no; fi | |||
| - ./waf build | |||
| matrix: | |||
| exclude: | |||
| - os: osx | |||
| compiler: gcc | |||
| @@ -133,6 +133,4 @@ WAFLIB_STRIP_EXTRAS=" | |||
| valadoc | |||
| why | |||
| win32_opts | |||
| xcode | |||
| xcode6 | |||
| " | |||
| @@ -17,12 +17,14 @@ def configure(conf): | |||
| conf.check(function_name='timeGetDevCaps', header_name=['windows.h', 'mmsystem.h'], lib='winmm', uselib_store="WINMM", define_name='HAVE_MMSYSTEM_H') | |||
| conf.check(function_name='EnumProcesses', header_name=['windows.h', 'psapi.h'], lib='psapi', uselib_store="PSAPI", define_name='HAVE_PSAPI_H') | |||
| def create_jack_process_obj(bld, target, sources, uselib = None): | |||
| def create_jack_process_obj(bld, target, sources, uselib = None, framework = None): | |||
| process = bld(features = ['cxx', 'cxxshlib']) | |||
| if not bld.env['IS_WINDOWS']: | |||
| process.env['cxxshlib_PATTERN'] = '%s.so' | |||
| process.defines = ['HAVE_CONFIG_H','SERVER_SIDE'] | |||
| if bld.env['IS_MACOSX']: | |||
| if framework: | |||
| process.framework = framework | |||
| env_includes = ['../macosx', '../posix', '../macosx/coreaudio'] | |||
| if bld.env['IS_LINUX']: | |||
| env_includes = ['../linux', '../posix', '../linux/alsa'] | |||
| @@ -37,8 +39,6 @@ def create_jack_process_obj(bld, target, sources, uselib = None): | |||
| if bld.env['IS_LINUX']: | |||
| process.env.append_value("CPPFLAGS", "-fvisibility=hidden") | |||
| if bld.env['IS_MACOSX']: | |||
| process.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64") | |||
| #process.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64") | |||
| process.env.append_value("CPPFLAGS", "-fvisibility=hidden") | |||
| process.install_path = '${ADDON_DIR}/' | |||
| process.use = [uselib.name] | |||
| @@ -113,8 +113,10 @@ def build(bld): | |||
| 'timestamps.c', | |||
| '../posix/JackPosixProcessSync.cpp', | |||
| '../posix/JackPosixThread.cpp', | |||
| '../macosx/JackMachThread.cpp', | |||
| '../macosx/JackMachSemaphore.cpp', | |||
| '../posix/JackPosixMutex.cpp', | |||
| '../macosx/JackMachThread.mm', | |||
| #'../macosx/JackMachSemaphore.mm', | |||
| '../posix/JackPosixSemaphore.cpp', | |||
| '../posix/JackSocket.cpp', | |||
| '../macosx/JackMachTime.c', | |||
| ] | |||
| @@ -135,6 +137,8 @@ def build(bld): | |||
| uselib.append('WINMM') | |||
| clientlib = bld(features = ['c', 'cxx', 'cxxshlib', 'cshlib']) | |||
| if bld.env['IS_MACOSX']: | |||
| clientlib.framework = ['CoreAudio', 'Accelerate'] | |||
| clientlib.defines = 'HAVE_CONFIG_H' | |||
| clientlib.use = uselib | |||
| if bld.env['IS_WINDOWS']: | |||
| @@ -185,10 +189,7 @@ def build(bld): | |||
| if bld.env['IS_MACOSX']: | |||
| clientlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") | |||
| clientlib.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64") | |||
| #clientlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module -arch i386 -arch ppc -arch x86_64" | |||
| clientlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module") | |||
| clientlib.env.append_value("LINKFLAGS", "-compatibility_version 1 -current_version 1") | |||
| clientlib.env.append_value("LINKFLAGS", "-single_module") | |||
| if bld.env['IS_SUN']: | |||
| clientlib.env.append_value("LINKFLAGS", "-lnsl -lsocket") | |||
| @@ -199,6 +200,8 @@ def build(bld): | |||
| return | |||
| serverlib = bld(features = ['c', 'cxx', 'cxxshlib', 'cshlib']) | |||
| if bld.env['IS_MACOSX']: | |||
| serverlib.framework = ['CoreAudio', 'CoreFoundation', 'Accelerate'] | |||
| serverlib.defines = ['HAVE_CONFIG_H','SERVER_SIDE'] | |||
| serverlib.includes = includes | |||
| serverlib.name = 'serverlib' | |||
| @@ -285,16 +288,15 @@ def build(bld): | |||
| if bld.env['IS_MACOSX']: | |||
| serverlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") | |||
| serverlib.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64") | |||
| #serverlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module -arch i386 -arch ppc -arch x86_64") | |||
| serverlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework CoreFoundation -framework vecLib -single_module") | |||
| serverlib.env.append_value("LINKFLAGS", "-compatibility_version 1 -current_version 1") | |||
| serverlib.env.append_value("LINKFLAGS", "-single_module") | |||
| if bld.env['IS_SUN']: | |||
| serverlib.env.append_value("LINKFLAGS", "-lnsl -lsocket") | |||
| if bld.env['BUILD_NETLIB']: | |||
| netlib = bld(features = ['c', 'cxx', 'cxxshlib', 'cshlib']) | |||
| if bld.env['IS_MACOSX']: | |||
| netlib.framework = ['CoreAudio'] | |||
| netlib.defines = ['HAVE_CONFIG_H','SERVER_SIDE'] | |||
| netlib.includes = includes | |||
| netlib.name = 'netlib' | |||
| @@ -303,6 +305,8 @@ def build(bld): | |||
| if bld.env['IS_WINDOWS']: | |||
| netlib.install_path = '${BINDIR}' | |||
| netlib.use += ['WS2_32', 'WINMM'] | |||
| elif bld.env['IS_MACOSX']: | |||
| netlib.install_path = '${LIBDIR}' | |||
| else: | |||
| netlib.use += ['RT'] | |||
| netlib.install_path = '${LIBDIR}' | |||
| @@ -327,8 +331,8 @@ def build(bld): | |||
| if bld.env['IS_MACOSX']: | |||
| netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp', '../posix/JackPosixMutex.cpp', '../macosx/JackMachThread.cpp', '../macosx/JackMachTime.c'] | |||
| netlib.env.append_value("LINKFLAGS", "-framework CoreAudio -single_module") | |||
| netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp', '../posix/JackPosixMutex.cpp', '../macosx/JackMachThread.mm', '../macosx/JackMachTime.c'] | |||
| netlib.env.append_value("LINKFLAGS", "-single_module") | |||
| if bld.env['IS_WINDOWS']: | |||
| netlib.source += ['../windows/JackNetWinSocket.cpp','../windows/JackWinThread.cpp', '../windows/JackMMCSS.cpp', '../windows/JackWinTime.c'] | |||
| @@ -360,10 +364,19 @@ def build(bld): | |||
| ] | |||
| if bld.env['BUILD_ADAPTER'] and bld.env['IS_MACOSX']: | |||
| audio_adapter_sources += ['../macosx/coreaudio/JackCoreAudioAdapter.cpp'] | |||
| process = create_jack_process_obj(bld, 'audioadapter', audio_adapter_sources, serverlib) | |||
| process.env.append_value("LINKFLAGS", "-framework CoreAudio -framework AudioUnit -framework AudioToolbox -framework CoreServices") | |||
| process.use = 'SAMPLERATE' | |||
| audio_adapter_sources += ['../macosx/coreaudio/JackCoreAudioAdapter.mm'] | |||
| process = create_jack_process_obj(bld, | |||
| 'audioadapter', | |||
| audio_adapter_sources, | |||
| serverlib, | |||
| framework = [ | |||
| "CoreAudio", | |||
| "AudioUnit", | |||
| "AudioToolbox", | |||
| "CoreServices" | |||
| ] | |||
| ) | |||
| process.use += ['SAMPLERATE'] | |||
| if bld.env['BUILD_ADAPTER'] and bld.env['IS_LINUX'] and bld.env['BUILD_DRIVER_ALSA']: | |||
| audio_adapter_sources += ['../linux/alsa/JackAlsaAdapter.cpp'] | |||
| @@ -66,14 +66,13 @@ def build(bld): | |||
| else: | |||
| use = ['clientlib'] | |||
| prog = bld(features='c cprogram') | |||
| if bld.env['IS_MACOSX']: | |||
| prog = bld(features='c cprogram', framework = ["Foundation"]) | |||
| else: | |||
| prog = bld(features='c cprogram') | |||
| prog.includes = os_incdir + ['../common/jack', '../common'] | |||
| prog.source = example_program_source | |||
| prog.use = use | |||
| if bld.env['IS_MACOSX']: | |||
| prog.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64") | |||
| #prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64") | |||
| prog.env.append_value("LINKFLAGS", "") | |||
| if bld.env['IS_LINUX']: | |||
| prog.use += ['RT', 'M'] | |||
| if bld.env['IS_SUN']: | |||
| @@ -86,10 +85,6 @@ def build(bld): | |||
| prog.includes = os_incdir + ['../common/jack', '../common'] | |||
| prog.source = 'transport.c' | |||
| prog.use = ['clientlib'] | |||
| if bld.env['IS_MACOSX']: | |||
| prog.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64") | |||
| #prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64") | |||
| prog.env.append_value("LINKFLAGS", "") | |||
| if bld.env['IS_LINUX']: | |||
| prog.use += ['RT', 'READLINE'] | |||
| if bld.env['IS_MACOSX']: | |||
| @@ -104,9 +99,6 @@ def build(bld): | |||
| prog.source = 'capture_client.c' | |||
| prog.use = ['clientlib'] | |||
| if bld.env['IS_MACOSX']: | |||
| prog.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64") | |||
| #prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64") | |||
| prog.env.append_value("LINKFLAGS", "") | |||
| prog.use += ['SNDFILE'] | |||
| if bld.env['IS_LINUX']: | |||
| prog.use += ['RT', 'SNDFILE'] | |||
| @@ -147,10 +139,6 @@ def build(bld): | |||
| lib.includes = os_incdir + ['../common/jack', '../common'] | |||
| lib.target = example_lib | |||
| lib.source = example_lib_source | |||
| if bld.env['IS_MACOSX']: | |||
| lib.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64") | |||
| #lib.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64") | |||
| lib.env.append_value("LINKFLAGS", "") | |||
| if bld.env['IS_SUN']: | |||
| lib.env.append_value("LINKFLAGS", "-lm") | |||
| lib.use = 'serverlib' | |||
| @@ -70,7 +70,7 @@ typedef unsigned char Boolean; | |||
| #include "JackPosixThread.h" | |||
| #ifndef MY_TARGET_OS_IPHONE | |||
| #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h> | |||
| #include <MacTypes.h> | |||
| #endif | |||
| #include <mach/thread_policy.h> | |||
| @@ -22,8 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include <string> | |||
| #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h> | |||
| #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/Debugging.h> | |||
| #include <MacTypes.h> | |||
| namespace Jack { | |||
| @@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #include <sstream> | |||
| #include <Foundation/Foundation.h> | |||
| #include "JackError.h" | |||
| #include "JackCoreMidiUtil.h" | |||
| @@ -25,13 +26,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| std::string | |||
| Jack::GetMacOSErrorString(OSStatus status) | |||
| { | |||
| const char *message = GetMacOSStatusErrorString(status); | |||
| if (! message) { | |||
| std::stringstream stream; | |||
| stream << "error (code: '" << status << "')"; | |||
| return stream.str(); | |||
| NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; | |||
| NSString *errorString = [error localizedDescription]; | |||
| std::string returnString; | |||
| if (errorString){ | |||
| returnString = std::string([errorString UTF8String]); | |||
| } else { | |||
| returnString = std::string("No error"); | |||
| } | |||
| return std::string(message); | |||
| return returnString; | |||
| } | |||
| void | |||
| @@ -25,8 +25,5 @@ def build(bld): | |||
| prog.source = test_program_sources | |||
| if bld.env['IS_LINUX']: | |||
| prog.uselib = 'RT' | |||
| if bld.env['IS_MACOSX']: | |||
| prog.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64") | |||
| #prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64") | |||
| prog.use = 'clientlib' | |||
| prog.target = test_program | |||
| @@ -0,0 +1,312 @@ | |||
| #! /usr/bin/env python | |||
| # encoding: utf-8 | |||
| # XCode 3/XCode 4 generator for Waf | |||
| # Nicolas Mercier 2011 | |||
| """ | |||
| Usage: | |||
| def options(opt): | |||
| opt.load('xcode') | |||
| $ waf configure xcode | |||
| """ | |||
| # TODO: support iOS projects | |||
| from waflib import Context, TaskGen, Build, Utils | |||
| import os, sys | |||
| HEADERS_GLOB = '**/(*.h|*.hpp|*.H|*.inl)' | |||
| MAP_EXT = { | |||
| '.h' : "sourcecode.c.h", | |||
| '.hh': "sourcecode.cpp.h", | |||
| '.inl': "sourcecode.cpp.h", | |||
| '.hpp': "sourcecode.cpp.h", | |||
| '.c': "sourcecode.c.c", | |||
| '.m': "sourcecode.c.objc", | |||
| '.mm': "sourcecode.cpp.objcpp", | |||
| '.cc': "sourcecode.cpp.cpp", | |||
| '.cpp': "sourcecode.cpp.cpp", | |||
| '.C': "sourcecode.cpp.cpp", | |||
| '.cxx': "sourcecode.cpp.cpp", | |||
| '.c++': "sourcecode.cpp.cpp", | |||
| '.l': "sourcecode.lex", # luthor | |||
| '.ll': "sourcecode.lex", | |||
| '.y': "sourcecode.yacc", | |||
| '.yy': "sourcecode.yacc", | |||
| '.plist': "text.plist.xml", | |||
| ".nib": "wrapper.nib", | |||
| ".xib": "text.xib", | |||
| } | |||
| part1 = 0 | |||
| part2 = 10000 | |||
| part3 = 0 | |||
| id = 562000999 | |||
| def newid(): | |||
| global id | |||
| id = id + 1 | |||
| return "%04X%04X%04X%012d" % (0, 10000, 0, id) | |||
| class XCodeNode: | |||
| def __init__(self): | |||
| self._id = newid() | |||
| def tostring(self, value): | |||
| if isinstance(value, dict): | |||
| result = "{\n" | |||
| for k,v in value.items(): | |||
| result = result + "\t\t\t%s = %s;\n" % (k, self.tostring(v)) | |||
| result = result + "\t\t}" | |||
| return result | |||
| elif isinstance(value, str): | |||
| return "\"%s\"" % value | |||
| elif isinstance(value, list): | |||
| result = "(\n" | |||
| for i in value: | |||
| result = result + "\t\t\t%s,\n" % self.tostring(i) | |||
| result = result + "\t\t)" | |||
| return result | |||
| elif isinstance(value, XCodeNode): | |||
| return value._id | |||
| else: | |||
| return str(value) | |||
| def write_recursive(self, value, file): | |||
| if isinstance(value, dict): | |||
| for k,v in value.items(): | |||
| self.write_recursive(v, file) | |||
| elif isinstance(value, list): | |||
| for i in value: | |||
| self.write_recursive(i, file) | |||
| elif isinstance(value, XCodeNode): | |||
| value.write(file) | |||
| def write(self, file): | |||
| for attribute,value in self.__dict__.items(): | |||
| if attribute[0] != '_': | |||
| self.write_recursive(value, file) | |||
| w = file.write | |||
| w("\t%s = {\n" % self._id) | |||
| w("\t\tisa = %s;\n" % self.__class__.__name__) | |||
| for attribute,value in self.__dict__.items(): | |||
| if attribute[0] != '_': | |||
| w("\t\t%s = %s;\n" % (attribute, self.tostring(value))) | |||
| w("\t};\n\n") | |||
| # Configurations | |||
| class XCBuildConfiguration(XCodeNode): | |||
| def __init__(self, name, settings = {}, env=None): | |||
| XCodeNode.__init__(self) | |||
| self.baseConfigurationReference = "" | |||
| self.buildSettings = settings | |||
| self.name = name | |||
| if env and env.ARCH: | |||
| settings['ARCHS'] = " ".join(env.ARCH) | |||
| class XCConfigurationList(XCodeNode): | |||
| def __init__(self, settings): | |||
| XCodeNode.__init__(self) | |||
| self.buildConfigurations = settings | |||
| self.defaultConfigurationIsVisible = 0 | |||
| self.defaultConfigurationName = settings and settings[0].name or "" | |||
| # Group/Files | |||
| class PBXFileReference(XCodeNode): | |||
| def __init__(self, name, path, filetype = '', sourcetree = "SOURCE_ROOT"): | |||
| XCodeNode.__init__(self) | |||
| self.fileEncoding = 4 | |||
| if not filetype: | |||
| _, ext = os.path.splitext(name) | |||
| filetype = MAP_EXT.get(ext, 'text') | |||
| self.lastKnownFileType = filetype | |||
| self.name = name | |||
| self.path = path | |||
| self.sourceTree = sourcetree | |||
| class PBXGroup(XCodeNode): | |||
| def __init__(self, name, sourcetree = "<group>"): | |||
| XCodeNode.__init__(self) | |||
| self.children = [] | |||
| self.name = name | |||
| self.sourceTree = sourcetree | |||
| def add(self, root, sources): | |||
| folders = {} | |||
| def folder(n): | |||
| if not n.is_child_of(root): | |||
| return self | |||
| try: | |||
| return folders[n] | |||
| except KeyError: | |||
| f = PBXGroup(n.name) | |||
| p = folder(n.parent) | |||
| folders[n] = f | |||
| p.children.append(f) | |||
| return f | |||
| for s in sources: | |||
| f = folder(s.parent) | |||
| source = PBXFileReference(s.name, s.abspath()) | |||
| f.children.append(source) | |||
| # Targets | |||
| class PBXLegacyTarget(XCodeNode): | |||
| def __init__(self, action, target=''): | |||
| XCodeNode.__init__(self) | |||
| self.buildConfigurationList = XCConfigurationList([XCBuildConfiguration('waf', {})]) | |||
| if not target: | |||
| self.buildArgumentsString = "%s %s" % (sys.argv[0], action) | |||
| else: | |||
| self.buildArgumentsString = "%s %s --targets=%s" % (sys.argv[0], action, target) | |||
| self.buildPhases = [] | |||
| self.buildToolPath = sys.executable | |||
| self.buildWorkingDirectory = "" | |||
| self.dependencies = [] | |||
| self.name = target or action | |||
| self.productName = target or action | |||
| self.passBuildSettingsInEnvironment = 0 | |||
| class PBXShellScriptBuildPhase(XCodeNode): | |||
| def __init__(self, action, target): | |||
| XCodeNode.__init__(self) | |||
| self.buildActionMask = 2147483647 | |||
| self.files = [] | |||
| self.inputPaths = [] | |||
| self.outputPaths = [] | |||
| self.runOnlyForDeploymentPostProcessing = 0 | |||
| self.shellPath = "/bin/sh" | |||
| self.shellScript = "%s %s %s --targets=%s" % (sys.executable, sys.argv[0], action, target) | |||
| class PBXNativeTarget(XCodeNode): | |||
| def __init__(self, action, target, node, env): | |||
| XCodeNode.__init__(self) | |||
| conf = XCBuildConfiguration('waf', {'PRODUCT_NAME':target, 'CONFIGURATION_BUILD_DIR':node.parent.abspath()}, env) | |||
| self.buildConfigurationList = XCConfigurationList([conf]) | |||
| self.buildPhases = [PBXShellScriptBuildPhase(action, target)] | |||
| self.buildRules = [] | |||
| self.dependencies = [] | |||
| self.name = target | |||
| self.productName = target | |||
| self.productType = "com.apple.product-type.application" | |||
| self.productReference = PBXFileReference(target, node.abspath(), 'wrapper.application', 'BUILT_PRODUCTS_DIR') | |||
| # Root project object | |||
| class PBXProject(XCodeNode): | |||
| def __init__(self, name, version): | |||
| XCodeNode.__init__(self) | |||
| self.buildConfigurationList = XCConfigurationList([XCBuildConfiguration('waf', {})]) | |||
| self.compatibilityVersion = version[0] | |||
| self.hasScannedForEncodings = 1; | |||
| self.mainGroup = PBXGroup(name) | |||
| self.projectRoot = "" | |||
| self.projectDirPath = "" | |||
| self.targets = [] | |||
| self._objectVersion = version[1] | |||
| self._output = PBXGroup('out') | |||
| self.mainGroup.children.append(self._output) | |||
| def write(self, file): | |||
| w = file.write | |||
| w("// !$*UTF8*$!\n") | |||
| w("{\n") | |||
| w("\tarchiveVersion = 1;\n") | |||
| w("\tclasses = {\n") | |||
| w("\t};\n") | |||
| w("\tobjectVersion = %d;\n" % self._objectVersion) | |||
| w("\tobjects = {\n\n") | |||
| XCodeNode.write(self, file) | |||
| w("\t};\n") | |||
| w("\trootObject = %s;\n" % self._id) | |||
| w("}\n") | |||
| def add_task_gen(self, tg): | |||
| if not getattr(tg, 'mac_app', False): | |||
| self.targets.append(PBXLegacyTarget('build', tg.name)) | |||
| else: | |||
| target = PBXNativeTarget('build', tg.name, tg.link_task.outputs[0].change_ext('.app'), tg.env) | |||
| self.targets.append(target) | |||
| self._output.children.append(target.productReference) | |||
| class xcode(Build.BuildContext): | |||
| cmd = 'xcode' | |||
| fun = 'build' | |||
| def collect_source(self, tg): | |||
| source_files = tg.to_nodes(getattr(tg, 'source', [])) | |||
| plist_files = tg.to_nodes(getattr(tg, 'mac_plist', [])) | |||
| resource_files = [tg.path.find_node(i) for i in Utils.to_list(getattr(tg, 'mac_resources', []))] | |||
| include_dirs = Utils.to_list(getattr(tg, 'includes', [])) + Utils.to_list(getattr(tg, 'export_dirs', [])) | |||
| include_files = [] | |||
| for x in include_dirs: | |||
| if not isinstance(x, str): | |||
| include_files.append(x) | |||
| continue | |||
| d = tg.path.find_node(x) | |||
| if d: | |||
| lst = [y for y in d.ant_glob(HEADERS_GLOB, flat=False)] | |||
| include_files.extend(lst) | |||
| # remove duplicates | |||
| source = list(set(source_files + plist_files + resource_files + include_files)) | |||
| source.sort(key=lambda x: x.abspath()) | |||
| return source | |||
| def execute(self): | |||
| """ | |||
| Entry point | |||
| """ | |||
| self.restore() | |||
| if not self.all_envs: | |||
| self.load_envs() | |||
| self.recurse([self.run_dir]) | |||
| appname = getattr(Context.g_module, Context.APPNAME, os.path.basename(self.srcnode.abspath())) | |||
| p = PBXProject(appname, ('Xcode 3.2', 46)) | |||
| for g in self.groups: | |||
| for tg in g: | |||
| if not isinstance(tg, TaskGen.task_gen): | |||
| continue | |||
| tg.post() | |||
| features = Utils.to_list(getattr(tg, 'features', '')) | |||
| group = PBXGroup(tg.name) | |||
| group.add(tg.path, self.collect_source(tg)) | |||
| p.mainGroup.children.append(group) | |||
| if 'cprogram' or 'cxxprogram' in features: | |||
| p.add_task_gen(tg) | |||
| # targets that don't produce the executable but that you might want to run | |||
| p.targets.append(PBXLegacyTarget('configure')) | |||
| p.targets.append(PBXLegacyTarget('dist')) | |||
| p.targets.append(PBXLegacyTarget('install')) | |||
| p.targets.append(PBXLegacyTarget('check')) | |||
| node = self.srcnode.make_node('%s.xcodeproj' % appname) | |||
| node.mkdir() | |||
| node = node.make_node('project.pbxproj') | |||
| p.write(open(node.abspath(), 'w')) | |||
| @@ -0,0 +1,656 @@ | |||
| #! /usr/bin/env python | |||
| # encoding: utf-8 | |||
| # XCode 3/XCode 4 generator for Waf | |||
| # Based on work by Nicolas Mercier 2011 | |||
| # Extended by Simon Warg 2015, https://github.com/mimon | |||
| # XCode project file format based on http://www.monobjc.net/xcode-project-file-format.html | |||
| """ | |||
| Usage: | |||
| See also demos/xcode6/ folder | |||
| def options(opt): | |||
| opt.load('xcode6') | |||
| def configure(cnf): | |||
| # <do your stuff> | |||
| # For example | |||
| cnf.env.SDKROOT = 'macosx10.9' | |||
| # Use cnf.PROJ_CONFIGURATION to completely set/override | |||
| # global project settings | |||
| # cnf.env.PROJ_CONFIGURATION = { | |||
| # 'Debug': { | |||
| # 'SDKROOT': 'macosx10.9' | |||
| # } | |||
| # 'MyCustomReleaseConfig': { | |||
| # 'SDKROOT': 'macosx10.10' | |||
| # } | |||
| # } | |||
| # In the end of configure() do | |||
| cnf.load('xcode6') | |||
| def build(bld): | |||
| # Make a Framework target | |||
| bld.framework( | |||
| source_files={ | |||
| 'Include': bld.path.ant_glob('include/MyLib/*.h'), | |||
| 'Source': bld.path.ant_glob('src/MyLib/*.cpp') | |||
| }, | |||
| includes='include', | |||
| export_headers=bld.path.ant_glob('include/MyLib/*.h'), | |||
| target='MyLib', | |||
| ) | |||
| # You can also make bld.dylib, bld.app, bld.stlib ... | |||
| $ waf configure xcode6 | |||
| """ | |||
| # TODO: support iOS projects | |||
| from waflib import Context, TaskGen, Build, Utils, ConfigSet, Configure, Errors | |||
| from waflib.Build import BuildContext | |||
| import os, sys, random, time | |||
| HEADERS_GLOB = '**/(*.h|*.hpp|*.H|*.inl)' | |||
| MAP_EXT = { | |||
| '': "folder", | |||
| '.h' : "sourcecode.c.h", | |||
| '.hh': "sourcecode.cpp.h", | |||
| '.inl': "sourcecode.cpp.h", | |||
| '.hpp': "sourcecode.cpp.h", | |||
| '.c': "sourcecode.c.c", | |||
| '.m': "sourcecode.c.objc", | |||
| '.mm': "sourcecode.cpp.objcpp", | |||
| '.cc': "sourcecode.cpp.cpp", | |||
| '.cpp': "sourcecode.cpp.cpp", | |||
| '.C': "sourcecode.cpp.cpp", | |||
| '.cxx': "sourcecode.cpp.cpp", | |||
| '.c++': "sourcecode.cpp.cpp", | |||
| '.l': "sourcecode.lex", # luthor | |||
| '.ll': "sourcecode.lex", | |||
| '.y': "sourcecode.yacc", | |||
| '.yy': "sourcecode.yacc", | |||
| '.plist': "text.plist.xml", | |||
| ".nib": "wrapper.nib", | |||
| ".xib": "text.xib", | |||
| } | |||
| # Used in PBXNativeTarget elements | |||
| PRODUCT_TYPE_APPLICATION = 'com.apple.product-type.application' | |||
| PRODUCT_TYPE_FRAMEWORK = 'com.apple.product-type.framework' | |||
| PRODUCT_TYPE_EXECUTABLE = 'com.apple.product-type.tool' | |||
| PRODUCT_TYPE_LIB_STATIC = 'com.apple.product-type.library.static' | |||
| PRODUCT_TYPE_LIB_DYNAMIC = 'com.apple.product-type.library.dynamic' | |||
| PRODUCT_TYPE_EXTENSION = 'com.apple.product-type.kernel-extension' | |||
| PRODUCT_TYPE_IOKIT = 'com.apple.product-type.kernel-extension.iokit' | |||
| # Used in PBXFileReference elements | |||
| FILE_TYPE_APPLICATION = 'wrapper.cfbundle' | |||
| FILE_TYPE_FRAMEWORK = 'wrapper.framework' | |||
| FILE_TYPE_LIB_DYNAMIC = 'compiled.mach-o.dylib' | |||
| FILE_TYPE_LIB_STATIC = 'archive.ar' | |||
| FILE_TYPE_EXECUTABLE = 'compiled.mach-o.executable' | |||
| # Tuple packs of the above | |||
| TARGET_TYPE_FRAMEWORK = (PRODUCT_TYPE_FRAMEWORK, FILE_TYPE_FRAMEWORK, '.framework') | |||
| TARGET_TYPE_APPLICATION = (PRODUCT_TYPE_APPLICATION, FILE_TYPE_APPLICATION, '.app') | |||
| TARGET_TYPE_DYNAMIC_LIB = (PRODUCT_TYPE_LIB_DYNAMIC, FILE_TYPE_LIB_DYNAMIC, '.dylib') | |||
| TARGET_TYPE_STATIC_LIB = (PRODUCT_TYPE_LIB_STATIC, FILE_TYPE_LIB_STATIC, '.a') | |||
| TARGET_TYPE_EXECUTABLE = (PRODUCT_TYPE_EXECUTABLE, FILE_TYPE_EXECUTABLE, '') | |||
| # Maps target type string to its data | |||
| TARGET_TYPES = { | |||
| 'framework': TARGET_TYPE_FRAMEWORK, | |||
| 'app': TARGET_TYPE_APPLICATION, | |||
| 'dylib': TARGET_TYPE_DYNAMIC_LIB, | |||
| 'stlib': TARGET_TYPE_STATIC_LIB, | |||
| 'exe' :TARGET_TYPE_EXECUTABLE, | |||
| } | |||
| """ | |||
| Configuration of the global project settings. Sets an environment variable 'PROJ_CONFIGURATION' | |||
| which is a dictionary of configuration name and buildsettings pair. | |||
| E.g.: | |||
| env.PROJ_CONFIGURATION = { | |||
| 'Debug': { | |||
| 'ARCHS': 'x86', | |||
| ... | |||
| } | |||
| 'Release': { | |||
| 'ARCHS' x86_64' | |||
| ... | |||
| } | |||
| } | |||
| The user can define a completely customized dictionary in configure() stage. Otherwise a default Debug/Release will be created | |||
| based on env variable | |||
| """ | |||
| def configure(self): | |||
| if not self.env.PROJ_CONFIGURATION: | |||
| self.to_log("A default project configuration was created since no custom one was given in the configure(conf) stage. Define your custom project settings by adding PROJ_CONFIGURATION to env. The env.PROJ_CONFIGURATION must be a dictionary with at least one key, where each key is the configuration name, and the value is a dictionary of key/value settings.\n") | |||
| # Check for any added config files added by the tool 'c_config'. | |||
| if 'cfg_files' in self.env: | |||
| self.env.INCLUDES = Utils.to_list(self.env.INCLUDES) + [os.path.abspath(os.path.dirname(f)) for f in self.env.cfg_files] | |||
| # Create default project configuration? | |||
| if 'PROJ_CONFIGURATION' not in self.env: | |||
| self.env.PROJ_CONFIGURATION = { | |||
| "Debug": self.env.get_merged_dict(), | |||
| "Release": self.env.get_merged_dict(), | |||
| } | |||
| # Some build settings are required to be present by XCode. We will supply default values | |||
| # if user hasn't defined any. | |||
| defaults_required = [('PRODUCT_NAME', '$(TARGET_NAME)')] | |||
| for cfgname,settings in self.env.PROJ_CONFIGURATION.iteritems(): | |||
| for default_var, default_val in defaults_required: | |||
| if default_var not in settings: | |||
| settings[default_var] = default_val | |||
| # Error check customization | |||
| if not isinstance(self.env.PROJ_CONFIGURATION, dict): | |||
| raise Errors.ConfigurationError("The env.PROJ_CONFIGURATION must be a dictionary with at least one key, where each key is the configuration name, and the value is a dictionary of key/value settings.") | |||
| part1 = 0 | |||
| part2 = 10000 | |||
| part3 = 0 | |||
| id = 562000999 | |||
| def newid(): | |||
| global id | |||
| id = id + 1 | |||
| return "%04X%04X%04X%012d" % (0, 10000, 0, id) | |||
| class XCodeNode: | |||
| def __init__(self): | |||
| self._id = newid() | |||
| self._been_written = False | |||
| def tostring(self, value): | |||
| if isinstance(value, dict): | |||
| result = "{\n" | |||
| for k,v in value.items(): | |||
| result = result + "\t\t\t%s = %s;\n" % (k, self.tostring(v)) | |||
| result = result + "\t\t}" | |||
| return result | |||
| elif isinstance(value, str): | |||
| return "\"%s\"" % value | |||
| elif isinstance(value, list): | |||
| result = "(\n" | |||
| for i in value: | |||
| result = result + "\t\t\t%s,\n" % self.tostring(i) | |||
| result = result + "\t\t)" | |||
| return result | |||
| elif isinstance(value, XCodeNode): | |||
| return value._id | |||
| else: | |||
| return str(value) | |||
| def write_recursive(self, value, file): | |||
| if isinstance(value, dict): | |||
| for k,v in value.items(): | |||
| self.write_recursive(v, file) | |||
| elif isinstance(value, list): | |||
| for i in value: | |||
| self.write_recursive(i, file) | |||
| elif isinstance(value, XCodeNode): | |||
| value.write(file) | |||
| def write(self, file): | |||
| if not self._been_written: | |||
| self._been_written = True | |||
| for attribute,value in self.__dict__.items(): | |||
| if attribute[0] != '_': | |||
| self.write_recursive(value, file) | |||
| w = file.write | |||
| w("\t%s = {\n" % self._id) | |||
| w("\t\tisa = %s;\n" % self.__class__.__name__) | |||
| for attribute,value in self.__dict__.items(): | |||
| if attribute[0] != '_': | |||
| w("\t\t%s = %s;\n" % (attribute, self.tostring(value))) | |||
| w("\t};\n\n") | |||
| # Configurations | |||
| class XCBuildConfiguration(XCodeNode): | |||
| def __init__(self, name, settings = {}, env=None): | |||
| XCodeNode.__init__(self) | |||
| self.baseConfigurationReference = "" | |||
| self.buildSettings = settings | |||
| self.name = name | |||
| if env and env.ARCH: | |||
| settings['ARCHS'] = " ".join(env.ARCH) | |||
| class XCConfigurationList(XCodeNode): | |||
| def __init__(self, configlst): | |||
| """ :param configlst: list of XCConfigurationList """ | |||
| XCodeNode.__init__(self) | |||
| self.buildConfigurations = configlst | |||
| self.defaultConfigurationIsVisible = 0 | |||
| self.defaultConfigurationName = configlst and configlst[0].name or "" | |||
| # Group/Files | |||
| class PBXFileReference(XCodeNode): | |||
| def __init__(self, name, path, filetype = '', sourcetree = "SOURCE_ROOT"): | |||
| XCodeNode.__init__(self) | |||
| self.fileEncoding = 4 | |||
| if not filetype: | |||
| _, ext = os.path.splitext(name) | |||
| filetype = MAP_EXT.get(ext, 'text') | |||
| self.lastKnownFileType = filetype | |||
| self.name = name | |||
| self.path = path | |||
| self.sourceTree = sourcetree | |||
| def __hash__(self): | |||
| return (self.path+self.name).__hash__() | |||
| def __eq__(self, other): | |||
| return (self.path, self.name) == (other.path, other.name) | |||
| class PBXBuildFile(XCodeNode): | |||
| """ This element indicate a file reference that is used in a PBXBuildPhase (either as an include or resource). """ | |||
| def __init__(self, fileRef, settings={}): | |||
| XCodeNode.__init__(self) | |||
| # fileRef is a reference to a PBXFileReference object | |||
| self.fileRef = fileRef | |||
| # A map of key/value pairs for additionnal settings. | |||
| self.settings = settings | |||
| def __hash__(self): | |||
| return (self.fileRef).__hash__() | |||
| def __eq__(self, other): | |||
| return self.fileRef == other.fileRef | |||
| class PBXGroup(XCodeNode): | |||
| def __init__(self, name, sourcetree = "<group>"): | |||
| XCodeNode.__init__(self) | |||
| self.children = [] | |||
| self.name = name | |||
| self.sourceTree = sourcetree | |||
| def add(self, sources): | |||
| """ sources param should be a list of PBXFileReference objects """ | |||
| self.children.extend(sources) | |||
| class PBXContainerItemProxy(XCodeNode): | |||
| """ This is the element for to decorate a target item. """ | |||
| def __init__(self, containerPortal, remoteGlobalIDString, remoteInfo='', proxyType=1): | |||
| XCodeNode.__init__(self) | |||
| self.containerPortal = containerPortal # PBXProject | |||
| self.remoteGlobalIDString = remoteGlobalIDString # PBXNativeTarget | |||
| self.remoteInfo = remoteInfo # Target name | |||
| self.proxyType = proxyType | |||
| class PBXTargetDependency(XCodeNode): | |||
| """ This is the element for referencing other target through content proxies. """ | |||
| def __init__(self, native_target, proxy): | |||
| XCodeNode.__init__(self) | |||
| self.target = native_target | |||
| self.targetProxy = proxy | |||
| class PBXFrameworksBuildPhase(XCodeNode): | |||
| """ This is the element for the framework link build phase, i.e. linking to frameworks """ | |||
| def __init__(self, pbxbuildfiles): | |||
| XCodeNode.__init__(self) | |||
| self.buildActionMask = 2147483647 | |||
| self.runOnlyForDeploymentPostprocessing = 0 | |||
| self.files = pbxbuildfiles #List of PBXBuildFile (.o, .framework, .dylib) | |||
| class PBXHeadersBuildPhase(XCodeNode): | |||
| """ This is the element for adding header files to be packaged into the .framework """ | |||
| def __init__(self, pbxbuildfiles): | |||
| XCodeNode.__init__(self) | |||
| self.buildActionMask = 2147483647 | |||
| self.runOnlyForDeploymentPostprocessing = 0 | |||
| self.files = pbxbuildfiles #List of PBXBuildFile (.o, .framework, .dylib) | |||
| class PBXCopyFilesBuildPhase(XCodeNode): | |||
| """ | |||
| Represents the PBXCopyFilesBuildPhase section. PBXBuildFile | |||
| can be added to this node to copy files after build is done. | |||
| """ | |||
| def __init__(self, pbxbuildfiles, dstpath, dstSubpathSpec=0, *args, **kwargs): | |||
| XCodeNode.__init__(self) | |||
| self.files = pbxbuildfiles | |||
| self.dstPath = dstpath | |||
| self.dstSubfolderSpec = dstSubpathSpec | |||
| class PBXSourcesBuildPhase(XCodeNode): | |||
| """ Represents the 'Compile Sources' build phase in a Xcode target """ | |||
| def __init__(self, buildfiles): | |||
| XCodeNode.__init__(self) | |||
| self.files = buildfiles # List of PBXBuildFile objects | |||
| class PBXLegacyTarget(XCodeNode): | |||
| def __init__(self, action, target=''): | |||
| XCodeNode.__init__(self) | |||
| self.buildConfigurationList = XCConfigurationList([XCBuildConfiguration('waf', {})]) | |||
| if not target: | |||
| self.buildArgumentsString = "%s %s" % (sys.argv[0], action) | |||
| else: | |||
| self.buildArgumentsString = "%s %s --targets=%s" % (sys.argv[0], action, target) | |||
| self.buildPhases = [] | |||
| self.buildToolPath = sys.executable | |||
| self.buildWorkingDirectory = "" | |||
| self.dependencies = [] | |||
| self.name = target or action | |||
| self.productName = target or action | |||
| self.passBuildSettingsInEnvironment = 0 | |||
| class PBXShellScriptBuildPhase(XCodeNode): | |||
| def __init__(self, action, target): | |||
| XCodeNode.__init__(self) | |||
| self.buildActionMask = 2147483647 | |||
| self.files = [] | |||
| self.inputPaths = [] | |||
| self.outputPaths = [] | |||
| self.runOnlyForDeploymentPostProcessing = 0 | |||
| self.shellPath = "/bin/sh" | |||
| self.shellScript = "%s %s %s --targets=%s" % (sys.executable, sys.argv[0], action, target) | |||
| class PBXNativeTarget(XCodeNode): | |||
| """ Represents a target in XCode, e.g. App, DyLib, Framework etc. """ | |||
| def __init__(self, target, node, target_type=TARGET_TYPE_APPLICATION, configlist=[], buildphases=[]): | |||
| XCodeNode.__init__(self) | |||
| product_type = target_type[0] | |||
| file_type = target_type[1] | |||
| self.buildConfigurationList = XCConfigurationList(configlist) | |||
| self.buildPhases = buildphases | |||
| self.buildRules = [] | |||
| self.dependencies = [] | |||
| self.name = target | |||
| self.productName = target | |||
| self.productType = product_type # See TARGET_TYPE_ tuples constants | |||
| self.productReference = PBXFileReference(node.name, node.abspath(), file_type, '') | |||
| def add_configuration(self, cf): | |||
| """ :type cf: XCBuildConfiguration """ | |||
| self.buildConfigurationList.buildConfigurations.append(cf) | |||
| def add_build_phase(self, phase): | |||
| # Some build phase types may appear only once. If a phase type already exists, then merge them. | |||
| if ( (phase.__class__ == PBXFrameworksBuildPhase) | |||
| or (phase.__class__ == PBXSourcesBuildPhase) ): | |||
| for b in self.buildPhases: | |||
| if b.__class__ == phase.__class__: | |||
| b.files.extend(phase.files) | |||
| return | |||
| self.buildPhases.append(phase) | |||
| def add_dependency(self, depnd): | |||
| self.dependencies.append(depnd) | |||
| # Root project object | |||
| class PBXProject(XCodeNode): | |||
| def __init__(self, name, version, env): | |||
| XCodeNode.__init__(self) | |||
| if not isinstance(env.PROJ_CONFIGURATION, dict): | |||
| raise Errors.WafError("Error: env.PROJ_CONFIGURATION must be a dictionary. This is done for you if you do not define one yourself. However, did you load the xcode module at the end of your wscript configure() ?") | |||
| # Retreive project configuration | |||
| configurations = [] | |||
| for config_name, settings in env.PROJ_CONFIGURATION.items(): | |||
| cf = XCBuildConfiguration(config_name, settings) | |||
| configurations.append(cf) | |||
| self.buildConfigurationList = XCConfigurationList(configurations) | |||
| self.compatibilityVersion = version[0] | |||
| self.hasScannedForEncodings = 1; | |||
| self.mainGroup = PBXGroup(name) | |||
| self.projectRoot = "" | |||
| self.projectDirPath = "" | |||
| self.targets = [] | |||
| self._objectVersion = version[1] | |||
| def create_target_dependency(self, target, name): | |||
| """ : param target : PXBNativeTarget """ | |||
| proxy = PBXContainerItemProxy(self, target, name) | |||
| dependecy = PBXTargetDependency(target, proxy) | |||
| return dependecy | |||
| def write(self, file): | |||
| # Make sure this is written only once | |||
| if self._been_written: | |||
| return | |||
| w = file.write | |||
| w("// !$*UTF8*$!\n") | |||
| w("{\n") | |||
| w("\tarchiveVersion = 1;\n") | |||
| w("\tclasses = {\n") | |||
| w("\t};\n") | |||
| w("\tobjectVersion = %d;\n" % self._objectVersion) | |||
| w("\tobjects = {\n\n") | |||
| XCodeNode.write(self, file) | |||
| w("\t};\n") | |||
| w("\trootObject = %s;\n" % self._id) | |||
| w("}\n") | |||
| def add_target(self, target): | |||
| self.targets.append(target) | |||
| def get_target(self, name): | |||
| """ Get a reference to PBXNativeTarget if it exists """ | |||
| for t in self.targets: | |||
| if t.name == name: | |||
| return t | |||
| return None | |||
| class xcode(Build.BuildContext): | |||
| cmd = 'xcode6' | |||
| fun = 'build' | |||
| file_refs = dict() | |||
| build_files = dict() | |||
| def as_nodes(self, files): | |||
| """ Returns a list of waflib.Nodes from a list of string of file paths """ | |||
| nodes = [] | |||
| for x in files: | |||
| if not isinstance(x, str): | |||
| d = x | |||
| else: | |||
| d = self.srcnode.find_node(x) | |||
| nodes.append(d) | |||
| return nodes | |||
| def create_group(self, name, files): | |||
| """ | |||
| Returns a new PBXGroup containing the files (paths) passed in the files arg | |||
| :type files: string | |||
| """ | |||
| group = PBXGroup(name) | |||
| """ | |||
| Do not use unique file reference here, since XCode seem to allow only one file reference | |||
| to be referenced by a group. | |||
| """ | |||
| files = [(PBXFileReference(d.name, d.abspath())) for d in self.as_nodes(files)] | |||
| group.add(files) | |||
| return group | |||
| def unique_filereference(self, fileref): | |||
| """ | |||
| Returns a unique fileref, possibly an existing one if the paths are the same. | |||
| Use this after you've constructed a PBXFileReference to make sure there is | |||
| only one PBXFileReference for the same file in the same project. | |||
| """ | |||
| if fileref not in self.file_refs: | |||
| self.file_refs[fileref] = fileref | |||
| return self.file_refs[fileref] | |||
| def unique_buildfile(self, buildfile): | |||
| """ | |||
| Returns a unique buildfile, possibly an existing one. | |||
| Use this after you've constructed a PBXBuildFile to make sure there is | |||
| only one PBXBuildFile for the same file in the same project. | |||
| """ | |||
| if buildfile not in self.build_files: | |||
| self.build_files[buildfile] = buildfile | |||
| return self.build_files[buildfile] | |||
| def execute(self): | |||
| """ | |||
| Entry point | |||
| """ | |||
| self.restore() | |||
| if not self.all_envs: | |||
| self.load_envs() | |||
| self.recurse([self.run_dir]) | |||
| appname = getattr(Context.g_module, Context.APPNAME, os.path.basename(self.srcnode.abspath())) | |||
| p = PBXProject(appname, ('Xcode 3.2', 46), self.env) | |||
| # If we don't create a Products group, then | |||
| # XCode will create one, which entails that | |||
| # we'll start to see duplicate files in the UI | |||
| # for some reason. | |||
| products_group = PBXGroup('Products') | |||
| p.mainGroup.children.append(products_group) | |||
| for g in self.groups: | |||
| for tg in g: | |||
| if not isinstance(tg, TaskGen.task_gen): | |||
| continue | |||
| tg.post() | |||
| target_group = PBXGroup(tg.name) | |||
| p.mainGroup.children.append(target_group) | |||
| # Determine what type to build - framework, app bundle etc. | |||
| target_type = getattr(tg, 'target_type', 'app') | |||
| if target_type not in TARGET_TYPES: | |||
| raise Errors.WafError("Target type '%s' does not exists. Available options are '%s'. In target '%s'" % (target_type, "', '".join(TARGET_TYPES.keys()), tg.name)) | |||
| else: | |||
| target_type = TARGET_TYPES[target_type] | |||
| file_ext = target_type[2] | |||
| # Create the output node | |||
| target_node = tg.path.find_or_declare(tg.name+file_ext) | |||
| target = PBXNativeTarget(tg.name, target_node, target_type, [], []) | |||
| products_group.children.append(target.productReference) | |||
| if hasattr(tg, 'source_files'): | |||
| # Create list of PBXFileReferences | |||
| sources = [] | |||
| if isinstance(tg.source_files, dict): | |||
| for grpname,files in tg.source_files.items(): | |||
| group = self.create_group(grpname, files) | |||
| target_group.children.append(group) | |||
| sources.extend(group.children) | |||
| elif isinstance(tg.source_files, list): | |||
| group = self.create_group("Source", tg.source_files) | |||
| target_group.children.append(group) | |||
| sources.extend(group.children) | |||
| else: | |||
| self.to_log("Argument 'source_files' passed to target '%s' was not a dictionary. Hence, some source files may not be included. Please provide a dictionary of source files, with group name as key and list of source files as value.\n" % tg.name) | |||
| supported_extensions = ['.c', '.cpp', '.m', '.mm'] | |||
| sources = filter(lambda fileref: os.path.splitext(fileref.path)[1] in supported_extensions, sources) | |||
| buildfiles = [self.unique_buildfile(PBXBuildFile(fileref)) for fileref in sources] | |||
| target.add_build_phase(PBXSourcesBuildPhase(buildfiles)) | |||
| # Create build settings which can override the project settings. Defaults to none if user | |||
| # did not pass argument. However, this will be filled up further below with target specfic | |||
| # search paths, libs to link etc. | |||
| settings = getattr(tg, 'settings', {}) | |||
| # Check if any framework to link against is some other target we've made | |||
| libs = getattr(tg, 'tmp_use_seen', []) | |||
| for lib in libs: | |||
| use_target = p.get_target(lib) | |||
| if use_target: | |||
| # Create an XCode dependency so that XCode knows to build the other target before this target | |||
| target.add_dependency(p.create_target_dependency(use_target, use_target.name)) | |||
| target.add_build_phase(PBXFrameworksBuildPhase([PBXBuildFile(use_target.productReference)])) | |||
| if lib in tg.env.LIB: | |||
| tg.env.LIB = list(filter(lambda x: x != lib, tg.env.LIB)) | |||
| # If 'export_headers' is present, add files to the Headers build phase in xcode. | |||
| # These are files that'll get packed into the Framework for instance. | |||
| exp_hdrs = getattr(tg, 'export_headers', []) | |||
| hdrs = self.as_nodes(Utils.to_list(exp_hdrs)) | |||
| files = [self.unique_filereference(PBXFileReference(n.name, n.abspath())) for n in hdrs] | |||
| target.add_build_phase(PBXHeadersBuildPhase([PBXBuildFile(f, {'ATTRIBUTES': ('Public',)}) for f in files])) | |||
| # Install path | |||
| installpaths = Utils.to_list(getattr(tg, 'install', [])) | |||
| prodbuildfile = PBXBuildFile(target.productReference) | |||
| for instpath in installpaths: | |||
| target.add_build_phase(PBXCopyFilesBuildPhase([prodbuildfile], instpath)) | |||
| # Merge frameworks and libs into one list, and prefix the frameworks | |||
| ld_flags = ['-framework %s' % lib.split('.framework')[0] for lib in Utils.to_list(tg.env.FRAMEWORK)] | |||
| ld_flags.extend(Utils.to_list(tg.env.STLIB) + Utils.to_list(tg.env.LIB)) | |||
| # Override target specfic build settings | |||
| bldsettings = { | |||
| 'HEADER_SEARCH_PATHS': ['$(inherited)'] + tg.env['INCPATHS'], | |||
| 'LIBRARY_SEARCH_PATHS': ['$(inherited)'] + Utils.to_list(tg.env.LIBPATH) + Utils.to_list(tg.env.STLIBPATH), | |||
| 'FRAMEWORK_SEARCH_PATHS': ['$(inherited)'] + Utils.to_list(tg.env.FRAMEWORKPATH), | |||
| 'OTHER_LDFLAGS': r'\n'.join(ld_flags) | |||
| } | |||
| # The keys represents different build configuration, e.g. Debug, Release and so on.. | |||
| # Insert our generated build settings to all configuration names | |||
| keys = set(settings.keys() + self.env.PROJ_CONFIGURATION.keys()) | |||
| for k in keys: | |||
| if k in settings: | |||
| settings[k].update(bldsettings) | |||
| else: | |||
| settings[k] = bldsettings | |||
| for k,v in settings.items(): | |||
| target.add_configuration(XCBuildConfiguration(k, v)) | |||
| p.add_target(target) | |||
| node = self.bldnode.make_node('%s.xcodeproj' % appname) | |||
| node.mkdir() | |||
| node = node.make_node('project.pbxproj') | |||
| p.write(open(node.abspath(), 'w')) | |||
| def build_target(self, tgtype, *k, **kw): | |||
| """ | |||
| Provide user-friendly methods to build different target types | |||
| E.g. bld.framework(source='..', ...) to build a Framework target. | |||
| E.g. bld.dylib(source='..', ...) to build a Dynamic library target. etc... | |||
| """ | |||
| self.load('ccroot') | |||
| kw['features'] = 'cxx cxxprogram' | |||
| kw['target_type'] = tgtype | |||
| return self(*k, **kw) | |||
| def app(self, *k, **kw): return self.build_target('app', *k, **kw) | |||
| def framework(self, *k, **kw): return self.build_target('framework', *k, **kw) | |||
| def dylib(self, *k, **kw): return self.build_target('dylib', *k, **kw) | |||
| def stlib(self, *k, **kw): return self.build_target('stlib', *k, **kw) | |||
| def exe(self, *k, **kw): return self.build_target('exe', *k, **kw) | |||
| @@ -387,6 +387,9 @@ def options(opt): | |||
| opt.load('compiler_cxx') | |||
| opt.load('compiler_c') | |||
| opt.load('xcode') | |||
| opt.load('xcode6') | |||
| # install directories | |||
| opt.add_option('--htmldir', type='string', default=None, help="HTML documentation directory [Default: <prefix>/share/jack-audio-connection-kit/reference/html/") | |||
| opt.add_option('--libdir', type='string', help="Library directory [Default: <prefix>/lib]") | |||
| @@ -478,6 +481,9 @@ def configure(conf): | |||
| conf.env.append_unique('CXXFLAGS', '-Wall') | |||
| conf.env.append_unique('CFLAGS', '-Wall') | |||
| if conf.env['IS_MACOSX']: | |||
| conf.check(lib='aften', uselib='AFTEN', define_name='AFTEN') | |||
| # configure all auto options | |||
| configure_auto_options(conf) | |||
| @@ -722,7 +728,8 @@ def build_jackd(bld): | |||
| includes = ['.', 'common', 'common/jack'], | |||
| target = 'jackd', | |||
| source = ['common/Jackdmp.cpp'], | |||
| use = ['serverlib']) | |||
| use = ['serverlib'] | |||
| ) | |||
| if bld.env['BUILD_JACKDBUS']: | |||
| jackd.source += ['dbus/audio_reserve.c', 'dbus/reserve.c'] | |||
| @@ -732,8 +739,8 @@ def build_jackd(bld): | |||
| jackd.use += ['DL', 'M', 'PTHREAD', 'RT', 'STDC++'] | |||
| if bld.env['IS_MACOSX']: | |||
| bld.framework = ['CoreFoundation'] | |||
| jackd.use += ['DL', 'PTHREAD'] | |||
| jackd.framework = ['CoreFoundation'] | |||
| if bld.env['IS_SUN']: | |||
| jackd.use += ['DL', 'PTHREAD'] | |||
| @@ -744,6 +751,15 @@ def build_jackd(bld): | |||
| # FIXME: Is SERVER_SIDE needed? | |||
| def create_driver_obj(bld, **kw): | |||
| if bld.env['IS_MACOSX'] or bld.env['IS_WINDOWS']: | |||
| # On MacOSX this is necessary. | |||
| # I do not know if this is necessary on Windows. | |||
| # Note added on 2015-12-13 by lilrc. | |||
| if 'use' in kw: | |||
| kw['use'] += ['serverlib'] | |||
| else: | |||
| kw['use'] = ['serverlib'] | |||
| driver = bld( | |||
| features = ['c', 'cshlib', 'cxx', 'cxxshlib'], | |||
| defines = ['HAVE_CONFIG_H', 'SERVER_SIDE'], | |||
| @@ -814,19 +830,20 @@ def build_drivers(bld): | |||
| ] | |||
| coreaudio_src = [ | |||
| 'macosx/coreaudio/JackCoreAudioDriver.cpp' | |||
| 'macosx/coreaudio/JackCoreAudioDriver.mm', | |||
| 'common/JackAC3Encoder.cpp' | |||
| ] | |||
| coremidi_src = [ | |||
| 'macosx/coremidi/JackCoreMidiInputPort.cpp', | |||
| 'macosx/coremidi/JackCoreMidiOutputPort.cpp', | |||
| 'macosx/coremidi/JackCoreMidiPhysicalInputPort.cpp', | |||
| 'macosx/coremidi/JackCoreMidiPhysicalOutputPort.cpp', | |||
| 'macosx/coremidi/JackCoreMidiVirtualInputPort.cpp', | |||
| 'macosx/coremidi/JackCoreMidiVirtualOutputPort.cpp', | |||
| 'macosx/coremidi/JackCoreMidiPort.cpp', | |||
| 'macosx/coremidi/JackCoreMidiUtil.cpp', | |||
| 'macosx/coremidi/JackCoreMidiDriver.cpp' | |||
| 'macosx/coremidi/JackCoreMidiInputPort.mm', | |||
| 'macosx/coremidi/JackCoreMidiOutputPort.mm', | |||
| 'macosx/coremidi/JackCoreMidiPhysicalInputPort.mm', | |||
| 'macosx/coremidi/JackCoreMidiPhysicalOutputPort.mm', | |||
| 'macosx/coremidi/JackCoreMidiVirtualInputPort.mm', | |||
| 'macosx/coremidi/JackCoreMidiVirtualOutputPort.mm', | |||
| 'macosx/coremidi/JackCoreMidiPort.mm', | |||
| 'macosx/coremidi/JackCoreMidiUtil.mm', | |||
| 'macosx/coremidi/JackCoreMidiDriver.mm' | |||
| ] | |||
| ffado_src = [ | |||
| @@ -929,21 +946,21 @@ def build_drivers(bld): | |||
| bld, | |||
| target = 'portaudio', | |||
| source = portaudio_src, | |||
| use = ['serverlib', 'PORTAUDIO']) # FIXME: Is serverlib needed here? | |||
| use = ['PORTAUDIO']) | |||
| if bld.env['BUILD_DRIVER_WINMME']: | |||
| create_driver_obj( | |||
| bld, | |||
| target = 'winmme', | |||
| source = winmme_src, | |||
| use = ['serverlib', 'WINMME']) # FIXME: Is serverlib needed here? | |||
| use = ['WINMME']) | |||
| if bld.env['IS_MACOSX']: | |||
| create_driver_obj( | |||
| bld, | |||
| target = 'coreaudio', | |||
| source = coreaudio_src, | |||
| use = ['serverlib'], # FIXME: Is this needed? | |||
| use = ['AFTEN'], | |||
| framework = ['AudioUnit', 'CoreAudio', 'CoreServices']) | |||
| create_driver_obj( | |||
| @@ -951,7 +968,7 @@ def build_drivers(bld): | |||
| target = 'coremidi', | |||
| source = coremidi_src, | |||
| use = ['serverlib'], # FIXME: Is this needed? | |||
| framework = ['AudioUnit', 'CoreMIDI', 'CoreServices']) | |||
| framework = ['AudioUnit', 'CoreMIDI', 'CoreServices', 'Foundation']) | |||
| if bld.env['IS_SUN']: | |||
| create_driver_obj( | |||
| @@ -1071,3 +1088,9 @@ def dist(ctx): | |||
| # This code blindly assumes it is working in the toplevel source directory. | |||
| if not os.path.exists('svnversion.h'): | |||
| os.system('./svnversion_regenerate.sh svnversion.h') | |||
| from waflib import TaskGen | |||
| @TaskGen.extension('.mm') | |||
| def mm_hook(self, node): | |||
| """Alias .mm files to be compiled the same as .cpp files, gcc will do the right thing.""" | |||
| return self.create_compiled_task('cxx', node) | |||