Friday, October 30, 2020

Apple Heard You Like Braces

    After cleaning up all of the user-visible warnings on Linux earlier this week, I moved on to doing the same for Mac. For the uninitiated, Apple uses a custom version of the Clang compiler. This compiler is very picky about how you should write your code, and it will throw all kinds of warnings at you. In this case, I was getting something like 400 instances of -Wmissing-braces.

    All of these warnings came from one file... the implementation for GCollision. GCollision is very large; some 13,000+ lines. GCollision also uses lines, vectors, and matrices that are defined in GMath like this:


The union is just there to let us access the two vectors (points) with an index if we wanted to loop or something like that. Using a GLINE is pretty straightforward. Here is an example of a declaration of a GLINE within some function: 

    The first line in the function sets data in the first vector of the line. The second line does the same for the second vector. All is well, right? 

    Not according to Apple:

    "Suggest braces around initialization of subobject"

    Apparently, this is caused by the way we declared our line/vector/matrix classes. Apple clang treats the class itself as one scope, the union as another scope, and the struct within the union as a third scope. 

    The solution to this warning is to add braces for each scope. So for our GLINE here, we have to add them for the scopes of the line class itself, and then also for the vector classes within the final scope.

    It looks like this...

    ...and it hurts me.


    After figuring out the solution, I now had to add braces like this to all ~400 instances of this warning in GCollision, by hand, on a remote Mac three timezones away.

    In the end it took me about four and a half hours.


    Why, Apple? Why did you make me do this? *cries in braces*

Monday, October 19, 2020

The Sandbox environment in iOS

     Over the last week I have been porting GFile to iOS. As such I have been getting used to the environment that iOS places app developers in. iOS apps only allow developers to access certain directories when doing file I/O. Any directory accessed outside of these specified locations will give you a "permission denied" error. The app needs to be given access to directories outside of it's "sandbox" by the user, and even then you still do not have access to the whole device. With these restrictions I need to conform the GFile implementation as to not access files that the operating system does not allow to be accessed.

    I first started out the GFile implementation by copying what was done on Mac, and mold it into something that would work on iOS. At the moment I have some of the functionality working on iOS, but not all of it. First thing was to get opening a file working, this was as simple as checking if the file was in the sandbox and give it to the user, if the file was not in the sandbox then I would return an error stating that the user did not have permissions to access the file.

    Another thing to consider was the directories that the user has access to, specifically giving those directories names. After a long meeting with the other App porting developer, we had come up with a few names for Gateware to use that are not platform-dependent like the names used by Apple and Microsoft. Here are some examples of directory name changes:

Library -- UserFolder

tmp -- TempFolder 

Library/Caches -- CacheFolder

    Overall the GFile port has been going smoothly, I hope to complete this by Wednesday. 

Porting GWindow to UWP

    Porting GWindow seemed like the obvious next step to take after porting GFile. GWindow is very important to Gateware and is essential for the library. Getting it to work on UWP and have parity with the rest of the Gateware platforms is crucial. This will be a short update as the GWindow port is still ongoing with many other things that will need to be done, such as the unit tests.

The Problem:

    I knew going in that GWindow was going to be a handful, what I didn't expect was for most of the library to be deemed unsupported by the UWP platform. Most of the imported stuff like WndProc is inaccessible on UWP because of the sandboxing that happens within CoreWindow, that makes functions such as ProcessWindowEvents useless. This left me with the question of "What is GWindow going to be used for in UWP?". 

The Solution:

    I beat my head against a metaphorical brick wall for about 3 days trying to figure this out before I just decided to only do the functions that made sense for UWP. The purpose of each implementation of the GWindow interface is to provide functionality for that platform, so that is what I did. Only a few functions made the cut, such as GetClientWidth, GetClientHeight, and GetWindowHandle.

    Figuring that out was the easy part, it was the revelation that to get those functions working, I would need access to the CoreWindow. This is made difficult by the fact it needs to be accessed from the main UI thread. This was solved by these two functions:

    Calling the second function, allows you to just pass a lambda expression that contains what you would like to happen on the UI thread. This is where I would get access to the CoreWindow and do the actions that I needed. 

To Be Done:

    Currently, the GetWindowHandle function is still not working. That is down to the return value that the function has, 'void*'. As of right now, I have not successfully gotten CoreWindow to cast to it correctly.

Monday, October 12, 2020

Rectifying XCode thinking an iOS project is a 32-Bit MacOS project

     I was planning on porting GFile to iOS, but my plans were derailed by XCode. Last week I had been trying to get XCode to recognize two separate targets in one project. I had achieved that task, but I had one other issue. XCode wanted to compile the iOS target as a 32-bit Mac executable. As such the symbols for iOS were not recognized and the build failed. And so I was stuck once again. The Unit Tests for Gateware's pure C++ code, which should run on anything that can compile C++11, was not even compiling due to this error. 

    Most of the compilation errors were from mismatching architectures. As such I resolved to fix this by creating a new iOS project via XCode and looking at what build settings were enabled by default, and matching those settings on the Gateware iOS target. After a lot of fiddling with the settings I had gotten the compilation errors down to just 6 parsing errors. These errors were just from the iOS specific classes. I had to change one final setting to resolve this error, the "hide Clang debug symbols" setting. 

    Once all of the settings were in order, I had one final task to complete to get the unit test app running in simulator. The "info.plist" file tells the iDevice what information to give to the installed app. I had CMake setup the app bundle name and version through a .plist template that CMake provides. After setting these two entries were filled, the app ran on simulator, and the unit tests for the Gateware Core and Math libraries ran and passed. 

    I hope to get more libraries ported over to iOS and this step in the process will help immensely with development and testing of the libraries.



Getting Gateware Unit Tests to Run on Xbox One

    Since last Wednesday when I wrote my last blog, I have got quite a bit done. The GFile port is officially done with all new GFile functionality working on all platforms. The issue that I found on Mac last week turned out to be a new bug that only seems to appear on MacBooks, very strange.  After that, I finally got the chance to merge with GApp, the class that Lari wrote for all future mobile ports of Gateware. There was only a few conflicts to resolve and a tweak to get it working perfectly. I finished all that before the end of the day on Friday and figured it was about time I got around to actually putting Gateware on an Xbox, the main reason of bringing Gateware to UWP.

The Process:

    The steps required to get an Xbox One or any other variant of the Xbox lineup into developer mode is quite simple. The Xbox One that I have currently was lent to me to work on and it already had dev mode enabled, but for the sake of knowing how it is done, I started from scratch. I deactivated it and went from there.


    There are very comprehensive guides that can be found on Microsoft's website. I followed them as long as I could until I ran into an issue. As of writing this, there seems to be a bug with the dev mode app that can be downloaded from the Windows Store. It seems to allows hang on this screen, which is a big problem if you want to start developing on the console.



    After looking around for a solution, I found an alternate solution as to how to get into dev mode. This solution requires hitting all four shoulder buttons on the controller at the same time in the System Console Info section in the settings app.


    Once all 4 buttons have been pressed the option shown above appears, pressing that will bring up the dev mode conformation screen.


    Pressing Continue, the console will appear to reboot and after about 5 or so minutes, the Xbox will boot up into dev mode.


    The next step in the process is getting Visual Studios setup properly to connect with the Xbox. Instead of me just rehashing what is already explained really well in a Microsoft document, I will just link it here. In short though, it is as simple as typing in the correct IP address in the properties tab of the project.

The Result:



WARNING: fixing warnings...

Week 1

    So I'm new but I've been here for a couple of weeks already. I just forgot to do the first weeks blog post. Super professional, I know. 

    In my defense, there really wasn't anything too interesting going on. I was just trying to get dev environments set up on the three major platforms (Windows, Mac, Linux). The only real problem I had was during the installation of Linux.

    I was trying to set up a dual boot situation on my main Windows machine so I would be able to boot into either. The Gateware repo has a tutorial on the subject which I followed. Everything started off just fine. I was able to boot into the Linux Mint installation environment from a USB drive and then create a new partition on one of my SSD's. The problem arose when I went to perform the actual install of Linux. 

    The installer is supposed to recognize your Windows installation and then give you an option to "install alongside Windows" but for whatever reason, mine didn't. I had to do everything manually. This meant I had to designate parts of the new partition as /root and /home and pick their sizes/formats by hand. Thankfully there's plenty of online materials and tutorials that tell you how big and what format these things should be. The only problem was a suspicious dropdown box at the bottom of the installer that I didn't pay attention to. This box is for telling the installer where to put the boot sector.

    It defaulted to my Windows drive...

    So, as you can probably surmise, I ended up overwriting my Windows boot sector and loosing access to my Windows install. All of my files and data were still there, I just couldn't boot into Windows to access them. 

    I didn't realize exactly what happened at first so I thought I could just boot into Linux, delete the boot sector, and then have my Windows back, good as new. So I did that and now I had no access to any operating systems at all. 

    The solution to this, was to go on another computer, create a Windows installation media USB drive, boot off of that, access the command prompt, and tell it to reinstall the Windows boot sector. Thankfully it worked, and I was able to begin the process again and properly select a different drive for the Linux boot sector. 

    And that's pretty much all the excitement for the first week. Everything else was just, "does this compile and run? Ok, cool. Moving on."

Week 2

    Now that I think about it, week one was way more interesting than week two. The first half of the week was just experimenting with the end-user side of Gateware to get a better understanding. The second half was just searching through warnings on Windows and fixing the ones that affect the end-user.

    That's pretty much it. 

Wednesday, October 7, 2020

Porting GFile to UWP

The Task:

    About two weeks ago, I ported the audio libraries over to UWP. Soon after I got the unit tests all passing I realized that the auditory output did not match what was heard in the win32 version of the Gateware unit tests. This was cause for concern but I could not continue to spend too much time on one library, so it was decided that I was to move on to another and mark the audio difference as a bug to come back to later. I decided to begin the porting of GFile as I had to do a little bit of file I/O work in the audio unit tests and it was fresh in my mind.

The Problem:

    My initial thoughts on the GFile port were ones of ease. While this did turn out to be the case, it did not seem like that at first. Everything I read up to that point in my research suggested that the code that was already written for the Win32 implementation of GFile should work just fine for UWP. But for the life of me, I could not get it to work. This led me to the conclusion that I should rewrite the entire GFile UWP implementation using WinRT API calls. This caused many problems in the end, mostly with functionality differences with the other platforms.

The Solution:

    It was this difference in functionality that would drive me back to looking at the code that was already there from Win32. It was at that point that I discovered why GFile was failing at writing files out to the directory that I had chosen, the install location. I found out that the install location of a UWP app is read-only, which is fine for assets and resources that are only meant to be read, so I made the change to writing to the app folders instead which are both read and write capable. That was the change that got GFile working perfectly using the Win32 code.

    That wasn't the end for GFile though. Severe code branching was happening in the unit tests, specifically for audio to help differentiate between the many platforms Gateware can run on. Imagine what is pictured to the right but for every sound requested for the audio unit tests, it was happening almost 90 times.  It wasn't that this code didn't work, it was just messy and not really sustainable as more and more platforms are eventually added to Gateware down the road, such as iOS and Android.

    This brought up the proposal of adding additional functionality to GFile to get the different accessible file locations for the different platforms. This is mostly for the addition of the mobile platforms as this has little application to the ones on desktop. Lari sat down with Jacob, the iOS dev on the project, and I last Friday and we came up with a solution. These new functions will get the correct directory for each platform you are on as each platform implementation will have their own version of this function. I finished the UWP implementation before the end of the weekend but have been finishing up the rest of the platforms such as Windows, Linux, and Mac through the beginning of the week. So far GFile is up and running on UWP, Windows, and Linux with all unit tests passing. Mac is still a issue but that may be because I am running an older build of Gateware that has since had some bugs fixed which I am experiencing, but that is a separate issue in of itself.

    With GFile done and working, GLog kind of just fell into place and it worked perfectly without any issues or tweaking needed. Next, is fixing up the Mac issue and finally merging with Lari's GApp branch.


    
 


Tuesday, October 6, 2020

XCode and iOS with CMake: A Challenge

    I was tasked to come up with a way to develop Gateware on iOS. At the moment Gateware is using CMake to create the projects to develop on. This way the Gateware team can make multiple projects for every platform that they develop for. At first I took this task as making another project for iOS specfically, and made a simple CMake script that made an XCode project that would build Gateware for iOS. Making a XCode project purely for building on iOS is pretty simple, but I learned that it is possible for a single XCode project to have multiple build targets, and set out to make the Gateware MacOS project also build for iOS. 

    It turns out that adding an iOS target to an XCode project through CMake is not very intuitive as making an XCode project only with iOS. At first I tried to change the Project settings when generating the iOS target. The issue with this approach is that the other targets in the project were using the project defaults, and changing the project default to iOS would effect the other targets to also target iOS. I would have to change the targets already setup in the project for this strategy to work, as that would require a large rewrite of the CMakeLists file, I set out to find another way to go about this issue.

    After searching the internet for a way to have a Mac and iOS target in a single project for XCode, I ended up going back to the CMake documentation. I found that in CMake you can change specific target settings in XCode using the set_target_properies command and XCODE_ATTRIBUTE property. I ended up creating a dummy target in CMake and overwriting the necessary build settings to essentially convert a Mac executable to an iOS app. The next step would be to get Vulkan installing on an iPhone using CMake.

References:

https://cmake.org/

https://gitlab.com/gateware-development/gateware