Is SwiftPM support C Language link custom build static library inside targets

Hi SwiftPM

Is SwiftPM support link custom build static library inside targets,
I've try system target, system library, it's works

put header, and .c source file, it's works

but if I put header in include folder, and libXX.a custom static library file, and type [swift build]
it's always get this message
"\warning: target 'xx' in package 'xx' contains no valid source files"

in this c targets i've remove all .swift file

in module.modulemap i just define it this format, and put in include folder with shim.h header

module XX {
header "xx.h"
export *
}

and i know after Xcode 8.3 it should not add "link" syntax in modulemap file, if it's custom C language targets

I've google it for 5 days.. please help, thank you so much.

Is your project open sourced? If so I can take a look.

There are many little gotchas when mixing C and Swift so it is much easier to help if I can get more context of the layout and the Package.swift file etc.

Hi Braden

my project is here

btw, if I put foo.c, and bar.c, and type "swift build", everything is okay, module.modulemap generated successful, but no luck with libCFoo.a, libBar.a
it's error out with
"\warning: target 'Foo' in package 'Foo' contains no valid source files"
error: target 'Foo' referenced in product 'Foo' could not be found

thank you for your help

I struggled in similar structure project several months ago, and succeeded to get it to work.

There are three points:

  1. Put dummy.c in the target directory
  2. Write module.modulemap by yourself
  3. Pass linker flag to specify the library directory

As written in readme, we need -Xlinker -LSources/Foo/lib.
I'm glad if someone tell me easier way🙂

2 Likes

Hi t-ae

It's works!!!
I've 3 question

What's the dummy.c empty file secret sauce, even in

Github Official Doc usage

and in Clang llvm docs
https://clang.llvm.org/docs/Modules.html#module-map-language

there is no place talk about this trick

When to write module.modulemap by myself, and when to let SwiftPM generate automatically

When to add link flag in custom C target package

Because I've google from this article

Migrating Perfect project to Swift 4 – Hacker Noon

It's say Xcode official release note

After Xcode 8.3

Swift package manager

Packages which use custom module maps for their c language targets should remove the link statement from the module map.

The package manager will automatically add the link flag if required.

i've confused, because I don't know what's real rule.

thank you.

It's only an empty file.
If there's no source files in the target directory, it can't compile.

It's written in here:

In case of complicated include layouts, a custom module.modulemap can be provided inside include.

I think having static link library in the module is a complicated case.

Hmm, I didn't know that part...
Anyway, if I removed the link part, it can't compile.


By the way, I forgot to mention to the critical problem.
This structure requires users to specify linker flag.
So packages depends on this also have to specify them.

In my case, the project was a executable. So it's not a big problem.
But if it is a public library, it's not user-friendry at all.
I recommend to search other way if your project is a library.

Hi t-ae
Thanks for your reply, I will follow your suggestion, you're great ppl :slight_smile:

In Swift 5, you can do like this:
// swift-tools-version:5.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "Foo",
products: [
// Products define the executables and libraries produced by a package, and make them visible to other packages.
.library(
name: "Foo",
targets: ["Foo"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: / package url /, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "Foo",
dependencies: ,

linkerSettings: [LinkerSetting.unsafeFlags(["-L./Sources/Foo/lib"])]),
.testTarget(
name: "FooTests",
dependencies: ["Foo"]),
]
)