Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Objective-)C++ External linkage issues for global constants in PSSpecifier.h #30

Closed
DGh0st opened this issue Sep 27, 2020 · 3 comments
Closed

Comments

@DGh0st
Copy link

DGh0st commented Sep 27, 2020

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)

@leptos-null
Copy link
Member

This is my fault. This goes back to the #24 discussion. My suggestion is to apply one of these options either to all declarations, or only variables:

  • Switch from __{BEGIN,END}_DECLS to OBJC_EXTERN
  • Add extern inside __{BEGIN,END}_DECLS

@pixelomer
Copy link

This issue is also preventing MobileGoose from compiling successfully. It was possible to compile this project without any modifications in the past.

pixelomer added a commit to pixelomer/MobileGoose that referenced this issue Oct 11, 2020
leptos-null added a commit to leptos-null/theos-headers that referenced this issue Oct 14, 2020
In 24ad952, I changed all external declarations to be enclosed
in __{BEGIN,END}_DECLS which is sufficient for functions, but
not for variables in C++.
Please refer to theos#30
for further information.

This effectively reverts much, but not all, of 24ad952
kirb pushed a commit that referenced this issue Oct 24, 2020
In 24ad952, I changed all external declarations to be enclosed
in __{BEGIN,END}_DECLS which is sufficient for functions, but
not for variables in C++.
Please refer to #30
for further information.

This effectively reverts much, but not all, of 24ad952
@kirb
Copy link
Member

kirb commented Oct 24, 2020

Fixed via #31

@kirb kirb closed this as completed Oct 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants