Plugin generated header files are not available from project

We have been experimenting with a SPM build plugin to dynamically generate source files for a package. The output of the plugin is 2 files, sqlite3.c and sqlite3.h. The c file is successfully built and linked, however, the header file is not available to the application with a dependency on the package. If we add a .h file to the outputFiles in the plugin, Xcode just generates a warning about unknown file type for the .h.

This then requires a build script to locate and copy the generated sqlite3.h file to a directory in the Headers Search Path, as described in this related GitHub thread: Swift Package Manager Support · Issue #371 · sqlcipher/sqlcipher (github.com)

Is there any way to automatically make the plugin generated header file output available to the dependent application?

A search of the forum turned up this post, which may be related. Swift static libraries don't copy generated Objective-C header - Using Swift - Swift Forums

7 Likes

Headers need to be exposed though clang modules. Have you tried to output a module.modulemap file with:

module SQLite3 {
  header "sqlite3.h"
  export *
}

I don’t know much about build plugin outputs, but regularly module.modulemap and sqlite3.h should be placed side by side in Sources/{target}/include/.

Hi @stevapple - thanks for taking a look at this. There is a modulemap file present, in this case it is exposing a bridging header which then references sqlite3.h. I also agree that under normal circumstances the sqlite3.h file would exist under the include directory for the target sources. However, in this case sqlite3.h is being generated dynamically by the build plugin. Due to the sandbox, the plugin can't write anything back to the module directory structure.

The code is instead specifying the output files as such:

        return [.buildCommand(
              displayName: "Running Amalgamation",
              executable: toolPath,
              arguments: [context.pluginWorkDirectory.string, outputDir.string],
              outputFiles: [
                outputDir.appending("sqlite3.c"),
                outputDir.appending("sqlite3.h")
              ]
        )]

This works for the c file, which is built accordingly into the module, but the inclusion of a .h in the output file list results in the following warning:

no rule to process file '/Users/xxx/Library/Developer/Xcode/DerivedData/sqlcipher-osx-swift-demo-abwythneycizmxftzbhpwlrzreav/SourcePackages/sqlcipher/sqlcipher/AmalgamationPlugin/gen/sqlite3.h' of type 'file' for architecture 'x86_64'

@stevapple don't you have ideas if it's possible to include .h output file into sources? Or may be you know somebody to invite into conversation who can help?

Currently, build tool plugins only support generating Swift code. This wasn't clearly spelled out in 5.6, but there's an explicit diagnostic now in 5.7: swift-package-manager/TargetSourcesBuilder.swift at main · apple/swift-package-manager · GitHub

One of the issues we need to tackle here before being able to support C-family languages is exactly what you're describing, how to expose header files.

3 Likes