It's often the case that we want to give tests a privileged access to the code-under-test. For example, in Swift we have -enable-testing
to cause internal symbols to be visible outside the module.
I'm trying to achieve something similar in a C target. Suppose we have a public function foo
and an "internal" function fooHelper
. In this listing, we emit a prototype and a symbol that can be called from a test. But ordinarily, we emit neither prototype nor symbol:
//header.h
int foo();
#if TESTING
int fooHelper();
#endif
//file.c
#if TESTING
#define MAYBE_STATIC
#else
#define MAYBE_STATIC static
#endif
MAYBE_STATIC int fooHelper() { /* */ }
int foo() {
fooHelper()
/* */
}
Now the problem becomes how to convince SwiftPM to emit such a TESTING
.
The obvious way is to configure cSettings
in Package.swift, perhaps conditioned on .when(configuration:.debug)
. However, this isn't correct: a) downstream packages which may build for debug, do not want the TESTING
, b) performance tests, which are built for release, do want the TESTING
.
The other obvious way is to pass -Xcc TESTING
at the cli, however I'm not sure how to get that to play nice with Xcode, which is the practical development workflow.
The non-obvious way is to create multiple targets and keep SwiftPM from being aware they contain the same sourcefiles by clever use of symlinks.
It would improve this situation considerably if any of:
- SwiftPM / Xcode emitted a cflag + swiftflag for testing
- There were a way to create and use a custom configuration, which we could then pass to
.when
to enable this setting - there were a way to figure out if we are the toplevel package, or a dependency. While this is not exactly a testing flag, it's pretty close for library code
- There were a real way to declare multiple targets on the same set of sources, one of which contains the setting and is nominated as a test dependency, the other one for public consumption.