How can I convince Xcode to emit a duplicate symbol linker error? - xcode

Here's a different one from the usual confusion over duplicate symbol errors... :-)
I'm working on some legacy Mac code in an Xcode project that has the same global, "trace", defined in several different source files - for instance:
File1.c: SInt32 trace;
File2.c: Boolean trace;
etc. It's clear the original author meant them to have file-specific scope, but just neglected to prefix any of these lines with "static". That's fine, easy enough to fix.
But I'm kind of shocked the linker isn't flagging these! It looks to me like Xcode's linker (I presume gnu ld) only emits duplicate symbol warnings or errors for functions, that are linked into the code segment - but not global variables that are linked into the data segment. Instead, it silently conflates them, which is causing bugs.
So... how do I convince Xcode to emit link errors for duplicate global variables? Or get this information in some other way that can be a routine part of my build?

Well, I thought I'd answered my own question... :-)
I posted earlier:
So if you're using Xcode with LLVM GCC
4.2, go to the build settings dialog, find the "LLVM GCC 4.2 - Code
Generation" section, and check the "No
Common Blocks" checkbox. This enables
the compiler's "-fno-common" option,
and changes the object file generation
so that ld will choke and emit an
error if you have two globals in
different source files with the same
name.
Unfortunately, that doesn't seem to solve all instances. It seems to work fine if all the globals have the same type.
But the example in the question is taken straight from the code, where a variable named "trace" is defined as a global in two different files with two different types. And that's still not caught by the build system when I check that checkbox.

Related

LinkOnceODRLinkage on Windows for global variables

I'm compiling two files with clang 6.0: testA.c and testB.c.
On both files I am running a custom compiler pass that inserts a zero-initialized global variable called globalVarTest. I set the linkage of such global variable to be LinkOnceODRLinkage.
Now, when I link testA.c and testB.c together (that is, the object files obtained by compiling them separately), the linker complains that there are multiple definitions of globalVarTest.
Isn't LinkOnceODRLinkage supposed to tell the linker that if both definitions match, the symbols is the same and it can therefore pick any of the two definitions when building the final executable?
UPDATE:
The same procedure works on Linux. Is this a limitation of the Windows linker? I have been able to achieve the same effect using COMDAT sections but I wonder why LLVM is not using that mechanism automatically without me requiring to explicitly set COMDATS.
I got an answer from the LLVM mailing list. Using LinkOnceODRLinkage does not work on Windows, even though it used to work in the past.
The best way to achieve the same effect is to explicitly use COMDAT sections. Apparently, this is what was happening automatically by setting LinkOnceODRLinkage, until the behavior changed.

Why does the Swift compiler mark errors pessimistically?

I find that Swift is quick to mark down changes i make as compiler errors in the side panel, and then when i compile, it decides i am right after all. Is Swift just pessimistic about my code?
Can I get the compiler to wait for me to finish the line before declaring it wrong?
There is nothing pessimistic. Xcode uses the same tool - the compiler - to get the errors. However, it usually compiles only one file, using cached compiled objects for the other files. It also doesn't invoke the compiler after every change in your code, so errors that are already fixed can stay there in the side panel.
Building the project fully forces Xcode to refresh the cache and get the current list of errors from the compiler. I do agree that Xcode has many imperfections and this is one of them. When you can't find an error, just rebuild the project.
Note that IDEs for other languages often rebuild the project automatically to solve such problems. This is currently not an option in Swift because it would take too much time.

How to check for functions which have no callers in the whole project?

How to check for functions which have no callers in the whole project?
I have turned these flags on: Unused Functions, Unused Values, Unused Variables in xCode, but it did not work.
Thanks a lot.
My guess is because Xcode doesn't look for Objective-C and Swift methods, Xcode looks for C functions instead.
Actually, there is no an efficient approach to do this with Xcode. You can try to find occurrences of those specific fields and methods using project find tool and comment or change access level of those fields and methods to compile errors. If you try to use one of the last one approaches, the fact of your project build successfully doesn't means you made your clean up correctly, KVC or #selector aren't detected in compile time, because it is accessed dynamically in run time.
I know AppCode have this as default and other useful tools to makes the code better.

What does BII_IMPLICIT_RULES_ENABLED do when switched on or off in CMakeLists.txt?

I was wondering about the BII_IMPLICIT_RULES_ENABLED flag which I had switched off in one of my CMakeLists.txt files, in order to get an OpenGL related block to compile on a Mac, following a suggestion from biicode. This setting is still there and everything works perfectly, but I would like to find out more about it. Could someone explain what it does exactly?
Thanks!
BII_IMPLICIT_RULES_ENABLED activates the addition of system libs to the target that has included certain headers. For example, if your code contains an:
#include "math.h"
And you are in *nix systems, then the library "m" (libm) will be added to your target via TARGET_LINK_LIBRARIES.
You can see the headers that are processed in your cmake/biicode.cmake file, in the HANDLE_SYSTEM_DEPS
My recommendation: Put it to False whenever possible, and handle the required system libs yourself, exactly what you have done. It is something that will be deprecated soon, or at least set to False by default to new projects. This option sometimes causes troubles, if something fails or there is a bug in biicode.cmake, e.g. in the past it tried to add libm to targets also in windows. It will be gradually deprecated and probably substituted by some CMake macros hosted (as in http://www.biicode.com/biicode/cmake) that could be used by users if they decide to, but not automatically as it is done now.

SecPKCS12Import() from Security.framework fails on OS X 10.6

When I attempt to use SecPKCS12Import() from the Security framework as provided by Mac OS X 10.6, the result code is always errSecUnimplemented, regardless of the arguments provided.
Furthermore, the linker is unable to find symbols for the constants relevant to this function declared in SecImportExport.h (i.e. kSecImportExportPassphrase, kSecImportItemIdentity, et al.).
What on Earth is going on with this library -- is the function implemented or is it not? Why can the linker resolve all other symbols in the framework, but not these? How should I convert a PKCS12-formatted binary blob to a SecIdentityRef or SecCertificateRef and SecKeyRef pair?
What am I doing wrong? I'm sure this is a PEBKAC issue. :-)
EDIT: I see that I was very unclear in my question. I'm aware that Security.framework is implemented, given that I am able to use the other functionality it provides without an issue. Given this, I'm fairly certain that I'm linking against the framework correctly, since if I remove the link, none of the symbols can be found -- as expected. When I relink the framework, all the symbols are found, with the exception of the constants relevant to SecPKCS12Import(), e.g. kSecImportExportPassphrase, kSecImportItemIdentity, etc.
Given that I cannot use these symbols, I passed in what could have been incorrect strings (#"kSecImportItemIdentity", etc.), but the error code returned was errSecUnimplemented. This led me to believe that perhaps this specific functionality has not been implemented.
I tried using the 10.5 SDK, but that didn't work, of course. :-)
EDIT: My import is just a regular #import <Security/Security.h>. For kicks, I tried #import <Security/SecImportExport.h> as well, but this effected no change. That said, the error is issued by the linker, not the compiler.
I ran dyldinfo -export Security.framework/Security to list the symbols exported by the library and found many of the new symbols, but kSecImportExportPassphrase and friends were conspicuously missing. This might explain why the linker cannot find the symbols. The symbol for SecPKCS12Import appears in the symbol table and I can call that with no issues, it's just the functionality does not seem to be there.
Security.framework is most certainly implemented — see the Security Reference Update which documents what has changed in the framework in 10.6 and prior. Since you know the headers to use, I assume you've already consulted the Security Framework Reference.
Are you sure you're properly importing and linking against the framework? (It's in /System/Library/Security.framework, so you shouldn't have to specify the path.)
Does the compiler issue warnings or errors stating that the symbols in SecImportExport.h are undefined? (If not, how do you know they're "declared but undefined"?)
When you say that this fails on 10.6, have you tried it on an earlier version of the OS successfully?
EDIT: Okay, since you're using other parts of Security.framework successfully, and the APIs and constants you're trying to use are 10.6 only, it doesn't seem like a linking issue. What do your import look like? Are you sure you're importing SecImportExport.h properly? The constants are declared just above the SecPKCS12Import() function, so if you get warnings for the constants, you should get one for the function being undefined as well.
EDIT: I have confirmed with a member of the team at Apple that works on Security.framework that this functionality is not currently implemented. Please file a bug to gripe about this at http://bugreport.apple.com against component Security (New Bugs), version X. Include the URL to this question in your report. Sorry there's not a better answer at the moment.
To my knowledge, Apple is great at partially implementing things or leaving no documentation. If you really can't find the real implementation you need, you can use OpenSSL to extract the blobs and then Security services to import them to a keychain or further process with Security/CDSA methods. That would get you going and you can ping the Apple dev connection with further questions, if you have the possibility.
Further, looking at /System/Library/Frameworks/Security.framework/Headers/SecImportExport.h on my 10.6.2 machine, I see references to PKCS#12 in the documentation of SecKeychainItemImport()
Search that file for "PKCS12" for further information.

Resources