A python module to manipulate XCode projects

Overview
GitHub Workflow Status (branch) Codacy branch coverage Codacy grade PyPI PyPI - Downloads PyPI - License

pbxproj

This module can read, modify, and write a .pbxproj file from an Xcode 4+ projects. The file is usually called project.pbxproj and can be found inside the .xcodeproj bundle. Because some task cannot be done by clicking on an UI or opening Xcode to do it for you, this python module lets you automate the modification process.

How to use it

The typical tasks with an Xcode project are adding files to the project and setting some standard compilation flags. It can be achieved with a simple snippet like this:

from pbxproj import XcodeProject
# open the project
project = XcodeProject.load('myapp.xcodeproj/project.pbxproj')

# add a file to it, force=false to not add it if it's already in the project
project.add_file('MyClass.swift', force=False)

# set a Other Linker Flags
project.add_other_ldflags('-ObjC')

# save the project, otherwise your changes won't be picked up by Xcode
project.save()

That's it. More details about available API's visit the wiki.

Installation

For installation instructions visit the wiki

CLI

For instructions and commands available visit the wiki

Documentation

For general documentation, visit the wiki. For technical documentation, the public functions are documented and contains details about what is expected.

Reporting bugs

Did you find a bug? Too bad, but we want to help you, we need you to:

  • Check you are running python3 and installed the package using the pip3 command.
  • Provide as many details about the error you are having.
  • If possible provide a sample project.pbxproj to reproduce the steps
  • If possible, try the sequence of steps on Xcode and provide the project.pbxproj generated by Xcode.

We cannot help you if your issue is a title: "it does not work". Or if there is no sequence of steps to reproduce the error. Those kind of issues will be ignored or closed automatically.

Contributing

Do you want to fix an issue yourself? Great! some house rules:

  • Provide a description of what problem you are solving, what case was not being taking into account
  • Provide unit tests for the case you have fixed. Pull request without unit test or PRs that decrease the coverage will not be approved until this changes.
  • Adhere to the coding style and conventions of the project, for instance, target_name is used to specify the target across all functions that use this parameter. Changes will be requested on PRs that don't follow this.
  • Write descriptive commit messages.

License

This project is licensed using MIT license.

Comments
  • remove_group does not seem to work

    remove_group does not seem to work

    project.remove_group_by_name("Hola") Does not remove the group "Hola".

    And the following code creates the group "Hola" and leaves it present in the project. Shouldn't it remove it too?

    group = project.get_or_create_group("Hola")
    project.remove_group(group)
    project.save()
    
    bug 
    opened by da-mian 20
  • How can I get the project target

    How can I get the project target

    How can I get the project target. because when I use this script to add files to Pods project, the code seems not work, But if I drag the folder to Pods project, it can works. This is my code

    8dfa3268-ab1d-4e64-ad0f-d7f0904b6d2c

    project = XcodeProject.Load(pbxproj_file_path)
    project.remove_group_by_name('UIKit', True)
    project.save()
    
    if production:
        main_group = project.get_groups_by_name('DKNightVersion')[0]
        uikit_group = project.get_or_create_group('UIKit', None, main_group)
    else:
        main_group = project.get_or_create_group('DKNightVersion')
        pod_group = project.get_or_create_group('Pod', None, main_group)
        class_group = project.get_or_create_group('Classes', None, pod_group)
        uikit_group = project.get_or_create_group('UIKit', None, class_group)
    
    groups = json.load(open(json_file_path))
    
    for group, files in groups.iteritems():
        new_group = project.get_or_create_group(group, None, uikit_group)
        for f in files:
            project.add_file(f, new_group)
    
    project.save()
    

    39d31f05-c374-42fc-80ce-60fe593197eb

    opened by draveness 16
  • Unity 5 Xcode project and Library Linking

    Unity 5 Xcode project and Library Linking

    I've noticed that for the Xcode (v6.2) projects generated by Unity 5 (v5.0.0f4) add_file_if_doesnt_exist() no longer appears to be adding some frameworks to the list of libraries linked with the binary under the Build Phases tab of the Xcode project. The references to the frameworks to be added exist under the PBXFileReference section of the project.pbxproj but they don't exist under the PBXBuildFile section. I've seen this when adding the AdSupport.framework:

    project_path = '<project_path>/Unity-iPhone.xcodeproj/project.pbxproj'
    framework_path = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/AdSupport.framework'
    framework_group = project.get_or_create_group('Frameworks')
    project = XcodeProject.Load(project_path)
    project.add_file_if_doesnt_exist(framework_path, tree='SDKROOT', parent=framework_group )
    

    The create_build_files argument defaults to True and the weak argument defaults to False.

    I think what's happening is that only the objects under the PBXFileReference section of the project.pbxproj are being checked for the existence of the framework in the project where it should instead be checking both the reference and build sections. I believe that add_file_if_doesnt_exist() should work like the following:

    if (framework exists in PBXFileReference) {
        if (create_build_files == true) {
            if (!framework exists in PBXBuildFile) {
                create build files entry in project.pbxproj for the framework
            }
        }
        return []  // not sure about this in the case that the build files entry is added
    }
    return result from calling add_file()       
    
    bug 
    opened by jp-at-work 16
  • Enhancement Request: cli show/list content of pbxproj file

    Enhancement Request: cli show/list content of pbxproj file

    Hi,

    I was looking for a way to print out the content of a pbxproj file in a human readable format and came across this project. It would be awesome if I could use this project to print out information about build targets like the src files required, flags, etc. I don't believe this is currently supported by the cli program or the library.

    Thanks!

    enhancement 
    opened by kwhat 12
  • 'PBXBuildFile' object has no attribute 'fileRef'

    'PBXBuildFile' object has no attribute 'fileRef'

    I have the problem, if the module is adding flags and the project.pbxproj has errors like

    9D1494321F73F8AB0078CFF8 /* (null) in Sources */ = {isa = PBXBuildFile; };

    i'm getting

    'PBXBuildFile' object has no attribute 'fileRef'

    Is it possible to ignore these entries, or to remove this entries automatically from the file?

    enhancement 
    opened by erdnussflips 9
  • Is it possible to add a file to multiple targets?

    Is it possible to add a file to multiple targets?

    I'm developing a script to generate boilerplate code to my project. I have two targets (ag: Debug and Production) and I need to add files to these ones only. Right now we have the option to specify one target or add to all. Is it possible change the target to accept an array?

    enhancement 
    opened by leoneparise 8
  • [FEAT] Support XML format of pbxproj

    [FEAT] Support XML format of pbxproj

    Hello there! The issue arises in the XCode projects generated via openFrameworks (https://github.com/openframeworks/openFrameworks) projectGenerator that generates projects in XML format that it creates by modifying this template: https://github.com/openframeworks/openFrameworks/blob/b674f7ec1f41d8f0fcfea86e3d3d3df3e9bdcf36/scripts/templates/osx/emptyExample.xcodeproj/project.pbxproj

    If you open a project in XCode and then save it with some minimal change, it'll open, but without it it'll crash, apparently expecting JSON (?). Would be glad if anyone has anything to tell on this! Thanks.

    enhancement 
    opened by yeswecan 7
  • [BUG] add_folder always resolves paths as absolute

    [BUG] add_folder always resolves paths as absolute

    Describe the bug add_folder method in class ProjectFiles add absolute path to PBXGroup.

    I used the new script to provide a method like the old "apply_mods" , I found the add_folder method in class ProjectFiles add wrong path to PBXGroup, which expect the relpath,but absolute path wrote.

    System information

    1. pbxproj version used: 2.11
    2. python version used: python 3.8
    3. Xcode version used: 11.2.1
    bug not-enough-info 
    opened by u8-xiaohei 7
  • AttributeError: 'NoneType' object has no attribute 'isa'

    AttributeError: 'NoneType' object has no attribute 'isa'

    I'm using mod-pbxproj to manipulate an Xcode project file generated by Unity. In the script it removes a file from the project then adds some others, but it's raising the exception when it tries to add the first of those additional files. If the deletion is skipped then it works fine. It's quite a complicated project file, but I've reduced it down to a smaller test case and worked out that the presence of a file assigned to the "Unity-iPhone Tests" target triggers this problem - if that's removed from the project file then the script works.

    I've attached a tarball containing two example project files (one exhibiting this behaviour and one that doesn't) and a test script demonstrating the issue:

    bug.tar.gz

    bug answered 
    opened by markshep 7
  • Variant groups

    Variant groups

    This is an amended version of the variant groups branch. I'm not sure if this is the best way to submit changes.

    While testing it, I noticed a few issues which are fixed in this pull request:

    • attempting to add a PBXVariantGroup as a child of a PBXGroup gives an exception as it isn't one of the expected types.
    • adding multiple localisation files adds duplicate PBXBuildFiles for the variant group, which causes builds to fail as Xcode tries to copy the same file repeatedly.

    With these two fixes, I can confirm that the variant groups work as expected for our use case (localising the app icon name by localising the Info.plist file).

    But...

    One thing I did find is that the system will automatically add the variants to any existing variant group that exists with the same name - even when that variant group is for a different target. For example, our project has a 'tests' target that contains a InfoPlist.strings variant group that's stored in a separate folder. With the system as it is, any InfoPlist.strings files we add to the project get added to this variant group - even though we want to add them for our main target. This code in question is this:

    for variant in self.objects.get_objects_in_section(u'PBXVariantGroup'):
        if variant.name == expected_name:
    

    I don't entirely understand how all of this works, but to me this seems like the incorrect - or at least, unexpected behaviour. I believe you should be able to have multiple variant groups for the same file. I've worked around this by removing the exiting variant group.

    I also noticed that adding a strings file that's outside the project causes an exception on this line in ProjectFiles.py - I have't fixed this:

    library_path = os.path.join(u'$(SRCROOT)', os.path.split(file_ref.path)[0])

    AttributeError: 'PBXVariantGroup' object has no attribute 'path'

    opened by eAi 7
  • [BUG] Error in openstep_parser: string index out of range

    [BUG] Error in openstep_parser: string index out of range

    Describe the bug I'm trying to use the default sample code on the homepage just to check how mod-pbxproj works, however I stumbled upon this error:

    Traceback (most recent call last): File "xcode_python_setup.py", line 3, in project = XcodeProject.load('../myapp/myapp.xcodeproj/project.pbxproj') File "/Library/Python/2.7/site-packages/pbxproj/XcodeProject.py", line 90, in load tree = osp.OpenStepDecoder.ParseFromFile(open(path, 'r')) File "build/bdist.macosx-10.15-x86_64/egg/openstep_parser/openstep_parser.py", line 42, in ParseFromFile File "build/bdist.macosx-10.15-x86_64/egg/openstep_parser/openstep_parser.py", line 46, in ParseFromString File "build/bdist.macosx-10.15-x86_64/egg/openstep_parser/openstep_parser.py", line 51, in _parse IndexError: string index out of range

    System information

    1. pbxproj version used: 3.2.0
    2. python version used: 3.6.12
    3. Xcode version used: 12.0 (12A7209)

    To Reproduce Steps to reproduce the behavior:

    1. Created a .py file with this code

    from pbxproj import XcodeProject project = XcodeProject.load('../myapp/myapp.xcodeproj/project.pbxproj') project.save()

    1. On the terminal, cd to a related folder and ran: "python xcode_python_setup.py"
    2. See error

    Expected behavior Just expected to see a clear python command without any errors.

    bug invalid 
    opened by VitorMMOliveira 6
  • [BUG] Update multible Flags

    [BUG] Update multible Flags

    Trying to update ALL IPHONEOS_DEPLOYMENT_TARGET from 9.0 to 12.0

    System information pbxproj version used: pbxproj 3.4.0 python version used: Python 3.10.6 Xcode version used: xCode Version 14.0.1 (14A400)

    To Reproduce Installed pbxproj

    pip3 install pbxproj

    created "update_pbxproj.py"

    from pbxproj import XcodeProject
    # open
    project = XcodeProject.load('ios/Runner.xcodeproj/project.pbxproj')
    
    # set variables
    project.set_flags('IPHONEOS_DEPLOYMENT_TARGET', '12.0')
    
    # save
    project.save()
    

    run script

    python3 update_pbxproj.py
    

    after open then ios/Runner.xcodeproj/project.pbxproj still have IPHONEOS_DEPLOYMENT_TARGET = 9.0;

    Expected behavior Every flags IPHONEOS_DEPLOYMENT_TARGET = 12.0;

    Screenshots

    bug not-enough-info 
    opened by mklarsen 2
  • update flag

    update flag

    is there a way to update existing flag ?

    I want to update CODE_SIGN_STYLE flag to manual and code sign feature is not adding manual at all places in project file.

    enhancement 
    opened by sikandernoori 0
  • Moving an existing group to another group

    Moving an existing group to another group

    Hello,

    Is it possible to use mod-pbxproj to move one group inside another group? For example:

    > Group A
      - aGroupAFile.mm
    > Group B
    

    to

    > Group B
      > Group A
        - aGroupAFile.mm
    

    Couldn't find any info online. I'd greatly appreciate any pointers.

    Thanks!

    question not-enough-info 
    opened by bibhas 2
  • [FEAT] How to add sub-project into current project, but sub-project has two kinds of target type

    [FEAT] How to add sub-project into current project, but sub-project has two kinds of target type

    Is your feature request related to a problem? Please describe. There is a framework xcode project B, which has two different kinds of platform targets, iOS and MacOS. After I added this framework project B into another app xcode project A as a dependency library. You will find out that, the list of the Build Phases -> Link Binary With Libraries, has both two targets which belong xcode proj B, one is for iOS, another is for MacOS. But the aim of this action is to add one compatible framework into current project as a dependency library, and this behavior should be ensure the dependency library must match the major app's target platform type, like iOS only, or MacOS only.

    I think the method below should be refactored.

    def add_project(self, path, parent=None, tree=TreeType.GROUP, target_name=None, force=True, file_options=FileOptions())
    
    enhancement 
    opened by imeteora 0
  • Missing support for easily adding swift packages to project

    Missing support for easily adding swift packages to project

    I have not found an api to perform all steps required to add a swift package to project. When a swift package is added to an xcode project, it is modified as follows:

    • a single entry is added to XCRemoteSwiftPackageReference section
    • a single entry is added to PBXProject section
    • an entry for each package product is added to XCSwiftPackageProductDependency section
    • an entry for each package product is added to PBXFrameworksBuildPhase section, for given target
    • an entry for each package product is added to PBXBuildFile section (the entry has productRef attribute in place of fileRef), for given target
    • an entry for each package product is added to PBXNativeTarget section, for given target

    As a side note, a file *.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved is also created, but I think this is out of scope.

    I have modified mod-pbxproj and added an add_package function that performs the steps stated above. It can be used as follows:

    from pbxproj import XcodeProject
        
    # open the project
    project = XcodeProject.load('DummyProject/DummyProject.xcodeproj/project.pbxproj')
    
    project.add_package('https://github.com/SnapKit/SnapKit.git', 'SnapKit', 'DummyProject (iOS)', {
        "kind": "upToNextMajorVersion",
        "minimumVersion": "5.0.1"
    })
    project.add_package('https://github.com/openid/AppAuth-iOS.git', ['AppAuth','AppAuthCore'], 'DummyProject (iOS)', {
        "kind": "upToNextMajorVersion",
        "minimumVersion": "1.4.0"
    })
    
    project.save()
    

    You can take a look the patch https://github.com/kronenthaler/mod-pbxproj/compare/master...garrik:develop

    This code just suits my needs but if you find it a viable solution, I would be happy to add tests, refactor, accept suggestion for improvement and contribute a pull request. Regards

    enhancement 
    opened by garrik 1
  • [FEAT] Add support for Creating/Deleting On Demand Resource Tags

    [FEAT] Add support for Creating/Deleting On Demand Resource Tags

    Is your feature request related to a problem? Please describe. On Demand Resource tags can only be manipulated through Xcode's project settings GUI. This is very annoying when you have processes that install new resources into your application, but then need to manually tag their resources

    Describe the solution you'd like

    • Asset Tags are defined in the KnownAssetTags object in the 
 /* Begin PBXProject section */ It seems it would be fairly easy to mutate this list.
    • Additionally, each file references it's created ODR tag at the end of it's resource declaration 6A73EA5125C074F800669235 /* 265 in Resources */ = {isa = PBXBuildFile; fileRef = 6A73EA2725C074F000669235 /* 265 */; settings = {ASSET_TAGS = (265, ); }; };

    Describe alternatives you've considered Doesn't seem to be any support for this in the ecosystem, seems people are mutating their pbx files directly via shell scripts. Would be nice to add to this very nice library :)

    enhancement answered 
    opened by ignkarman 3
Releases(3.2.3)
Owner
Ignacio Calderon
Ignacio Calderon
HeadHunter parser

HHparser Description Program for finding work at HeadHunter service Features Find job Parse vacancies Dependencies python pip geckodriver firefox Inst

memphisboy 1 Oct 30, 2021
general-phylomoji: a phylogenetic tree of emoji

general-phylomoji: a phylogenetic tree of emoji

2 Dec 11, 2021
A script to parse and display buy_tag and sell_reason for freqtrade backtesting trades

freqtrade-buyreasons A script to parse and display buy_tag and sell_reason for freqtrade backtesting trades Usage Copy the buy_reasons.py script into

Robert Davey 31 Jan 01, 2023
A python package containing all the basic functions and classes for python. From simple addition to advanced file encryption.

A python package containing all the basic functions and classes for python. From simple addition to advanced file encryption.

PyBash 11 May 22, 2022
NetConfParser is a tool that helps you analyze the rpcs coming and going from a netconf client to a server

NetConfParser is a tool that helps you analyze the rpcs coming and going from a netconf client to a server

Aero 1 Mar 31, 2022
Brainfuck rollup scaling experiment for fun

Optimistic Brainfuck Ever wanted to run Brainfuck on ethereum? Don't ask, now you can! And at a fraction of the cost, thanks to optimistic rollup tech

Diederik Loerakker 48 Dec 28, 2022
Various importers for cointracker

cointracker_importers Various importers for cointracker To convert nexo .csv format to cointracker .csv format: Download nexo csv file. run python Nex

Stefanos Anastasiou 9 Oct 24, 2022
VerSign: Easy Signature Verification in Python

VerSign: Easy Signature Verification in Python versign is a small Python package which can be used to perform verification of offline signatures. It a

Muhammad Saif Ullah Khan 3 Dec 01, 2022
A library from RCTI+ to handle RabbitMQ tasks (connect, send, receive, etc) in Python.

Introduction A library from RCTI+ to handle RabbitMQ tasks (connect, send, receive, etc) in Python. Requirements Python =3.7.3 Pika ==1.2.0 Aio-pika

Dali Kewara 1 Feb 05, 2022
Find version automatically based on git tags and commit messages.

GIT-CONVENTIONAL-VERSION Find version automatically based on git tags and commit messages. The tool is very specific in its function, so it is very fl

0 Nov 07, 2021
Simple tool for creating changelogs

Description Simple utility for quickly generating changelogs, assuming your commits are ordered as they should be. This tool will simply log all lates

2 Jan 05, 2022
Runes - Simple Cookies You Can Extend (similar to Macaroons)

Runes - Simple Cookies You Can Extend (similar to Macaroons) is a paper called "Macaroons: Cookies with Context

Rusty Russell 22 Dec 11, 2022
A simple and easy to use Spam Bot made in Python!

This is a simple spam bot made in python. You can use to to spam anyone with anything on any platform.

7 Sep 08, 2022
An okayish python script to generate a random Euler circuit with given number of vertices and edges.

Euler-Circuit-Test-Case-Generator An okayish python script to generate a random Euler circuit with given number of vertices and edges. Executing the S

Alen Antony 1 Nov 13, 2021
API Rate Limit Decorator

ratelimit APIs are a very common way to interact with web services. As the need to consume data grows, so does the number of API calls necessary to re

Tomas Basham 575 Jan 05, 2023
NFT-Generator is the best way to generate thousands of NFTs quick and easily with Python.

NFT-Generator is the best way to generate thousands of NFTs quick and easily with Python. Just add your files, set your configuration and run the scri

78 Dec 27, 2022
Dill_tils is a package that has my commonly used functions inside it for ease of use.

DilllonB07 Utilities Dill_tils is a package that has my commonly used functions inside it for ease of use. Installation Anyone can use this package by

Dillon Barnes 2 Dec 05, 2021
Program to extract signatures from documents.

Extracting Signatures from Bank Checks Introduction Ahmed et al. [1] suggest a connected components-based method for segmenting signatures in document

Muhammad Saif Ullah Khan 9 Jan 26, 2022
ZX Spectrum Utilities: (zx-spectrum-utils)

Here are a few utility programs that can be used with the zx spectrum. The ZX Spectrum is one of the first home computers from the early 1980s.

Graham Oakes 4 Mar 07, 2022
Creating low-level foundations and abstractions for asynchronous programming in Python.

DIY Async I/O Creating low-level foundations and abstractions for asynchronous programming in Python (i.e., implementing concurrency without using thr

Doc Jones 4 Dec 11, 2021