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
Pyfunctools is a module that provides functions, methods and classes that help in the creation of projects in python

Pyfunctools Pyfunctools is a module that provides functions, methods and classes that help in the creation of projects in python, bringing functional

Natanael dos Santos Feitosa 5 Dec 22, 2022
A small python library that helps you to generate localization strings for your mobile projects.

LocalizationUtiltiy A small python library that helps you to generate localization strings for your mobile projects. This small script aims to help yo

null 1 Nov 12, 2021
A utility that makes it easy to work with Python projects containing lots of packages, of which you only want to develop some.

Mixed development source packages on top of stable constraints using pip mxdev [mɪks dɛv] is a utility that makes it easy to work with Python projects

BlueDynamics Alliance 6 Jun 8, 2022
Go through a random file in your favourite open source projects!

Random Source Codes Never be bored again! Staring at your screen and just scrolling the great world wide web? Would you rather read through some code

Mridul Seth 1 Nov 3, 2022
Simple python module to get the information regarding battery in python.

Battery Stats A python3 module created for easily reading the current parameters of Battery in realtime. It reads battery stats from /sys/class/power_

Shreyas Ashtamkar 5 Oct 21, 2022
A python module to update the console without flashing.

A python module to update the console without flashing.

Matthias 112 Dec 19, 2022
A python module to validate input.

A python module to validate input.

Matthias 6 Sep 13, 2022
A module for account creation with python

A module for account creation with python

Fayas Noushad 3 Dec 1, 2021
A string extractor module for python

A string extractor module for python

Fayas Noushad 4 Jul 19, 2022
A python module for extract domains

A python module for extract domains

Fayas Noushad 4 Aug 10, 2022
An URL checking python module

An URL checking python module

Fayas Noushad 6 Aug 10, 2022
A multipurpose python module

pysherlock pysherlock is a Python library for dealing with web scraping using images, it's a Python application of the rendertron headless browser API

Sachit 2 Nov 11, 2021
Python module and its web equivalent, to hide text within text by manipulating bits

cacherdutexte.github.io This project contains : Python modules (binary and decimal system 6) with a dedicated tkinter program to use it. A web version

null 2 Sep 4, 2022
A python mathematics module

A python mathematics module

Fayas Noushad 4 Nov 28, 2021
A hashtag from string extract python module

A hashtag from string extract python module

Fayas Noushad 3 Aug 10, 2022
A random cats photos python module

A random cats photos python module

Fayas Noushad 6 Dec 1, 2021
glip is a module for retrieve ip address like local-ip, global-ip, external-ip as string.

gle_ip_info glip is a module for retrieve ip address like local-ip, global-ip, external-ip as string.

Fatin Shadab 3 Nov 21, 2021
Import the module and create an object of the class LocalVariable.

LocalVariable Import the module and create an object of the class LocalVariable. Call the save method with the name and the value of a variable as arg

Sajedur Rahman Fiad 2 Dec 14, 2022
Extends the pyranges module with operations on joined genomic intervals

tiedpyranges Extends the pyranges module with operations on joined genomic intervals (e.g. exons of same transcript) Install with: pip install tiedpyr

Marco Mariotti 4 Aug 5, 2022