在命令行 xcodebuild 调用后分发 .app 文件

发布于 2025-01-07 09:17:31 字数 503 浏览 0 评论 0原文

我正在构建/存档我的 Mac 应用程序,以便通过命令行调用(如下)进行分发,并安装了 Xcode 4.3。需要明确的是,在 Xcode 4.3 之前,我没有针对此问题的有效解决方案,因此针对早期 Xcode 版本的建议仍然很有效。调用如下:

/usr/bin/xcodebuild -project "ProjectPath/Project.pbxproj" -scheme "Project" -sdk macosx10.7 archive

它成功运行,并生成一个 .xcarchive 文件,位于我的 ~/Library/Developer/Xcode/Archives/ 文件夹中。获取生成的存档文件的路径的正确方法是什么?我正在寻找一种方法来获取其中包含的 .app 文件的路径,以便我可以分发它。

我查看了 xcodebuild 的 MAN 页面(并在网上进行了大量搜索),但没有找到任何线索。

I'm building/archiving my Mac app for distribution from a command line call (below), with Xcode 4.3 installed. To be clear, I didn't have a working solution for this problem earlier to Xcode 4.3, so advice for earlier Xcode releases could easily still be valid. Here's the call:

/usr/bin/xcodebuild -project "ProjectPath/Project.pbxproj" -scheme "Project" -sdk macosx10.7 archive

This runs successfully, and it generates an .xcarchive file, located in my ~/Library/Developer/Xcode/Archives/<date> folder. What's the proper way to get the path the the archive file generated? I'm looking for a way to get a path to the .app file contained therein, so I can distribute it.

I've looked at the MAN page for xcodebuild (and done copious searching online) and didn't find any clues there.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

永言不败 2025-01-14 09:17:31

有一个更简单的方法,只需指定要归档的archivePath即可:

xcodebuild -archivePath GoTray -scheme GoTray archive

然后您将在当前目录下的GoTray.xcarchive处获得xcarchive文件。

接下来,再次运行 xcodebuild 以从 xcarchive 文件中导出应用程序:

xcodebuild -exportArchive -exportFormat APP -archivePath GoTray.xcarchive -exportPath GoTray

There is an easier way, simply specify the archivePath you want to archive:

xcodebuild -archivePath GoTray -scheme GoTray archive

Then you will get the xcarchive file at GoTray.xcarchive in current directory.

Next, run xcodebuild again to export app from the xcarchive file:

xcodebuild -exportArchive -exportFormat APP -archivePath GoTray.xcarchive -exportPath GoTray
戏蝶舞 2025-01-14 09:17:31

基于此处提供的答案,我想出了一个令人满意的多部分解决方案。这一切的关键是使用 Xcode 在构建过程中创建的环境变量。

首先,我对构建方案的存档阶段进行了后期操作(粘贴到 Xcode 项目的 UI 中)。它调用我编写的 Python 脚本(在下一节中提供),向其传递我想要提取的环境变量的名称以及文本文件的路径:

# Export the archive paths to be used after Archive finishes
"${PROJECT_DIR}/Script/grab_env_vars.py" "${PROJECT_DIR}/build/archive-env.txt"
"ARCHIVE_PATH" "ARCHIVE_PRODUCTS_PATH" "ARCHIVE_DSYMS_PATH"
"INSTALL_PATH" "WRAPPER_NAME"

然后该脚本将它们写入 中的文本文件key = value 对:

import sys
import os

def main(args):
    if len(args) < 2:
        print('No file path passed in to grab_env_vars')
        return

    if len(args) < 3:
        print('No environment variable names passed in to grab_env_vars')

    output_file = args[1]

    output_path = os.path.dirname(output_file)
    if not os.path.exists(output_path):
        os.makedirs(output_path)

    with open(output_file, 'w') as f:
        for i in range(2, len(args)):
            arg_name = args[i]
            arg_value = os.environ[arg_name]
            #print('env {}: {}'.format(arg_name, arg_value))
            f.write('{} = {}\n'.format(arg_name, arg_value))

def get_archive_vars(path):
    return dict((line.strip().split(' = ') for line in file(path)))

if __name__ == '__main__':
    main(sys.argv)

然后,最后,在我的构建脚本(也是 Python)中,我解析出这些值并可以访问存档的路径以及其中的应用程序包:

env_vars = grab_env_vars.get_archive_vars(ENV_FILE)
archive_path = env_vars['ARCHIVE_PRODUCTS_PATH']
install_path = env_vars['INSTALL_PATH'][1:] #Chop off the leading '/' for the join below
wrapper_name = env_vars['WRAPPER_NAME']
archived_app = os.path.join(archive_path, install_path, wrapper_name)

这就是我解决它的方法,并且它应该很容易适应其他脚本环境。这对我的限制是有意义的:我希望项目中的代码尽可能少,与 Bash 相比,我更喜欢 Python 脚本,并且该脚本可以轻松地在其他项目中重用并用于其他目的。

Building on the answer provided here, I came up with a satisfactory multi-part solution. The key to it all, was to use the environment variables Xcode creates during the build.

First, I have a post-action on the Archive phase of my build scheme (pasted into the Xcode project's UI). It calls a Python script I wrote (provided in the next section), passing it the names of the environment variables I want to pull out, and a path to a text file:

# Export the archive paths to be used after Archive finishes
"${PROJECT_DIR}/Script/grab_env_vars.py" "${PROJECT_DIR}/build/archive-env.txt"
"ARCHIVE_PATH" "ARCHIVE_PRODUCTS_PATH" "ARCHIVE_DSYMS_PATH"
"INSTALL_PATH" "WRAPPER_NAME"

That script then writes them to a text file in key = value pairs:

import sys
import os

def main(args):
    if len(args) < 2:
        print('No file path passed in to grab_env_vars')
        return

    if len(args) < 3:
        print('No environment variable names passed in to grab_env_vars')

    output_file = args[1]

    output_path = os.path.dirname(output_file)
    if not os.path.exists(output_path):
        os.makedirs(output_path)

    with open(output_file, 'w') as f:
        for i in range(2, len(args)):
            arg_name = args[i]
            arg_value = os.environ[arg_name]
            #print('env {}: {}'.format(arg_name, arg_value))
            f.write('{} = {}\n'.format(arg_name, arg_value))

def get_archive_vars(path):
    return dict((line.strip().split(' = ') for line in file(path)))

if __name__ == '__main__':
    main(sys.argv)

Then, finally, in my build script (also Python), I parse out those values and can get to the path of the archive, and the app bundle therein:

env_vars = grab_env_vars.get_archive_vars(ENV_FILE)
archive_path = env_vars['ARCHIVE_PRODUCTS_PATH']
install_path = env_vars['INSTALL_PATH'][1:] #Chop off the leading '/' for the join below
wrapper_name = env_vars['WRAPPER_NAME']
archived_app = os.path.join(archive_path, install_path, wrapper_name)

This was the way I solved it, and it should be pretty easily adaptable to other scripting environments. It makes sense with my constraints: I wanted to have as little code as possible in the project, I prefer Python scripting to Bash, and this script is easily reusable in other projects and for other purposes.

陈独秀 2025-01-14 09:17:31

您可以使用一些 shell,获取 Archives 目录中的最新文件夹(或使用当前日期),然后获取该目录中的最新存档。

You could just use a bit of shell, get the most recent folder in the Archives dir (or use the current date), and then get the most recent archive in that directory.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文