Description
Importing the PSSpecifier.h in (Objective-)c++ context gives the following errors:
...
==> Compiling api/HSWidgetCombinedAdditionalOptionsAndPreferencesViewController.mm (arm64)…
In file included from api/HSWidgetCombinedAdditionalOptionsAndPreferencesViewController.mm:1:
In file included from api/HSWidgetCombinedAdditionalOptionsAndPreferencesViewController.h:3:
In file included from api/HSWidgetPreferencesListController.h:5:
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:6:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSAccessoryKey; // @"accessory"
^
= 0
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:7:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSActionKey; // @"action"
^
= 0
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:8:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSAdjustFontSizeToFitWidthKey; // @"adjustFontSizeToFitWidth"
^
= 0
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:9:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSAlignmentKey; // @"alignment"
^
= 0
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:10:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSAppGroupBundleIDKey; // @"appGroupBundleID"
^
= 0
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:11:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSAutoCapsKey; // @"autoCaps"
^
= 0
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:12:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSAutoCorrectionKey; // @"autoCorrection"
^
= 0
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:13:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSBestGuesserKey; // @"bestGuess"
^
= 0
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:14:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSBundleCustomIconPathKey; // @"icon2"
^
= 0
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:15:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSBundleHasBundleIconKey; // @"hasBundleIcon"
^
= 0
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:16:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSBundleHasIconKey; // @"hasIcon"
^
= 0
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:17:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSBundleIconPathKey; // @"icon"
^
= 0
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:18:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSBundleIsControllerKey; // @"isController"
^
= 0
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:19:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSBundleOverridePrincipalClassKey; // @"overridePrincipalClass"
^
= 0
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:20:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSBundlePathKey; // @"bundle"
^
= 0
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:21:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSBundleTintedIconPathKey; // @"tintedIcon"
^
= 0
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:22:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSButtonActionKey; // @"buttonAction"
^
= 0
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:23:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSCancelKey; // @"cancel"
^
= 0
/home/dgh0st/theos/vendor/include/Preferences/PSSpecifier.h:24:17: error: default initialization of an object of const type 'NSString *const'
NSString *const PSCellClassKey; // @"cellClass"
^
= 0
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
make[3]: *** [/home/dgh0st/theos/makefiles/instance/rules.mk:201: /mnt/c/cygwin64/home/DGh0st/HSWidgets/.theos/obj/debug/arm64/api/HSWidgetCombinedAdditionalOptionsAndPreferencesViewController.mm.770ee366.o] Error 1
...
Notes:
For reference, the errors shown above are while compiling HSWidgets with latest Theos. But the issue is also reproduceable when creating a new empty preference subproject and including PSSpecifier.h
in a Objective-c++ file (.mm
).
Potential Root Cause:
I think the issue is the way these global constants are defined in PSSpecifier.h
.
For C, following is the output after the pre-processor:
...
NSString *const PSAccessoryKey; // @"accessory"
NSString *const PSActionKey; // @"action"
NSString *const PSAdjustFontSizeToFitWidthKey; // @"adjustFontSizeToFitWidth"
...
By default C compiler provides external linkage for all non-static global variables so this works as expected.
For c++ global constants have internal linkage by default so we need the extern "C", which is what the __BEGIN_DECLS
is responsible for. However c++ treats extern "C"
blocks slightly differently when it comes to variables. According to the c++ standard, this is the difference that it has:
extern "C" int a; // declaration
extern "C" {
int b; // definition
}
First is considered as declaration only, but second block statement is considered as a definition so the compiler needs to make sure memory will be created for b. If this were a const
then it would require a default value. Which is the case for the PSSpecifier.h
.
The way to make it not create space for the current translation unit, and ultimately not complain about the initialization, would be to either use:
extern "C" {
extern int b; // declaration
}
or
extern "C" int b; // declaration
(both of which are equivalent according to c++ standards)