#import “TargetName-Swift.h” without hardcoding TargetName

How do I not hardcode the target/module name here?

#import “TargetName-Swift.h”

Is that possible?

Little-known C fact: you can put a macro after #include, and that applies to #import as well. So you should be able to set a macro with the module’s name, and have it expand to the full header name in quotes. This is “implementation-defined” so it may not work on every compiler depending on how clever you’re trying to be, but I think it’s the best you’ll get.

1 Like

How a normal #include with a non-macro character-sequence searches for the content to drop in are already implementation-defined, so this is not of any additional concern.


§ 6.10.2 p2:

A preprocessing directive of the form

#include <h-char-sequence> new-line

searches a sequence of implementation-defined places for a header identified uniquely by the specified sequence between the < and > delimiters, and causes the replacement of that directive by the entire contents of the header. How the places are specified or the header identified is implementation-defined.

1 Like

I need to make my own macro, right? Xcode refers to this name as $(TARGET_NAME) but I guess this is not exposed to C.

Hmm - doesn’t work for me. Tried this:

Preprocessor macros, added:
HDR="targetName-Swift.h"

Usage:
#import HDR

Getting error:
Expected "FILENAME" or <FILENAME>

Embedding HDR in quotes doesn’t work obviously.

The most direct solution is to put the quotes in the macro. Using preprocessor stringification (#HDR) may also work because the header name happens to be made of valid preprocessor tokens (you may need some indirection to not get the literal string "HDR"). Going even further, you could use that to build the full name from the MODULE_NAME macro that Xcode provides (IIRC).

None of this is exactly a good idea, because it implies you have a file that’s a member of multiple targets, or a target that’s configured multiple ways. If it’s the latter, I recommend setting the generated header name to a fixed string instead—it’s just another build setting. But sometimes building the same file multiple ways is the least bad answer, so.

I tried various permutations to include a name with macro but nothing works for me, does it actually work for you?

setting the generated header name to a fixed string

This one works.

Keeping in mind that this is overly clever: Compiler Explorer

1 Like

This works indeed, thank you!

Slightly modified code:

// setup:
#define stringify(x) #x
#define generatedHeaderName(x) stringify(x-Swift.h)

// usage:
#include generatedHeaderName(MY_SWIFT_MODULE_NAME)

where MY_SWIFT_MODULE_NAME=ModuleName added to the preprocessor macros section. MY_SWIFT_MODULE_NAME="ModuleName" works equally well.

Interestingly generatedHeaderName(...) doesn't work with one of the names Xcode is referring to (I tried MODULE_NAME, SWIFT_MODULE_NAME, TARGET_NAME, PRODUCT_NAME). Is there another trick to use those instead of adding my custom define?

Xcode’s build settings don’t automatically turn into C macros, but you can define your macros in terms of other build settings. You can also look at the run line in the build log to see if there’s already one with the right value.

2 Likes

Yes, it works indeed:

MY_SWIFT_MODULE_NAME=$(SWIFT_MODULE_NAME)