Which gcc version introduced `-fstack-protector-strong`? - bash

In my build script, I want to conditionally add -fstack-protector-strong to my CFLAGS if the gcc supports it (my project builds using multiple versions of gcc).
I want my build script (written in bash) to parse the output of gcc --version and automatically add this flag if the gcc supports it.
Which version of gcc is the earliest to include the -fstack-protector-strong flag?

I want my build script (written in bash) to parse the output of gcc --version and automatically add this flag if the gcc supports it.
Instead of doing that, just call gcc -fstack-protector-strong with a valid source file and see if it compiles. Such method works universally for any compile option, which will save you time for searching which version has which options. You may take inspiration from CMake check_c_compile_flag function.

Taking inspiration from #KamilCuk's answer but bashifying it:
add_supported_cc_flag() {
CC=$1
CFLAG_TO_CHECK=$2
C_FILE=/tmp/test.$$.c
O_FILE=${C_FILE/.c/.o}
rm -f ${C_FILE}
cat > ${C_FILE} <<EOF
int main() { return 0; }
EOF
if $CC ${CFLAG_TO_CHECK} -c ${C_FILE} -o ${O_FILE} >/dev/null 2>&1
then
echo ${CFLAG_TO_CHECK}
fi
rm -f ${C_FILE} ${O_FILE}
}
CFLAGS="${CFLAGS} $(add_supported_cc_flag gcc -fstack-protector-strong)"

It appears that -fstack-protector-strong was first available in gcc 4.9.0.
The option doesn't show up in https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/Optimize-Options.html (4.8.5 was the last 4.8.x gcc version), but the option does show up in https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/Optimize-Options.html.
Note that -fstack-protector-all and -fstack-protector are available prior to gcc 4.9.0.

Related

GCC Default Link -l

When I need to use, for example, the gnu function gsl_sf_bessel_J0 in a program, I simply compile it with gcc -lgsl -o gsl_test.c gsl_test. Why do I have to include -lgsl for it to work? Is there any way I can set it as a default so I don't have to type it out everytime?
If you compile with the -v flag, you'll see the command the GCC front-end invokes to link your final executable*. If your program uses a function like gsl_sf_bessel_J0 that isn't in one of the default libraries (possibly limited to libc and maybe also libm), you need to explicitly link it.
If you don't like typing it all the time, make a simple Makefile. Your case is simple enough that you can handle it with just environment variables, actually:
$ export CC=gcc
$ export LDLIBS=-lgsl
$ make gsl_test
gcc gsl_test.c -lgsl -o gsl_test
$
make's default built-in rules will do the rest.
*: for reference, my compiler links your example as:
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld"
-demangle
-dynamic
-arch x86_64
-macosx_version_min 10.12.0
-o gsl_test
/var/folders/cp/wvm69p1n7_bbjpxxqmttwn700000gn/T/gsl_test-0afe3a.o
-lgsl
-lSystem
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/8.0.0/lib/darwin/libclang_rt.osx.a

gcc 4.8.2 cc1plus: error: unrecognized command line option "-std=gnu++11"

I have a system in which I've been compiling programs with C++11 using automake and everything has been working.
However, when a different user take the same exact Makefile they get the aforementioned error.
Now, if they type in g++ --std=gnu++11 program.cpp then there are no complaints.
I've narrowed it down to a line that is causing the issue; however, I don't know how to fix it.
depbase=`echo no_endl.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
g++ -DHAVE_CONFIG_H -I. -I../.. -g --std=gnu++11 -g -O2 -MT no_endl.o -MD -MP -MF $depbase.Tpo -c -o no_endl.o no_endl.cpp &&\
mv -f $depbase.Tpo $depbase.Po
The problem is with depbase; however, I don't know what is going on with it or why it is there.
Below is the Automake file that I used to generate the Makefile:
bin_PROGRAMS = no_endl
AM_CXXFLAGS = -g --std=gnu++11
no_endl_SOURCES = no_endl.cpp
The only difference between my g++ and their g++ is I have an alias so g++ turns into g++ -g.
Helpful information
g++ --version
g++ (GCC) 4.8.2 20140120 (Red Hat 4.8.2-15)
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
If there is any other information that I need to provide, then let me know.
Related Question
I solved the problem.
The problem was the $PATH variables for me and other users.
Now, other users have an alias for g++ to the newer version, but their $PATH omits the actual location.
Make works based on their $PATH variable, so to fix it, I just had to make sure their path had the same location as mine.
You probably need the following additional m4 macro file that handles corner cases of substituted C++11 compilers.
https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html#ax_cxx_compile_stdcxx_11

Remake is skipping over the shell commands I want to debug

I've got a problem with the way I am shelling out. I'm working with Bash, but its on Debian Sid (Unstable) in a ARM64 Chroot. (I'm doing this because its our Debian package maintainer. Otherwise, I run away from the unstable, bleeding edge stuff)...
# echo $0
/bin/bash
It appears one of my shell commands is creating an -o2 rather than an -O2. I suspect memory is being trashed while shelling out, and the -o2 is just a symptom.
# make cryptlib.o
g++ -DNDEBUG -g3 -o2 -pipe -c cryptlib.cpp
Here's the same command under Remake:
# remake -X -f GNUmakefile cryptlib.o
GNU Make 3.82+dbg0.9
Built for aarch64-unknown-linux-gnu
Copyright (C) 2010 Free Software Foundation, Inc.
...
Updating goal targets....
File `cryptlib.o' does not exist.
Must remake target `cryptlib.o'.
Invoking recipe from GNUmakefile:449 to update target `cryptlib.o'.
##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
g++ -DNDEBUG -g3 -o2 -pipe -c cryptlib.cpp
##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
++ (/cryptopp-git/GNUmakefile:448)
cryptlib.o
remake<0>
As can be seen, the stuff I am interested in has already passed. Line 449 is very uninteresting. Its just a standard recipe that uses CXX, CXXFLAGS and $<.
Unfortunately, I don't really see what I should be doing to debug this issue. According to 1.1.6 Debugging Shell Commands, there's a step, but it does not really tell me how to use it. When I attempt to add it to the command:
remake -X step -f GNUmakefile cryptlib.o
It results in No rule to make target 'step'.
How do I debug this makefile with Remake? Or even without it?
The recipe's in your makefile aren't involved with setting that variable's value.
That's is a make variable. It is set at make-parse time by make itself (and the make-level contents of your makefile).
I don't see anything in the linked GNUMakefile that says either -o2 or -g3 both of which are in the make-run compilation command.
That makefile does include a GNUMakefile.deps file if it exists. I suppose that might have the erroneous value in it. Do you have a GNUMakefile.deps file?
Does grep find -g3 or -o2 anywhere in your source directory? (In case there's some other included makefile?)
The last place that make might be getting this value from is the process environment (because CXXFLAGS is defined with the ?= operator).
Do you have CXXFLAGS defined incorrectly in your environment?

Changing OCaml's gcc after installation

I installed OCaml via OPAM, and by default it uses gcc as the command to compile .c files. For instance, if I run ocamlopt -verbose file.c, I obtain:
+ gcc -Wall -D_FILE_OFFSET_BITS=64 -D_REENTRANT -g
-fno-omit-frame-pointer -c -I'/home/user/.opam/4.02.1+fp/lib/ocaml' 'test.c'
I'd like to change the GCC binary that is used by OCaml, for instance to replace it with gcc-5.1 or /opt/my-gcc/bin/gcc.
Is it possible to do so without reconfiguring and recompiling OCaml? I suppose I could add a gcc alias to a directory in the PATH, but I'd prefer a cleaner solution if there is one.
To check if gcc was not chosen based on a textual configuration file (that I could easily change), I searched for occurrences of gcc in my /home/user/.opam/4.02.1+fp directory, but the only occurrence in a non-binary file that I found was in lib/ocaml/Makefile.config, and changing it does nothing for the already-compiled binary.
ocamlopt uses gcc for three things. First, for compiling .c files that appear on the command line of ocamlopt. Second, for assembling the .s files that it generates internally when compiling an OCaml source file. Third, for linking the object files together at the end.
For the first and third, you can supply a different compiler with the -cc flag.
For the second, you need to rebuild the OCaml compiler.
Update
Here's what I see on OS X when compiling a C and an OCaml module with the -verbose flag:
$ ocamlopt -verbose -cc gcc -o m m.ml c.c 2>&1 | grep -v warning
+ clang -arch x86_64 -c -o 'm.o' \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlasm461f1b.s' \
+ gcc -c -I'/usr/local/lib/ocaml' 'c.c'
+ clang -arch x86_64 -c -o \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlstartup695941.o' \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlstartupb6b001.s'
+ gcc -o 'm' '-L/usr/local/lib/ocaml' \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlstartup695941.o' \
'/usr/local/lib/ocaml/std_exit.o' 'm.o' \
'/usr/local/lib/ocaml/stdlib.a' 'c.o' \
'/usr/local/lib/ocaml/libasmrun.a'
So, the compiler given by the -cc option is used to do the compilation of the .c file and the final linking. To change the handling of the .s files you need to rebuild the compiler. I'm going to update my answer above.

How do you use cgo WITHOUT using make?

I use a custom build tool to compile go projects and I need a way to use cgo in my project.
The problem is that the cgo documentation only tells you how to use it with make.
What I really need to know is which generated files to process with which tools and in what order it needs to be done. I tried to read make.pkg in the go source dir but my best effort fails.
My test dll is very simple, a single function that returns 1 every time it is called and the go code to use this function is similarly simple.
The output from the console produced by a successful run of make on a cgo project would be very helpful.
Output of running make on 32-bit Linux in directory misc/cgo/life:
# gomake _obj/life.a
CGOPKGPATH= cgo -- life.go
touch _obj/_cgo_run
8g -o _go_.8 _obj/life.cgo1.go _obj/_cgo_gotypes.go
8c -FVw -I ${GOROOT}/pkg/linux_386 -I . -o "_cgo_defun.8" _obj/_cgo_defun.c
gcc -m32 -I . -g -fPIC -O2 -o _cgo_main.o -c _obj/_cgo_main.c
gcc -m32 -g -fPIC -O2 -o c-life.o -c c-life.c
gcc -m32 -I . -g -fPIC -O2 -o life.cgo2.o -c _obj/life.cgo2.c
gcc -m32 -I . -g -fPIC -O2 -o _cgo_export.o -c _obj/_cgo_export.c
gcc -m32 -g -fPIC -O2 -o _cgo1_.o _cgo_main.o c-life.o life.cgo2.o _cgo_export.o
cgo -dynimport _cgo1_.o >_obj/_cgo_import.c_ && mv -f _obj/_cgo_import.c_ _obj/_cgo_import.c
8c -FVw -I . -o "_cgo_import.8" _obj/_cgo_import.c
rm -f _obj/life.a
gopack grc _obj/life.a _go_.8 _cgo_defun.8 _cgo_import.8 c-life.o life.cgo2.o _cgo_export.o
The line cgo -- life.go creates the following files:
_obj/_cgo_.o
_obj/life.cgo1.go
_obj/life.cgo2.c
_obj/_cgo_gotypes.go
_obj/_cgo_defun.c
_obj/_cgo_main.c
_obj/_cgo_flags
_obj/_cgo_export.c
_cgo_export.h
"I use a custom build tool to compile go projects and I need a way to use cgo in my project."
... and this approach leads to problems. Using the standard way with a Makefile is simple, easy, proven, documented, etc.
I realize I'm not (directly) answering your question. Instead my "answer" is: I strongly suggest to use the standard way. Don't create problems for your self by choosing other, not directly supported options.
That said, I think there is a way to avoid the Makefiles, I just never been there, sorry. I'm usually lazy/short of time, so I use the simplest/fastest way to get things done. You might want to try the same ;-)

Resources