SwiftGen / SwiftGenPlugin

SwiftGen plugin for SPM
MIT License
94 stars 62 forks source link

Plugin doesn't work with Xcode 15 #14

Open MaxenceMottard opened 1 year ago

MaxenceMottard commented 1 year ago

I tried to build my project with Xcode 15 and got a new error:

Error Domain=NSCocoaErrorDomain Code=513 "You don’t have permission to save the file “Strings+Generated.swift” in the folder “Generated”." UserInfo={NSFilePath=ticketchain/Supporting Files/Generated/Strings+Generated.swift, NSUnderlyingError=0x6000023308a0 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}

Does anyone know how to fix it ?

itayAmza commented 1 year ago

Hi, I also get Plug-in ended with non-zero exit code: 1) error when running on Xcode 15. In 2 different projects, on 2 different macs. Both projects used SwiftGenPlugin before, and when I switch back to Xcode 14, it builds fine. It might be worth mentioning that the errors accrues only when adding new strings (when the build tool plugin is actually running). The full error:

Error: You don’t have permission to save the file “Strings+Generated.swift”.
Executing configuration file /Users/my.user/Documents/MyProject/swiftgen.yml
 $ swiftgen strings --templateName structured-swift5 --param enumName=Strings --output Strings+Generated.swift ./MyProject/en.lproj
 $ swiftgen xcassets --templateName swift5 --output XCAssets+Generated.swift ./MyProject/Resources/Images.xcassets
Not writing the file as content is unchanged

Plug-in ended with non-zero exit code: 1)
SynthesOne commented 1 year ago

As a temporary solution until the update comes in, you can use this functionality https://github.com/SwiftGen/SwiftGenPlugin#using-it-as-a-command to bypass the access rights error.

Kyle-Ye commented 1 year ago

Is there some breaking change for SwiftPM's plugin permission control. Many user of Xcode 15 beta/Swift 5.9 beta is experiencing an unexpected build issue. cc @neonichu

Kyle-Ye commented 1 year ago

The upstream feedback: "If this works on Xcode 14, it was just a bug and Xcode 15 fixed it."

https://github.com/apple/swift-package-manager/issues/6814

And we may consider using SwiftGen-Generate to replace such usage. (buildTool can't have writeToPackageDirectory permission currently.)

However there is other issue with SwiftGen-Generate and the fix PR(#9) is still open.

puneet25 commented 1 year ago

For me this plugin is working as expected on Xcode 15 on my local machine. It is failing on Xcode Cloud with the same error. Seems to be an Xcode Cloud bug because prebuildcommand should have access to plugin work directory

hugovanderlei commented 1 year ago

I'm stuck with this error and can't build my project

TomaszLizer commented 1 year ago

I have mistakenly created similar issue but in SwiftGen cli repo: https://github.com/SwiftGen/SwiftGen/issues/1075 Generally this is also issue for me in my current project. Command workaround is not best solution since in my case we are using SwiftGen plugin inside other Swift Package.

p-x9 commented 1 year ago

When running the BuildToolPlugin from the command line, I can avoid errors by adding the "--disable-sandbox" option. (When building an SPM target that depends on a plugin,)

Is there a configuration to automatically apply this option when running the plugin from an Xcode project?

TomaszLizer commented 1 year ago

I was able to "make it work" by passing hardcoded config to SwiftGen. What I did was to direct output to Plugin output directory. Pros:

Cons:

Here is what I did:


  static func swiftgen(using configuration: Path, context: PluginContext, target: Target) throws -> Command {
    .prebuildCommand(
      displayName: "SwiftGen BuildTool Plugin",
      executable: try context.tool(named: "swiftgen").path,
      arguments: [
        "strings",
        "--templateName", "structured-swift5",
        "--param", "publicAccess",
        "--param", "lookupFunction=stringLookup",
        "--output",  context.pluginWorkDirectory.appending(["StringsGenerated.swift"]),
        target.directory.appending(subpath: "Resources/Localized/en.lproj")
      ],
      environment: [
        "PROJECT_DIR": context.package.directory,
        "TARGET_NAME": target.name,
        "PRODUCT_MODULE_NAME": target.moduleName,
        "DERIVED_SOURCES_DIR": context.pluginWorkDirectory
      ],
      outputFilesDirectory: context.pluginWorkDirectory
    )
  }

Changes I have made were the ones arguments: I have just hardcoded how my swiftgen.yml is actually mapped to cli arguments and run it agains sandbox directory (see output). This generated file and added it to sources but those are not available to user (are available build time to module and user can jump to source).

If someone knows magic command that can be used to alter output dir if swiftgen (maybe some env variable?), then It will be trivial to fix, if not this will require swiftGen CLI itself to be extended.

TomaszLizer commented 1 year ago

[Update] Got it sorted out and works with current SwiftGenPlugin! :)

Plugin already provides environment variables one of which is DERIVED_SOURCES_DIR. SwiftGen tool itself allows for environment variable usage - that means we can easily use such env variable in config. Below is example swiftgen.yml config working with Xcode 15:

xcassets:
  inputs: Resources/Assets.xcassets
  outputs:
    templateName: swift5
    output: ${DERIVED_SOURCES_DIR}/AssetsGenerated.swift
    params:
        bundle: Bundle.module
        publicAccess: true

strings:
  inputs: Resources/Localized/en.lproj
  outputs:
    templateName: structured-swift5
    output: ${DERIVED_SOURCES_DIR}/StringsGenerated.swift
    params:
        publicAccess: true
        lookupFunction: stringLookup

See that output uses ${DERIVED_SOURCES_DIR} env variable which is expanded by swiftgne during run, see docs: https://github.com/SwiftGen/SwiftGen/blob/6.6.2/Documentation/ConfigFile.md#environment-variables

One downside (at least for me) is that now it works, but won't create file that can be checked in to the repository. That is little bit sad, because it allowed me to see what is changing while eg manipulating localisable strings. At the same time pros is that no-one will ever again try to manipulate that by hand... 🗡️

[Update2]: All of that is mentioned in the plugin documentation... https://github.com/SwiftGen/SwiftGenPlugin#add-a-swiftgen-config Solving the issue for few hours saved me 15 minutes of reading documentation 🤦‍♂️

tomas-bat commented 1 year ago

Using DERIVED_SOURCES_DIR still doesn't work if I have a custom DerivedData directory on an external drive (Xcode -> Settings -> Locations). There were no issues with this prior to Xcode 15. Not sure if this is a SwiftGen issue, though. Probably an SPM issue.

TomaszLizer commented 1 year ago

Using DERIVED_SOURCES_DIR still doesn't work if I have a custom DerivedData directory on an external drive (Xcode -> Settings -> Locations). There were no issues with this prior to Xcode 15. Not sure if this is a SwiftGen issue, though. Probably an SPM issue.

Does it work for you with standard DerivedData directory? I noticed that swiftgen will also fail if you would try to have nests folder structure for generated files. Eg those should lie flat in the DERIVED_SOURCES_DIR or otherwise folder cannot be created. If it still fails then I suppose that is SPM issue and good one to create issue on their side.

tomas-bat commented 1 year ago

Does it work for you with standard DerivedData directory? I noticed that swiftgen will also fail if you would try to have nests folder structure for generated files. Eg those should lie flat in the DERIVED_SOURCES_DIR or otherwise folder cannot be created. If it still fails then I suppose that is SPM issue and good one to create issue on their side.

Yes, it does work with the standard DerivedData location. I created an SPM issue.

paul-sotoworks commented 1 year ago

One downside (at least for me) is that now it works, but won't create file that can be checked in to the repository. That is little bit sad, because it allowed me to see what is changing while eg manipulating localisable strings. At the same time pros is that no-one will ever again try to manipulate that by hand... 🗡️

As far as creating the file to check into repo, we created a build phase Run Script to copy the SwiftGenPlugin generated file: cp "$SCRIPT_INPUT_FILE_0" "$SCRIPT_OUTPUT_FILE_0"

We didn't know the path to DERIVED_SOURCES_DIR, so we searched inside DerivedData to find our generated file, and wound up with the following input file for the Run Script: $BUILD_ROOT/../../SourcePackages/plugins/main.output/YOUR_TARGET_NAME/SwiftGenPlugin/YOUR_OUTPUT_FILE_NAME

Output file: $SRCROOT/YOUR_DESTINATION_PATH

Replace the YOUR* sub-components in the path.

Update: The input file path doesn't work since the ../main.output/.. path component is based on the name of the root directory for the project.

tekinarslan commented 1 year ago
mludi commented 1 year ago
  • Open Terminal

  • Go to Your yml file location under Localpackages- > XYourUIkit -> sources....

  • Run this command.

  • swift package --allow-writing-to-package-directory generate-code-for-resources

https://github.com/SwiftGen/SwiftGenPlugin/issues/14#issuecomment-1655112439