Home | Articles | Talks
————————————————————————————————————————————--
————————————————————————————————————————————--
You should take a look at Electron. Have you ever used slack under osx? Was build with Electron and it is all html, css and JavaScript.
15 Oct 2018
Our app will already work at this point: when you launch it and press the button, Xcode will display a nice log message saying Hello from the AppDelegate. Just one more thing As a final touch, and to setup the project exactly like the old-style Apple template (and Xcode 9 “no storyboard version), CTRL-drag from the Window object to the. For a Mac app built with Mac Catalyst, create separate archives for the iPad and Mac version. When creating the archive for the Mac version, choose My Mac as the run destination. From the archive, export a version of the app to distribute to users: In the Archives organizer, select the archive, then click Distribute App.
A build system, despite its scary-sounding name, is just a regular program, which knows how to build other programs. As an iOS developer, you’re certainly familiar with how to build a project using Xcode. You go to the
Product
menu and select Build
, or you use the ⌘B
keyboard shortcut.
You may have also heard about Xcode Command Line Tools. It’s a set of tools which allows you to build Xcode projects directly from the terminal using the
xcodebuild
command. A very convenient thing for automating your processes, for example on your CI.
No matter how you’ve initiated it, the building itself is orchestrated by Xcode’s build system.
Can we replicate the building process and build the app “manually”, without Xcode’s build system?
Is it possible to sign the resulting app? Or even deploy it to an actual iOS device?
⚠️ Disclaimer 1 ⚠️
What is this post about:
Writing a non-reusable script that builds one concrete iOS project the simplest way possible.
What is this post NOT about:
Writing a complex and universal build system.
Content
The App We’re About to Build
I let Xcode 10.0 generate a new project using the
Single View App
template, and named it “ExampleApp”. This is going to be the reference app we will try to build “manually”. The only adjustment to the project I made was adding a UILabel
with ?
to the main (and only) ViewController
.
I also created the
build.bash
file in the root folder of the project. We’re going use this file for the actual build script.
Don’t forget to make the file executable by running the following in the terminal:
Step 1: Prepare Working Folders
⚠️ Disclaimer 2 ⚠️
The complete “recipe” of how the app should be built is contained in its
xcodeproj
file. This article is not about how to parse and retrieve this information from it.
We will ignore the project file for the sake of this article. To make our life easier, we will hard-code all the details like the project name, source files, or build settings, directly into the build script.
Let’s start with some housekeeping. We need to define and create a set of folders we will be using during the building process.
When you run the script, your terminal should like this:
Notice, that the script created two folders:
Step 2: Compile Swift Files
Did you know you can call the Swift compiler directly from the terminal using
swiftc
?
With the correct flags, compiling all
.swift
source files is quite a straightforward operation.
I’d like to talk a little bit about the
-emit-executable
flag. According to the documentation, when this flag is used, the compiler “emits a linked executable”. When you run swiftc
in the verbose mode (-v
), you can actually see, what’s happening under the hood. The compiler creates .o
object for every .swift
file, and then calls ld
to link them into the final executable file.
Notice, that we set output (
-o
) to ExampleApp.app/ExampleApp
. That’s the resulting executable file from the compilation process.
Run the script and you should see the following:
You can also check, that the resulting executable was created inside the
ExampleApp.app
bundle:
Step 3: Compile Storyboards
Source code files are not the only files which need to be compiled. We also need to compile all
.storyboard
files. The compiler for storyboards (and all the other interface builder files) is called ibtool
. The resulting files from the process have the extension .storyboardc
.
Fun fact
storyboardc
files are file bundles. When you inspect the content of the bundle, you will see, that a compiled storyboard is actually just a bunch of nib
files.
ibtool
doesn’t accept more than one file at a time. We need to use a for loop to iterate over all storyboards.
Let’s run the script and verify the content of
ExampleApp.app
:
Step 4: Process and Copy Info.plist
A valid app bundle has to contain
Info.plist
. Unfortunately, we can’t simply copy the one from the project directory. This raw file contains several variables which we need to replace with the actual values.
To deal easily with
plist
files, Apple provides us with a tool called PlistBuddy. Because we don’t want to modify the original plist
we first create a temporary copy in the _BuildTemp
folder, and modify it there. Finally, we copy the processed plist
to the app bundle.
Let’s run the script:
We should also verify that the processed
plist
file is there, and its content is correct:
Running ExampleApp in the Simulator
How To Make A Mac App Without Xcode Install
At this point, we should have a valid
.app
bundle. At least for running it in the iOS simulator. You can open the simulator directly from the terminal window:
To interact with iOS simulators, Apple created a tool named
simctl
. Here’s how you can install the ExampleApp
app bundle to the currently running simulator. The second command starts the installed app.
I must admit I was extremely surprised when I saw the app was working!
The truth is, I thought one more step would be needed. Swift doesn’t have a stable binary interface yet and Swift runtime is not included in iOS. Thus every app has to have its own copy of the Swift runtime libraries included in the bundle.
We haven’t copied the runtime libraries into the bundle but the app works!
When compiling Swift files using
swiftc
, you can specify a dylib
runtime search folder using -Xlinker -rpath
flags. By doing so, you’re letting the linker know where to search for dynamic libraries, like the Swift-runtime ones. It turns out if you don’t specify them as I did, the search path defaults to:
This is exactly the place where the Swift runtime libraries are stored on your computer!
The iOS simulator is not sandboxed and has access to all your files. It means it can easily load the runtime libraries from any arbitrary place. I had no idea about this.
As long as you target the iOS simulator, you can create a valid, fully functional, Swift iOS app without including the Swift runtime libs in the bundle.
Building for Device
As you can see, building for Simulator is quite forgiving. We don’t need to include the runtime libraries in the bundle. We also don’t need to sign it and deal with provisioning.
Changing the build script so it can produce a valid app bundle, which can be executed on an iOS device, is another level of fun.
Firstly, we need to let the script know when to build for device.
Let’s use the
--device
flag to signal the script the desired target architecture. We update the code from step 1:
Secondly, we need to update the code from step 2:
Changes we made:
- We check the value of
BUILDING_FOR_DEVICE
and setTARGET
andSDK_PATH
variables accordingly. - We introduced the
OTHER_FLAGS
variable. This variable is empty for simulator builds. For device builds, we pass to the compiler additional information about where to find dynamic libraries in the app bundle. For device builds, we will HAVE TO include Swift runtime in the app bundle.
Finally:
Because all the next steps will be needed only for device builds, if we build for simulator, we can exit the build script right after step 4.
Let’s add this to the end of the script:
Step 5: Copy Swift Runtime Libraries
I already mentioned, when building for device, we need to include the Swift runtime libraries in the app bundle. Fortunately, no magic is required here. We can just simply copy the libraries to the bundle.
Let’s run the script and verify the result. Don’t forget to use
--device
.
Step 6: Code Signing
I spent over 20 hours trying to figure out all the steps needed to successfully build the app for device. A half of this time I spent on this one step.
Before we start, here’s a nice picture of kittens for you.
6.1 Provisioning Profile
All your installed provisioning profiles are stored in
~/Library/MobileDevice/Provisioning Profiles/
. The first challenge is to find the correct one to use for this app.
I’d strongly recommend to figure everything out in Xcode, first. If I’m not mistaken, with the free Apple dev account, you can’t even create a new provisioning profile using the web portal. You have to use Xcode for that.
Once you have the code signing working there, make a note of which provisioning profile and signing identity were used.
For the app bundle to be valid, it has to contain a file named
embedded.mobileprovision
in its root. Let’s copy the correct provisioning profile to the app bundle, and rename it:
6.2 Signing Entitlements
Another file needed to successfully sign the bundle is the
.xcent
file. This file is just another plist
, created by merging project’s Entitlements
file with additional signing information.
There’s no
Entitlements
file in our project, so this part of merging is done ?.
The additional signing information, I was referring to, is the Apple dev team ID. This ID has to be the one from the signing identity you are about to use in the next step.
Let’s create the
.xcent
file and set the required values:
6.3 Signing
Now, when we have all the required pieces in place, we perform the actual signing. The tool which will help us with this is called
codesign
.
You need to specify which identity should be used for signing. You can list all available identities in the terminal using:
For the app bundle to be valid, we need to sign all dynamic libraries in the
Frameworks
folder, and then the bundle itself. We use the xcent
file only for the final signing. Let’s finish this!
Celebrate!
The last part of the script we need to write is the final message:
You can now run the script, sit back, and enjoy your victory:
Installing to an iOS Device
Unfortunately, installing the app to a connected iOS device is not at all that straightforward as it was for the simulator. Luckily, there are 3rd party tools which make the task much more pleasant.
I’m using ios-deploy.
You can list all connected devices using
-c
and then copy the identifier of the device.
Finally, you install the app bundle to the device using:
Next Steps
Here’s the GitHub repo with the final version of the script.
I learned a lot when writing this article. I don’t personally plan to work on this script anymore. However, if someone is interested in improving it, here are some ideas:
- I didn’t need to touch
*.xcassets
files because there was no content inside. However, these files also need to be compiled. - It would be nice to get incremental builds working for Swift.
- The script currently builds only Swift files. What about projects with Objective-C, C++, Objective-C++, C sources?
- I don’t think it would make sense to parse
xcodeproj
and get the build parameters from it. What about getting the build settings from an XcodeGen file? - What about target dependencies (like custom embedded frameworks) that also need to be built?
Special thanks to Harlan Haskins for helping me with the article by answering my questions.
Do you see a typo or have a comment? PRs and issues appreciated!
Recent Posts
How to Install Xcode on Windows and build your own iOS or MacOS apps
If you really want to make Apps for iOSand MacOS Without paying any single penny on Apple hardware (MacBook or iMac) then you are at right place.
Here, In this article, we have answers to all your queries.
You must have heard about this myth that if you really want to build apps for iOS or macOS then you must own a MacBook or an iMac which is certainly not true.
You can make iOS apps without using Macbook or iMac. Yes! it is possible.
The reason they say this is because of Xcode (an IDE which is only available for MacOS ).
This software is only meant for Mac machines but now with the help of certain tools, you can operate Xcode in windows as well.
Now the question arises How to use Xcode on windows? There are many ways to do that.
We will tell you about the most efficient ways by which you will be able to achieve your iOS development goal.
Different Ways to use Xcode in Windows.
1. Virtual Machine (Vmware Workstation)
The first and foremost way to use Xcode in your windows machine is the use of a virtual machine.
It is a software which is capable of running different OS (operating system) in the existing OS.
In simple words, you will be able to use and control macOs and that can be of any version by just by installing it on Vmware. Ios internet browser.
Vmware is a virtual machine software. It basically fools your computer to believe that its Apple iMac or MacBook so that Xcode can be run on it.
Now the harsh reality.
Everything offers some pros and cons.
Vmware also has some pros and cons with it.
Yes, you will be able to enjoy macOS free of cost but it won’t be as responsive and fast as a real MacBook or iMac.
Even if you have the strongest hardware you may face some issues like lag or heating issues.
So we won’t strongly recommend it to you but if you just want to have a taste of it then of course you can go for this option.
2. Rent a Mac
The second option in this list is renting a Mac online.
This service is widely used by many developers who can’t afford to purchase Apple’s expensive MacBook or iMac.
You can even remotely access a mac by sitting in any part of the globe.
The best thing about this option is that the cost is really low and it’s the fastest option to get up and running.
Now there are many companies that offer this fantastic service.
Some of them are:
This is the most well-known service for renting a mac online. We personally witnessed it a few months back and was very satisfied with their plans and quality service. As We said this before that it will be a bit slow but do very justice with its price.
You can get more information by visiting their website or by clicking the name above.
This is another service offered to use macOS X remotely. After MacinCloud this is the second best choice to opt for. But here too the issues will be the same related to speed and smoothness.
Our third option in this category is XcodeClub. This service is run by a dedicated developer himself and if we see the reviews many people are liking it. If you can’t go with the choices above then I recommend you to give this a try. So now you can work without Xcode for Windows, if your machine is not resource-rich. You can head-over to this cloud solution.
Building a Hackintosh
What is Hackintosh
Hackintosh is basically a pc which is capable of running MacOS as smooth as real iMac and MacBook. Yes, it is possible. In this option, you don’t need to use any virtual machine ( VMware ) or any online mac renting service. This requires the most effort out of all the options above presented. However, it can work for someone who wants a separate physical computer running MacOS. Now you can use Xcode on Windows to modify an operating system. You only need few things such as bootable USB-drive etc. In order to learn more about building Hackintosh, you can visit many websites on the Internet or just YouTube it. There are numerous step-by-step guides to follow.
Third Party Solutions
Last but not the least option you have, is the use of the third party solutions. But again as we said earlier you have to compromise some features either its speed or something else. Here you won’t be using Xcode in these solutions but you’ll be able to generate an app that can run on iOS devices. Check out these great Xcode alternatives if you are not satisfied with Xcode
ReactNative helps you to create real and exciting mobile apps using JavaScript only. This is supported by both ios and Android platforms. React Native acts as a framework that builds a hierarchy of UI (User Interface) components to build the JavaScript code. With React Native Framework, you can render UI for both iOS and Android platforms. Also, this framework is open source. The big advantage of React Native is that its components have counterpart rights which allows you to reuse the components for building both Android and iOS app. You won’t need Xcode for Windows to run this application.
Xamarin is a software company founded in 2011. Recently in 2016, Microsoft acquired it. Xamarin provides developers with tools to develop cross-platform mobile applications. As per Xamarin stats, more than 15000 companies rely on their tools and the list includes many big names out there.
This allows you to built hybrid cross-platform mobile apps using HTML, CSS, and JavaScript. It’s an open-source cross-platform Mobile Application development framework by Nitobi Software (now Adobe) which allows web developers to build mobile apps. Despite the fact that you’re utilizing HTML/CSS and JavaScript to create applications, recollect that it’s not a customary desktop program environment and the client encounter example is fundamentally extraordinary.
Appcelerator is an open source framework that allows the creation of native mobile apps on platforms of iOS and Android. It focuses on streamlining development whilst using powerful native components from JavaScript code. The biggest benefit of Appcelerator for developers is the ease of cross-platform development. From a single code base, a developer can produce an app that will run on virtually every tablet and phone in the market.
Also Read:
Download Xcode From Apple
Conclusion
What Is An Xcode
So these were some ways to develop iOS and macOS apps for Windows. To do that you will need Xcode for Windows or any alternative for developing Mac, iOS apps . Tell us what method do you like and want to follow, would love to hear that.