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
cpp20.py is a Python script to compile C++20 code using modules.

cpp20.py is a Python script to compile C++20 code using modules. It browses the source files to determine their dependencies. Then, it compiles then in order using the correct flags.

Julien VERNAY 6 Aug 26, 2022
JavaScript to Python Translator & JavaScript interpreter written in 100% pure Python🚀

Pure Python JavaScript Translator/Interpreter Everything is done in 100% pure Python so it's extremely easy to install and use. Supports Python 2 & 3.

Piotr Dabkowski 2.1k Dec 30, 2022
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
Simple RGB to HEX game made in python

Simple RGB to HEX game made in python

5 Aug 26, 2022
Python Libraries with functions and constants related to electrical engineering.

ElectricPy Electrical-Engineering-for-Python Python Libraries with functions and constants related to electrical engineering. The functions and consta

Joe Stanley 39 Dec 23, 2022
Delete all of your forked repositories on Github

Fork Purger Delete all of your forked repositories on Github Installation Install using pip: pip install fork-purger Exploration Under construc

Redowan Delowar 29 Dec 17, 2022
EVE-NG tools, A Utility to make operations with EVE-NG more friendly.

EVE-NG tools, A Utility to make operations with EVE-NG more friendly. Also it support different snapshot operations with same style as Libvirt/KVM

Bassem Aly 8 Jan 05, 2023
Python library to decorate and beautify strings

outputformat Python library to decorate and beautify your standard output 💖 Ins

Felipe Delestro Matos 259 Dec 13, 2022
A morse code encoder and decoder utility.

morsedecode A morse code encoder and decoder utility. Installation Install it via pip: pip install morsedecode Alternatively, you can use pipx to run

Tushar Sadhwani 2 Dec 25, 2021
A script copies movie and TV files to your GD drive, or create Hard Link in a seperate dir, in Emby-happy struct.

torcp A script copies movie and TV files to your GD drive, or create Hard Link in a seperate dir, in Emby-happy struct. Usage: python3 torcp.py -h Exa

ccf2012 105 Dec 22, 2022
A python module to validate input.

A python module to validate input.

Matthias 6 Sep 13, 2022
Create a Web Component (a Custom Element) from a python file

wyc Create a Web Component (a Custom Element) from a python file (transpile python code to javascript (es2015)). Features Use python to define your cu

7 Oct 09, 2022
🍰 ConnectMP - An easy and efficient way to share data between Processes in Python.

ConnectMP - Taking Multi-Process Data Sharing to the moon 🚀 Contribute · Community · Documentation 🎫 Introduction : 🍤 ConnectMP is the easiest and

Aiden Ellis 1 Dec 24, 2021
A script to check for common mistakes in LaTeX source files of scientific papers.

LaTeX Paper Linter This script checks for common mistakes in LaTeX source files of scientific papers. Usage python3 paperlint.py file.tex [-i/x inc

Michael Schwarz 12 Nov 16, 2022
ULID implementation for Python

What is this? This is a port of the original JavaScript ULID implementation to Python. A ULID is a universally unique lexicographically sortable ident

Martin Domke 158 Jan 04, 2023
Helper script to bootstrap a Python environment with the tools required to build and install packages.

python-bootstrap Helper script to bootstrap a Python environment with the tools required to build and install packages. Usage $ python -m bootstrap.bu

Filipe Laíns 7 Oct 06, 2022
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
Python program for Linux users to change any url to any domain name they want.

URLMask Python program for Linux users to change a URL to ANY domain. A program than can take any url and mask it to any domain name you like. E.g. ne

2 Jun 20, 2022
Gradually automate your procedures, one step at a time

Gradualist Gradually automate your procedures, one step at a time Inspired by https://blog.danslimmon.com/2019/07/15/ Features Main Features Converts

Ross Jacobs 8 Jul 24, 2022
MicroMIUI - Script to optimize miui and not only

MicroMIUI - Script to optimize miui and not only

Groiznyi-Studio 1 Nov 02, 2021