Hi folks!
This is my first thread and sorry it seems a little long. I made a title for each part, you can pick what you are interested in : )
There are few discussion about using Swift on microcontrollers. Maybe most of you guys here are pure software engineers. I’m an electronic engineer, I’m eager to use such a modern language in my work(I mean bare-metal/RTOS based microcontroller, nothing to do with Raspberry Pi, that's a totally different thing). Just image, you can truly leave the Apple system and using Swift language for IOT hardware, like arduino, mbed or MicroPython do, but in a more modern language. That's what I plan to do.
In the past half year, I was trying really hard to make this dream come true, below is all the related information.
Hardware and traditional toolchain:
To achieve my purpose, I chose the ARM Cortex-M7 chip for my experiment. The performance of the chip is excellent. The LLVM backend has good support for it. And I can add extra ROM and SDRAM to my hardware if
Swift consumes too much sources. Once the experiment succeed, I can manage to produce a bunch of them in a short time. I use Arm Gcc toolchina Downloads | GNU Arm Embedded Toolchain Downloads – Arm Developer for their headers, libc, libm, libgcc, libstdc++ etc. It matchs the ARM chip very well.
Modifying to the compiler(Swift 4.2 right now):
Thanks to the talented structure of LLVM. It's not hard to add my own BareMetal toolchina triple(thumbv7em--none-eabi for now) to the Swift Compiler. I need to thanks @Brian_Gesiak here. His blog modocache.io gave me a deep insight to the swift compiler! I also add "-function-sections" and "-fdata-sections" to the compiler which is very important to reduce the final size of a static linked object file.
Bare-metal or RTOS:
Refer to this project: GitHub - spevans/swift-project1: A minimal bare metal kernel in Swift (Thanks to @spevans). It is a truly bare-metal swift program on the x86 machine. It’s really an awesome project. Simon Evans implemented all the lower stuff he need to run his swift program(a swift kernel) in bare-metal. Most of the lower stuff are related to memory management which the runtime relied on. In my practice, I want to do this easier. I choose a RTOS called Zephyr to be my lower kernel, so I don’t need to care about memory management. In addition, this Zephyr is POSIX compatible, so it's easier to port thread related stuff later.
Cross compiling the stdlib:
After I add my own triple to the compiler, it's very smooth to compile the whole stdlib.
Cross compiling the Runtime:
The clang already support triple thumbv7em--none-eabi, so it's not hard to compile most of the runtime files(Just did some miner change for the incompatible places). At first, I thought all the *.mm files in the runtime and stubs directory are Objective-C related. Since I won't use OC at all, I excluded them when I compiling. But then I found even with my pure easy swift program, it might emit calls to the functions in those .mm file. I don't know why. So here comes the question:
1. When compiling the Runtime and stubs files, can I exclude all the *.mm file in the runtime and stubs directory if I only use pure swift on my hardware? If so, how can I prohibit the call to those function in the *.mm files?
The biggest problem now, libicu, UNICODE stuff:
When compiling the stubs/UnicodeNormalization.cpp, I found it is heavily depend on the libicu, which is another huge project ICU - International Components for Unicode - Downloading ICU. After some research, seems no one tried to cross compile the libicu to a bare-metal microcontroller, it is heavily relied on system call itself. At first, I thought this might affect the swift String type a lot, if it's impossible to cross compile the libicu. I may just have to implement my own C/C++ like String type. But I was wrong, all the swift stdlib are heavily relied on libicu. It's so frustrating. Many basic type such as Dictionary would emit runtime call to the libicu : (
I don’t know shall I implement my whole microstdlib?(like @carlos4242 is doing) First, that's a huge of work. Second, I want my porting remain the same as the official Swift. Here comes my another question.
2. Do you guys have any good idea on how can I handle the libicu stuff?
Any related information would be helpful. Thanks very much!
Andy