diff --git a/_manifest.lua b/_manifest.lua index 4c11a55..44d2931 100644 --- a/_manifest.lua +++ b/_manifest.lua @@ -4,4 +4,5 @@ return { "xcode4_workspace.lua", "xcode_common.lua", "xcode_project.lua", + "xcode_scheme.lua", } diff --git a/_preload.lua b/_preload.lua index 4c1cc1b..8470efc 100644 --- a/_preload.lua +++ b/_preload.lua @@ -53,6 +53,7 @@ onProject = function(prj) p.generate(prj, ".xcodeproj/project.pbxproj", p.modules.xcode.generateProject) + p.generate(prj, ".xcodeproj/xcshareddata/xcschemes/" .. prj.name .. ".xcscheme", p.modules.xcode.scheme.generate) end, } diff --git a/tests/_tests.lua b/tests/_tests.lua index 3c9b714..eed4702 100644 --- a/tests/_tests.lua +++ b/tests/_tests.lua @@ -6,4 +6,5 @@ return { "test_xcode4_workspace.lua", "test_xcode_dependencies.lua", "test_xcode_project.lua", + "test_xcode_scheme.lua", } diff --git a/tests/test_xcode_dependencies.lua b/tests/test_xcode_dependencies.lua index 6bb952d..7a2dc24 100644 --- a/tests/test_xcode_dependencies.lua +++ b/tests/test_xcode_dependencies.lua @@ -22,24 +22,31 @@ end function suite.setup() - _ACTION = "xcode4" + premake.action.set("xcode4") xcode.used_ids = { } -- reset the list of generated IDs wks, prj = test.createWorkspace() links { "MyProject2" } + dependson { "MyProject3" } prj2 = test.createproject(wks) kind "StaticLib" configuration "Debug" targetsuffix "-d" + configuration {} + + local prj3 = test.createproject(wks) + kind "SharedLib" + links { "MyProject2" } + configuration "Debug" + targetsuffix "-d" + configuration {} end local function prepare() - wks = premake.oven.bakeWorkspace(wks) xcode.prepareWorkspace(wks) - local prj3 = premake.workspace.getproject(wks, 1) - --prj2 = test.getproject(wks, 2) - tr = xcode.buildprjtree(prj3) + local prj1 = test.getproject(wks, 1) + tr = xcode.buildprjtree(prj1) end @@ -58,7 +65,7 @@ end function suite.PBXBuildFile_ListsDependencyTargets_OnSharedLib() - kind "SharedLib" + prj2.kind = "SharedLib" prepare() xcode.PBXBuildFile(tr) test.capture [[ @@ -92,6 +99,20 @@ remoteGlobalIDString = [libMyProject2-d.a:target]; remoteInfo = "libMyProject2-d.a"; }; + [MyProject3.xcodeproj:prodprox] /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = [MyProject3.xcodeproj] /* MyProject3.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = [libMyProject3-d.dylib:product]; + remoteInfo = "libMyProject3-d.dylib"; + }; + [MyProject3.xcodeproj:targprox] /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = [MyProject3.xcodeproj] /* MyProject3.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = [libMyProject3-d.dylib:target]; + remoteInfo = "libMyProject3-d.dylib"; + }; /* End PBXContainerItemProxy section */ ]] end @@ -107,6 +128,7 @@ test.capture [[ /* Begin PBXFileReference section */ [MyProject2.xcodeproj] /* libMyProject2-d.a */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "MyProject2.xcodeproj"; path = MyProject2.xcodeproj; sourceTree = SOURCE_ROOT; }; + [MyProject3.xcodeproj] /* libMyProject3-d.dylib */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "MyProject3.xcodeproj"; path = MyProject3.xcodeproj; sourceTree = SOURCE_ROOT; }; [MyProject:product] /* MyProject */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; name = MyProject; path = MyProject; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ ]] @@ -114,12 +136,12 @@ function suite.PBXFileReference_UsesRelativePaths() prj.location = "MyProject" - prj2.location = "MyProject2" prepare() xcode.PBXFileReference(tr) test.capture [[ /* Begin PBXFileReference section */ [MyProject2.xcodeproj] /* libMyProject2-d.a */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "MyProject2.xcodeproj"; path = ../MyProject2.xcodeproj; sourceTree = SOURCE_ROOT; }; + [MyProject3.xcodeproj] /* libMyProject3-d.dylib */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "MyProject3.xcodeproj"; path = ../MyProject3.xcodeproj; sourceTree = SOURCE_ROOT; }; [MyProject:product] /* MyProject */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; name = MyProject; path = MyProject; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ ]] @@ -148,7 +170,7 @@ end function suite.PBXFrameworksBuildPhase_ListsDependencies_OnSharedLib() - kind "SharedLib" + prj2.kind="SharedLib" prepare() xcode.PBXFrameworksBuildPhase(tr) test.capture [[ @@ -182,6 +204,14 @@ name = Products; sourceTree = ""; }; + [MyProject3.xcodeproj:prodgrp] /* Products */ = { + isa = PBXGroup; + children = ( + [libMyProject3-d.dylib] /* libMyProject3-d.dylib */, + ); + name = Products; + sourceTree = ""; + }; [MyProject] /* MyProject */ = { isa = PBXGroup; children = ( @@ -203,6 +233,7 @@ isa = PBXGroup; children = ( [MyProject2.xcodeproj] /* MyProject2.xcodeproj */, + [MyProject3.xcodeproj] /* MyProject3.xcodeproj */, ); name = Projects; sourceTree = ""; @@ -233,6 +264,7 @@ ); dependencies = ( [MyProject2.xcodeproj:targdep] /* PBXTargetDependency */, + [MyProject3.xcodeproj:targdep] /* PBXTargetDependency */, ); name = MyProject; productInstallPath = "$(HOME)/bin"; @@ -266,6 +298,10 @@ ProductGroup = [MyProject2.xcodeproj:prodgrp] /* Products */; ProjectRef = [MyProject2.xcodeproj] /* MyProject2.xcodeproj */; }, + { + ProductGroup = [MyProject3.xcodeproj:prodgrp] /* Products */; + ProjectRef = [MyProject3.xcodeproj] /* MyProject3.xcodeproj */; + }, ); projectRoot = ""; targets = ( @@ -293,6 +329,13 @@ remoteRef = [MyProject2.xcodeproj:prodprox] /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + [libMyProject3-d.dylib] /* libMyProject3-d.dylib */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.dylib"; + path = "libMyProject3-d.dylib"; + remoteRef = [MyProject3.xcodeproj:prodprox] /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; /* End PBXReferenceProxy section */ ]] end @@ -312,6 +355,11 @@ name = "libMyProject2-d.a"; targetProxy = [MyProject2.xcodeproj:targprox] /* PBXContainerItemProxy */; }; + [MyProject3.xcodeproj:targdep] /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "libMyProject3-d.dylib"; + targetProxy = [MyProject3.xcodeproj:targprox] /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ ]] end diff --git a/tests/test_xcode_scheme.lua b/tests/test_xcode_scheme.lua new file mode 100644 index 0000000..cc4a50e --- /dev/null +++ b/tests/test_xcode_scheme.lua @@ -0,0 +1,210 @@ +--- +-- tests/test_xcode_scheme.lua +-- Automated test suite for Xcode scheme generation. +-- Copyright (c) 2011-2016 Jason Perkins and the Premake project +--- + + + local suite = test.declare("xcode4_scheme") + local xcode = premake.modules.xcode + local scheme = xcode.scheme + +--------------------------------------------------------------------------- +-- Setup/Teardown +--------------------------------------------------------------------------- + + local wks, prj + + function suite.teardown() + wks = nil + prj = nil + end + + function suite.setup() + _ACTION = "xcode4" + xcode.used_ids = { } -- reset the list of generated IDs + + wks = test.createWorkspace() + end + + local function prepare() + wks = premake.oven.bakeWorkspace(wks) + xcode.prepareWorkspace(wks) + prj = premake.workspace.getproject(wks, 1) + local tr = xcode.buildprjtree(prj) + end + +--------------------------------------------------------------------------- +-- Header +--------------------------------------------------------------------------- + + function suite.scheme_header() + prepare() + scheme.Header(prj) + test.capture [[ + + + ]] + end + +--------------------------------------------------------------------------- +-- Footer +--------------------------------------------------------------------------- + + function suite.scheme_footer() + prepare() + scheme.Footer(prj) + test.capture [[ + + ]] + end + +--------------------------------------------------------------------------- +-- Build +--------------------------------------------------------------------------- + + function suite.scheme_build() + prepare() + scheme.build(prj) + test.capture [[ + + + + + + + + + ]] + end + +--------------------------------------------------------------------------- +-- Test +--------------------------------------------------------------------------- + + function suite.scheme_test() + prepare() + scheme.test(prj) + test.capture [[ + + + + + + + + + ]] + end + +--------------------------------------------------------------------------- +-- Launch +--------------------------------------------------------------------------- + + function suite.scheme_launch() + prepare() + scheme.launch(prj) + test.capture [[ + + + + + + + + + ]] + end + +--------------------------------------------------------------------------- +-- Profile +--------------------------------------------------------------------------- + + function suite.scheme_profile() + prepare() + scheme.profile(prj) + test.capture [[ + + + + + + + ]] + end + +--------------------------------------------------------------------------- +-- Analyze +--------------------------------------------------------------------------- + + function suite.scheme_analyze() + prepare() + scheme.analyze(prj) + test.capture [[ + + + ]] + end + +--------------------------------------------------------------------------- +-- Archive +--------------------------------------------------------------------------- + + function suite.scheme_archive() + prepare() + scheme.archive(prj) + test.capture [[ + + + ]] + end + diff --git a/xcode.lua b/xcode.lua index a10454b..a21d252 100644 --- a/xcode.lua +++ b/xcode.lua @@ -15,5 +15,6 @@ include("xcode_common.lua") include("xcode4_workspace.lua") include("xcode_project.lua") + include("xcode_scheme.lua") return m diff --git a/xcode_common.lua b/xcode_common.lua index ff3b569..91de2d6 100644 --- a/xcode_common.lua +++ b/xcode_common.lua @@ -224,6 +224,10 @@ end end + function xcode.printSettingsTable(level, settings) + printSettingsTable(level, settings) + end + local function overrideSettings(settings, overrides) if type(overrides) == 'table' then for name, value in pairs(overrides) do @@ -368,7 +372,7 @@ local settings = {}; tree.traverse(tr, { onnode = function(node) - if node.buildid then + if node.buildid and (not node.not_a_link_dependency) then settings[node.buildid] = function(level) _p(level,'%s /* %s in %s */ = {isa = PBXBuildFile; fileRef = %s /* %s */; };', node.buildid, node.name, xcode.getbuildcategory(node), node.id, node.name) @@ -529,7 +533,7 @@ -- write out project dependencies tree.traverse(tr.projects, { onleaf = function(node) - if node.buildid then + if node.buildid and not node.not_a_link_dependency then _p(4,'%s /* %s in Frameworks */,', node.buildid, node.name) end end diff --git a/xcode_project.lua b/xcode_project.lua index e17ca57..4341953 100644 --- a/xcode_project.lua +++ b/xcode_project.lua @@ -88,7 +88,7 @@ -- the special folder "Projects" lists sibling project dependencies tr.projects = tree.new("Projects") - for _, dep in ipairs(project.getdependencies(prj, "sibling", "object")) do + for _, dep in ipairs(project.getdependencies(prj)) do -- create a child node for the dependency's xcodeproj local xcpath = xcode.getxcodeprojname(dep) local xcnode = tree.insert(tr.projects, tree.new(path.getname(xcpath))) @@ -98,6 +98,7 @@ xcnode.productproxyid = xcode.newid(xcnode.name, "prodprox") xcnode.targetproxyid = xcode.newid(xcnode.name, "targprox") xcnode.targetdependid = xcode.newid(xcnode.name, "targdep") + xcnode.not_a_link_dependency = not table.contains(project.getdependencies(prj, "linkOnly"), dep) -- create a grandchild node for the dependency's link target local lprj = premake.workspace.findproject(prj.workspace, dep.name) @@ -105,6 +106,7 @@ node = tree.insert(xcnode, tree.new(cfg.linktarget.name)) node.path = cfg.linktarget.fullpath node.cfg = cfg + node.not_a_link_dependency = xcnode.not_a_link_dependency end if #tr.projects.children > 0 then diff --git a/xcode_scheme.lua b/xcode_scheme.lua new file mode 100644 index 0000000..66f9063 --- /dev/null +++ b/xcode_scheme.lua @@ -0,0 +1,140 @@ +--- +-- xcode/xcode4_scheme.lua +-- Generate a shared scheme for an Xcode C/C++ project. +-- Copyright (c) 2009-2016 Jason Perkins and the Premake project +--- + + local p = premake + local m = p.modules.xcode + + local project = p.project + local config = p.config + local fileconfig = p.fileconfig + local tree = p.tree + + m.scheme = {} + local scheme = m.scheme + + function scheme.Header(prj) + p.w('') + p.push('') + end + + function scheme.Footer(prj) + p.pop('') + end + + function scheme.buildablereference(prj) + local tr = project.getsourcetree(prj) + for _, node in ipairs(tr.products.children) do + p.push('', tr.name) + p.pop('') + end + end + + function scheme.build(prj) + p.push('') + p.push('') + p.push('') + scheme.buildablereference(prj) + p.pop('') + p.pop('') + p.pop('') + end + + function scheme.test(prj) + p.push('') + p.push('') + p.pop('') + p.push('') + scheme.buildablereference(prj) + p.pop('') + p.pop('') + end + + function scheme.launch(prj) + p.push('') + p.push('') + scheme.buildablereference(prj) + p.pop('') + p.push('') + p.pop('') + p.pop('') + end + + function scheme.profile(prj) + p.push('') + p.push('') + scheme.buildablereference(prj) + p.pop('') + p.pop('') + end + + function scheme.analyze(prj) + p.push('') + p.pop('') + end + + function scheme.archive(prj) + p.push('') + p.pop('') + end + +-- +-- Generate the shared data scheme for an xcode project +-- +-- @param prj +-- The Premake project to generate. +-- + + m.scheme.project = function(prj) + return { + scheme.Header, + scheme.build, + scheme.test, + scheme.launch, + scheme.profile, + scheme.analyze, + scheme.archive, + scheme.Footer, + } + end + + function m.scheme.generate(prj) + p.callArray(m.scheme.project, prj) + end +