Where does g++ look for libraries to link? - linux

So I'm currently using Lubuntu 18.4 32bit and was trying to get the GLFW library up and going. I noticed that when you compile a program using GLFW you need to link many libraries and was wondering where exactly does g++ look in the filesystem when you type g++ main.cpp -lglfw?

For compiler:
echo | g++ -x c++ -E -Wp,-v - >/dev/null
echo | prints empty "source code" and closes stdin
-x c++ to specify the language (with this option it prints more detailed info)
-E says g++ to stop after preprocessing stage
- at the end means read code from stdin
-Wp,-v to pass -v directly to preprocessor
>/dev/null to redirect extra output to /dev/null (void)
Example output:
ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../x86_64-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/x86_64-pc-linux-gnu
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/backward
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/include
/usr/local/include
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/include-fixed
/usr/include
End of search list.
For linker:
ld --verbose | grep SEARCH_DIR | tr -s ' ;' \\012
--verbose tells ld to print settings info
| grep SEARCH_DIR select lib directory info
| tr -s ' ;' \\012 makes output pretty (replace ; with new line)
Example output:
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib64")
SEARCH_DIR("/usr/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib")
So the GLFW library should be in one of those directories.
Source: https://transang.me/library-path-in-gcc/

Related

How to capture and prefix to process output started within a bash script?

I'm writing a small bash script where I am compiling 2 programs then executing them in the background within a bash script. These 2 programs do output some generic text. However I need to prefix these outputs like PROGRAM1: xxxxx. How do I achieve that? I have found several answers here however they weren't exactly applicable to this situation.
Here's the code:
#!/bin/bash
echo "This program compiles 2 programs, executes them (executes the 2nd one first, then sleeps for 0.01 second which then executes program 1), then observes the outputs"
gcc -O3 -std=c11 one.c -o one
gcc -O3 -std=c11 two.c -o two
./two &
sleep 0.01
TWO_PID=$(pgrep two)
./one $TWO_PID
#"Prefix output statements here"
#add code here
#Cleanup
rm -f one two
You can do something like this
#! /bin/bash
# ...
label() {
while read -r l; do
echo "$1: $l"
done
}
./two | label "two" &
two_pid=$(pgrep two)
./one $two_pid | label "one"
You don't need the sleep and be careful as pgrep could match more than one process.
Also, instead of compiling and removing you should use make.

Unable to redirect error to /dev/null in gnu make

In a gnu script, I want to check if an intel c compiler is in the path.
To do this, I run the following command:
COMPILER_IN_PATH := $(shell icc -dumpversion | grep 2021.3.0)
Later I test to see if COMPILER_IN_PATH is set.
If an intel compiler is in the path, the above command works fine.
However, if an intel compiler is not in the path, though the above command works (COMPILER_IN_PATH will not be set), I see the following error message in the output when this line is run:
/bin/sh: icc: command not found
I would like to get rid of that error message. How do I redirect stderr somewhere (to /dev/null, I suppose) while reading the stdout into the COMPILER_IN_PATH variable ?
Here are some of my failed attempts:
icc -dumpversion | grep 2021 > /dev/null 2>&1
Ambiguous output redirect.
icc -dumpversion | grep 2021 2> /dev/null
icc: Command not found.
grep: 2: No such file or directory
You are redirecting the output of the grep command. You want to redirect the output of the icc command.
COMPILER_IN_PATH := $(shell icc -dumpversion 2>/dev/null | grep 2021.3.0)

How to find all shared libraries actually used during execution in Linux?

I have an executable and I would like to find out which shared libraries were actually used during a specific run. I know ldd would list all the shared library dependencies of that executable but I would like to find out the subset of those that were actually used during a specific run*. Is this possible?
*what I mean with specific run is running the executable with certain input parameters that would cause only a small part of the code to be run.
You can use ltrace(1) for this:
$ PROG='ls -l'
# Collect call info
$ ltrace -o calls.txt -l '*' $PROG &> /dev/null
# Analyze collected data
$ cat calls.txt | sed -ne '/->/{ s/^\(.*\)->.*/\1/; p }' | sort -u
libacl.so.1
libcap.so.2
libc.so.6
libselinux.so.1
ls
# Compare with ldd
$ ldd /bin/ls | wc -l
10
You could use strace and grep for open .so files.
strace $MYPROG | grep -E '^open*\.so
lsof also should work to grep for open libraries.
lsof -p $PID | awk '{print $9}' | grep '\.so'
This assumes the shared libraries have .so extension

readelf reports so file as NEEDED, but no functions (or other symbols) is used from it

Readelf reports, that libutil.so.1 is needed by ssh utility:
$readelf -s /usr/bin/ssh | grep libutil
0x0000000000000001 (NEEDED) Shared library: [libutil.so.1]
As nm says, libutil.so.1 has only 6 external symbols:
$nm -D /lib64/libutil.so.1 | grep "T "
000000331e0015a0 T forkpty
000000331e000fa0 T login
000000331e0010f0 T login_tty
000000331e001190 T logout
000000331e0012e0 T logwtmp
000000331e0013d0 T openpty
But these symbols not referenced from ssh:
$nm -D /usr/bin/ssh | grep forkpty
$nm -D /usr/bin/ssh | grep login
$nm -D /usr/bin/ssh | grep login_tty
$nm -D /usr/bin/ssh | grep logout
$nm -D /usr/bin/ssh | grep logwtmp
$nm -D /usr/bin/ssh | grep openpty
(grep not showing any matches)
What's going on? Why library referenced as NEEDED, but no symbols from it used? This is not sole example. I met many such "empty" references, while analysing dependencies of another executables.
The DT_NEEDED tagging is generated by the link editor (ld) based on the -l flags provided. The default for the GNU link editor and most other editors, with some exceptions, is to create a DT_NEEDED tag for each -l flag provided.
When using GNU ld or gold, you can pass --as-needed before the -l flags to only emit DT_NEEDED tags for the libraries that are indeed used. This may still emit not obvious tags if the symbols are actually used indirectly.
I have actually written a significant amount about --as-needed and how it works, so you can look through my blog posts if you are more curious.

Color highlighting of Makefile warnings and errors

I have written a Makefile which works fine; I am just posting the part of it under investigation:
BUILD_PRINT = #echo -e "\e[1;34mBuilding $<\e[0m"
COMPILE_cpp = $(CXX) $(CFLAGS) -o $# -c $< $(MAKEDEP) $(INCLUDES)
%.o : %.cpp
$(BUILD_PRINT)
$(COMPILE_cpp)
.SUFFIXES: .o .cpp
I would like to highlight the warnings and errors given by the compiler without using external tools (such as colorgcc or CMake); I thought that a good way to hack it was via "bash script tricks". Looking at the solution posted in How Can I highlight the warning and error lines in the make output? I have tried the following:
pathpat="(/[^/]*)+:[0-9]+"
ccred=$(echo -e "\033[0;31m")
ccyellow=$(echo -e "\033[0;33m")
ccend=$(echo -e "\033[0m")
BUILD_PRINT = #echo -e "\e[1;34mBuilding $<\e[0m"
COMPILE_cpp = $(CXX) $(CFLAGS) -o $# -c $< $(MAKEDEP) $(INCLUDES)
%.o : %.cpp
$(BUILD_PRINT)
$(COMPILE_cpp) 2>&1 | sed -e "/[Ee]rror[: ]/ s%$pathpat%$ccred&$ccend%g" -e "/[Ww]arning[: ]/ s%$pathpat%$ccyellow&$ccend%g" echo "${PIPESTATUS[0]}"
.SUFFIXES: .o .cpp
but it is not working. I get the following output
Building main.cpp
g++ -o main.o -c main.cpp 2>&1 | sed -e "/[Ee]rror[: ]/ s%athpat%cred&cend%g" -e "/[Ww]arning[: ]/ s%athpat%cyellow&cend%g" echo ""
sed: can't read echo: No such file or directory
sed: can't read : No such file or directory
Thanks in advance!
In make context the following lines do not behave the way they would in the shell:
ccred=$(echo -e "\033[0;31m")
ccyellow=$(echo -e "\033[0;33m")
ccend=$(echo -e "\033[0m")
In the shell those would put the echoed output into those variables. In make that tries to run the echo command, which doesn't exist, and ends up creating empty variables.
Those lines should either be
ccred=$(shell echo -e "\033[0;31m") to run the commands through the shell and store the output and then used as $(ccred) in the body
ccred=\033[0;31m to store the string in the variable and then used as $$(echo -e '$(ccred)') in the body
ccred=echo -e "\033[0;31m" to store the command in the variable and then used as $$($(ccred) in the body
Either of the first or second options is likely fine. (Use := instead of = in the first option to have make only run the echo command once, at make parse time, instead of every time ccred is used.)
make and shell variables share a prefix sigil $. As such to use shell variables in make contexts requires escaping the $ in shell contexts by doubling it to $$. As such s%$pathpat%$ccred&$ccend%g needs to be s%$$pathpat%$$ccred&$$ccend%g, etc.
Each line of a make rule body is executed as a distinct shell command, as such the commands cannot interact with each other. In order to use constructs like echo "${PIPESTATUS[0]}" meaningfully therefore requires that they be on the same command line in make. As such the compile line in that pattern rule would need to be $(COMPILE_cpp) 2>&1 | sed ...; echo "${PIPESTATUS[0]}".
However, even that isn't going to do what you want since you don't need to echo the exit status from the compilation you need to exit with it, so you probably want ; exit "${PIPESTATUS[0]}" there instead.
Got it working.
First of all thanks #EtanReisner and #rici. Here's the code:
BUILD_PRINT = \e[1;34mBuilding $<\e[0m
COMPILE_cpp = $(CXX) $(CFLAGS) -o $# -c $< $(MAKEDEP) $(INCLUDES)
COMPILE_cpp_OUT=$$($(COMPILE_cpp) 2>&1 | sed -e 's/error/\\\e[1;31merror\\\e[0m/g' -e s/warning/\\\e[1;33mwarning\\\e[0m/g')
%.o : %.cpp
#echo -e "$(BUILD_PRINT)\n$(COMPILE_cpp)\n$(COMPILE_cpp_OUT)"
.SUFFIXES: .o .cpp
All the commands are invoked by only one echo because I want all the outputs (command string and warnings/errors) coherently grouped for each file built when I launch a parallel build with make -j.
$(BUILD_PRINT) just prints out the path of the file currently being built.
$(COMPILE_cpp) prints out the string of the compiler, so that I can see the command with all the flags/dependencies/etc...
$(COMPILE_cpp_OUT) stores the output of the compiler and change some relevant word colour via sed command.

Resources