summaryrefslogtreecommitdiff
path: root/xmake/plugins/project/xcode
diff options
context:
space:
mode:
authorruki <[email protected]>2025-07-02 22:47:13 +0800
committerruki <[email protected]>2025-07-02 22:47:13 +0800
commitcc50f4503c1b7159fdabe89429844ec6ca8eea1f (patch)
tree367da67b893f601348bd63531df4ef3aeb17c01e /xmake/plugins/project/xcode
parentb1d2fc1295e85eb6773aa209ed19f6e6d2f21141 (diff)
rename xcode2 to xcode
Diffstat (limited to 'xmake/plugins/project/xcode')
-rw-r--r--xmake/plugins/project/xcode/get_xcode_info.lua300
-rw-r--r--xmake/plugins/project/xcode/pbxproj.lua271
-rw-r--r--xmake/plugins/project/xcode/xcodeproj.lua31
3 files changed, 583 insertions, 19 deletions
diff --git a/xmake/plugins/project/xcode/get_xcode_info.lua b/xmake/plugins/project/xcode/get_xcode_info.lua
new file mode 100644
index 000000000..d8d6d3b6f
--- /dev/null
+++ b/xmake/plugins/project/xcode/get_xcode_info.lua
@@ -0,0 +1,300 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author JXMaster
+-- @file get_xcode_info.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.project.config")
+import("core.project.project")
+
+function _get_project_modes()
+ local ret_modes = {}
+ local modes = option.get("modes")
+ if modes then
+ if not modes:find("\"") then
+ modes = modes:gsub(",", path.envsep())
+ end
+ for _, mode in ipairs(path.splitenv(modes)) do
+ table.insert(ret_modes, mode:trim())
+ end
+ else
+ ret_modes = project.modes()
+ end
+ return ret_modes
+end
+
+-- tranlate path
+function _translate_path(filepath, outputdir)
+ filepath = path.translate(filepath)
+ if filepath == "" then
+ return ""
+ end
+ if path.is_absolute(filepath) then
+ if filepath:startswith(project.directory()) then
+ return path.relative(filepath, outputdir)
+ end
+ return filepath
+ else
+ return path.relative(path.absolute(filepath), outputdir)
+ end
+end
+
+function _add_PBXFileReference(xcinfo, file_info)
+ local obj = {}
+ obj.explicitFileType = file_info.explicitFileType
+ obj.lastKnownFileType = file_info.lastKnownFileType
+ obj.name = file_info.name
+ obj.path = file_info.path
+ obj.sourceTree = file_info.sourceTree
+ obj.includeInIndex = file_info.includeInIndex
+ local uuid = xcinfo:gen_uuid()
+ xcinfo.sections.PBXFileReference = xcinfo.sections.PBXFileReference or {}
+ xcinfo.sections.PBXFileReference[uuid] = obj
+ return uuid
+end
+
+function _add_PBXGroup(xcinfo, name, sourceTree)
+ local obj = {}
+ obj.name = name
+ obj.sourceTree = sourceTree
+ obj.children = {}
+ local uuid = xcinfo:gen_uuid()
+ xcinfo.sections.PBXGroup = xcinfo.sections.PBXGroup or {}
+ xcinfo.sections.PBXGroup[uuid] = obj
+ return uuid
+end
+
+-- target may be nil.
+function _add_XCBuildConfiguration(xcinfo, mode, target)
+ local obj = {}
+ obj.name = mode
+ obj.buildSettings = {}
+ -- This allows scripts to read/write files that are not in the Input/Output list of
+ -- the phase.
+ obj.buildSettings.ENABLE_USER_SCRIPT_SANDBOXING = false
+ if target then
+ local rules = target:rules()
+ local is_app_bundle = false
+ if rules["xcode.application"] ~= nil then
+ is_app_bundle = true
+ end
+ if is_app_bundle then
+ obj.buildSettings.GENERATE_INFOPLIST_FILE = true
+ obj.buildSettings.PRODUCT_NAME = "\"$(TARGET_NAME)\""
+ end
+ else
+ -- This is for root project.
+ obj.buildSettings.SUPPORTED_PLATFORMS = "\"macosx iphoneos\""
+ obj.buildSettings.SDKROOT = "macosx"
+ obj.buildSettings["\"SDKROOT[sdk=macosx*]\""] = "macosx"
+ obj.buildSettings["\"SDKROOT[sdk=iphoneos]\""] = "iphoneos"
+
+ end
+ local uuid = xcinfo:gen_uuid()
+ xcinfo.sections.XCBuildConfiguration = xcinfo.sections.XCBuildConfiguration or {}
+ xcinfo.sections.XCBuildConfiguration[uuid] = obj
+ return uuid
+end
+
+-- target may be nil.
+function _add_XCConfigurationList(xcinfo, target)
+ local obj = {}
+ local modes = _get_project_modes()
+ obj.buildConfigurations = {}
+ for _, mode in ipairs(modes) do
+ table.insert(obj.buildConfigurations, _add_XCBuildConfiguration(xcinfo, mode, target))
+ end
+ local uuid = xcinfo:gen_uuid()
+ xcinfo.sections.XCConfigurationList = xcinfo.sections.XCConfigurationList or {}
+ xcinfo.sections.XCConfigurationList[uuid] = obj
+ return uuid
+end
+
+function _add_PBXShellScriptBuildPhase(xcinfo, target)
+ local obj = {}
+ local shellscript = {}
+ local projectdir = _translate_path(os.projectdir(), xcinfo.project_dir)
+ if projectdir ~= "." then
+ table.insert(shellscript, "cd " .. projectdir)
+ end
+ table.insert(shellscript, [[
+export XMAKE_PROGRAM_FILE=\"]] .. os.programfile() .. [[\"
+export XMAKE_PROGRAM_DIR=\"]] .. os.programdir() .. [[\"
+export XMAKE_COLORTERM=\"nocolor\"
+
+# Running xmake scripts.
+${XMAKE_PROGRAM_FILE} f -y -m ${CONFIGURATION} -p ${PLATFORM_NAME} -a ${NATIVE_ARCH} -o ${BUILD_DIR} || exit -1
+${XMAKE_PROGRAM_FILE} build ${TARGET_NAME} || exit -1
+
+# Copy files to build path.
+XMAKE_BUILD_DIR=${BUILD_DIR}/${PLATFORM_NAME}/${NATIVE_ARCH}/${CONFIGURATION}
+if test -e ${CONFIGURATION_BUILD_DIR}; then
+ rm -r ${CONFIGURATION_BUILD_DIR}/*
+fi
+if test -e ${XMAKE_BUILD_DIR}; then
+ cp -r ${XMAKE_BUILD_DIR}/* ${CONFIGURATION_BUILD_DIR}
+fi
+]])
+ obj.shellScript = table.concat(shellscript, "\n")
+ local uuid = xcinfo:gen_uuid()
+ xcinfo.sections.PBXShellScriptBuildPhase = xcinfo.sections.PBXShellScriptBuildPhase or {}
+ xcinfo.sections.PBXShellScriptBuildPhase[uuid] = obj
+ return uuid
+end
+
+function _add_target_files(xcinfo, group, files)
+ for _, v in table.orderpairs(files) do
+ local file_info = {}
+ file_info.name = path.filename(v)
+ file_info.path = path.join(project.directory(), v)
+ file_info.sourceTree = "\"<absolute>\""
+ local ext = path.extension(v)
+ if ext == ".h" then
+ file_info.lastKnownFileType = "sourcecode.c.h"
+ elseif ext == ".c" then
+ file_info.lastKnownFileType = "sourcecode.c.c"
+ elseif ext == ".m" then
+ file_info.lastKnownFileType = "sourcecode.c.objc"
+ elseif ext == ".hpp" then
+ file_info.lastKnownFileType = "sourcecode.cpp.h"
+ elseif ext == ".cpp" then
+ file_info.lastKnownFileType = "sourcecode.cpp.cpp"
+ elseif ext == ".mm" then
+ file_info.lastKnownFileType = "sourcecode.cpp.objcpp"
+ elseif ext == ".plist" then
+ file_info.lastKnownFileType = "text.plist"
+ end
+ table.insert(group.children, _add_PBXFileReference(xcinfo, file_info))
+ end
+end
+
+function _add_PBXNativeTarget(xcinfo, target_name, target)
+ local obj = {}
+ obj.name = target_name
+ obj.productName = target_name
+ local rules = target:rules()
+ local is_app_bundle = false
+ if rules["xcode.application"] ~= nil then
+ is_app_bundle = true
+ end
+ -- Add product file.
+ local product_file = {}
+ if target:kind() == "static" then
+ product_file.explicitFileType = "com.apple.product-type.library.static"
+ elseif target:kind() == "shared" then
+ product_file.explicitFileType = "com.apple.product-type.library.dynamic"
+ elseif target:kind() == "binary" then
+ if is_app_bundle then
+ product_file.explicitFileType = "wrapper.application"
+ else
+ product_file.explicitFileType = "com.apple.product-type.tool"
+ end
+ end
+ if is_app_bundle then
+ product_file.name = target:filename() .. ".app"
+ else
+ product_file.name = target:filename()
+ end
+ product_file.path = product_file.name
+ product_file.sourceTree = "BUILT_PRODUCTS_DIR"
+ product_file.includeInIndex = 0
+ obj.productReference = _add_PBXFileReference(xcinfo, product_file)
+ if is_app_bundle then
+ obj.productType = "com.apple.product-type.application"
+ else
+ obj.productType = product_file.explicitFileType
+ end
+ -- Add product file to product group.
+ local project_obj = xcinfo.sections.PBXProject[xcinfo.root_object]
+ local product_group = xcinfo.sections.PBXGroup[project_obj.productRefGroup]
+ table.insert(product_group.children, obj.productReference)
+
+ -- Add files.
+ local headerfiles = target:headerfiles()
+ local sourcefiles = target:sourcefiles()
+ obj.headerFileGroup = _add_PBXGroup(xcinfo, "Header Files", "<group>")
+ obj.sourceFileGroup = _add_PBXGroup(xcinfo, "Source Files", "<group>")
+ local header_group = xcinfo.sections.PBXGroup[obj.headerFileGroup]
+ local source_group = xcinfo.sections.PBXGroup[obj.sourceFileGroup]
+ _add_target_files(xcinfo, header_group, headerfiles)
+ _add_target_files(xcinfo, source_group, sourcefiles)
+ obj.mainGroup = _add_PBXGroup(xcinfo, obj.productName, "<group>")
+ local main_group = xcinfo.sections.PBXGroup[obj.mainGroup]
+ table.insert(main_group.children, obj.headerFileGroup)
+ table.insert(main_group.children, obj.sourceFileGroup)
+ -- Add configuration list for target.
+ obj.buildConfigurationList = _add_XCConfigurationList(xcinfo, target)
+ -- Add build phases.
+ obj.buildPhases = {}
+ table.insert(obj.buildPhases, _add_PBXShellScriptBuildPhase(xcinfo, target))
+ local uuid = xcinfo:gen_uuid()
+ xcinfo.sections.PBXNativeTarget = xcinfo.sections.PBXNativeTarget or {}
+ xcinfo.sections.PBXNativeTarget[uuid] = obj
+ return uuid
+end
+
+function main(outputdir)
+ local xcinfo = {}
+
+ xcinfo.project_dir = outputdir
+ xcinfo.project_bundle = (project.name() or path.filename(project.directory())) .. ".xcodeproj"
+ xcinfo.project_dir_uuid = string.upper(hash.strhash32(xcinfo.project_dir))
+ xcinfo.project_bundle_uuid = string.upper(hash.strhash32(xcinfo.project_bundle))
+ xcinfo.uuid_counter = 0
+ xcinfo.gen_uuid = function(self)
+ local counter = self.uuid_counter
+ self.uuid_counter = self.uuid_counter + 1
+ return self.project_dir_uuid .. self.project_bundle_uuid .. string.format("%08X", counter)
+ end
+
+ -- Used to collect Xcode nodes.
+ -- nodes are grouped by their types. For example, all PBXFileReference
+ -- nodes will be in xcinfo.sections.PBXFileReference, indexed by their UUIDs.
+ xcinfo.sections = {}
+
+ -- Add project node
+ local sections = xcinfo.sections
+ sections.PBXProject = {}
+ local project_uuid = xcinfo:gen_uuid()
+ xcinfo.root_object = project_uuid
+ sections.PBXProject[project_uuid] = {}
+ local project_obj = sections.PBXProject[project_uuid]
+
+ -- collect buildConfigurationList
+ project_obj.buildConfigurationList = _add_XCConfigurationList(xcinfo)
+
+ -- collect main group
+ project_obj.mainGroup = _add_PBXGroup(xcinfo, nil, "<group>")
+ local main_group = xcinfo.sections.PBXGroup[project_obj.mainGroup]
+
+ -- collect product ref group
+ project_obj.productRefGroup = _add_PBXGroup(xcinfo, "Products", "<group>");
+
+ -- collect targets.
+ project_obj.targets = {}
+ for target_name, target in table.orderpairs(project.targets()) do
+ local target = _add_PBXNativeTarget(xcinfo, target_name, target)
+ table.insert(project_obj.targets, target)
+ local target_obj = xcinfo.sections.PBXNativeTarget[target]
+ table.insert(main_group.children, target_obj.mainGroup)
+ end
+ table.insert(main_group.children, project_obj.productRefGroup)
+
+ return xcinfo
+end
diff --git a/xmake/plugins/project/xcode/pbxproj.lua b/xmake/plugins/project/xcode/pbxproj.lua
new file mode 100644
index 000000000..ef2d73abf
--- /dev/null
+++ b/xmake/plugins/project/xcode/pbxproj.lua
@@ -0,0 +1,271 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author JXMaster
+-- @file pbxproj.lua
+--
+
+-- imports
+import("core.project.config")
+import("core.project.project")
+
+function _write_file_if_needed(file, content)
+ if os.isfile(file) and io.readfile(file) == content then
+ dprint("skipped file %s since the file has the same content", path.relative(file))
+ return
+ end
+ -- we need utf8 with bom encoding for unicode
+ -- @see https://github.com/xmake-io/xmake/issues/1689
+ io.writefile(file, content, {encoding = "utf8"})
+end
+
+function _write_section_PBXFileReference(info, lines)
+ table.insert(lines, "/* Begin PBXFileReference section */")
+ for uuid, obj in table.orderpairs(info.sections.PBXFileReference) do
+ table.insert(lines, "\t\t" .. uuid .. " = {")
+ table.insert(lines, "\t\t\tisa = PBXFileReference;")
+ if obj.explicitFileType then
+ table.insert(lines, "\t\t\texplicitFileType = \"" .. obj.explicitFileType .. "\";")
+ end
+ if obj.lastKnownFileType then
+ table.insert(lines, "\t\t\tlastKnownFileType = \"" .. obj.lastKnownFileType .. "\";")
+ end
+ if obj.includeInIndex then
+ table.insert(lines, "\t\t\tincludeInIndex = " .. obj.includeInIndex .. ";")
+ end
+ if obj.name then
+ table.insert(lines, "\t\t\tname = \"" .. obj.name .. "\";")
+ end
+ if obj.path then
+ table.insert(lines, "\t\t\tpath = \"" .. obj.path .. "\";")
+ end
+ if obj.sourceTree then
+ table.insert(lines, "\t\t\tsourceTree = " .. obj.sourceTree .. ";")
+ end
+ table.insert(lines, "\t\t};")
+ end
+ table.insert(lines, "/* End PBXFileReference section */")
+end
+
+function _write_section_PBXGroup(info, lines)
+ table.insert(lines, "/* Begin PBXGroup section */")
+ for uuid, obj in table.orderpairs(info.sections.PBXGroup) do
+ table.insert(lines, "\t\t" .. uuid .. " = {")
+ table.insert(lines, "\t\t\tisa = PBXGroup;")
+ if obj.name then
+ table.insert(lines, "\t\t\tname = \"" .. obj.name .. "\";")
+ end
+ table.insert(lines, "\t\t\tchildren = (")
+ for _, child in ipairs(obj.children) do
+ local child_obj = info.sections.PBXFileReference[child]
+ if child_obj == nil then
+ child_obj = info.sections.PBXGroup[child]
+ end
+ local child_name
+ if child_obj then
+ child_name = child_obj.name
+ end
+ if child_name == nil then
+ child_name = ""
+ end
+ table.insert(lines, "\t\t\t\t" .. child .. " /* " .. child_name .. " */,")
+ end
+ table.insert(lines, "\t\t\t);")
+ table.insert(lines, "\t\t\tsourceTree = \"" .. obj.sourceTree .. "\";")
+ table.insert(lines, "\t\t};")
+ end
+ table.insert(lines, "/* End PBXGroup section */")
+end
+
+function _write_section_PBXNativeTarget(info, lines)
+ table.insert(lines, "/* Begin PBXNativeTarget section */")
+ for uuid, obj in table.orderpairs(info.sections.PBXNativeTarget) do
+ table.insert(lines, "\t\t" .. uuid .. " /* " .. obj.name .. " */ = {")
+ table.insert(lines, "\t\t\tisa = PBXNativeTarget;")
+ table.insert(lines, "\t\t\tbuildConfigurationList = " .. obj.buildConfigurationList .. " /* Build configuration list for PBXNativeTarget \"" .. obj.name .. "\" */;")
+ table.insert(lines, "\t\t\tbuildPhases = (")
+ for _, build_phase_uuid in ipairs(obj.buildPhases) do
+ table.insert(lines, "\t\t\t\t" .. build_phase_uuid .. ",")
+ end
+ table.insert(lines, "\t\t\t);")
+ table.insert(lines, "\t\t\tbuildRules = (")
+ table.insert(lines, "\t\t\t);")
+ table.insert(lines, "\t\t\tdependencies = (")
+ table.insert(lines, "\t\t\t);")
+ table.insert(lines, "\t\t\tname = " .. obj.name .. ";")
+ table.insert(lines, "\t\t\tpackageProductDependencies = (")
+ table.insert(lines, "\t\t\t);")
+ table.insert(lines, "\t\t\tproductName = " .. obj.productName .. ";")
+ local product_reference_name
+ local product_reference_obj = info.sections.PBXFileReference[obj.productReference]
+ if product_reference_obj then
+ product_reference_name = product_reference_obj.name
+ end
+ if product_reference_name == nil then
+ product_reference_name = ""
+ end
+ table.insert(lines, "\t\t\tproductReference = " .. obj.productReference .. " /* " .. product_reference_name .. " */;")
+ table.insert(lines, "\t\t\tproductType = " .. obj.productType .. ";")
+ table.insert(lines, "\t\t};")
+ end
+ table.insert(lines, "/* End PBXNativeTarget section */")
+end
+
+function _write_section_PBXProject(info, lines)
+ table.insert(lines, "/* Begin PBXProject section */")
+ for uuid, obj in table.orderpairs(info.sections.PBXProject) do
+ table.insert(lines, "\t\t" .. uuid .. " /* Project object */ = {")
+ table.insert(lines, "\t\t\tisa = PBXProject;")
+ table.insert(lines, [[
+ attributes = {
+ BuildIndependentTargetsInParallel = 1;
+ };]])
+ table.insert(lines, "\t\t\tbuildConfigurationList = " .. obj.buildConfigurationList .. " /* Build configuration list for PBXProject */;")
+ table.insert(lines, [[
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );]])
+ table.insert(lines, "mainGroup = " .. obj.mainGroup .. ";")
+ table.insert(lines, [[
+ minimizedProjectReferenceProxies = 1;
+ preferredProjectObjectVersion = 77;]])
+ table.insert(lines, "productRefGroup = " .. obj.productRefGroup .. ";")
+ table.insert(lines, [[
+ projectDirPath = "";
+ projectRoot = "";]])
+ table.insert(lines, "\t\t\ttargets = (")
+ for _, target_uuid in ipairs(obj.targets) do
+ table.insert(lines, "\t\t\t\t" .. target_uuid .. " /* " .. info.sections.PBXNativeTarget[target_uuid].name .. " */,")
+ end
+ table.insert(lines, "\t\t\t);")
+ table.insert(lines, "\t\t};")
+ end
+ table.insert(lines, "/* End PBXProject section */")
+end
+
+function _write_section_PBXShellScriptBuildPhase(info, lines)
+ table.insert(lines, "/* Begin PBXShellScriptBuildPhase section */")
+ for uuid, obj in table.orderpairs(info.sections.PBXShellScriptBuildPhase) do
+ table.insert(lines, "\t\t" .. uuid .. " /* Run Xmake Build Command */ = {")
+ table.insert(lines, [[
+ isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ );
+ name = "Xmake Build";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "]] .. obj.shellScript .. "\";")
+ table.insert(lines, "\t\t};")
+ end
+ table.insert(lines, "/* End PBXShellScriptBuildPhase section */")
+end
+
+function _write_section_XCBuildConfiguration(info, lines)
+ table.insert(lines, "/* Begin XCBuildConfiguration section */")
+ for uuid, obj in table.orderpairs(info.sections.XCBuildConfiguration) do
+ table.insert(lines, "\t\t" .. uuid .. " /* " .. obj.name .. " */ = {")
+ table.insert(lines, [[
+ isa = XCBuildConfiguration;
+ buildSettings = {]])
+ for k, v in pairs(obj.buildSettings) do
+ local string_value = ""
+ if v == true then
+ string_value = "YES"
+ elseif v == false then
+ string_value = "NO"
+ elseif type(v) == "string" then
+ string_value = v
+ elseif type(v) == "number" then
+ string_value = tostring(v)
+ end
+ table.insert(lines, "\t\t\t\t" .. k .. " = " .. string_value .. ";")
+ end
+ table.insert(lines, [[
+ };
+ name = ]] .. obj.name .. ";")
+ table.insert(lines, "\t\t};")
+ end
+ table.insert(lines, "/* End XCBuildConfiguration section */")
+end
+
+function _write_section_XCConfigurationList(info, lines)
+ table.insert(lines, "/* Begin XCConfigurationList section */")
+ for uuid, obj in table.orderpairs(info.sections.XCConfigurationList) do
+ table.insert(lines, "\t\t" .. uuid .. " = {")
+ table.insert(lines, [[
+ isa = XCConfigurationList;
+ buildConfigurations = (]])
+ for _, build_config in ipairs(obj.buildConfigurations) do
+ table.insert(lines, "\t\t\t\t" .. build_config .. " /* " .. info.sections.XCBuildConfiguration[build_config].name .. " */,")
+ end
+ table.insert(lines, [[
+ );
+ defaultConfigurationIsVisible = 0;]])
+ table.insert(lines, "\t\t};")
+ end
+ table.insert(lines, "/* End XCConfigurationList section */")
+end
+
+local write_section_funcs = {
+ _write_section_PBXFileReference,
+ _write_section_PBXGroup,
+ _write_section_PBXNativeTarget,
+ _write_section_PBXProject,
+ _write_section_PBXShellScriptBuildPhase,
+ _write_section_XCBuildConfiguration,
+ _write_section_XCConfigurationList
+}
+
+function _write_pbxproj(info)
+ local lines = {}
+ table.insert(lines, [[// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 77;
+ objects = {
+]])
+ -- write sections.
+ for _, write_section in ipairs(write_section_funcs) do
+ write_section(info, lines)
+ end
+
+ table.insert(lines,
+[[ };
+ rootObject = ]] .. info.root_object .. [[ /* Project object */;
+}]])
+ return table.concat(lines, "\n") .. "\n"
+end
+
+function main(info)
+ local content = _write_pbxproj(info)
+ local file_name = path.join(info.project_dir, info.project_bundle, "project.pbxproj")
+ _write_file_if_needed(file_name, content)
+end
diff --git a/xmake/plugins/project/xcode/xcodeproj.lua b/xmake/plugins/project/xcode/xcodeproj.lua
index 15ba420f8..6f9e104e7 100644
--- a/xmake/plugins/project/xcode/xcodeproj.lua
+++ b/xmake/plugins/project/xcode/xcodeproj.lua
@@ -14,32 +14,25 @@
--
-- Copyright (C) 2015-present, TBOOX Open Source Group.
--
--- @author ruki
+-- @author JXMaster
-- @file xcodeproj.lua
--
-- imports
-import(".cmake.cmakelists")
-import("lib.detect.find_tool")
+import("get_xcode_info")
+import("pbxproj")
--- TODO maybe we need to implement it by myself, do not use cmake
function make(outputdir)
- -- check
- assert(is_plat(os.host()), "only support host platform now!")
+ -- collect xcode info.
+ -- see get_xcode_info.lua file for detailed description
+ -- of the returned info table.
+ local info = get_xcode_info(outputdir)
- -- find cmake
- local cmake = assert(find_tool("cmake"), "we need cmake to generate xcode project!")
+ -- create xcode dir.
+ local project_bundle = path.join(info.project_dir, info.project_bundle)
+ os.mkdir(project_bundle)
- -- get the cmakelists file
- local cmakefile = path.join(outputdir, "CMakeLists.txt")
- if not os.isfile(cmakefile) then
- cmakelists.make(outputdir)
- end
- assert(os.isfile(cmakefile), "CMakeLists.txt not found!")
-
- -- generate xcode project
- local oldir = os.cd(os.projectdir())
- os.vrunv(cmake.program, {"-G", "Xcode", cmakefile})
- os.cd(oldir)
+ -- create .pbxproj file.
+ pbxproj(info)
end