EEVblog Electronics Community Forum

Products => Computers => Programming => Topic started by: DiTBho on February 16, 2023, 10:47:20 am

Title: GNU binutils, get version
Post by: DiTBho on February 16, 2023, 10:47:20 am
So, I need to run old toolchains, and and found old binutils respond differently when queried about the version

Code: [Select]
   bu_v="`$ld --version 2> /dev/null | head -n1 | cut -d" " -f4`"
(new)

Code: [Select]
   bu_v="`$ld --version 2> /dev/null | head -n1 | cut -d" " -f5`"
(old)
 
is there a way to always get the same answer?  :-//
(is there a better way to do it?)


this stuff has to be used from a bash script

Code: [Select]
# mytc_version_get tc mipsel-unknown-linux-gnu
2.21.1/4.5.3
(binutils/gcc (crosscompiler))

Code: [Select]
# mytc_version_get bu mipsel-unknown-linux-gnu
2.21.1
(binutils (crosscompiler))

Code: [Select]
# mytc_version_get cc mipsel-unknown-linux-gnu
4.5.3
(gcc (crosscompiler))

Code: [Select]
# mytc_version_get tc
2.33.1/9.3.0
(binutils/gcc (host))
Title: Re: GNU binutils, get version
Post by: DC1MC on February 16, 2023, 11:02:30 am
Post as many as possible xxxx-ld --version of your toolchains, so we can determine a logic to extract the version. I expect that in the true and tested tradition of "real-programmers" the host OS packaging system is totally ignored and these are installed from archives in different places as it seems fit and eventually added to the path  :palm:.

On my development machines I always pack these myself if not provided, so I can always query dpkg, but out of curiosity I've run the command on few of the toolchains installed:

Code: [Select]
ld --version
GNU ld (GNU Binutils for Ubuntu) 2.30

arm-v5te-linux-gnueabi-ld --version
GNU ld (GNU Binutils) 2.31.1

arm-ppc-linux-uclibcgnueabi-ld --version
GNU ld (crosstool-NG crosstool-ng-1.23.0) 2.28

aarch64-v8a-linux-gnu-ld --version
GNU ld (GNU Binutils) 2.35

So here the parsing is elementary, but I'm curious to see the variations for your toolchains. My really old toolchains are installed on a virtual Ubuntu 16.04 that is not started now.

 Cheers,
 DC1MC
Title: Re: GNU binutils, get version
Post by: Kalvin on February 16, 2023, 11:03:47 am
is there a way to always get the same answer?  :-//
(is there a better way to do it?)

If you can't force the same version output format string from different tools versions, then you could try to first parse/match some known version format. If that fails, then try to parse/match some other format etc. until the parser is able to return a valid version string.
Title: Re: GNU binutils, get version
Post by: DiTBho on February 16, 2023, 11:20:56 am
Code: [Select]
mipsel-unknown-linux-gnu-ld --version

Code: [Select]
GNU ld (GNU Binutils 2.35.1 p2) 2.35.1
Copyright (C) 2020 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.

Code: [Select]
GNU ld (GNU Binutils) 2.21.1
Copyright 2011 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.
Title: Re: GNU binutils, get version
Post by: DC1MC on February 16, 2023, 11:27:51 am
OK, then pipe your --version results like this, to see if we have some outliers:
Code: [Select]
<your toolchain component> --version | head -n 1 | tr -d ' '| cut -f 2 -d\)
Title: Re: GNU binutils, get version
Post by: Kalvin on February 16, 2023, 11:36:16 am
The version is the last number at the end of the first line? That is pretty simple to parse with grep.

For example in my system:

Code: [Select]
$ ld --version
GNU ld (GNU Binutils for Ubuntu) 2.38
Copyright (C) 2022 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.

This oneliner will produce version number 2.38:

Code: [Select]
$ ld --version | head -n 1 | grep -o "[^[:blank:]]*$"
2.38
Title: Re: GNU binutils, get version
Post by: DC1MC on February 16, 2023, 12:13:15 pm
The version is the last number at the end of the first line? That is pretty simple to parse with grep.

For example in my system:

Code: [Select]
$ ld --version
GNU ld (GNU Binutils for Ubuntu) 2.38
Copyright (C) 2022 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.

This oneliner will produce version number 2.38:

Code: [Select]
$ ld --version | head -n 1 | grep -o "[^[:blank:]]*$"
2.38

this as well, now we need to see if we have some strange versions like 4.22.3/20060821 or, worse 3.35.2 20110222
Title: Re: GNU binutils, get version
Post by: Kalvin on February 16, 2023, 12:18:16 pm
The version is the last number at the end of the first line? That is pretty simple to parse with grep.

For example in my system:

Code: [Select]
$ ld --version
GNU ld (GNU Binutils for Ubuntu) 2.38
Copyright (C) 2022 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.

This oneliner will produce version number 2.38:

Code: [Select]
$ ld --version | head -n 1 | grep -o "[^[:blank:]]*$"
2.38

this as well, now we need to see if we have some strange versions like 4.22.3/20060821 or, worse 3.35.2 20110222

Grep is able to perform alternative matching using | operator, so it may be still possible to parse different version string formats with a single oneliner.
Title: Re: GNU binutils, get version
Post by: DiTBho on February 16, 2023, 12:27:01 pm
@DC1MC
it works!!!
perfect job  :-+ :-+ :-+

Title: Re: GNU binutils, get version
Post by: DC1MC on February 16, 2023, 12:37:12 pm
@DC1MC
it works!!!
perfect job  :-+ :-+ :-+

Most welcome  ^-^
Title: Re: GNU binutils, get version
Post by: DiTBho on February 16, 2023, 12:41:21 pm
Code: [Select]
# ./mybuild-2023

   kernel-2.6.37.1(mips.32/le)

tc) show toolchain version
up) script_update

 0) clean
 1) configure
 2) compile app
 3) app module
 4) tftp kernel@192.168.1.21:
 5) tools

app_name       = kernel-2.6.37.1-32bit
machine_note   = revB
qualified_host = { macmini-intel } ... accepted
toolchain = mipsel-unknown-linux-gnu:2.21.1/4.5.3
checking toolchain ... failed
[!] panic
    module=profile/do/utils_ver
    reason=found gcc-v4.5.3, needed gcc-v{ 4.6.0 .. 4.7.0 }

This is a practical application when you want to share a kernel/firmware repo among different machines with different ecosystems, or among different ecosystems on the same machine.

That check remembers me I have to select the proper toolchain version.

Code: [Select]

 [1] aarch64-unknown-linux-gnu-6.5.0
 [2] aarch64-unknown-linux-gnu-9.3.0 *

 [3] armv5tel-softfloat-linux-gnueabi-6.5.0 *
 [4] armv5tel-softfloat-linux-gnueabi-9.3.0

 [5] armv7a-unknown-linux-gnueabihf-6.5.0
 [6] armv7a-unknown-linux-gnueabihf-8.4.0
 [7] armv7a-unknown-linux-gnueabihf-9.3.0 *

 [8] hppa-unknown-linux-gnu-6.5.0
 [9] hppa-unknown-linux-gnu-9.3.0 *

 [10] hppa64-unknown-linux-gnu-6.5.0
 [11] hppa64-unknown-linux-gnu-9.3.0 *

 [12] i686-pc-linux-gnu-4.9.4-gnat2016
 [13] i686-pc-linux-gnu-6.5.0
 [14] i686-pc-linux-gnu-7.3.1-gnat2018
 [15] i686-pc-linux-gnu-7.5.0
 [16] i686-pc-linux-gnu-8.3.1-gnat2019
 [17] i686-pc-linux-gnu-8.4.0
 [18] i686-pc-linux-gnu-9.3.0 *
 [19] i686-pc-linux-gnu-10.2.0

 [20] mips-unknown-linux-gnu-4.1.2-legacy
 [21] mips-unknown-linux-gnu-4.5.3-legacy
 [22] mips-unknown-linux-gnu-6.5.0
 [23] mips-unknown-linux-gnu-9.3.0 *

 [24] mips64-unknown-linux-gnu-6.5.0 *
 [25] mips64-unknown-linux-gnu-9.3.0

 [26] mipsel-unknown-linux-gnu-4.5.3-legacy *
 [27] mipsel-unknown-linux-gnu-6.5.0
 [28] mipsel-unknown-linux-gnu-9.3.0

 [29] powerpc-unknown-linux-gnu-6.5.0
 [30] powerpc-unknown-linux-gnu-9.3.0 *

 [31] powerpc64-unknown-linux-gnu-9.3.0 *

 [32] sparc64-unknown-linux-gnu-6.5.0 *
 [33] sparc64-unknown-linux-gnu-9.3.0

 [34] x86_64-pc-linux-gnu-10.2.0 *

Or ... that I have to compile the correct version of the cross-compiler  :o :o :o
Title: Re: GNU binutils, get version
Post by: eutectique on February 16, 2023, 05:03:42 pm
In case you are still interested, here are some more strings:
Code: [Select]
GNU ld (2.34-4ubuntu1+13ubuntu1) 2.3
GNU ld (GNU Arm Embedded Toolchain 9-2020-q2-update) 2.34.0.20200428
GNU ld (GNU Arm Embedded Toolchain 10.3-2021.10) 2.36.1.20210621
GNU ld (GNU Toolchain for the Arm Architecture 11.2-2022.02 (arm-11.14)) 2.37.20220122
GNU ld (Arm GNU Toolchain 12.2.MPACBTI-Bet1 (Build arm-12-mpacbti.16)) 2.39.50.20220821
GNU ld (Zephyr SDK 0.15.2) 2.38

The pattern seems to be "GNU ld (some text) some.number.and.more"
Title: Re: GNU binutils, get version
Post by: Nominal Animal on February 17, 2023, 11:55:16 am
I'd use GNU sed and
    ld --version 2>/dev/null | sed -ne 's|^.* \([0-9][^ ]*\) *$|\1|p ; q'
to print the final token on the first line that is preceded by a space and starts with a digit, and nothing else.  The q is a GNU extension, so if you use some other sed, check that it supports q first.

If you prefer awk,
    ld --version 2>/dev/null | awk 'NR > 1 { exit } NF > 1 { print $NF }'
which does not require GNU awk, and works fine with other awk variants like mawk.
Title: Re: GNU binutils, get version
Post by: DiTBho on February 17, 2023, 12:00:43 pm
Code: [Select]
function toolchain_cc_get_ver()
{
    local test
    local cc="$1"

    test="`$cc 1> /dev/null 2> /dev/null`"
    test="$?"
    if [ "$test" == "0" ]
       then
           #not installed"
           ans="?"
       else
           ans="`$cc -dumpversion 2> /dev/null`"
       fi
    #return ans
}

function toolchain_bu_get_ver()
{
    local test
    local ld="$1"

    test="`$ld 1> /dev/null 2> /dev/null`"
    test="$?"
    if [ "$test" == "0" ]
       then
           #not installed"
           ans="?"
       else
           ans="`$ld --version 2> /dev/null | head -n1 | tr -d ' ' | cut -f 2 -d\)`"
       fi
    #return ans
}

function get_fixed()
{
   local name=$1
   local value=$3
   local myarch=$4
   local content=$2

   if [ "*$myarch" != "*" ]
      then
          value="$myarch-$value"
      fi

   # if name is not defined by ENV
   #            then define it
   #echo "[$1][$2][$3][$4]"
   if [ "*$content" == "*" ]
      then
          eval $name=$value
      fi
}

function get_info()
{
   local   myarch="$1"
   #global cc
   #global cc_v
   #global ld
   #global bu_v
   #global tc_v

   # echo "myarch=[$myarch]"

   get_fixed "cc" "$cc" "gcc" "$myarch"
   get_fixed "ld" "$ld" "ld"  "$myarch"

   toolchain_cc_get_ver "$cc"
   cc_v="$ans"

   toolchain_bu_get_ver "$ld"
   bu_v="$ans"

   tc_v="$bu_v/$cc_v"
}

function app()
{
   local   option="$1"
   local   myarch="$2"
   #global cc
   #global cc_v
   #global ld
   #global bu_v
   #global tc_v

   get_info "$myarch"

   case $option in
     "cc") echo "$cc_v"  ;;
     "bu") echo "$bu_v"  ;;
     "as") echo "$bu_v"  ;;
     "ld") echo "$bu_v"  ;;
        *) echo "$tc_v"  ;;
   esac
}

app "$1" "$2"

This is the final bash-script.

needs to run it on
- GNU/Linux
- BSD/NetBSD

g-sed is supported  :-+
Title: Re: GNU binutils, get version
Post by: DiTBho on February 17, 2023, 12:32:26 pm
Code: [Select]
function fooo()
{
    local argc="$#"     # how many args line ?
    local args=("$@")   # args[]={arg0..argC}

    i=$(($argc-1))
    item="${args[$i]}"
    echo "[$item]"
}

test="`ld --version | head -n1`"
fooo $test

test="`mips-unknown-linux-gnu-ld --version | head -n1`"
fooo $test

test="`mipsel-unknown-linux-gnu-ld --version | head -n1`"
fooo $test

test="`mipsle-unknown-linux-gnu-ld --version | head -n1`"
fooo $test

Code: [Select]
[2.33.1]
[2.34.0]
[2.35.1]
[2.21.1]

Maybe too silly (sorry), but this trick seems to work too :o :o :o
Title: Re: GNU binutils, get version
Post by: Kalvin on February 17, 2023, 12:49:56 pm
Hint: It is also possible to use Bash's here-document feature to embed a Perl/Python script straight into the Bash command file. This way it is possible to use more suitable tool for a job without external script file dependencies.

For example, if parsing the version number information seems to get too complicated using basic grep and cut, it is possible to use Perl or Python do the parsing instead, and use the full potential and expressiveness of those programming languages.
Title: Re: GNU binutils, get version
Post by: Nominal Animal on February 17, 2023, 01:00:00 pm
This is the final bash-script.
Bash?
Code: [Select]
# LastToken VARNAME COMMAND...
function LastTokenOf() {
    declare -n thevar=$1
    shift 1
    local tokens=($(LANG=C LC_ALL=C "$@" 2>/dev/null | head -n 1))
    if [ ${#tokens[@]} -gt 1 ]; then
        thevar="${tokens[-1]}"
    elif [ -z "${tokens[*]}" ]; then
        thevar="none"
    else
        thevar="unknown"
    fi
}

LastTokenOf LD_VERSION ${LD:-ld} --version
LastTokenOf GCC_VERSION $(CC:-gcc} --version
using traditional test ([) instead of Bash-specific [[, so that it'll run even on ancient Bashes.

The variable will be set to the last token on the first line, to "none" if the command is not found or it produces no output or an empty first line, or to "unknown" if the command prints a single token on its first line.
Title: Re: GNU binutils, get version
Post by: eutectique on February 18, 2023, 07:26:32 pm
Just one small note for the sake of completeness, about -v versus --version. The former produces just one line with the version information, while the latter adds copyright and stuff:

Code: [Select]
> arm-none-eabi-ld -v
GNU ld (GNU Toolchain for the Arm Architecture 11.2-2022.02 (arm-11.14)) 2.37.20220122

> arm-none-eabi-ld --version
GNU ld (GNU Toolchain for the Arm Architecture 11.2-2022.02 (arm-11.14)) 2.37.20220122
Copyright (C) 2021 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.
Title: Re: GNU binutils, get version
Post by: Kalvin on February 19, 2023, 01:29:04 pm
Here is an example of a Bash-script which is using a here-document embedding a Python script which will parse a version number.

Bash script file parse_version.sh:
Code: [Select]
#!/bin/bash
#
# parse_version.sh
#
PYTHON="python3"

function parse_version() {
    local VERSIONSTR="$@"

    VER=$(${PYTHON} - <<EOF
import re
s = '$VERSIONSTR'
PATTERNS = [
    r'\s([\d\.]+)\/[\d]+$',   # 4.22.3/20060821   => 4.22.3
    r'\s([\d\.]+)\s[\d\.]+$', # 3.35.2 20110222   => 3.35.2
    r'\s([\d\.]+)\.\d{8}$',   # 2.39.50.20220821  => 2.39.50
    r'\s([\d\.]+)$'           # 2.38              => 2.38
]
for p in PATTERNS:
    m = re.search(p, s)
    if m is not None:
        # Found valid version string
        v =  m.group(1)
        print(v)
        exit(0)
# Did not find valid version string
print('None')
exit(1)
EOF
)
}

#
# Run tests for the given test version strings
#

VERSIONS=( \
    "1 GNU ld (GNU Binutils for Ubuntu) 2.38" \
    "2 GNU ld (GNU Binutils for Ubuntu) 4.22.3/20060821" \
    "3 GNU ld (GNU Binutils for Ubuntu) 3.35.2 20110222" \
    "4 GNU ld (2.34-4ubuntu1+13ubuntu1) 2.3" \
    "5 GNU ld (GNU Arm Embedded Toolchain 9-2020-q2-update) 2.34.0.20200428" \
    "6 GNU ld (GNU Arm Embedded Toolchain 10.3-2021.10) 2.36.1.20210621" \
    "7 GNU ld (GNU Toolchain for the Arm Architecture 11.2-2022.02 (arm-11.14)) 2.37.20220122" \
    "8 GNU ld (Arm GNU Toolchain 12.2.MPACBTI-Bet1 (Build arm-12-mpacbti.16)) 2.39.50.20220821" \
    "9 GNU ld (Zephyr SDK 0.15.2) 2.38" \
    "10 GNU ld (Zephyr SDK 0.15.2)" \
    "11 GNU ld (Zephyr SDK 0.15.2) 1.2.H")

for v in "${VERSIONS[@]}"; do
    parse_version $v
    echo "Exit code=$?, Version='$VER'"
done

Produced output:
Code: [Select]
$ ./parse_version.sh
Exit code=0, Version='2.38'
Exit code=0, Version='4.22.3'
Exit code=0, Version='3.35.2'
Exit code=0, Version='2.3'
Exit code=0, Version='2.34.0'
Exit code=0, Version='2.36.1'
Exit code=0, Version='2.37'
Exit code=0, Version='2.39.50'
Exit code=0, Version='2.38'
Exit code=1, Version='None'
Exit code=1, Version='None'
Title: Re: GNU binutils, get version
Post by: DiTBho on February 19, 2023, 06:53:16 pm
WOW, impressed!

Thanks you  :D