MP-WP, a genesis

February 8th, 2018

This site runs on a found version of mp-wp. To get it to work on a php 5.6 installation, I needed to make some changes. These were done in an ad-hoc fashion and, as a result of the sometimes live fixing process, I had no log or
record of what I did. This cannot stand, so I redid most of the word starting
by making a genesis of the mp-wp, I found in the channel1.

As a vpatch cannot contain binaries or special character sequences, I removed all the binaries (gif, png, jpg and swf) and put these in tarfiles. The sha512sum of the tarfiles I put in a README and in the tarfiles.sha512sum.
All removals and edits done to the version I found and before the patch was made are described in the README file.

This genesis does not contain images, so these are distributed separately in

After pressing the genesis, go into the blog directory. Copy the tar-files to the blog directory. Check the sha 512 sums. In the blog directory unpack each tar-file (tar xf wp-admin-images.tar.gz etc). Done.

On this genesis, I currently have two patches, one to suppress and fix some warnings;

And one to fix the comments;

There is still a whole lot of pruning on the todo list, with the first item being to investigate and hopefully remove the 'kses' filtering system.

  1. I know that work was / is being done on a genesis vpatch of mp-wp, but that seems to be stuck for now. []

GNAT and Pragma Inline_Always: A report

February 5th, 2018

Will the GNAT ADA compiler inline a function when using Pragma Inline_Always? and proves the dump of a function a red herring? In short, yes it will and no it doesn't. The Pragma Inline_Always needs to be put in the specification files ('*.ads') and not in the implementation files ('*.adb'). The dump of a
function in a binary can accurately show if inlining was performed or not.

To run the code, use the following v-patch on the code in FFA chapter 11;

We start with the preliminaries, as for the gnat version (gprbuild -version):

GPRBUILD GPL 2016 (20160515) (x86_64-pc-linux-gnu)
Copyright (C) 2004-2016, AdaCore
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

In FFA almost all functions have the pragma Inline_Always adornment. According to the gcc 4.9.4 documentation: Similar to pragma Inline except that inlining is not subject to the use of option -gnatn or -gnatN and the inlining happens regardless of whether these options are used.

All of the code is based on a copy of the ffademo files provided in the FFA chapter 1 genesis.

I base the tests on the FZ_Add procedure and use it to implement the slowest possible multiplication function. This multiplication function is specified to multiply a FZ by a natural number. To multiply we will add the input FZ to a tally as many times as given by the natural number.

   procedure Mul_By_Sum
     (N        : in     Natural;
      X        : in     FZ;
      Z        :    out FZ;
      Overflow :    out WBool)
   is

      C : WBool := 0;
   begin
      Z := (others => 0);
      for i in 1 .. N loop
         FZ_Add (X, Z, Z, C);
      end loop;
      Overflow := C;
   end Mul_By_Sum;

   procedure Inline_Experiment is
      X : FZ (1 .. 256) := (others => 0);
      Z : FZ (1 .. 256) := (others => 0);

      -- Carry.
      C : WBool := 0;

      N : Indices := 256;
   begin
      for i in 1 .. N loop
         X (i) := Word (i);
      end loop;

      Mul_By_Sum (10000000, X, Z, C);

      Dump (Z);

   end Inline_Experiment;

The experiment is divided over 3 programs, each with their own set of files;

  • inline_exp1_main; the FZ_Add and W_Carry procedures from libffa are used as is.
  • inline_exp2_main; the FZ_Add and W_Carry procedures are copied and included in the body of the module. For clarity we add a '2' to the procedure names.
  • inline_exp3_main: the FZ_Add and W_Carry functions are copied to a separate module and pragma Inline_Always is included in the specification file. For clarity we add a '3' to the procedure names.

Read the code in ffainline (except for the mul_by_sum these are all either calls to ffalib or copies of the code from ffalib), build and run everything with:

cd ffa/ffainline

gprbuild

time ./bin/inline_exp1_main > exp1.txt

time ./bin/inline_exp2_main > exp2.txt

time ./bin/inline_exp3_main > exp3.txt

diff exp0.txt exp1.txt

diff exp0.txt exp2.txt

diff exp0.txt exp3.txt

The diffs should be empty, and the timings should differ. A table with
my timings;



Experiment Time
(seconds)
1 8.579
2 4.924
3 4.871

The second and third versions are a little more than 40% faster than the first version. The only difference between the codes is where the procedures are defined, so the timing difference is all due to inlining. Let's check by disassembling the code with objdump. As everything will be disassembled by objdump, we need a small script to return the just code for one function;

#!/bin/sh

FUNCTIONLINE=`objdump -t $1  |  sort | nl | grep $2`
LINENR=`echo $FUNCTIONLINE | awk '{print $1}'`
NEXTLINENR=`expr $LINENR + 1`
NEXTLINE=`objdump -t $1  | sort | nl -s ' @ ' | grep $NEXTLINENR @ `
START=`echo $FUNCTIONLINE | awk '{print $2}'`
STOP=`echo $NEXTLINE | awk '{print $3}'`
objdump --start-address=0x$START --stop-address=0x$STOP -S -d $1

The dump for the first version of mul by sum2.

./dump-function.sh inline_exp1_main inline_exp1__mul_by_sum


inline_exp1_main:     file format elf64-x86-64

Disassembly of section .text:

0000000000401430 <inline_exp1__mul_by_sum>:
  401430:       55                      push   %rbp
  401431:       48 89 e5                mov    %rsp,%rbp
  401434:       41 57                   push   %r15
  401436:       41 56                   push   %r14
  401438:       41 55                   push   %r13
  40143a:       41 54                   push   %r12
  40143c:       53                      push   %rbx
  40143d:       48 81 ec 38 10 00 00    sub    $0x1038,%rsp
  401444:       48 83 0c 24 00          orq    $0x0,(%rsp)
  401449:       48 81 c4 20 10 00 00    add    $0x1020,%rsp
  401450:       49 63 40 04             movslq 0x4(%r8),%rax
  401454:       49 89 cc                mov    %rcx,%r12
  401457:       49 63 08                movslq (%r8),%rcx
  40145a:       49 89 d7                mov    %rdx,%r15
  40145d:       31 d2                   xor    %edx,%edx
  40145f:       41 89 fd                mov    %edi,%r13d
  401462:       48 89 75 c8             mov    %rsi,-0x38(%rbp)
  401466:       4c 89 c3                mov    %r8,%rbx
  401469:       39 c1                   cmp    %eax,%ecx
  40146b:       7f 1c                   jg     401489 <inline_exp1__mul_by_sum+0x59>
  40146d:       48 29 c8                sub    %rcx,%rax
  401470:       48 8d 14 c5 08 00 00    lea    0x8(,%rax,8),%rdx
  401477:       00
  401478:       48 b8 00 00 00 00 04    movabs $0x400000000,%rax
  40147f:       00 00 00
  401482:       48 39 c2                cmp    %rax,%rdx
  401485:       48 0f 47 d0             cmova  %rax,%rdx
  401489:       31 f6                   xor    %esi,%esi
  40148b:       4c 89 e7                mov    %r12,%rdi
  40148e:       e8 bd 80 03 00          callq  439550 <memset>
  401493:       45 85 ed                test   %r13d,%r13d
  401496:       7e 38                   jle    4014d0 <inline_exp1__mul_by_sum+0xa0>
  401498:       45 31 f6                xor    %r14d,%r14d
  40149b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
  4014a0:       48 8b 7d c8             mov    -0x38(%rbp),%rdi
  4014a4:       41 83 c6 01             add    $0x1,%r14d
  4014a8:       4d 89 e0                mov    %r12,%r8
  4014ab:       49 89 d9                mov    %rbx,%r9
  4014ae:       4c 89 e2                mov    %r12,%rdx
  4014b1:       48 89 d9                mov    %rbx,%rcx
  4014b4:       4c 89 fe                mov    %r15,%rsi
  4014b7:       e8 c4 00 00 00          callq  401580 <fz_arith__fz_add>
  4014bc:       45 39 f5                cmp    %r14d,%r13d
  4014bf:       75 df                   jne    4014a0 <inline_exp1__mul_by_sum+0x70>
  4014c1:       48 83 c4 18             add    $0x18,%rsp
  4014c5:       5b                      pop    %rbx
  4014c6:       41 5c                   pop    %r12
  4014c8:       41 5d                   pop    %r13
  4014ca:       41 5e                   pop    %r14
  4014cc:       41 5f                   pop    %r15
  4014ce:       5d                      pop    %rbp
  4014cf:       c3                      retq
  4014d0:       31 c0                   xor    %eax,%eax
  4014d2:       48 83 c4 18             add    $0x18,%rsp
  4014d6:       5b                      pop    %rbx
  4014d7:       41 5c                   pop    %r12
  4014d9:       41 5d                   pop    %r13
  4014db:       41 5e                   pop    %r14
  4014dd:       41 5f                   pop    %r15
  4014df:       5d                      pop    %rbp
  4014e0:       c3                      retq
  4014e1:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  4014e8:       00 00 00
  4014eb:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

Can you see the callq 401580 <fz_arith__fz_add> in there? clearly the FZ_Add was not inlined. Now for the second version;

./dump-function.sh inline_exp2_main inline_exp2__mul_by_sum


inline_exp2_main:     file format elf64-x86-64

Disassembly of section .text:

0000000000401420 <inline_exp2__mul_by_sum>:
  401420:       55                      push   %rbp
  401421:       48 89 e5                mov    %rsp,%rbp
  401424:       41 57                   push   %r15
  401426:       41 56                   push   %r14
  401428:       41 55                   push   %r13
  40142a:       41 54                   push   %r12
  40142c:       53                      push   %rbx
  40142d:       48 81 ec 38 10 00 00    sub    $0x1038,%rsp
  401434:       48 83 0c 24 00          orq    $0x0,(%rsp)
  401439:       48 81 c4 20 10 00 00    add    $0x1020,%rsp
  401440:       49 63 40 04             movslq 0x4(%r8),%rax
  401444:       49 89 cf                mov    %rcx,%r15
  401447:       49 63 08                movslq (%r8),%rcx
  40144a:       49 89 d6                mov    %rdx,%r14
  40144d:       31 d2                   xor    %edx,%edx
  40144f:       89 fb                   mov    %edi,%ebx
  401451:       49 89 f4                mov    %rsi,%r12
  401454:       4d 89 c5                mov    %r8,%r13
  401457:       39 c1                   cmp    %eax,%ecx
  401459:       7f 1c                   jg     401477 <inline_exp2__mul_by_sum+0x57>
  40145b:       48 29 c8                sub    %rcx,%rax
  40145e:       48 8d 14 c5 08 00 00    lea    0x8(,%rax,8),%rdx
  401465:       00
  401466:       48 b8 00 00 00 00 04    movabs $0x400000000,%rax
  40146d:       00 00 00
  401470:       48 39 c2                cmp    %rax,%rdx
  401473:       48 0f 47 d0             cmova  %rax,%rdx
  401477:       31 f6                   xor    %esi,%esi
  401479:       4c 89 ff                mov    %r15,%rdi
  40147c:       e8 af 7e 03 00          callq  439330 <memset>
  401481:       85 db                   test   %ebx,%ebx
  401483:       0f 8e db 00 00 00       jle    401564 <inline_exp2__mul_by_sum+0x144>
  401489:       49 63 06                movslq (%r14),%rax
  40148c:       45 8b 55 00             mov    0x0(%r13),%r10d
  401490:       45 8b 5d 04             mov    0x4(%r13),%r11d
  401494:       45 8b 76 04             mov    0x4(%r14),%r14d
  401498:       49 89 c5                mov    %rax,%r13
  40149b:       48 89 45 c0             mov    %rax,-0x40(%rbp)
  40149f:       49 63 c2                movslq %r10d,%rax
  4014a2:       4c 89 ef                mov    %r13,%rdi
  4014a5:       48 29 c7                sub    %rax,%rdi
  4014a8:       49 8d 04 ff             lea    (%r15,%rdi,8),%rax
  4014ac:       45 31 ff                xor    %r15d,%r15d
  4014af:       48 89 45 c8             mov    %rax,-0x38(%rbp)
  4014b3:       4c 89 e8                mov    %r13,%rax
  4014b6:       48 f7 d8                neg    %rax
  4014b9:       49 8d 3c c4             lea    (%r12,%rax,8),%rdi
  4014bd:       4d 63 e6                movslq %r14d,%r12
  4014c0:       41 83 c7 01             add    $0x1,%r15d
  4014c4:       45 39 ee                cmp    %r13d,%r14d
  4014c7:       0f 8c 93 00 00 00       jl     401560 <inline_exp2__mul_by_sum+0x140>
  4014cd:       48 8b 45 c0             mov    -0x40(%rbp),%rax
  4014d1:       4c 8b 4d c8             mov    -0x38(%rbp),%r9
  4014d5:       31 f6                   xor    %esi,%esi
  4014d7:       4c 8d 40 ff             lea    -0x1(%rax),%r8
  4014db:       48 89 f0                mov    %rsi,%rax
  4014de:       66 90                   xchg   %ax,%ax
  4014e0:       49 83 c0 01             add    $0x1,%r8
  4014e4:       45 39 c3                cmp    %r8d,%r11d
  4014e7:       4a 8b 0c c7             mov    (%rdi,%r8,8),%rcx
  4014eb:       7c 53                   jl     401540 <inline_exp2__mul_by_sum+0x120>
  4014ed:       45 39 c2                cmp    %r8d,%r10d
  4014f0:       7f 4e                   jg     401540 <inline_exp2__mul_by_sum+0x120>
  4014f2:       49 8b 11                mov    (%r9),%rdx
  4014f5:       48 01 c8                add    %rcx,%rax
  4014f8:       49 83 c1 08             add    $0x8,%r9
  4014fc:       48 01 d0                add    %rdx,%rax
  4014ff:       48 89 d6                mov    %rdx,%rsi
  401502:       48 21 ca                and    %rcx,%rdx
  401505:       49 89 41 f8             mov    %rax,-0x8(%r9)
  401509:       48 09 ce                or     %rcx,%rsi
  40150c:       48 f7 d0                not    %rax
  40150f:       48 21 f0                and    %rsi,%rax
  401512:       48 09 d0                or     %rdx,%rax
  401515:       48 c1 e8 3f             shr    $0x3f,%rax
  401519:       4d 39 e0                cmp    %r12,%r8
  40151c:       75 c2                   jne    4014e0 <inline_exp2__mul_by_sum+0xc0>
  40151e:       48 89 c6                mov    %rax,%rsi
  401521:       44 39 fb                cmp    %r15d,%ebx
  401524:       75 9a                   jne    4014c0 <inline_exp2__mul_by_sum+0xa0>
  401526:       48 89 f0                mov    %rsi,%rax
  401529:       48 83 c4 18             add    $0x18,%rsp
  40152d:       5b                      pop    %rbx
  40152e:       41 5c                   pop    %r12
  401530:       41 5d                   pop    %r13
  401532:       41 5e                   pop    %r14
  401534:       41 5f                   pop    %r15
  401536:       5d                      pop    %rbp
  401537:       c3                      retq
  401538:       0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)
  40153f:       00
  401540:       45 39 d5                cmp    %r10d,%r13d
  401543:       7c 05                   jl     40154a <inline_exp2__mul_by_sum+0x12a>
  401545:       45 39 de                cmp    %r11d,%r14d
  401548:       7e a8                   jle    4014f2 <inline_exp2__mul_by_sum+0xd2>
  40154a:       be 2f 00 00 00          mov    $0x2f,%esi
  40154f:       bf 80 c4 49 00          mov    $0x49c480,%edi
  401554:       31 c0                   xor    %eax,%eax
  401556:       e8 e1 0e 00 00          callq  40243c <__gnat_rcheck_CE_Index_Check>
  40155b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
  401560:       31 f6                   xor    %esi,%esi
  401562:       eb bd                   jmp    401521 <inline_exp2__mul_by_sum+0x101>
  401564:       31 c0                   xor    %eax,%eax
  401566:       48 83 c4 18             add    $0x18,%rsp
  40156a:       5b                      pop    %rbx
  40156b:       41 5c                   pop    %r12
  40156d:       41 5d                   pop    %r13
  40156f:       41 5e                   pop    %r14
  401571:       41 5f                   pop    %r15
  401573:       5d                      pop    %rbp
  401574:       c3                      retq
  401575:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  40157c:       00 00 00
  40157f:       90                      nop

In this version the call is gone, and the instructions that can be expected from FZ_Add and W_Carry are included. So inlining is happening and can be checked with objdump.

In the logs an assertion was made that gnat/gcc would include an inlined function for reference in the produced binary. This is not so, setting the "-ffunction-sections" flag for the compiler and combining this with the "--gc-sections" for the linker will remove all sections for symbols that are not referenced3.

  1. This an demonstration patch, purely to investigate the inline options, not for production purposes []
  2. an ada symbol name can be easily guessed; all lower case module name, two _, all lower case procedure / function name []
  3. easy to check with nm on the binaries, no fz_add in experiment 2 or 3 []

On FFA Chapter 1

January 26th, 2018

To be specific:
"Finite Field Arithmetic." Chapter 1: Genesis.

Chapter 1 starts with a background on the FFA code and a list of the files you need to start out with. It contains a link to FSF GNAT, but a gnat like this will not work as either the ADA part is broken (gcc < 5) or the gcc itself is tampered with (gcc > 5). You will need a GNAT from adacore1.

Next comes the unpacking and building description, following this part is straightforward.

For building the code, the gprbuild tool is used. This is a typical alternative build system, this one has superior support for ADA. I do not recommend it for anything else. If you do not trust this tool, it is not hard to write a makefile or a simple bash script based on the few command line parameters given in this script. Of the flags used, I still have one -fdump-scos2 that seems unnecessary, apparently it creates coverage information.

After the description of the build we get this line;

Do not run the demo yet. (you read programs before running, don’t you?)

No, I do not!. I have not read gcc or this previously unknown 'gprbuild'. And those where unsigned!

The code starts with a file that did not readily fit in my head; restrict.adc. The only way to get to grips with this file was reading the gnat documentation and the ada reference manual. I made a list of all restrictions according to the GNAT documentation and then checked which where used. To summarise; everything that touches any tasking (ada term for multi-threading) is off limits, everything that does dynamic allocation is off limits, everything that depends on a clock is off limits (delay and Calendar), plus some more to make the code as static as possible. A lot of these pragmas are specific for GNAT. One, I could not find documentation for: "No_Fixed_IO". This is the list of restrictions available in GNAT but not used by FFA3.

No_Anonymous_Allocators         Max_Storage_At_Blocking
Max_Entry_Queue_Length          No_Access_Subprograms
No_Dependence                   No_Direct_Boolean_Operators
No_Exception_Handlers           No_Exceptions
No_Fixed_Point                  No_IO
No_Local_Allocators             No_Long_Long_Integers
No_Recursion                    No_Reentrancy
No_Specification_of_Aspect      No_Use_Of_Entity
No_Obsolescent_Features         SPARK_05
No_Implementation_Pragmas

The implementation is split up over different ADA modules, you can read the code on the site but make sure to study the copy created in the V-press.

The first module is defined in 'iron.ads', it is specified to be a Pure module, meaning the package will not have an internal state4. In 'iron.ads', we get to define the size of a word expressed as a number of bits per word, this is called MachineBitness. And a ByteBits, which is needed for communicating the ffa words as this will be on a per byte basis. Unfortunately, it also defines a MachineBitnessLog2, to be explained in another chapter5.

The next module words.ads.This is a fun paragraph, try to parse it

.. of FFA, the machine Word. A Word, from this point on, is simply a single machine word on your particular machine.

Or a little bit less self-referential; Word is the smallest unit used for the arithmetic in FFA, values of type Word can range from 0 (inclusive) up to 2 to power of the Bitness (exclusive). Remarkably, 'WBit_Index' is also defined here and maybe the bit is the smallest unit in FFA6

I could not determine the reason of this line; for Word'Size use Bitness;. The standard, does not help7.

The 'w_shifts.ads' is a module to include the shifts, ask yourself, why not use the pragma Provide_Shift_Operators?

The 'word_ops.ads' file is an irritating Ada necessity, all important information is in 'word_ops.adb'. This last file must be inspected in depth. The carry and borrow functions are brilliant inventions so pay close attention, some extra comments and hints are provided (although the "To derive the..." lines are not very useful, you should be able to get this information from reading the code.). Working these two functions out with a 2-bit word on a paper will help. Also, can you think of another constant time implementation for W_Carry or W_Borrow?

The W_Mux function will be used for all selections and it needs a lot of attention too. Ask yourself; "If WBool is defined as subtype WBool is Word range 0 .. 1;, what is the result of (Sel-1) if Sel is 0?", plus "In how many ways can Mux be defined?"

W_Mux and W_Swap are both unused in this chapter.

The module 'fz_type.ads'; "Gaze upon the combination of abstract mathematical concepts and low level bit fiddling, all in one small library!". Ask yourself; "Do we need Word_Index or Indices?8".

In 'fz_arith.ads', the Precondition pragma is used twice. An array Words with unspecified length is denoted by FZ, addition and subtraction are defined for values of FZ of equal length, hence preconditions are needed to check the lengths for all instantiations of these functions.

The code in 'fz_arith.adb', is not very complex but does close need attention9. Look at the summation, the sum is (A+B) + Carry, but the next carry is determined by just A, B and the Sum. Are we lucky this is correct?. The whole comment starting with The alert reader might ask why the iteration schemes differ... could have been avoided by making the FZ_Add iteration scheme follow the FZ_Sub scheme. This would increase the usefulness of FZ_Add.

I will skip commenting on the input/output and demo

The comments section is interesting, especially seeing how the only non-used function (W_Swap) gets all the attention

  1. specifically 2015 or 2016, not earlier and also not later. []
  2. see GNAT User's Guide []
  3. Why not use No_Fixed_Point or No_Reentrancy? []
  4. Ada has a complex module system all kinds of silly rules. []
  5. I recommend to remove this, when you implement this promised chapter it will then quickly fail and you can see if it is explained. []
  6. This is another unexplained constant, probably "to be used later". So a good algorithm for understanding the FFA code would be to remove every statement / definition that is not used in the same defining chapter, to be added if and when needed. []
  7. First let's read the "Static Semantics", it mentions 2 situation where this matters, one is about packed records, I would set the size for a Word in packed records on a case by case basis. The other situation is for "untyped conversions" and these should never happen in FFA code. For fun, let's read "Implementation Advice", this is typical Ada language reference manual language. []
  8. This is a serious question, as each new type/subtype definition introduces an extra concept to be dealt with an understood. []
  9. For example; from the fact that this code compiles, we can conclude that Ada is case insensitive. []

Building GNAT on MUSL, now with a signature

January 17th, 2018

An update of the 2018-01-12 version, download (ada-musl-cross-2018-01-17.tar.gz), unpack, verify (ada-musl-cross-2018-01-17.txt) and then build

    ./ada-build.sh PREFIX-DIRECTORY

After a while you'll get executables in PREFIX-DIRECTORY/x86_64-linux-musl/bin.

Some final remarks; (a) The archive includes a hashes directory and the hash of all downloaded files will be checked as part of the build process. (b) I've removed all unnecessary patch files. (c) The scripts have been tested on a GNU C library based system and will create a compiler (itself statically linked against MUSL C) that compiles and links against the MUSL C library.(d)MPC moved its download directory1 (e) You will need the AdaCore binary release of GNAT, version 2016, to run the build.

  1. Moving directories of released files is somehow OK. This kind of busy work is beyond me. []

Building GNAT on MUSL

January 15th, 2018

**Updated**: This version does not work!. Go here to the 2018-01-17 version

All of this, to be able to build the excellent FFA library. GNAT is an ADA compiler frontend, it is implemented on the GCC backend and working versions are provided by www.adacore.com1. MUSL is a C-library, and a lot smaller and more sane than the GNU C Library, it can be found here. Building the compiler takes some very specific steps which are implemented for you in a set of scripts2. These, you download, unpack and then build using ./ada-build.sh PREFIX-DIRECTORY. After a while you get executables in PREFIX-DIRECTORY/x86_64-linux-musl/bin.

As we are now in 2018, the 27th year of the linux, you will have problems. What follows is a short list
of the problems I encountered3

  1. GNAT needs GNAT. Download the binary 2016 version of gnat from the AdaCore website, unpack and add the path to the bin directory found within (DIR/gnat-gpl-2016-x86_64-linux-bin). Test it by running a gnat command like gnatmake. Now, re-run the ada-build.sh script.
  2. The gcc in GNAT cannot create executables. You have a new binutils version and the GNAT version of ld is incompatible. Copy the system linker (should be in /usr/bin/ld) to the libexec/gcc/x86_64-pc-linux-gnu/4.9.4 directory in the GNAT distribution.

With the script it is a lot easier to build GNAT on musl, it did take some headaches to get to this point

  1. The AdaCore distribution releases gcc and GNAT in separate files, a small script was needed to create a combined file for further processing
  2. The GNAT source code uses some C code and in this C code it uses GNU Library specific calls, these where easily changed to C/POSIX calls.4
  3. The multithreading code in GNAT is based on 1 non-portable call. This call has an implementation in the GNU library but not in the MUSL C library (to be able to change a preferred scheduling algorithm on read-write locks, specific function was pthread_rwlockattr_setkind_np and parameter PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP). This had to be commented out. Commenting out lead to style warnings (even comments are checked on style)
  4. The names of the gnattools (gnatmake / gnatbind / gnatlink) where hardcoded in the makefiles, these had to be changed to allow for different names and extra command line arguments.5
  5. The 2016 version of the gprbuild tool could only be built by an existing gprbuild tool, this was easily fixed by using the 2017 version. The 2017 version comes with a bootstrap script.
  6. The gprbuild tool uses a database of known compiler names6 these did not include a pattern for the compilers created by these scripts.

I hope not to have to touch or think of this code for a couple of months. This is enough reason for a small list of things to do for the next time.

  1. Let's remove all patches for old gcc versions and old musl libraries, leaving only 4.9.4.
  2. The current script builds cross compilers, instead or also make a native compiler without triples in the name.
  3. It seems that the 4.9.4 branch of gcc still receives updates, determine if these are relevant
  4. Move 2017 adacore to 4.9.4.
  5. Make the whole thing a V-patch.

And that's it.

  1. GCC also includes a version of GNAT, this version is derived (by way of some magic) from the AdaCore version. Unfortunately, if you want to know out how this derivation works, you find that the number of changed lines between the source code of GNAT releases (say 2014 and 2015) is large. This is also true for the number of changed lines between GNAT and GCC releases. Untangling this ball of twine will take some time and I worry about my sanity even starting such a task. Based on a cursory investigation, I pose that the GCC version is derived from a development version of GNAT between the 2014 and 2015 releases. For our purposes this GCC version is broken. []
  2. The GNAT build scripts are derived from the original musl cross compiler build scripts, to be found here []
  3. Feel free to add your problems in the comments below []
  4. Easily, but slowly, some problems could only be found when rebuilding from scratch. []
  5. All these tools build dynamicilly linked executables by default and I want static. []
  6. In the form of regular expression statements in the file 'share/gprconfig/compilers.xml' []