My C library compiles and gets packaged into an xcframework without a problem, but my Swift project that uses this through a Swift Package then has some errors...
Namely, I'm getting
Token is not a valid binary operator in a preprocessor subexpression
This error shows up, for example, for the or
in #if defined(__ANDROID__) or defined(__iOS__)
.
This header file has #include <iso646.h>
(which defines or
), and I tried #include "iso646.h"
for if SWIFT_PACKAGE
, but that didn't help. I also tried to hard-code the contents of this system header into my header, without luck.
Why is my Swift project choking on these?
Edit:
I tried a minimal reproducible example, and I get the same error message.
Here's the code:
Minimis.c:
#include "stdio.h"
void f(void) {
printf("f called from within xcframework");
}
Minimis.h:
#import <Foundation/Foundation.h>
//! Project version number for Minimis.
FOUNDATION_EXPORT double MinimisVersionNumber;
//! Project version string for Minimis.
FOUNDATION_EXPORT const unsigned char MinimisVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <Minimis/PublicHeader.h>
#include "iso646.h"
#if A and B
#pragma message ("A and B are defined")
#else
#warning Neither A nor B are defined
#endif
void f(void);
Creating an xcframework and a Swift Package from that causes the failure on the #if A and B
header line when trying to use the Swift Package in a Swift Project.
I tried modifying the module.modulemap file that gets included with my xcframework to include the iso646 header, like:
framework module Minimis {
umbrella header "Minimis.h"
export *
module * { export * }
link "iso646"
}
... but that doesn't resolve the error. I also tried to create a Swift Package Library that just wraps some C standard libraries, but then I didn't see how to include that in my other Swift Package (I'm using a binary target to pull in my xcframework, and the binaryTarget method doesn't take dependencies).
After checking the content of <iso646.h>, I found that and
is defined here.
And using some trick I found __ISO646_H
was already defined in command line to deliberately prevent someone from using it.
The code is here and only Apple will know why.
Reply from pre-Apple employees https://forums.swift.org/t/including-c-system-headers-through-a-swift-package/66543/7