From ea5eb2a80dac61a4e5174b90042cedd933af9a83 Mon Sep 17 00:00:00 2001 From: blackbox Date: Mon, 3 Apr 2017 00:34:03 +0200 Subject: XCode frameworks support - supported as "Link with Libraries". - Frameworks added as a group to the project - no need to specify custom linker flags anymore, xcodeproj works just like ninja example mason.build file : dep_main += [dependency('appleframeworks', modules : ['Foundation', 'AppKit', 'IOKIT', 'QuartzCore', 'OpenGL', 'GLUT', 'OpenAL'], required : true)] --- mesonbuild/backend/xcodebackend.py | 84 +++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 16c0daf..fae5822 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -14,6 +14,7 @@ from . import backends from .. import build +from .. import dependencies from .. import mesonlib import uuid, os, sys @@ -77,6 +78,7 @@ class XCodeBackend(backends.Backend): self.generate_buildall_configurations_map() self.generate_test_configurations_map() self.generate_native_target_map() + self.generate_native_frameworks_map() self.generate_source_phase_map() self.generate_target_dependency_map() self.generate_pbxdep_map() @@ -91,6 +93,7 @@ class XCodeBackend(backends.Backend): self.generate_pbx_build_style() self.generate_pbx_container_item_proxy() self.generate_pbx_file_reference() + self.generate_pbx_frameworks_buildphase() self.generate_pbx_group() self.generate_pbx_native_target() self.generate_pbx_project() @@ -133,7 +136,14 @@ class XCodeBackend(backends.Backend): self.buildstylemap = {'debug': self.gen_id()} def generate_build_phase_map(self): - self.buildphasemap = {} + # Probably should be a vector of maps, one vector-entry for each native_targets (e.g. macos/ios/...) + # and each native-target can have their own Frameworks-section (with its own unique-id) + self.buildphasemap = {} + # system ones + self.buildphasemap['Frameworks'] = self.gen_id() + self.buildphasemap['Resources'] = self.gen_id() + self.buildphasemap['Sources'] = self.gen_id() + self.buildphasemap['Encode images'] = self.gen_id() for t in self.build.targets: self.buildphasemap[t] = self.gen_id() @@ -162,6 +172,16 @@ class XCodeBackend(backends.Backend): for t in self.build.targets: self.native_targets[t] = self.gen_id() + def generate_native_frameworks_map(self): + self.native_frameworks = {} + self.native_frameworks_fileref = {} + for t in self.build.targets.values(): + for dep in t.get_external_deps(): + if isinstance(dep, dependencies.AppleFrameworks): + for f in dep.frameworks: + self.native_frameworks[f] = self.gen_id() + self.native_frameworks_fileref[f] = self.gen_id() + def generate_target_dependency_map(self): self.target_dependency_map = {} for tname, t in self.build.targets.items(): @@ -222,7 +242,14 @@ class XCodeBackend(backends.Backend): self.ofile.write('\n/* Begin PBXBuildFile section */\n') templ = '%s /* %s */ = { isa = PBXBuildFile; fileRef = %s /* %s */; settings = { COMPILER_FLAGS = "%s"; }; };\n' otempl = '%s /* %s */ = { isa = PBXBuildFile; fileRef = %s /* %s */;};\n' + for t in self.build.targets.values(): + + for dep in t.get_external_deps(): + if isinstance(dep, dependencies.AppleFrameworks): + for f in dep.frameworks: + self.ofile.write('%s /* %s.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = %s /* %s.framework */; };\n' %(self.native_frameworks[f], f, self.native_frameworks_fileref[f], f)) + for s in t.sources: if isinstance(s, mesonlib.File): s = s.fname @@ -276,6 +303,13 @@ class XCodeBackend(backends.Backend): def generate_pbx_file_reference(self): self.ofile.write('\n/* Begin PBXFileReference section */\n') + + for t in self.build.targets.values(): + for dep in t.get_external_deps(): + if isinstance(dep, dependencies.AppleFrameworks): + for f in dep.frameworks: + self.ofile.write('%s /* %s.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = %s.framework; path = System/Library/Frameworks/%s.framework; sourceTree = SDKROOT; };\n' %(self.native_frameworks_fileref[f], f, f, f)) + src_templ = '%s /* %s */ = { isa = PBXFileReference; explicitFileType = "%s"; fileEncoding = 4; name = "%s"; path = "%s"; sourceTree = SOURCE_ROOT; };\n' for fname, idval in self.filemap.items(): fullpath = os.path.join(self.environment.get_source_dir(), fname) @@ -300,6 +334,29 @@ class XCodeBackend(backends.Backend): self.ofile.write(target_templ % (idval, tname, typestr, path, reftype)) self.ofile.write('/* End PBXFileReference section */\n') + def generate_pbx_frameworks_buildphase(self): + self.ofile.write('\n/* Begin PBXFrameworksBuildPhase section */\n') + self.indent_level += 1 + self.write_line('%s /* %s */ = {\n' %(self.buildphasemap['Frameworks'], 'Frameworks')) + self.indent_level += 1 + self.write_line('isa = PBXFrameworksBuildPhase;\n') + self.write_line('buildActionMask = %s;\n' %(2147483647)) + self.write_line('files = (\n') + self.indent_level += 1 + + for t in self.build.targets.values(): + for dep in t.get_external_deps(): + if isinstance(dep, dependencies.AppleFrameworks): + for f in dep.frameworks: + self.write_line('%s /* %s.framework in Frameworks */,\n' %(self.native_frameworks[f], f)) + + self.indent_level -= 1 + self.write_line(');\n') + self.write_line('runOnlyForDeploymentPostprocessing = 0;\n') + self.indent_level -= 1 + self.write_line('};\n') + self.ofile.write('/* End PBXFrameworksBuildPhase section */\n') + def generate_pbx_group(self): groupmap = {} target_src_map = {} @@ -310,6 +367,7 @@ class XCodeBackend(backends.Backend): sources_id = self.gen_id() resources_id = self.gen_id() products_id = self.gen_id() + frameworks_id = self.gen_id() self.write_line('%s = {' % self.maingroup_id) self.indent_level += 1 self.write_line('isa = PBXGroup;') @@ -318,6 +376,7 @@ class XCodeBackend(backends.Backend): self.write_line('%s /* Sources */,' % sources_id) self.write_line('%s /* Resources */,' % resources_id) self.write_line('%s /* Products */,' % products_id) + self.write_line('%s /* Frameworks */,' % frameworks_id) self.indent_level -= 1 self.write_line(');') self.write_line('sourceTree = "";') @@ -348,6 +407,26 @@ class XCodeBackend(backends.Backend): self.write_line('sourceTree = "";') self.indent_level -= 1 self.write_line('};') + + self.write_line('%s /* Frameworks */ = {' % frameworks_id) + self.indent_level += 1 + self.write_line('isa = PBXGroup;') + self.write_line('children = (') + # write frameworks + self.indent_level += 1 + + for t in self.build.targets.values(): + for dep in t.get_external_deps(): + if isinstance(dep, dependencies.AppleFrameworks): + for f in dep.frameworks: + self.write_line('%s /* %s.framework */,\n' %(self.native_frameworks_fileref[f], f)) + + self.indent_level -= 1 + self.write_line(');') + self.write_line('name = Frameworks;') + self.write_line('sourceTree = "";') + self.indent_level -= 1 + self.write_line('};') # Targets for t in self.build.targets: @@ -409,7 +488,8 @@ class XCodeBackend(backends.Backend): % (self.buildconflistmap[tname], tname)) self.write_line('buildPhases = (') self.indent_level += 1 - self.write_line('%s /* Sources */,' % self.buildphasemap[tname]) + for bpname, bpval in self.buildphasemap.items(): + self.write_line('%s /* %s xxx */,' % (self.buildphasemap[bpname], bpname)) self.indent_level -= 1 self.write_line(');') self.write_line('buildRules = (') -- cgit v1.1 From 03ebe2f56f92a5e6213abfa252b7746eb50dd411 Mon Sep 17 00:00:00 2001 From: blackbox Date: Mon, 3 Apr 2017 23:00:25 +0200 Subject: remove debug-marker --- mesonbuild/backend/xcodebackend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index fae5822..0f9eadb 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -489,7 +489,7 @@ class XCodeBackend(backends.Backend): self.write_line('buildPhases = (') self.indent_level += 1 for bpname, bpval in self.buildphasemap.items(): - self.write_line('%s /* %s xxx */,' % (self.buildphasemap[bpname], bpname)) + self.write_line('%s /* %s */,' % (self.buildphasemap[bpname], bpname)) self.indent_level -= 1 self.write_line(');') self.write_line('buildRules = (') -- cgit v1.1 From dd443ad0eb9b0d8a54945bb3920eedcfb7a05109 Mon Sep 17 00:00:00 2001 From: blackbox Date: Mon, 3 Apr 2017 23:57:56 +0200 Subject: codestyle --- mesonbuild/backend/xcodebackend.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 0f9eadb..2b78b33 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -136,9 +136,9 @@ class XCodeBackend(backends.Backend): self.buildstylemap = {'debug': self.gen_id()} def generate_build_phase_map(self): - # Probably should be a vector of maps, one vector-entry for each native_targets (e.g. macos/ios/...) + # Probably should be a vector of maps, one vector-entry for each native_targets (e.g. macos/ios/...) # and each native-target can have their own Frameworks-section (with its own unique-id) - self.buildphasemap = {} + self.buildphasemap = {} # system ones self.buildphasemap['Frameworks'] = self.gen_id() self.buildphasemap['Resources'] = self.gen_id() @@ -248,7 +248,7 @@ class XCodeBackend(backends.Backend): for dep in t.get_external_deps(): if isinstance(dep, dependencies.AppleFrameworks): for f in dep.frameworks: - self.ofile.write('%s /* %s.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = %s /* %s.framework */; };\n' %(self.native_frameworks[f], f, self.native_frameworks_fileref[f], f)) + self.ofile.write('%s /* %s.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = %s /* %s.framework */; };\n' % (self.native_frameworks[f], f, self.native_frameworks_fileref[f], f)) for s in t.sources: if isinstance(s, mesonlib.File): @@ -308,8 +308,7 @@ class XCodeBackend(backends.Backend): for dep in t.get_external_deps(): if isinstance(dep, dependencies.AppleFrameworks): for f in dep.frameworks: - self.ofile.write('%s /* %s.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = %s.framework; path = System/Library/Frameworks/%s.framework; sourceTree = SDKROOT; };\n' %(self.native_frameworks_fileref[f], f, f, f)) - + self.ofile.write('%s /* %s.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = %s.framework; path = System/Library/Frameworks/%s.framework; sourceTree = SDKROOT; };\n' % (self.native_frameworks_fileref[f], f, f, f)) src_templ = '%s /* %s */ = { isa = PBXFileReference; explicitFileType = "%s"; fileEncoding = 4; name = "%s"; path = "%s"; sourceTree = SOURCE_ROOT; };\n' for fname, idval in self.filemap.items(): fullpath = os.path.join(self.environment.get_source_dir(), fname) @@ -337,19 +336,17 @@ class XCodeBackend(backends.Backend): def generate_pbx_frameworks_buildphase(self): self.ofile.write('\n/* Begin PBXFrameworksBuildPhase section */\n') self.indent_level += 1 - self.write_line('%s /* %s */ = {\n' %(self.buildphasemap['Frameworks'], 'Frameworks')) + self.write_line('%s /* %s */ = {\n' % (self.buildphasemap['Frameworks'], 'Frameworks')) self.indent_level += 1 self.write_line('isa = PBXFrameworksBuildPhase;\n') - self.write_line('buildActionMask = %s;\n' %(2147483647)) + self.write_line('buildActionMask = %s;\n' % (2147483647)) self.write_line('files = (\n') self.indent_level += 1 - for t in self.build.targets.values(): for dep in t.get_external_deps(): if isinstance(dep, dependencies.AppleFrameworks): for f in dep.frameworks: - self.write_line('%s /* %s.framework in Frameworks */,\n' %(self.native_frameworks[f], f)) - + self.write_line('%s /* %s.framework in Frameworks */,\n' % (self.native_frameworks[f], f)) self.indent_level -= 1 self.write_line(');\n') self.write_line('runOnlyForDeploymentPostprocessing = 0;\n') @@ -407,7 +404,7 @@ class XCodeBackend(backends.Backend): self.write_line('sourceTree = "";') self.indent_level -= 1 self.write_line('};') - + self.write_line('%s /* Frameworks */ = {' % frameworks_id) self.indent_level += 1 self.write_line('isa = PBXGroup;') @@ -419,8 +416,8 @@ class XCodeBackend(backends.Backend): for dep in t.get_external_deps(): if isinstance(dep, dependencies.AppleFrameworks): for f in dep.frameworks: - self.write_line('%s /* %s.framework */,\n' %(self.native_frameworks_fileref[f], f)) - + self.write_line('%s /* %s.framework */,\n' % (self.native_frameworks_fileref[f], f)) + self.indent_level -= 1 self.write_line(');') self.write_line('name = Frameworks;') -- cgit v1.1 From db176c85dbe67b412c7cacef63f5c2d09fd7f246 Mon Sep 17 00:00:00 2001 From: blackbox Date: Wed, 5 Apr 2017 23:44:29 +0200 Subject: xcode-backend framework fixes - frameworks-per-target ( each needs its own uid ) --- mesonbuild/backend/xcodebackend.py | 56 +++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 2b78b33..35c0d84 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -136,16 +136,14 @@ class XCodeBackend(backends.Backend): self.buildstylemap = {'debug': self.gen_id()} def generate_build_phase_map(self): - # Probably should be a vector of maps, one vector-entry for each native_targets (e.g. macos/ios/...) - # and each native-target can have their own Frameworks-section (with its own unique-id) - self.buildphasemap = {} - # system ones - self.buildphasemap['Frameworks'] = self.gen_id() - self.buildphasemap['Resources'] = self.gen_id() - self.buildphasemap['Sources'] = self.gen_id() - self.buildphasemap['Encode images'] = self.gen_id() - for t in self.build.targets: - self.buildphasemap[t] = self.gen_id() + for tname, t in self.build.targets.items(): + # generate id for our own target-name + t.buildphasemap = {} + t.buildphasemap[tname] = self.gen_id() + # each target can have it's own Frameworks/Sources/..., generate id's for those + t.buildphasemap['Frameworks'] = self.gen_id() + t.buildphasemap['Resources'] = self.gen_id() + t.buildphasemap['Sources'] = self.gen_id() def generate_build_configuration_map(self): self.buildconfmap = {} @@ -334,24 +332,24 @@ class XCodeBackend(backends.Backend): self.ofile.write('/* End PBXFileReference section */\n') def generate_pbx_frameworks_buildphase(self): - self.ofile.write('\n/* Begin PBXFrameworksBuildPhase section */\n') - self.indent_level += 1 - self.write_line('%s /* %s */ = {\n' % (self.buildphasemap['Frameworks'], 'Frameworks')) - self.indent_level += 1 - self.write_line('isa = PBXFrameworksBuildPhase;\n') - self.write_line('buildActionMask = %s;\n' % (2147483647)) - self.write_line('files = (\n') - self.indent_level += 1 - for t in self.build.targets.values(): + for tname, t in self.build.targets.items(): + self.ofile.write('\n/* Begin PBXFrameworksBuildPhase section */\n') + self.indent_level += 1 + self.write_line('%s /* %s */ = {\n' %(t.buildphasemap['Frameworks'], 'Frameworks')) + self.indent_level += 1 + self.write_line('isa = PBXFrameworksBuildPhase;\n') + self.write_line('buildActionMask = %s;\n' %(2147483647)) + self.write_line('files = (\n') + self.indent_level += 1 for dep in t.get_external_deps(): if isinstance(dep, dependencies.AppleFrameworks): for f in dep.frameworks: - self.write_line('%s /* %s.framework in Frameworks */,\n' % (self.native_frameworks[f], f)) - self.indent_level -= 1 - self.write_line(');\n') - self.write_line('runOnlyForDeploymentPostprocessing = 0;\n') - self.indent_level -= 1 - self.write_line('};\n') + self.write_line('%s /* %s.framework in Frameworks */,\n' %(self.native_frameworks[f], f)) + self.indent_level -= 1 + self.write_line(');\n') + self.write_line('runOnlyForDeploymentPostprocessing = 0;\n') + self.indent_level -= 1 + self.write_line('};\n') self.ofile.write('/* End PBXFrameworksBuildPhase section */\n') def generate_pbx_group(self): @@ -485,8 +483,9 @@ class XCodeBackend(backends.Backend): % (self.buildconflistmap[tname], tname)) self.write_line('buildPhases = (') self.indent_level += 1 - for bpname, bpval in self.buildphasemap.items(): - self.write_line('%s /* %s */,' % (self.buildphasemap[bpname], bpname)) + t = self.build.targets[tname] + for bpname, bpval in t.buildphasemap.items(): + self.write_line('%s /* %s yyy */,' % (bpval, bpname)) self.indent_level -= 1 self.write_line(');') self.write_line('buildRules = (') @@ -580,7 +579,8 @@ class XCodeBackend(backends.Backend): def generate_pbx_sources_build_phase(self): self.ofile.write('\n/* Begin PBXSourcesBuildPhase section */\n') for name, phase_id in self.source_phase.items(): - self.write_line('%s /* Sources */ = {' % self.buildphasemap[name]) + t = self.build.targets[name] + self.write_line('%s /* Sources */ = {' % (t.buildphasemap[name])) self.indent_level += 1 self.write_line('isa = PBXSourcesBuildPhase;') self.write_line('buildActionMask = 2147483647;') -- cgit v1.1 From 8de531328859bfe2272b24d9897bbca5b0f9fbc7 Mon Sep 17 00:00:00 2001 From: blackbox Date: Sun, 9 Apr 2017 22:02:16 +0200 Subject: unit-test for testing xcode frameworks --- test cases/osx/4 framework/meson.build | 18 ++++++++++++++++++ test cases/osx/4 framework/prog.c | 3 +++ test cases/osx/4 framework/stat.c | 1 + test cases/osx/4 framework/xcode-frameworks.png | Bin 0 -> 421385 bytes 4 files changed, 22 insertions(+) create mode 100644 test cases/osx/4 framework/meson.build create mode 100644 test cases/osx/4 framework/prog.c create mode 100644 test cases/osx/4 framework/stat.c create mode 100644 test cases/osx/4 framework/xcode-frameworks.png diff --git a/test cases/osx/4 framework/meson.build b/test cases/osx/4 framework/meson.build new file mode 100644 index 0000000..8d93bf9 --- /dev/null +++ b/test cases/osx/4 framework/meson.build @@ -0,0 +1,18 @@ +# Primitive test for adding frameworks in XCode +# When opening the xcodeproj, the Folder "Frameworks" should contain two frameworks (OpenGL.framework and Foundation.framework) +# "Target Membership" of ... +# - OpenGL.framework should be only to prog@exe +# - Foundation.framework should be only to stat@sta +# "Build Phase" / "Link Binary with Libraries" for the target +# - "prog@exe" should be only "Foundation.framework" +# - "stat@sta" should be only "OpenGL.framework" +# see "xcode-frameworks.png" for an example + +project('xcode framework test', 'c', default_options : ['libdir=libtest']) + +dep_libs = [dependency('appleframeworks', modules : ['OpenGL'], required : true)] +dep_main = [dependency('appleframeworks', modules : ['Foundation'], required : true)] + +stlib = static_library('stat', 'stat.c', install : true, dependencies: dep_libs) +exe = executable('prog', 'prog.c', install : true, dependencies: dep_main) + diff --git a/test cases/osx/4 framework/prog.c b/test cases/osx/4 framework/prog.c new file mode 100644 index 0000000..11b7fad --- /dev/null +++ b/test cases/osx/4 framework/prog.c @@ -0,0 +1,3 @@ +int main(int argc, char **argv) { + return 0; +} diff --git a/test cases/osx/4 framework/stat.c b/test cases/osx/4 framework/stat.c new file mode 100644 index 0000000..fa76a65 --- /dev/null +++ b/test cases/osx/4 framework/stat.c @@ -0,0 +1 @@ +int func() { return 933; } diff --git a/test cases/osx/4 framework/xcode-frameworks.png b/test cases/osx/4 framework/xcode-frameworks.png new file mode 100644 index 0000000..673d05a Binary files /dev/null and b/test cases/osx/4 framework/xcode-frameworks.png differ -- cgit v1.1