I have a Qt project that was developed on MacOS. I've been given the job to make it compile on Windows.
My current problem is that compiler (Microsofts LLVM clang-cl) seems to be ignoring objective-c++ files, and the QtCreator is freaking out on #import statement (#import of type library is an unspported Microsoft feature). It also freaks out about a lot of stuff after that, but I'm guessing it's due to the import not being handled properly.
I was led to believe that win32-clang-mvsc was the only QtCreator compiler that supports compilation of objective-c++ files on windows, however, it doesn't seem to support the #import statement.
I've looked around and it seems that I would need GNUstep to be able to compile that on windows, and I'm not entirely sure it would work.
Is it possible to use the whichever compiler GNUstep provides with QtCreator? Or is there some way to use the compiler I'm already using to compile the files with #import statement?
The error I'm getting on the build is that ***.obj file doesn't exists, where *** is the name of the file with the #import statement. I'm guessing the compiler skips it and doesn't generate the .obj file, so something can't find it. I'd guess it was the linker, but I'd expect linker errors then, not a generic file not found error.
You can use the GNUstep Windows MSVC Toolchain to build Objective-C code using Clang on Windows. We’re also using this in a Qt project. You’ll just need to tell your build system to use the necessary flags for Objective-C files (e.g. using QMAKE_EXTRA_COMPILERS if you’re using QMake). This Qt example project for using Objective-C in a Qt project for Android should get you started.
The error you’re seeing about #import is likely because your project is using some clang-cl flags like /TC//TP that force the compiler to treat the file as C/C++ irrespective of its extension. Removing these flags should make this error disappear.
Please open issues in the GitHub project linked above if you need further help with the setup.
Related
I have a project which I need to compile with different preprocessor macros. To reduce the compile time, I would like to compile only the files which re changed due to the macros and then somehow put them in the app binary. Is it possible to do using Xcode or command line tools for iOS?
If the macros are defined in a header file, it might only recompile files that #import or #include that header. Make sure to import the header only in source files where the macros are used to limit the recompiles.
If the macros are defined in the project file, imported or defined in a prefix file or added from the command-line, then it will likely recompile the whole project as it can't tell who depends on them. (Unless some newer version of Xcode can analyze and adapt for that.)
I'm running find_package(OpenCV, REQUIRED) to locate a library. It's installed on the build system and the target system, however the target is slightly different in that one part of the library is not available.
So when building, I get back linker flags like -lfoo -lbar. However, bar isn't available on the target machine and I'm not using it anywhere in the application. Of cource, since it was linked in, the runtime linker complains that it cannot be found.
Is there anyway to override the libraries linked in with find_package? I'll probably just do a string replace type of solution, though I'd be thankful for any help there too since I'm a CMake novice.
Thanks
I suppose you can remove undesired libraries from OpenCV_LIBRARIES variable:
list(REMOVE_ITEM OpenCV_LIBRARIES bar)
Alternatively, you can read FindOpenCV.cmake source to check if it supports COMPONENTS keyword.
I looked into using tgmath.h to deal with the CGFloat typedef float/double mess when dealing with arm64.
This answer has a pretty good description of how to use it, except that it didn't work at all for me. No matter what, my code was still calling the math.h functions.
After spending some time looking at all of the project compiler settings, I found that disabling the "Modules" feature (#import vs #import - iOS 7) makes it all work. More specifically, the option in the project settings is called Enable Modules(C and Objective-C) in the Apple LLVM 5.1 - Language - Modules dropdown.
To see a quick example of this issue, download a project that uses tgmath, such as MBProgressHUD, and see what happens when you enable the modules project setting. The tgmath.h calls get replaced with regular math.h calls.
My question is:
Why do modules prevent tgmath from being imported properly?
Is there a way to get around it and use both tgmath and modules? I would like to still be able to use them.
I'm not sure what's causing the issue, but as a workaround you could at least disable modules for only the file(s) where you're using tgmath.h:
Navigate to the target's Build Phases tab in Xcode.
Under the Compile Sources phase, locate the source files.
Double-click the source file and type -fno-modules in the Compiler Flags popover to disable Clang modules for that file.
At least this way you would still get the benefits of modules in most of your project. (This is assuming, of course, you don't need tgmath.h in the majority of your source files.)
It might already be in your math library under the name ctgmath: Link
I am playing around with some of the new iOS 7 features and working with some of the Image Effects as discussed in the WWDC video "Implementing Engaging UI on iOS". For producing a blur effect within the source code for the session, UIImage was extended via a category which imports UIKit like so:
#import UIKit;
I think I saw something about this in another session video but I'm having trouble finding it. I'm looking for any background information on when to use this. Can it only be used with Apple frameworks? Are the benefits of using this compiler directive enough that I should go back and update old code?
It's a new feature called Modules or "semantic import". There's more info in the WWDC 2013 videos for Session 205 and 404. It's kind of a better implementation of the pre-compiled headers. You can use modules with any of the system frameworks in iOS 7 and Mavericks. Modules are a packaging together of the framework executable and its headers and are touted as being safer and more efficient than #import.
One of the big advantages of using #import is that you don't need to add the framework in the project settings, it's done automatically. That means that you can skip the step where you click the plus button and search for the framework (golden toolbox), then move it to the "Frameworks" group. It will save many developers from the cryptic "Linker error" messages.
You don't actually need to use the #import keyword. If you opt-in to using modules, all #import and #include directives are mapped to use #import automatically. That means that you don't have to change your source code (or the source code of libraries that you download from elsewhere). Supposedly using modules improves the build performance too, especially if you haven't been using PCHs well or if your project has many small source files.
Modules are pre-built for most Apple frameworks (UIKit, MapKit, GameKit, etc). You can use them with frameworks you create yourself: they are created automatically if you create a Swift framework in Xcode, and you can manually create a ".modulemap" file yourself for any Apple or 3rd-party library.
You can use code-completion to see the list of available frameworks:
Modules are enabled by default in new projects in Xcode 5. To enable them in an older project, go into your project build settings, search for "Modules" and set "Enable Modules" to "YES". The "Link Frameworks" should be "YES" too:
You have to be using Xcode 5 and the iOS 7 or Mavericks SDK, but you can still release for older OSs (say iOS 4.3 or whatever). Modules don't change how your code is built or any of the source code.
From the WWDC slides:
Imports complete semantic description of a framework
Doesn't need to parse the headers
Better way to import a framework’s interface
Loads binary representation
More flexible than precompiled headers
Immune to effects of local macro definitions (e.g. #define readonly 0x01)
Enabled for new projects by default
To explicitly use modules:
Replace #import <Cocoa/Cocoa.h> with #import Cocoa;
You can also import just one header with this notation:
#import iAd.ADBannerView;
The submodules autocomplete for you in Xcode.
Nice answer you can find in book Learning Cocoa with Objective-C (ISBN: 978-1-491-90139-7)
Modules are a new means of including and linking files and libraries into your projects. To understand how modules work and what benefits they have, it is important to look back into the history of Objective-C and the #import statement
Whenever you want to include a file for use, you will generally have some code that looks like this:
#import "someFile.h"
Or in the case of frameworks:
#import <SomeLibrary/SomeFile.h>
Because Objective-C is a superset of the C programming language, the #import state‐ ment is a minor refinement upon C’s #include statement. The #include statement is very simple; it copies everything it finds in the included file into your code during compilation. This can sometimes cause significant problems. For example, imagine you have two header files: SomeFileA.h and SomeFileB.h; SomeFileA.h includes SomeFileB.h, and SomeFileB.h includes SomeFileA.h. This creates a loop, and can confuse the coimpiler. To deal with this, C programmers have to write guards against this type of event from occurring.
When using #import, you don’t need to worry about this issue or write header guards to avoid it. However, #import is still just a glorified copy-and-paste action, causing slow compilation time among a host of other smaller but still very dangerous issues (such as an included file overriding something you have declared elsewhere in your own code.)
Modules are an attempt to get around this. They are no longer a copy-and-paste into source code, but a serialised representation of the included files that can be imported into your source code only when and where they’re needed. By using modules, code will generally compile faster, and be safer than using either #include or #import.
Returning to the previous example of importing a framework:
#import <SomeLibrary/SomeFile.h>
To import this library as a module, the code would be changed to:
#import SomeLibrary;
This has the added bonus of Xcode linking the SomeLibrary framework into the project automatically. Modules also allow you to only include the components you really need into your project. For example, if you want to use the AwesomeObject component in the AwesomeLibrary framework, normally you would have to import everything just to use the one piece. However, using modules, you can just import the specific object you want to use:
#import AwesomeLibrary.AwesomeObject;
For all new projects made in Xcode 5, modules are enabled by default. If you want to use modules in older projects (and you really should) they will have to be enabled in the project’s build settings. Once you do that, you can use both #import and #import statements in your code together without any concern.
#import Module(ObjC) or Semantic import
instead of usual module using
//as example
#include <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
History:
[#include -> #import] -> [Precompiled Headers .pch] -> #import Module(ObjC); -> [import Module(Swift)]
It is a part of LLVM Modules
#import <module_name>; declaration says to compiler to load(instead of compile) a precompiled binary of module which decrease a building time. Previously compiler compiled dependency every time when runt into it but now it should be compiled beforehand and just loaded
//previously
run into dependency -> compile dependency
run into dependency -> compile dependency
//#import
compile dependency
run into dependency -> load compiled binary
run into dependency -> load compiled binary
[Modulemap] - bridge between module and headers
Xcode
Enable Modules(C and Objective-C)(CLANG_ENABLE_MODULES) - CLANG #include, #import directives are automatically converted to #import that brings all advantages. Modulemap allows to do it seamless because contains a map between headers and sub/modules
Pass -fmodules
#include, #import -> #import
Link Frameworks Automatically(CLANG_MODULES_AUTOLINK) - enables system modules auto linking. Requires activated CLANG_ENABLE_MODULES. Auto-linking allows to pass -framework <framework_name> based on #import, #import(Objective-C), import(Swift)
If NO - passes -fno-autolink flag
CLANG_ENABLE_MODULES == NO and CLANG_MODULES_AUTOLINK == NO
If you want to handle system(#import <UIKit/UIKit.h>) linking manually(instead of auto-linking) you have two variants:
Add dependency into General -> Frameworks and Libraries or Frameworks, Libraries, and Embedded Content
Build Settings -> Other Linker Flags(OTHER_LDFLAGS) -> -framework <module_name>
Next error will be thrown if:
Undefined symbol: _OBJC_CLASS_$_UIView
Undefined symbols for architecture x86_64:
"_OBJC_CLASS_$_UIView", referenced from:
objc-class-ref in ClassB.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1
CLANG_ENABLE_MODULES is disabled
CLANG_MODULES_AUTOLINK is disabled and no manual linking
Reverse engineering
otool -l <binary>
//-l print the load commands
//find LC_LINKER_OPTION
//cmd LC_LINKER_OPTION
It currently only works for the built in system frameworks. If you use #import like apple still do importing the UIKit framework in the app delegate it is replaced (if modules is on and its recognised as a system framework) and the compiler will remap it to be a module import and not an import of the header files anyway.
So leaving the #import will be just the same as its converted to a module import where possible anyway
It seems that since XCode 7.x a lot of warnings are coming out when enabling clang module with CLANG_ENABLE_MODULES
Take a look at Lots of warnings when building with Xcode 7 with 3rd party libraries
There is a few benefits of using modules. You can use it only with Apple's framework unless module map is created. #import is a bit similar to pre-compiling headers files when added to .pch file which is a way to tune app the compilation process. Additionally you do not have to add libraries in the old way, using #import is much faster and efficient in fact. If you still look for a nice reference I will highly recommend you reading this article.
I'm working on an open-source project that can optionally use a closed-source framework. If the closed-source framework is included in the project, there will be additional functionality. But if the framework isn't included in the project, the project should still compile properly.
How do I check at compile-time if the framework is included in the project?
Basically, I want to do something like this:
#ifdef _MY_FRAMEWORK_EXISTS
#import <MyFramework/MyFramework.h>
#endif
I've seen older questions from 2 years ago like this one, but no answer has surfaced so I might be missing something new now.
I DON'T want to check at run-time via NSClassFromString(), because this will fail at compile time when I try to import MyFramework and it doesn't exist.
You can check for the presence of a header file using the __has_include language extension.
http://clang.llvm.org/docs/LanguageExtensions.html#include-file-checking-macros
However, that only tells you if the header file is installed. It can't tell you if "Link Binary With Libraries" has linked to its framework.
I recommend reading the Mac Developer Library : Framework Programming Guide (which includes a section on Weak Linking).
What do you mean by "exists" or "included in the project"? Do you mean added to the "Link Binary With Libraries" build phase (as described by Including Frameworks)? All that does is affect the linking, not the compilation, build phase. To see this, build. Then, search for -framework in the build log of Xcode's Log Navigator.
So, yes, if you want to affect the compilation of the code you provided, you could manually define the macro _MY_FRAMEWORK_EXISTS.
I don't really understand what you are trying to do. Can you explain what you want at a higher level? Perhaps, there's a better way to go about it.
"Minimal overhead" is nice, but too much magic might be confusing. For example, Xcode's magic hides what really happens when including a framework.
I also recommend checking out how the Facebook SDK for iOS works for high & low-level ideas. It might do the kinds of things you want to do.