mirror of https://gitlab.com/ita1024/waf.git
Replace param 'source_files' with 'group_files'.
The 'source_files' param to the xcode6 tool was originally separated from the conventional 'source' param because it was used to control how the source files would appear in the XCode folder UI. Also, it'd allow to add any file extensions, and not limited to those extensions supported by the loaded set of waf tools. This commit renames 'source_files' param to 'group_files'. It also changes the semantic so that 'group_files' now is used like the following: bld( source='...', # These are now the files compiled by XCode 'group_files': ..., # Optionally customize the way source files appear i the UI ) Previously, 'source_files' was used to collect source files for compilation in XCode, and to customize the UI folder structure. In this commit source_files is used only to let the user group files in different UI folders (and add additional resource files besides source files). I want to do the renaming to better reflect the param's meaning. Additional changes: * Remove unique_filereference * Updated examples
This commit is contained in:
parent
8bc0cfbcb3
commit
c967d29e48
|
@ -0,0 +1 @@
|
|||
Sample text file.
|
|
@ -20,6 +20,7 @@ a static library target and an executable target.
|
|||
The generated XCode project can then be opened
|
||||
and XCode can then build those targets.
|
||||
Tested with XCode 8.
|
||||
|
||||
"""
|
||||
|
||||
def options(opt):
|
||||
|
@ -45,46 +46,58 @@ def configure(conf):
|
|||
conf.check(cxxflags='-std=c++11', uselib_store='STD11', mandatory=False)
|
||||
|
||||
def build(bld):
|
||||
|
||||
# Make .framework targets
|
||||
tg = bld.framework(
|
||||
includes='include',
|
||||
|
||||
# Specify source files for xcode
|
||||
# This will become the groups (folders) inside XCode.
|
||||
# Give a dictionary to group by name. Use a list to add everything in one
|
||||
source_files={
|
||||
'MyLibSource': bld.path.ant_glob('src/MyLib/*.cpp|*.m|*.mm'),
|
||||
'Include': bld.path.ant_glob(incl=['include/MyLib/*.h', 'include'], dir=True)
|
||||
},
|
||||
|
||||
# source files for waf builds
|
||||
# Source files
|
||||
source=bld.path.ant_glob('src/MyLib/*.cpp'),
|
||||
|
||||
# export_headers will put the files in the
|
||||
# 'Header Build Phase' in Xcode - i.e tell XCode to ship them with your .framework
|
||||
export_headers=bld.path.ant_glob(incl=['include/MyLib/*.h', 'include/MyLib/SupportLib'], dir=True),
|
||||
# If you don't want the source files to appear in a default
|
||||
# 'Source' folder, you can define your own folder structure
|
||||
# using a dictionary, where the key is the desired name of the folder
|
||||
# and the value are the files.
|
||||
group_files={
|
||||
'Source files': bld.path.ant_glob('src/MyLib/*.cpp|*.m|*.mm'),
|
||||
'Include': bld.path.ant_glob(incl=['include/MyLib/*.h'], dir=True),
|
||||
'Help': ['src/sample.txt']
|
||||
},
|
||||
|
||||
# If you want to ship your header files with your .framework, then
|
||||
# specify them using the 'export_headers' param
|
||||
export_headers=bld.path.ant_glob(incl=['include/MyLib/*.h', 'include/MyLib/SupportLib/*.h']),
|
||||
target='MyLib',
|
||||
|
||||
# The 'install' param will set the INSTALL_PATH for the
|
||||
# binary, and will also trigger XCode to copy the target to that
|
||||
# path
|
||||
install='~/Library/Frameworks'
|
||||
)
|
||||
|
||||
# Make .a static library targets
|
||||
bld.stlib(
|
||||
source=bld.path.ant_glob('src/MyLib/*.cpp'),
|
||||
includes = 'include',
|
||||
target='MyStaticLib',
|
||||
)
|
||||
|
||||
# Make standard executable target
|
||||
bld.program(
|
||||
source=['src/test.cpp'],
|
||||
includes='include',
|
||||
target='MyExe',
|
||||
use='MyDynLib'
|
||||
)
|
||||
|
||||
# Make .dylib shared libraries
|
||||
bld.shlib(
|
||||
source=bld.path.ant_glob('src/MyLib/*.cpp'),
|
||||
includes='include',
|
||||
target='MyDynLib',
|
||||
)
|
||||
|
||||
#bld.env.LIB_SDL2 = '/Library/Frameworks/SDL2.framework/SDL2'
|
||||
# Make an app bundle target
|
||||
tg2 = bld.app(
|
||||
source=bld.path.ant_glob('src/*.cpp'),
|
||||
includes='include',
|
||||
|
@ -96,5 +109,3 @@ def build(bld):
|
|||
# Override default setting in a target
|
||||
settings={"Debug": {"CONFIG_NAME": 'Debug'}}
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -6,52 +6,10 @@
|
|||
# XCode project file format based on http://www.monobjc.net/xcode-project-file-format.html
|
||||
|
||||
"""
|
||||
Usage:
|
||||
See playground/xcode6/ for usage examples.
|
||||
|
||||
See also demos/xcode6/ folder
|
||||
|
||||
def options(opt):
|
||||
opt.load('compiler_cxx xcode6')
|
||||
|
||||
def configure(cnf):
|
||||
# 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('compiler_cxx xcode6')
|
||||
|
||||
def build(bld):
|
||||
|
||||
# Make a Framework target
|
||||
bld.framework(
|
||||
source={
|
||||
'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 ...
|
||||
|
||||
# To generate your XCode project, open the folder with the wscript
|
||||
# in your terminal and run the following:
|
||||
# $ waf configure xcode6
|
||||
"""
|
||||
|
||||
# TODO: support iOS projects(?)
|
||||
|
||||
from waflib import Context, TaskGen, Build, Utils, Errors, Logs
|
||||
import os, sys
|
||||
|
||||
|
@ -185,6 +143,13 @@ def newid():
|
|||
id += 1
|
||||
return "%04X%04X%04X%012d" % (0, 10000, 0, id)
|
||||
|
||||
"""
|
||||
Represents a tree node in the XCode project plist file format.
|
||||
When written to a file, all attributes of XCodeNode are stringified together with
|
||||
its value. However, attributes starting with an underscore _ are ignored
|
||||
during that process and allows you to store arbitray values that are not supposed
|
||||
to be written out.
|
||||
"""
|
||||
class XCodeNode:
|
||||
def __init__(self):
|
||||
self._id = newid()
|
||||
|
@ -256,6 +221,7 @@ class XCConfigurationList(XCodeNode):
|
|||
# Group/Files
|
||||
class PBXFileReference(XCodeNode):
|
||||
def __init__(self, name, path, filetype = '', sourcetree = "SOURCE_ROOT"):
|
||||
|
||||
XCodeNode.__init__(self)
|
||||
self.fileEncoding = 4
|
||||
if not filetype:
|
||||
|
@ -291,16 +257,49 @@ class PBXBuildFile(XCodeNode):
|
|||
return self.fileRef == other.fileRef
|
||||
|
||||
class PBXGroup(XCodeNode):
|
||||
def __init__(self, name, sourcetree = "<group>"):
|
||||
def __init__(self, name, sourcetree = 'SOURCE_TREE'):
|
||||
XCodeNode.__init__(self)
|
||||
self.children = []
|
||||
self.name = name
|
||||
self.sourceTree = sourcetree
|
||||
|
||||
# Maintain a lookup table for all PBXFileReferences
|
||||
# that are contained in this group.
|
||||
self._filerefs = {}
|
||||
|
||||
def add(self, sources):
|
||||
""" sources param should be a list of PBXFileReference objects """
|
||||
"""
|
||||
Add a list of PBXFileReferences to this group
|
||||
|
||||
:param sources: list of PBXFileReferences objects
|
||||
"""
|
||||
self._filerefs.update(dict(zip(sources, sources)))
|
||||
self.children.extend(sources)
|
||||
|
||||
def get_sub_groups(self):
|
||||
"""
|
||||
Returns all child PBXGroup objects contained in this group
|
||||
"""
|
||||
return list(filter(lambda x: isinstance(x, PBXGroup), self.children))
|
||||
|
||||
def find_fileref(self, fileref):
|
||||
"""
|
||||
Recursively search this group for an existing PBXFileReference. Returns None
|
||||
if none were found.
|
||||
|
||||
The reason you'd want to reuse existing PBXFileReferences from a PBXGroup is that XCode doesn't like PBXFileReferences that aren't part of a PBXGroup heirarchy.
|
||||
If it isn't, the consequence is that certain UI features like 'Reveal in Finder'
|
||||
stops working.
|
||||
"""
|
||||
if fileref in self._filerefs:
|
||||
return self._filerefs[fileref]
|
||||
elif self.children:
|
||||
for childgroup in self.get_sub_groups():
|
||||
f = childgroup.find_fileref(fileref)
|
||||
if f:
|
||||
return f
|
||||
return None
|
||||
|
||||
class PBXContainerItemProxy(XCodeNode):
|
||||
""" This is the element for to decorate a target item. """
|
||||
def __init__(self, containerPortal, remoteGlobalIDString, remoteInfo='', proxyType=1):
|
||||
|
@ -501,29 +500,37 @@ def process_xcode(self):
|
|||
|
||||
products_group.children.append(target.productReference)
|
||||
|
||||
if hasattr(self, 'source_files') or hasattr(self, 'source'):
|
||||
# Create list of PBXFileReferences
|
||||
sources = []
|
||||
if hasattr(self, 'source_files') and isinstance(self.source_files, dict):
|
||||
for grpname,files in self.source_files.items():
|
||||
group = bld.create_group(grpname, files)
|
||||
target_group.children.append(group)
|
||||
sources.extend(group.children)
|
||||
else:
|
||||
src = getattr(self, 'source_files', []) or self.source
|
||||
group = bld.create_group("Source", src)
|
||||
# Pull source files from the 'source' attribute and assign them to a UI group.
|
||||
# Use a default UI group named 'Source' unless the user
|
||||
# provides a 'group_files' dictionary to customize the UI grouping.
|
||||
sources = getattr(self, 'source', [])
|
||||
if hasattr(self, 'group_files'):
|
||||
group_files = getattr(self, 'group_files', [])
|
||||
for grpname,files in group_files.items():
|
||||
group = bld.create_group(grpname, files)
|
||||
target_group.children.append(group)
|
||||
sources.extend(group.children)
|
||||
else:
|
||||
group = bld.create_group('Source', sources)
|
||||
target_group.children.append(group)
|
||||
|
||||
# FIXME too complex
|
||||
sources = list(filter(lambda fileref: os.path.splitext(fileref.path)[1] in XCODE_EXTS, sources))
|
||||
buildfiles = [bld.unique_buildfile(PBXBuildFile(fileref)) for fileref in sources]
|
||||
target.add_build_phase(PBXSourcesBuildPhase(buildfiles))
|
||||
# Create a PBXFileReference for each source file.
|
||||
# If the source file already exists as a PBXFileReference in any of the UI groups, then
|
||||
# reuse that PBXFileReference object (XCode does not like it if we don't reuse)
|
||||
for idx, path in enumerate(sources):
|
||||
fileref = PBXFileReference(path.name, path.abspath())
|
||||
existing_fileref = target_group.find_fileref(fileref)
|
||||
if existing_fileref:
|
||||
sources[idx] = existing_fileref
|
||||
else:
|
||||
sources[idx] = fileref
|
||||
|
||||
# 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 specific
|
||||
# search paths, libs to link etc.
|
||||
settings = getattr(self, 'settings', {})
|
||||
# If the 'source' attribute contains any file extension that XCode can't work with,
|
||||
# then remove it. The allowed file extensions are defined in XCODE_EXTS.
|
||||
is_valid_file_extension = lambda file: os.path.splitext(file.path)[1] in XCODE_EXTS
|
||||
sources = list(filter(is_valid_file_extension, sources))
|
||||
|
||||
buildfiles = [bld.unique_buildfile(PBXBuildFile(fileref)) for fileref in sources]
|
||||
target.add_build_phase(PBXSourcesBuildPhase(buildfiles))
|
||||
|
||||
# Check if any framework to link against is some other target we've made
|
||||
libs = getattr(self, 'tmp_use_seen', [])
|
||||
|
@ -531,8 +538,11 @@ def process_xcode(self):
|
|||
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)]))
|
||||
dependency = p.create_target_dependency(use_target, use_target.name)
|
||||
target.add_dependency(dependency)
|
||||
|
||||
buildphase = PBXFrameworksBuildPhase([PBXBuildFile(use_target.productReference)])
|
||||
target.add_build_phase(buildphase)
|
||||
if lib in self.env.LIB:
|
||||
self.env.LIB = list(filter(lambda x: x != lib, self.env.LIB))
|
||||
|
||||
|
@ -540,8 +550,10 @@ def process_xcode(self):
|
|||
# These are files that'll get packed into the Framework for instance.
|
||||
exp_hdrs = getattr(self, 'export_headers', [])
|
||||
hdrs = bld.as_nodes(Utils.to_list(exp_hdrs))
|
||||
files = [bld.unique_filereference(PBXFileReference(n.name, n.abspath())) for n in hdrs]
|
||||
target.add_build_phase(PBXHeadersBuildPhase([PBXBuildFile(f, {'ATTRIBUTES': ('Public',)}) for f in files]))
|
||||
files = [p.mainGroup.find_fileref(PBXFileReference(n.name, n.abspath())) for n in hdrs]
|
||||
files = [PBXBuildFile(f, {'ATTRIBUTES': ('Public',)}) for f in files]
|
||||
buildphase = PBXHeadersBuildPhase(files)
|
||||
target.add_build_phase(buildphase)
|
||||
|
||||
# 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(self.env.FRAMEWORK)]
|
||||
|
@ -566,6 +578,11 @@ def process_xcode(self):
|
|||
if not bldsettings['INSTALL_PATH']:
|
||||
del bldsettings['INSTALL_PATH']
|
||||
|
||||
# Create build settings which can override the project settings. Defaults to none if user
|
||||
# did not pass argument. This will be filled up with target specific
|
||||
# search paths, libs to link etc.
|
||||
settings = getattr(self, 'settings', {})
|
||||
|
||||
# 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() + bld.env.PROJ_CONFIGURATION.keys())
|
||||
|
@ -593,6 +610,8 @@ class xcode(Build.BuildContext):
|
|||
d = x
|
||||
else:
|
||||
d = self.srcnode.find_node(x)
|
||||
if not d:
|
||||
raise Errors.WafError('File \'%s\' was not found' % x)
|
||||
nodes.append(d)
|
||||
return nodes
|
||||
|
||||
|
@ -606,24 +625,13 @@ class xcode(Build.BuildContext):
|
|||
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)
|
||||
files_ = []
|
||||
for d in self.as_nodes(Utils.to_list(files)):
|
||||
fileref = PBXFileReference(d.name, d.abspath())
|
||||
files_.append(fileref)
|
||||
group.add(files_)
|
||||
return group
|
||||
|
||||
def unique_filereference(self, ref):
|
||||
"""
|
||||
Returns a unique file reference, 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.
|
||||
"""
|
||||
try:
|
||||
file_refs = self.file_refs
|
||||
except AttributeError:
|
||||
file_refs = self.file_refs = {}
|
||||
if ref not in file_refs:
|
||||
file_refs[ref] = ref
|
||||
return file_refs[ref]
|
||||
|
||||
def unique_buildfile(self, buildfile):
|
||||
"""
|
||||
Returns a unique buildfile, possibly an existing one.
|
||||
|
|
Loading…
Reference in New Issue