g++: "command not found" after declaring variables in Bash - shell

The g++ command doesn't work after declaring a variable before the g++ command.
For example, the following works:
echo "Train LINE starts"
g++ -lm -pthread -Ofast -march=native -Wall -funroll-loops -ffast-math -Wno-unused-result line.cpp -o line -lgsl -lm -lgslcblas
But this does not:
PATH="foo path"
echo "Train LINE starts"
g++ -lm -pthread -Ofast -march=native -Wall -funroll-loops -ffast-math -Wno-unused-result line.cpp -o line -lgsl -lm -lgslcblas
Instead, I get an error: g++: command not found. Is it the correct way of declaring variables?

The PATH variable holds the path to your programs witch the shell is looking for. So if you change that, the shell doesn't find the program. You can add an folder by using
PATH=/usr/local/progdir:$PATH
export PATH

The PATH environment variable consists of a colon-delimited list of directories. The shell searches for executable files in these directories in response to commands issued by a user.
For example, if g++ executable is located in /usr/bin directory, then you can implicitly call /usr/bin/g++ only if PATH contains /usr/bin:
echo $PATH
/usr/bin:/bin:/opt/bin
If you want to add a search path, you should append it to the existing value of the variable:
PATH="$PATH:/new/search/path"

In your example you redefine PATH which is used to lookup the directory where g++ lives. Use a different variable name.

If you want to append a new path in PATH variable, use this:
PATH=$PATH:foopath
instead of:
PATH="foo path"
If you are using PATH as variable for anything else, use another name.

Related

what is implied by using the -L in gcc flag in gcc post-ceded by a dot

psp-gcc -I. -IC:/pspsdk/psp/sdk/include -O2 -G0 -Wall -D_PSP_FW_VERSION=150 -L. -LC:/pspsdk/psp/sdk/lib main.o -lpspdebug -lpspdisplay -lpspge -lpspctrl -lpspsdk -lc -lpspnet -lpspnet_inet -lpspnet_apctl -lpspnet_resolver -lpsputility -lpspuser -lpspkernel -o controller_basic.elf
it uses -I.
and it also uses -L.
note the dot after each of them, that is not a grammar dot, but a dot within the command itself, that i have no idea what it does, and i doubt i will find anything on the official docs without spending days reading through it
The . (dot) refers to the current directory. Therefore these options are specifying that the current directory should be searched for any required header files (-I.) and any required libraries (-L.).
From the GCC manual:
-Idir
Add the directory dir to the head of the list of directories to be searched for header files.
-Ldir
Add directory dir to the list of directories to be searched for -l.
-l library
Search the library named library when linking.
From the POSIX specification:
The special filename dot shall refer to the directory specified by its predecessor.

make: gcc: Command not found with include in makefile

I am trying to a create a makefile architecture so I have one global makefile at the top which call another in a subdirectory.
Global makefile :
CC = gcc
CFLAGS = -W -Wall -pedantic
LDFLAGS =
PROJECT = proj
SOURCES =
PATH = $(PROJECT)
include $(PATH)/Makefile
all : $(PROJECT).exe
$(PROJECT).exe :
$(CC) $(CFLAGS) $(LDFLAGS) $(DEFINES) $(INCLUDES) $(SOURCES) -o $#
clean :
rm -rf *.exe
Subdirectory makefile :
CC = gcc
CFLAGS = -W -Wall -pedantic
LDFLAGS =
SOURCES += $(PATH)/main.c
When I "make" in the top directory I have the following error :
gcc -W -Wall -pedantic proj/main.c -o proj.exe
make: gcc: Command not found
make: *** [Makefile:17: FK16_jake.exe] Error 127
But when i type exactly the same command (gcc -W -Wall -pedantic proj/main.c -o proj.exe) in my terminal, it's building.
And if I remove the makefile include, he recognize gcc but don't build because no sources (normal behavior).
You are overriding PATH, which is used to determine where to look for executables. Change this variable and it should work.
In the UNIX shell, the environment variable PATH specifies the set of directories to search for executables when you run a command.
The GNU Make manual says:
When make runs a recipe, variables defined in the makefile are
placed into the environment of each shell. This allows you to pass
values to sub-make invocations (see Recursive Use of make). By default, only variables that came from the environment
or the command line are passed to recursive invocations.
Because PATH is a shell variable and is defined in the environment of make, it is "came from the environment". That means when you modify the value with PATH = $(PROJECT) the updated value will be set in the environment of the shell that runs the recipe for $(PROJECT).exe. That means the shell runs with a bad value for the PATH and so cannot find gcc.
To avoid this confusion, do not use PATH as a makefile variable. Use another name which is not the same as an environment variable that the shell depends on. You could call it PROJECT_PATH instead, or just use $(PROJECT) instead of $(PATH).

g++ linker options changes target file name

I need help it is bug or I don't understand how compilation options are working ?
I have sample main.c file and try to compile it as:
$ g++ -nostdlib -g -fno-rtti -fno-exceptions -ffreestanding -nostdinc -nostdinc++ -Wl,--build-id=none,-g,-nostdlib,-nostartfiles,-zmax-page-size=0x1000 main.c -o main
and as output I have this:
$ ls
main.c startfiles
I am trying to understand why g++ created file named "startfiles" not "main" ?
If you read the GNU ld official documentation you will see that there is no option named -nostartfiles. What you do pass for arguments to the linker with that is the options -n and -ostartfiles.
If I were you, I would check those other options you try to pass to the linker as well.
-nostartfiles is a compiler flag as far as I know, not a linker flag.
For the linker, it's the same as -n -o startfiles, which is why you're getting that output file name.

gcc -S not working?

I am trying to have a look at assembly code generated by g++. The normal way is -S. As I also want the corresponding source code, I am adding a -fverbose-asm. (I tried both with and without.)
I expect a .s file to be generated, but none is.
What am I doing wrong ?
Invoking: Cross G++ Compiler
arm-angstrom-linux-gnueabi-g++ -march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp -flax-vector-conversions -S -fverbose-asm -DNAMESPACE -I/usr/local/angstrom/arm/lib/gcc/arm-angstrom-linux-gnueabi/4.3.3/include -O2 -Wall -c -fmessage-length=0 -Wl,-rpath-link,/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/lib,--hash-style=gnu -mthumb-interwork -mno-thumb -isystem/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/include -fexpensive-optimizations -frename-registers -fomit-frame-pointer -fpermissive -fPIC -mfpu=neon -MMD -MP -MF"Src/Kernel Filters SSEI.d" -MT"Src/Kernel\ Filters\ SSEI.d" -o "Src/Kernel Filters SSEI.o" "../Src/Kernel Filters SSEI.cpp"
Your assembly output is the file Src/Kernel Filters SSEI.o
Another issue is that -MT seems used incorrectly, it causes the target of the generated dependency to be the dependency file itself, rather than the object file.
You should not have any -o option to GCC to get the .s file. You are correct in passing -fverbose-asm -S to it. You may want some optimization, e.g. -O1
I suspect that your Src/Kernel Filters SSEI.o file may contain assembly code. I also strongly recommend avoiding spaces in your source or object file name. Name it Kernel_Filters_SSEI.cpp

gcc and linking files with CFLAGS

I am trying to run program from the Learn C Hard Way book
I need to pass the library filename 'build/liblcthw.a' as the last parameter.
For eg :
Doesnt Work on Ubuntu :
gcc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG build/liblcthw.a tests/list_tests.c -o tests/list_tests
Works on Ubuntu :
gcc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG tests/list_tests.c -o tests/list_tests build/liblcthw.a
How do I handle this in Makefile ? CFLAGS will only add it before the source filename and it doesnt work. How do I force CFALGS to add the library filename at the end of the command ?
CFLAGS are flags for the C compiler. Libraries typically go into a variable called LDLIBS. Set LDLIBS=build/liblcthw.a and see if that works.
The first invocation doesn't succeed because the order of sources and libraries in the command line is wrong. The correct order is source files, then object files, followed by static libraries followed by dynamic libraries.

Resources