Can I change gcc default options without using command-line? - gcc

I am plagued by the Gentoo bug #580414.
In short, the default options mislead configure into not detecting standard include files because some headers contain this code:
#if defined _FORTIFY_SOURCE && _FORTIFY_SOURCE > 0
# if !defined __OPTIMIZE__ || __OPTIMIZE__ <= 0
# warning _FORTIFY_SOURCE requires compiling with optimization (-O)
, and __OPTIMIZE__ is off by default and _FORTIFY_SOURCE is on by default, and the generated warning is perceived as an error, indicating that "stdint.h", "stdlib.h" and many others are absent. Compilation eventually fails and I cannot install programs or even upgrade the gcc itself.
Can I simply put something in environment vars or in the /etc directory to turn on -O or turn off _FORTIFY_SOURCE for every invocation of gcc without editing gentoo build scripts?
Tried in /etc/portage/make.conf
EPATCH_USER_EXCLUDE='*10_all_default-fortify-source*'
CFLAGS="-O2 -O -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0"
CFLAGS_FOR_BUILD="-O2 -O -U_FORTIFY_SOURCE"
without any improvement.

There is no such environment variable. CFLAGS in make.conf won't work because the build systems usually do something like this:
$(CC) $(CFLAGS) $(MY_HARDCODED_CFLAGS)
thus overwriting your flags.
But to mangle any argument passed to gcc, you can use the following workaround.
create a directory, eg. under /usr/local/bin/
create a script which will mangle its arguments as you wish and then passes them to gcc or "/usr/bin/" + basename(argv[0]) (beware of infinite recursion)
make this script executable
create symlinks to the script in that directory with names like gcc, cc, x86_64-pc-linux-gnu-gcc
put a bunch of lines like this into /etc/portage/bashrc:
the_dir="/usr/local/bin/THE_DIR"
if [[ "${PATH}" != *"${the_dir}"* ]] ; then
export PATH="${the_dir}:${PATH}"
fi
Also to save yourself from possible problems in the future, do not forget to put a note about this change somewhere. (As should be done with any workaround anyway.)

Just documenting the commands I actually used to resolve the issue.
mv /usr/bin/i686-pc-linux-gnu-gcc /usr/bin/i686-pc-linux-gnu-gcc.OLD
cat >/usr/bin/i686-pc-linux-gnu-gcc
/usr/bin/i686-pc-linux-gnu-gcc.OLD -O "$#"
ctrl+D
chmod +x /usr/bin/i686-pc-linux-gnu-gcc
cp /usr/i686-pc-linux-gnu/gcc-bin/4.6.3/i686-pc-linux-gnu-gcc /usr/i686-pc-linux-gnu/gcc-bin/4.6.3/i686-pc-linux-gnuu-gcc
mv /usr/bin/i686-pc-linux-gnu-g++ /usr/bin/i686-pc-linux-gnuu-g++
cat >/usr/bin/i686-pc-linux-gnu-g++
/usr/bin/i686-pc-linux-gnuu-g++ -O "$#"
ctrl+D
chmod +x /usr/bin/i686-pc-linux-gnu-g++
cp /usr/i686-pc-linux-gnu/gcc-bin/4.6.3/i686-pc-linux-gnu-g++ /usr/i686-pc-linux-gnu/gcc-bin/4.6.3/i686-pc-linux-gnuu-g++
cp /etc/env.d/gcc/i686-pc-linux-gnu-4.6.3.O /etc/env.d/gcc/i686-pc-linux-gnuu-4.6.3
The credit all goes to rindeal. Recap:
identify the binaries that get invoked as compilers
rename them
in their place, create shell scripts that prepend "-O"
create a gcc profile to appease gcc-config
emerge all the unwieldy packages!

Related

Stop GNU make from compiling by default

I just want to use GNU make to compress some files.
So I wrote the Makefile as follows:
lib.tar.lzma: $(shell find ~/lib -name "*")
rm -f lib.tar.lzma
tar -cavf lib.tar.lzma -C ~/ lib/
However, after I run make, it automatically compile the c++ source code in that directory.
How can I stop it from compiling them? I just want to compress them.
Update:
I got the following error:
<builtin>: recipe for target '/home/xxx/lib/app' failed
It seems a built-in recipe.
(We don't know your entire Makefile and your full file tree, so this is only a guess; I assume that you have shown us a fragment of your much bigger Makefile)
However, after I run make, it automatically compile the c++ source code in that directory.
This is probably happening because your $(shell find ~/lib -name "*") is expanded to something containing your object files. Since they are in your dependencies their source file is recompiled if it is newer. BTW you might want to use instead $(shell cd .. ; find lib -name "*") or if lib has no subdirectory even $(wildcard ../lib/*)
You probably don't need any dependency for that lib.tar.lzma target, so just have:
lib.tar.lzma:
rm -f lib.tar.lzma
tar -cavf lib.tar.lzma -C ~/ lib/
BTW, that -C ~/ perhaps should be -C $$HOME since make use /bin/sh to run commands, and that POSIX shell don't know about ~ ; perhaps a -C .. might be better ...
Perhaps you might write some shell script make-backup.sh to do a more clever tar and you would then code
lib.tar.lzma: make-backup.sh
./make-backup.sh $#
However, perhaps you do have dependencies (e.g. if you need to archive some generated files). Then you need to list them explicitly and wisely (you certainly don't want to depend on all the files; perhaps only the source ones). Also, you might not need to archive any object files *.o, if you have some (but YMMV).
I recommend using make --trace or remake -x to debug your Makefile.
BTW, having a Makefile only for a backup is useless; write a shell script instead.
I also strongly recommend using some version control system (like git) if you don't use any. Notice that git has an archive subcommand which might be a more clever backup.

Configure GCC to add compile flags globally

Can I configure GCC to add some file globally, for every project? I want to make it temporarily and only with flags like: -fdiagnostics-color.
I don't understand why do you need it but you can do a wrapper:
which gcc - will print a patch to GCC (copy it to clipboard)
mkdir somedir; cd somedir
create file with name gcc
and add into it: full path to gcc(from clipboard) -fdiagnostics-color somefile.c $# this command will add -fdiagnostics-color somefile.c before every line that came to gcc.
chmod +x gcc - set execution rights to gcc wrapper
And finally
add path to your wrapper. export PATH=somedir:$PATH
You might read about GCC spec files and alter the spec file used by your particular version of gcc. But this is generally frowned upon.
The usual practice would be to use GNU make and add a CFLAGS += -fdiagnostics-color to your Makefile. BTW with a recent enough GCC this (adding -fdiagnostics-color flag) is not even necessary since (at least by setting your GCC_COLORS environment variable) the default is -fdiagnostics-color=auto

gfortran include path -- is there an alternative to passing multiple -I options?

I have some Fortran code which uses included modules, and I am wondering what environment variables actually work to set the include path.
To test this out I've been using one of the NAG example codes.
This works:
$ gfortran e04ucfe.f90 -lnag_nag -I/opt/NAG/fll6a23dfl/nag_interface_blocks
This doesn't work:
$ export CPATH=/opt/NAG/fll6a23dfl/nag_interface_blocks
$ gfortran e04ucfe.f90 -lnag_nag
e04ucfe.f90:10.37:
USE nag_library, ONLY : nag_wp
1
Fatal Error: Can't open module file 'nag_library.mod' for reading at (1): No such file or directory
However, the GCC/GFortran documentation states that:
The gfortran compiler currently does not make use of any environment
variables to control its operation above and beyond those that affect
the operation of gcc.
(see https://gcc.gnu.org/onlinedocs/gfortran/Environment-Variables.html and https://gcc.gnu.org/onlinedocs/gcc/Environment-Variables.html#Environment-Variables)
I've tried ltrace-ing the gfortran run and can see it looking at other environment variables (e.g. the regular PATH) but not CPATH.
I can work around this with this:
gfortran e04ucfe.f90 -lnag_nag `echo -I$CPATH | sed -e 's/:/ -I/'`
...but why is this necessary? CPATH works fine with gcc, including for other languages than C/C++, so why doesn't this work with gfortran?
Is there something I can successfully use to the same effect as CPATH for gcc with gfortran, to avoid having to pass multiple -I arguments?
Side note: LIBRARY_PATH works fine in a similar way, for replacing the -L/path/to/libs on the gfortran command-line.
As far as I know gfortran does not support this, which is quite annoying. But it is possible to work around it. If you name the following script gfortran and put it in a directory in your $PATH that is searched before the one with the real gfortran in it, then you will have the behavior you want, with $CPATH transparently being expanded into -I arguments:
#!/bin/bash
/path/to/gfortran $(for i in ${CPATH//:/ }; do echo -I"$i"; done) "$#"
Remember to mark it as executable. For example, if my $PATH is /home/amaurea/local/bin:/usr/local/bin:/usr/bin:/bin and gfortran lives in /usr/local/bin, I would set it up as
$ cd /home/amaurea/local/bin
$ cat <<HERE > gfortran
#!/bin/bash
/usr/bin/gfortran $(for i in ${CPATH//:/ }; do echo -I"$i"; done) "$#"
HERE
$ chmod a+x gfortran
Alternatively you can formulate it as a shell alias, but that would be less flexible and will not work in as many situations.
If you are using Makefiles, I got this to work using the subst command. This replaces the : with -I for each path in the file.
usr/bin/gfortran e04ucfe.f90 -lnag_nag -I${subst :, -I,$(CPATH)}

NetBeans: change compiler/linker parameters with command line

I want to change the compiler/linker parameters without using NetBeans GUI, i.e. I want every new project I make has already set gcc parameters (like -I and -l -L) in makefile without enter in the project properties window by user interface. I need it for an installation script which already set netbeans for working with fixed library (for example openCV) at first boot. I already tried changing toolchain file like GNU_c.xml and GNU_cpp.xml but without results. Same thing making a GCC alias/bash function before starting netbeans (no inerithance between subshell that netbeans creates for compiling/linking files), also modifying .bashrc file with alias same results.
Is there a way to do this?
You could define an alias in your .bashrc, for example :
$ echo "alias gcc='gcc -l -Wall -Wextra" >> ~/.bashrc
$ source ~/.bashrc
In the case of NetBeans, I don't know if it launches an instance of bash to run gcc but if not, you could define a script as an executable that contains something like (for example):
#!/bin/bash
gcc -l -Wall -Wextra "$#"
# or [gcc "$#"] only if you have define the previous alias in your bashrc

How does gnu-make deal with quotes in the makefile if called in cmd.exe?

I have a c source file to which I want to pass a quoted macro via gcc's -D
command line flag. (See also How do I pass a quoted string with -D to gcc in cmd.exe?). And I am working in cmd.exe.
It's possible to compile the program directly like so:
c:\MinGW\bin\gcc.exe -DDEFINED_STRING="\"foo bar baz\"" foo.c -o foo.exe
But if I create a makefile with the following content
foo.exe: foo.c
c:\MinGW\bin\gcc.exe -DDEFINED_STRING="\"foo bar baz\"" foo.c -o foo.exe
and then execute a make, gnu's make will try to invoke /bin/sh and the backslashes of the path to gcc.exe dissapear:
gcc-4.7.0/gcc/config/avr -c c:/temp/gcc-4.7.0/gcc/gcc.c -o o/gcc/gcc.o
/bin/sh: c:MinGWbing++.exe: command not found
make: *** [o/gcc/gcc.o] Error 127
Stragnly enough, this doesn't happen when I use -DDEFINED_STRING=foo (that is: without quotes).
make -v prints GNU Make 3.81
Making in a Windows environment has many nuances. In this case, it looks like you just need to escape your backslashes like so:
foo.exe: foo.c
c:\\MinGW\\bin\\gcc.exe -DDEFINED_STRING="\"foo bar baz\"" foo.c -o foo.exe
Alternatively, switch them to forward slashes or the preferred /cygdrive/c style. As a side note, I seem to recall that Windows style filenames are no longer supported in dependencies as of Make 3.81.
You might also want to set the SHELL variable and review some of the caveats mentioned in the manual and in the NEWS file included in the source tarball.

Resources