How can I find and test the *actual linker* a compiler is using, on an arbitrary system? - gcc

I need to pass some objects from [ some assembler | another compiler | an archive ] directly to the linker.
But seems that the ld being found on the path is [ broken | missing | linking for the wrong ABI ].
And sometimes, I can't even find ld at all.
How can I find the actual linker being used, by whatever the C compiler happens to be,
[ on a Mac | on Linux | on BSD | from a configure script ]?

I just had to figure this one out.
It was kind of tough, so I thought I'd share.
Give this a shot:
#!/usr/bin/env sh
# 'main;' is the shortest C program possible (I think.).
# So it is compiled, linked, and written to /dev/null.
# So if the linker can't link, this should return 1.
for link in collect2 ld; do # Order matters, because of GCC.
echo 'main;' | $CC -v -x c - -o /dev/null -\#\#\# 2>&1 | grep -q $link &&
echo 'main;' | $CC -v -x c - -o /dev/null -\#\#\# 2>&1 | grep $link |
sed -e "s|\(.*$link\).*|\1|" -e 's/ //g' -e 's|"||' && break
done
# That should work on just about anything, and returns an absolute path,
# except with ICC. If we want to try to get an absolute path there too,
# we have to:
# If 'which' is missing, and it might not have an -s flag.
which="$(which which >/dev/null 2>&1)" || which=echo
$which "$(for link in collect2 ld; do
echo 'main;' | $CC -v -x c - -o /dev/null -\#\#\# 2>&1 | grep -q $link &&
echo 'main;' | $CC -v -x c - -o /dev/null -\#\#\# 2>&1 | grep $link |
sed -e "s|\(.*$link\).*|\1|" -e 's/ //g' -e 's|"||' && break
done)"
So you might have just said,
Come on guy, no way that's necessary! Just, like, which ld.
Honestly and truly, that doesn't work for me a large portion of the time.
Its not so unusual today, since ld is frequently a wrapper.
Lets test it, see what turns up:
#!/usr/bin/env sh
# On my Mac, nothing too special, I swear.
# Just a MacBook, Xcode, GCC from Homebrew, and one commercial compiler.
echo; $which ld; echo "...Not necessarily."; echo
for CC in cc gcc clang icc; do echo $c:
for link in collect2 ld; do
echo 'main;' | $CC -v -x c - -o /dev/null -\#\#\# 2>&1 | grep -q $link &&
echo 'main;' | $CC -v -x c - -o /dev/null -\#\#\# 2>&1 | grep $link |
sed -e "s|\(.*$link\).*|\1|" -e 's/ //g' -e 's|"||' && break
done
which="$(which which 2>/dev/null 1>&1)" || which=echo
$which "$(for link in collect2 ld; do
echo 'main;' | $CC -v -x c - -o /dev/null -\#\#\# 2>&1 | grep -q $link &&
echo 'main;' | $CC -v -x c - -o /dev/null -\#\#\# 2>&1 | grep $link |
sed -e "s|\(.*$link\).*|\1|" -e 's/ //g' -e 's|"||' && break
done)"
echo
done
Returns:
/usr/bin/ld
...Not necessarily.
cc:
/Applications/Xcode51-Beta4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld
/Applications/Xcode51-Beta4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld
gcc:
/Users/Shared/usr/local/Cellar/gcc49/4.9-20140119/libexec/gcc/x86_64-apple-darwin13.1.0/4.9.0/collect2
/Users/Shared/usr/local/Cellar/gcc49/4.9-20140119/libexec/gcc/x86_64-apple-darwin13.1.0/4.9.0/collect2
clang:
/Applications/Xcode51-Beta4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld
/Applications/Xcode51-Beta4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld
icc:
ld
/usr/bin/ld

Related

Distinct static library compiled with -ffunction-sections flag

How to distinct static library compiled with -ffunction-sections compiler flag?
I want to determine is some particular .a library can benefit from -Wl,--gc-sections flag.
If there is way to list all the section names, then I can apply | wc -l to it and infer, that there is too many sections and the library is likely compiled with mentioned flags.
readelf -S just prints archived *.o filenames.
A simple take on this:
# Collect function sections
$ readelf -S tmp.o | sed -ne 's/.*\] \.text.\([a-zA-Z0-9_]\+\) .*/\1/p' | sort -u > fun_sec.lst
# Collect function symbols
$ nm tmp.o | grep ' T ' | awk '{print $3}' | sort -u > fun_sym.lst
# Compare
$ COMM=$(comm -12 fun_sym.lst fun_sec.lst | wc -l)
$ UNIQ=$(comm -3 fun_sym.lst fun_sec.lst | wc -l)
$ if test $COMM -gt $UNIQ; then echo "tmp.o was likely compiled with -ffunction-sections"; fi

grep -c kills script when no match using set -e

Basic example:
#!/bin/bash
set -e
set -x
NUM_LINES=$(printf "Hello\nHi" | grep -c "How$")
echo "Number of lines: ${NUM_LINES}" # never prints 0
Output:
++ grep -c 'How$'
++ printf 'Hello\nHi'
+ NUM_LINES=0
If there are matches, it prints the correct number of lines. Also grep "How$" | wc -l works instead of using grep -c "How$".
You can suppress grep's exit code by running : when it "fails". : always succeeds.
NUM_LINES=$(printf "Hello\nHi" | grep -c "How$" || :)

wget bash function without messy output

I am learning to customize wget in a bash function and having trouble. I would like to display Downloading (file):% instead of the messy output of wget. The function below seems close I am having trouble calling it for my specific needs.
For example, my standard wget is:
cd 'C:\Users\cmccabe\Desktop\wget'
wget -O getCSV.txt http://xxx.xx.xxx.xxx/data/getCSV.csv
and that downloads the .csv as a .txt in the directory specified with all the messy wget output.
This function seems like it will do more-or-less what I need, but I can not seem to get it to function correctly using my data. Below is what I have tried. Thank you :).
#!/bin/bash
download() {
local url=$1 wget -O getCSV.txt http://xxx.xx.xxx.xxx/data/getCSV.csv
local destin=$2 'C:\Users\cmccabe\Desktop\wget'
echo -n " "
if [ "$destin" ]; then
wget --progress=dot "$url" -O "$destin" 2>&1 | grep --line-buffered "%" | \
sed -u -e "s,\.,,g" | awk '{printf("\b\b\b\b%4s", $2)}'
else
wget --progress=dot "$url" 2>&1 | grep --line-buffered "%" | \
sed -u -e "s,\.,,g" | awk '{printf("\b\b\b\b%4s", $2)}'
fi
echo -ne "\b\b\b\b"
echo " DONE"
}
EDITED CODE
#!/bin/bash
download () {
url=http://xxx.xx.xxx.xxx/data/getCSV.csv
destin='C:\Users\cmccabe\Desktop\wget'
echo -n " "
if [ "$destin" ]; then
wget -O getCSV.txt --progress=dot "$url" -O "$destin" 2>&1 | grep --line-buffered "%" | \
sed -u -e "s,\.,,g" | awk '{printf("\b\b\b\b%4s", $2)}'
else
wget -O getCSV.txt --progress=dot $url 2>&1 | grep --line-buffered "%" | \
sed -u -e "s,\.,,g" | awk '{printf("\b\b\b\b%4s", $2)}'
fi
echo -ne "\b\b\b\b"
echo " DONE"
menu
}
menu() {
while true
do
printf "\n Welcome to NGS menu (v1), please make a selection from the MENU \n
==================================\n\n
\t 1 Patient QC\n
==================================\n\n"
printf "\t Your choice: "; read menu_choice
case "$menu_choice" in
1) patient ;;
*) printf "\n Invalid choice."; sleep 2 ;;
esac
done
}

Add floating numbers in bash

I'm trying something very easy but all code that I'm trying doesnt work.
I need add two float numbers in bash. I'm doing this:
result1=`$CURL -o /dev/null -s -w %{time_total} $url1`
result2=`$CURL -o /dev/null -s -w %{time_total} $url2`
result3=`$CURL -o /dev/null -s -w %{time_total} $url3`
total= `expr $result2 + $result3`
echo $total | $GAWK -F: '{ print "connection_1.value " $1 }'
but in the prompt I'm getting this output:
./http_response_2: line 12: 0,018+0,255: command not found
connection_1.value
I'm trying too do this:
result1=`$CURL -o /dev/null -s -w %{time_total} $url1`
result2=`$CURL -o /dev/null -s -w %{time_total} $url2`
result3=`$CURL -o /dev/null -s -w %{time_total} $url3`
total= `$result2 + $result3 | bc`
getting the same result.
Thanks in advance!
There are 3 issues:
There should be no space between total= & `
echo missing before $result2 + $result3
There is comma in your input, instead of decimal point.
Fixing all these issues:
total=$(tr ',' '.' <<< "$result2 + $result3" | bc -l)
If you are concerned about the leading 0 before decimal point, try:
total=$(tr ',' '.' <<< "$result2 + $result3" | bc -l | xargs printf "%g")
Instead of replacing commas with dots, don't produce commas in the first place.
They emerge from localization, so use LC_ALL=C as prefix, like:
LC_ALL=C curl -o /dev/null -s -w %{time_total} www.google.com
and abandon the outdated backticks, use $(...) instead:
result1=$(LC_ALL=C $CURL -o /dev/null -s -w %{time_total} $url1)

Bash error with subtraction

I've got some problem with substraction and I don't know why :(
it's my code:
#!/bin/bash
w3m http://www.weather.com/weather/hourbyhour/graph/PLXX0027 > plik.txt
image= grep -o 'http.*' plik.txt
t= cat plik.txt |sed '105q;d' | grep -o '[0-9][0-9]'
a=32
temp=$((t-a))
echo $temp
I've received sth like:
name#name ~/Desktop $ sh p.sh
http://s.imwx.com/v.20120328.084252//img/wxicon/70/14.png
25
-32
but i wan to receive substraction of 25-32... (of course 25 depends of value in webpage) but why it don't want substract it?
Try defining properly all variables, with $() surrounding them.
#!/bin/bash
w3m http://www.weather.com/weather/hourbyhour/graph/PLXX0027 > plik.txt
image=$(grep -o 'http.*' plik.txt)
t=$(cat plik.txt |sed '105q;d' | grep -o '[0-9][0-9]')
a=32
temp=$((t-a))
echo $temp

Resources