Compiling from command line only (on Windows, and possibly all OSes)


#1

Lately I’ve been thinking about reevaluating how I program for the Pokitto,
and it brought me to wondering how to compile code for Pokitto at the most basic level,
with as few extraneous tools as possible - no makefiles, just GCC (and related tools distributed by ARM).

Before I saturate my brain with the contents of GCC’s documentation,
does anyone have any ideas as to roughly what might have to be done,
or perhaps know of a ‘Reader’s Digest version’ of how to compile things with GCC,
or have any insight at all?

I have skimmed @drummyfish’s related article:

But that uses a makefile, requires making symlinks and is potentially Linux specific,
so it only provides so much enlightenment.

I will most probably end up giving up on this escapade before seeing it through to fruition,
but if this idea is out there maybe someone else will one day take up the discarded mantle.


#2

I’m interested in the details too, I dunno too much about it, but @FManga will most likely know.

I guess you’ll need some kind of script anyway, to replace the Makefile – I think on Windows you can use something like a .bat file (under Unix I often use .sh files instead of Makefiles). I’d suggest taking a look at what the Makefile does and then emulate it with a tool of your choice – it contains the gcc flags that you can simply copy paste. Then compile all source files (including the library files) into .o object files, then link them. And of course you have to use the gcc with ARM backed, which I link to in my post.

The Makefile has the advantage of only recompiling parts that need to be recompiled because of changes made, i.e. it is fast. Recompiling the whole PokittoLib takes a significant amount of time, so you’ll have to handle this yourself somehow (possibly have one script for compiling the library and one for compiling your programs).


#3

Yes, I was actually thinking of using a Lua script.
Lua’s lightweight*, easy to compile and easy to make portable.
(It can even run off a USB stick without the need to copy anything to the host computer.)

* The 5.3.5 version compiled for x64 including just the .dll, the main .exe and the compiler .exe is just 375KB, which is roughly the same size as the .html+.css manual. All together the software and the manual is still less than 1GB.

I’ve considered that, but it’s a long old file and I’d have to research how makefiles work,
so I thought I’d try my luck here first before I spent too much time digging into it.

And potentially compile the libraries into .lib files (or equivalent) depending on whether that would speed up compilation or not.

(The main problem with that is that the way the PokittoLib currently works is dependent on macros and conditional compilation, so static library files would need to be recompiled when settings changed. Admittedly that probably won’t happen often for the same project.)

I know more or less how the compile-link process works,
the parts I don’t know are what commands to send GCC to perform those steps and where the .ld file fits into the process (I think it helps map the .elf to the .bin, but that’s just a guess based on a conversation I vaguely remember from months back).

That was the first thing I grabbed, before even the makefile.

They do, but I’ve always found them rather cumbersome.
Using an actual programming language (e.g. Lua, or maybe even Python) is more flexible and has a number of other advantages

See my remark about .lib files. Static libraries were invented to solve that exact problem.
(I think Linux’s equivalent is something like .so files, or maybe another kind of .elf file.)


#4

I don’t know how similar it is for ARM, but AFAIK with x86 you use -c (compile only) to create the .o files (like gcc -c -o main.o main.c) and you link everything simply by handing them over to gcc without any special flag (like gcc -o runnableprogram main.o something.o something2.o). Installed libraries are linked via -l, like -lSDL2 (the order matters sometimes).

EDIT: from the Makefile it looks like you’ll want to add these flags also:

-mcpu=cortex-m0plus -mthumb


#5

That’s a start at least, I’ll give that a try when I have a moment.

I would suspect it would be mostly the same for ARM as it is for x86,
with perhaps the exception of that pesky .ld file.

I’m vaguely aware of the -I flag being used for includes.
I think it’s specifically angle-bracket includes rather than quote includes, though quote includes fall back to the angle bracket system upon failure to match a local file.


#6

As I read the Makefile:

  • To create firmware.bin you need project.hex and you use arm-none-eabi-objcopy program.
  • To create project.hex you need project.elf and you use arm-none-eabi-objcopy program.
  • To create project.elf you need the compiled .o files and a linker script for the project (project.link_script.ld) and you do it with arm-none-eabi-gcc program (linker).
  • The .o files you create from source files (.c, .cpp, .h, …) and you do it with gtc/arm-none-eabi-g++ program (compiler).
  • To create the project link script you need some weird ld file (PokittoLib/mbed-pokitto/targets/cmsis/TARGET_NXP/TARGET_LPC11U6X/TOOLCHAIN_GCC_ARM/TARGET_LPC11U68/LPC11U68.ld) and you do it with arm-none-eabi-cpp' program.

#7

The makefile is a good starting point. You can ignore all the make-specific stuff and just look at what parameters are passed to gcc and the linker.

Instead of a lib, you’d compile each compilation unit into an o file (using -c) and simply link everything together in the end.

Not sure how a general-purpose programming language is supposed to be better at something than a domain-specific one. You’ll have to reimplement things that make gives you for free (such as knowing which C files need to be recompiled because they depend on a header that was modified).

In this case, the equivalent is an archive (.a). It’s pretty much just a bundle of .o files.
.so files are the equivalent of .dlls. You won’t gain much from bundling your .o files together into an .a, unless you want to distribute it or something.


#8

I’d have to identify that part first.

Without actually understanding some of the ‘make-specific stuff’ it’s hard to tell what happens in what order, assuming it’s even sequential.

At the very least I’d have to identify and track the ‘variables’ (assuming that’s their proper name).

The primary advantage is not needing Cygwin or Mingw to get it working.
The secondary advantage is that general purpose languages tend to be better understood and arguably easier to understand than domain specific ones.

And lastly because I’d just like to be able to do it in a very minimal way.
Understanding how to do it with nothing but the compiler toolkit gives a deeper insight into the whole process (or rather fills in some gaps).

Potentially, but I’m not overly concerned about that to begin with.

It’s debatable whether this is less hassle than make, but it’s certainly more fun.

If nothing else, tracking a single file may be less hassle than tracking multiple files.
Worth a thought anyway.


#9

I understand @Pharap’s effort here though, even if Makefile is the typical textbook solution. I’d possibly like to create my own scripts too, make them more minimal and also learn how the whole process works in detail. As I said above, I’d make one script for compiling the library and one script for compiling a program + linking the library. Make’s dependency resolving is not really needed here.


#10

I’ve made some minor progress with this.

I’ve untangled roughly what the makefile is doing and I’ve managed to construct a script that seems to successfully build (to .o files) the entirety of the PokittoLib and the hello world example.

There was a little problem with pathing (I think the makefile in zboy is outdated - it refers to PokittoLib/ instead of Pokitto/) and an error in \POKITTO_LIBS\ImageFormat\BmpImage.cpp (couldn’t find max) that I had to patch,
but beyond that everything seems to have compiled which is a miracle in itself.

Next comes linking.


#11

I ended up getting a bit distracted so this is an hour or so later than it should have been, but behold, a .bin that was successfully compiled with nothing but the PokittoLib, the arm gcc collection and a ~500 line Lua script:

hello.bin (46.0 KB)

That’s roughly 200 lines more than the makefile, but Lua is a tiny executable,
so once you factor in the size of make itself (or its equivalents) this approach ends up being smaller.

It still needs a lot of tweaking before the script can be used to compile other projects,
but I’ve proven that it’s possible, which is more than I thought I’d manage in one day,
so I’ll call that it for now.

If anyone really wants to read the script, I’ll post it, but I warn that it’s an utter mess and will only compile a basic main.cpp with a certain directory configuration.
(Also it doesn’t compile assembly files because I didn’t have any to test with and couldn’t really be bothered anyway.)

compile.lua (16.0 KB)


For some reason this accomplishment feels a lot like…


[Tutorial][Advanced]4.CLI building on GNU/Linux/Unix
#12

Here is the same also in Bash now:


#13

I’m actually aiming to create something more flexible that uses a .lua script as a project settings file, but it’s taking some time because I’m a bit rusty and I’ve been occupied with other things as well (e.g. visiting the polling station).

(One of Lua’s intended purposes was to be used as an alternative to configuration/resource files like .ini files and X11 resource files.)

At the moment a project script looks something like this:

return
{
	name = "hello", -- Project name, used for .elf and .bin file
	build = "build", -- Where all the .o files end up
	output = "output",  -- Where the .elf and .bin files end up
	source = "source", -- Where the .cpp and .h files are
	libraries = "libraries", -- For 3rd party libraries
	flags = -- So the user can override the build flags
	{
		c = {},
		cpp = {},
		asm = {},
	},
}

It’s simple enough that someone who isn’t very tech savvy and/or doesn’t know Lua can edit it,
but because it’s a Lua script it’s also possible to do stuff like conditional editing of the settings.

I’m planning to implement build targets as well, so hopefully the final product will have a command like:

pokitto-build.lua /path/to/project optional-build-target-name

Nothing’s set in stone yet though.


Also, while I think of it, after spending some time digging through the GCC documentation I’m not convinced that the build step that creates a .link_script.ld from the .ld file is actually necessary.
All it seems to do is strip the file of comments, there doesn’t actually seem to be anything in it that needs ‘preprocessing’.