summaryrefslogtreecommitdiff
path: root/content/windows.md
blob: e3704de5ceb224fddc107a06f92e4bfe5a381c00 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
Title: Support Windows not supporting Windows
Date: 2023-03-18
Category:
Tags:
Slug: windows
Lang: en
Summary:
    About the possibility of having Windows users as clients being a software
    developer that doesn't use Windows, and how to solve that technically.

I hate Windows. I don't like it, I don't support the software practices of
Microsoft and I probably never will. That doesn't mean I don't live in this
world, where unfortunately most of the people uses Windows. Many people have no
other choice than using Windows and they still deserve to have some good free
software in their computers.

Of course, I always try to encourage my clients (and everyone around me!) to
use free software and stop using Windows, but sometimes it's impossible, and
it's always better for them to use Windows with some free software made by
me[^money] than using Windows with more proprietary bloatware done by any
garbage corporation that doesn't care about their freedom.

[^money]: And I can earn some money in the process.

Since I started with ElenQ Technology I always had this issue in mind, and the
time to tackle it has come, so:

> How could I make software for Windows users if I don't use Windows, I don't
> have any machine that runs Windows and I don't support Windows in any way?

Until recently, most of my clients asked me for Web based tools, so I dodged
that ball without even realizing it, but I always had that the impression I
would have to tackle the issue someday and I was just delaying the moment to
make some research.

During the last couple of weeks, in my spare time, I made that research a
little bit and this is a simple high-level result of that research.

Needless to say this research is for myself and I have a very strong
background to take in consideration (read the blog and you'll see!), so it
probably won't fit your needs in any way, but it does fit mine and probably
some of my near colleagues'.

1. [Web-based](#web)
    1. [Web Extensions](#webext)
2. [Java Virtual Machine](#jvm)
    1. [GUIs](#jvmgui)
    2. [Interesting JVM languages](#jvmlangs)
        1. [Clojure](#clojure)
        2. [Kawa](#kawa)
    3. [Distribution: JAR files and UberJAR](#jar)
3. [Native Binaries](#native)
    1. [MinGW](#mingw)
    2. [Zig](#zig)
    3. [Distribution: statically built binaries](#staticbin)
    4. [GUIs](#guilibs)
4. [Distribution with Windows Installers](#wininst)
5. [Conclusion](#conclusion)
6. [Final words](#finalwords)

### Web-based {#web}

Most of the times I am asked to do Web stuff, because most of the people just
use Webs for everything[^ask-vs-need].

[^ask-vs-need]: Often times what the clients want or they ask for is not what
  they need, so be careful with that.

Clients are used to work with websites, the UIs are easy to make, they work in
any device... They are cool for many things, but when you need to make any
interesting native operation they don't make any sense (i.e. reading or
creating files locally) and they require deployment, one way or another, and
that may carry extra costs or efforts and maintenance.

#### Web Extensions {#webext}

Another interesting option are Web Extensions (browser extensions). They are
kinda easy to make and making them work in several browsers[^web-ext] is almost
no effort, they don't require deployment (no servers, no pain) and they have
more permissions than a regular website.

[^web-ext]: API support in all the browsers is not the same, be careful with
  that.

The problem they have is the browser is still a constrained environment, and
you might not be able to do anything you'd like in there and they force the
users to have the browser open in order to run them.


### JVM runs everywhere! {#jvm}

I've never been a Java fan. I don't really like the language and the fact that
it supposes you are using an IDE to code in it, but I have to say the JVM is a
really interesting environment.

The main problem it has is it's pretty large, but it's not a huge deal to tell
my clients to install it (if they don't have it already) and it provides most
of the functionality I'd ever need out of the box.

#### GUI {#jvmgui}

It comes with GUI stuff by default (Swing and AWT[^swing]) and there are more
modern ways to make GUIs like JavaFX, which I didn't manage to make it work in
my Guix machine.

[^swing]: Welcome back to 2001.

#### Interesting JVM languages {#jvmlangs}

The best thing about the Java Virtual Machine is you don't need to use Java for
it. There are some cool languages full of parenthesis you can use in it.

##### Clojure {#clojure}

I have some Clojure past. It's a language I love. It had a couple of things I
didn't like about it though:

- The startup time of Clojure made me feel uncomfortable.
- I was worried about the size of the JVM.
- Most of my code relied too heavily in Leiningen for everything and I didn't
  know very well what was going on internally or which libraries were being
  used (a little bit of an NPM effect), and I was worried about the maintenance
  of the software if I was asked to make changes in the
  future[^maintenance-future].
- The Java interaction is really well designed at a language level, but
  integrating Clojure's functional programming with heavily imperative Java
  code (like GUIs) feels uncomfortable.

I have to say I don't code in Clojure for a long time and I wasn't that good
programmer at the time I played around with it. Probably I would make a way
better use of it right now, and things that I felt weird may feel way more
comfortable.

None of this issues is a big deal anyway. For these kind of projects for
Windows, it might be a great choice, as most of the problems don't mean a lot
any more in this context. I may give Clojure another go.

[^maintenance-future]: Guix can help here!

##### Kawa {#kawa}

Recently I discovered Kawa, and it looks great.
Kawa programs are easy to build with no additional tools, it's a scheme, it's
**fast**, and its Java interaction feels natural.

Of course, there are almost no libraries written in Kawa, no tutorials, no
learning resources further than the documentation (which is very good, by the
way).

It's minimalistic, it's easy to set up and is really fast: it might be a good
choice for many projects.

#### Distribution: JAR files and UberJARs {#jar}

The Java world might be "too enterprisey" for someone like me, but it has
interesting features. The `jar` files are just zip files that have Java
bytecode and resources inside.

In any machine with Java installed they are launched automatically when they
are clicked. There's no need to unpack them or anything like that.

There are several ways to make those `jar` files, and one is simply insert all
the dependencies of the Java application inside of the `jar`. That's called the
UberJAR.

Doing this makes you sure to have all the dependencies and resource files (such
as icons and stuff like that) inside of a file that you can distribute and will
always run if there's a JVM installed in the target machine. Simple
distribution!

The only problem they have is they are not located in the correct system folder
to appear in the application launchers[^jpackage].

[^jpackage]: The Java ecosystem provides a tool to solve this [called
  `javapackage`](https://openjdk.org/jeps/343) but unfortunately it doesn't
  cross-compile (Wine for the win?) and it would add a full Java runtime to the
  installer. Maybe it's too much.

### Native binaries {#native}

Sharing prebuilt binaries is also feasible if you are using the right tools,
but it might be tricky to distribute.

The first thing you have to do if you want to share binaries is cross-compile
them for windows. I found a couple of tools that fit very well with my style
here: MinGW and Zig.

#### MinGW {#mingw}

Recently I discovered this and it happens to be great. Simply put, MinGW a
cross-compiler toolchain for Windows. It has everything you need to build your
C/C++ software for Windows: gcc, binutils, libraries and header files.

Pretty straightforward.

Guix also supports this as a target so I can even `guix build --target=` with
it and have all the fun.

#### Zig {#zig}

Zig is a great programming language and the tooling around it is absolutely
fantastic. It's designed to be easy to cross-compile and don't need anything
else than the Zig compiler itself to be able to build your Zig, C or C++
software for a Windows machine. Just change the target and boom, works!

Zig also comes with a build-system, that lets you describe how to build your
whole project and build it with a simple command. No need to use external tools
like GNU Autotools, Make, CMake, Meson or anything like that. One Zig
installation comes with everything you need.

> Another advantage of Zig is that I love the language and I'm looking for an
> excuse to learn it. I think it's very well designed and I love the community
> it has. I don't like the syntax that much but I think I'll get used to it.

#### Distribution: statically built binaries {#staticbin}

In order to distribute the binaries, there only obvious choice is to statically
link everything and give it in one `.exe` file to my clients. I can't really
trust non-tech users to install all the dependencies in place and I can't guide
them in the process of how to do it because I don't know how to do it myself,
and I can't try as I don't own any Windows machine.

Statically built binaries require no installation so that's great, but they are
not set in the correct folder of the system and they don't support resources as
icons and stuff like that[^resources-bin]. They might be ok for many things but
they are not a perfect solution either.

[^resources-bin]: The problem with the resources can be bypassed by a
  self-expanding executable: a program that unpacks its binary contents in the
  current folder. They can be made by 7zip and other tools like this, but I
  don't really like it, as they pollute the current folder and you might not
  expect that to happen. Some games are distributed like this.

#### GUIs {#guilibs}

This kind of clients require GUIs most of the time. I don't imagine them
running a script from the shell.

There are many GUI libraries I could use but I'd like to use anything that is
small and easy to build for any target. That leaves most of them out.

- I tried to build [IUP](https://www.tecgraf.puc-rio.br/iup/) myself but the
  build process is basically broken. It looks good and uses native GUI
  components, but if the build process is broken I can't really trust it. I
  could just use the binaries they provide but I don't like that.

- I built [FLTK](https://www.fltk.org/index.php) successfully without problems
  and I even [packaged it in my personal Guix
  channel](http://git.elenq.tech/guix-packages/commit/?id=b952e7778843adbebae0d12d6f1601e4594313eb).
  It's not beautiful, but it works, and I don't expect it to be hard to build
  for Windows either.

- I could go for something like Dear ImGUI, but ImGUIs are better suited for
  programs that are being rendered continuously like games and such.

- Qt, GTK, wxWidgets and those are great too, but probably too much for a
  simple man like me[^kde].

[^kde]: Probably you didn't know but my first free software contribution was
  for KDE and I had to deal with Qt. It was right in the migration from Qt4 to
  Qt5. Good times.


### Distribution with Windows installers {#wininst}

Software distribution can be eased using a Windows Installer like MSI or MSIX.
Those packages know where to install everything and they do automagically, as
Windows users are used to.

They require extra tools but they might be simple enough to deal with and help
a lot removing the downsides of the distribution methods described previously.

- GNOME project has a tool called `msitools`, which exposes a similar interface
  to WixToolset, a popular Windows installer generator. I can use that to build
  and inspect MSI installers.

- Microsoft also provides [a tool for MSIX
  installers](https://github.com/microsoft/msix-packaging) that is Open Source
  but it happens to insert
  [telemetry](https://github.com/microsoft/msix-packaging/issues/569) (what a
  surprise!).

- There's a [Python package called
  `msicreator`](https://github.com/jpakkane/msicreator) that simplifies the use
  of `msitools` with a simpler approach that might be more than enough for my
  needs.

There are also some language-specific tools like PyInstaller but that forces me
to use Python, which I like but I don't know if I want to keep using for
everything. Also, it includes the interpreter in the installer, which feels
like a little bit too much.

### Conclusion

Each choice comes with its downsides and shines in specific scenarios. Working
in a classic C/C++ setup with MinGW might be great but I have to make sure I
don't use a complex dependency tree, as everything might fail to compile or
distribute for Windows.

I want to learn Zig. It's really cool and I think it will ease the process
significantly. I'm not sure about the C integration but I need to give it a go
first. It might become my go-to language for these kind of applications.

On these cases I need still to find the best GUI library to use (suggestions
welcome!).

The JVM case is also interesting. It comes batteries included and has Swing by
default, which is horrible but it's something. For faster development I could
use some flexible language like Clojure or Kawa there, being the second way
faster than the first but also way less know (which shouldn't be a problem as I
don't want to rely in many external libraries).

All these options look feasible so I could just go for any of them. Obviously,
some have way better performance than others (C/C++/Zig vs Clojure) but the
ease of development is also something I have to take in account. That I'd need
to think about when the projects come.

We'll see...[^chicken]

[^chicken]: I can always chicken out and go for PyInstaller + PyQt when the
  projects come. 😐

### Final words {#finalwords}

It's obvious that I left many options out and I can't wait to get some emails
of people recommending me to learn Go or Rust[^rust], but this non-exhaustive
research is mostly based on my personal (and current) preference.

Surely you'll think I'm making it way more difficult than it actually is:
*"just install a virtual machine and build there! Buy a Windows machine if you
really want to solve this issue!!"* and you'd probably be right, but it doesn't
feel right to me. So I won't.

If you have other ideas or success stories that fit this line of thinking don't
hesitate to [contact me](https://ekaitz.elenq.tech/pages/about.html).

Stay safe!

[^rust]: I don't like Go but I'm open to learn Rust even if its a little bit
  more complex than I'd like it to be (and I don't like the syntax). It would
  require me to allocate a long time for it, which is not a problem, but I need
  to be sure that I will be able to get some benefit from it.