GCC and linking environment variables and flags - gcc

The following link in the official documentation for GCC:
https://gcc.gnu.org/onlinedocs/gcc/gcc-command-options/environment-variables-affecting-gcc.html
Explains the following environment variables:
LANG
LC_CTYPE
LC_MESSAGES
LC_ALL
TMPDIR
GCC_COMPARE_DEBUG
GCC_EXEC_PREFIX
COMPILER_PATH
LIBRARY_PATH
CPATH
C_INCLUDE_PATH
CPLUS_INCLUDE_PATH
OBJC_INCLUDE_PATH
DEPENDENCIES_OUTPUT
SUNPRO_DEPENDENCIES
But I have also heard/read before about these other compiling flags:
For compiling C code: CC, CFLAGS
For compiling C++ code: CXX, CPPFLAGS
And linking flags:
For the linking stage: LDFLAGS
After the code is compiled: LD_LIBRARY_PATH
What is the meaning of CC, CFLAGS, CXX, and CPPFLAGS? Why aren't they included in the official list of environment variables for gcc?

To begin with, all the variables you mentioned: CC, CFLAGS, CXX, CXXFLAGS, LDFLAGS, LD_LIBRARY_PATH, are originated from Unix OS family. These variables have nothing to do with GCC in the first place, that's why you see no trace of them in the manuals.
The only meaningful variable (which has no direct connection with GCC too) among these is LD_LIBRARY_PATH. You'll probably find this variable to be defined out-of-the-box on any modern Unix-like OS. Here is the the LD.SO(8) man-page from Linux Programmer's Manual which mentions LD_LIBRARY_PATH and its purpose. Here is one more extract:
The LD_LIBRARY_PATH environment variable contains a colon-separated list of directories that are searched by the dynamic linker when looking for a shared library to load.
The directories are searched in the order they are mentioned in.
If not specified, the linker uses the default, which is /lib:/usr/lib:/usr/local/lib.
As you can see LD_LIBRARY_PATH is nothing but an OS-specific environment variable for proper loading of shared libraries. Windows has similar environment variable in this regard: PATH. Windows will scan directories listed in it when searching for dynamic-link library (DLL, a counterpart of SO on Linux) too.
Concerning the rest of the variables (CC, CFLAGS, CXX, CXXFLAGS, LDFLAGS), you see them so often due to the historical reasons. Since the rise of Unix era, software projects were built using Make (scroll down and look at the examples of typical makefiles) — one of the pioneering build tools. These variables were so extensively used in makefiles that eventually they became sort of a convention (see Implicit Rules, for instance). That's why you can even see them defined out-of-the-box on, for example, Linux, and most likely pointing to GCC (as it is considered to be the native toolchain for Linux).
To conclude, the point is: don't scratch your head over CC, CFLAGS, CXX, CXXFLAGS, LDFLAGS, and friends, as they are just a blast from the past. ;)
BONUS
Using plain old Make directly to build complex software today quickly becomes tedious and error-prone. As a result, numerous sophisticated build system generators like GNU Automake or CMake have been developed. In brief, their goal is to provide (arguably) more readable, easy-to-maintain, and high-level syntax to define an arbitrarily complex build system for an arbitrary software project to be built. Typically, before actually building the project, one has to generate a native build system (which could also be represented by plain old makefiles, for example, for portability reasons, but not necessarily) out of this high-level definition using the corresponding set of tools. Finally, one has to build the project with the tool(s) corresponding to the generated (native) build system (for example, Make in case of plain old makefiles, but not necessarily).
Since you are asking these questions, I suspect that you are about to dive into native software development with C or C++. If so, I would strongly recommend you to pick a modern build system (CMake would be my personal recommendation) in the first place, play with it, and learn it well.

In simple terms CC, CFLAGS, LDFLAGS etc are gnu Makefile variables. If defined, these will be used by implicit rules even without actually being mentioned in commands/rules

You can definitely use environment variable with GCC for CFLAGS and CC (and anything else). You just have to pass the variables to the the compile line, with slight differences depending on the operating system.
Linux set CFLAGS environment variable:
export CFLAGS="-g -Wall -std=c89 -pedantic"
Compile on Linux using CFLAGS
gcc $CFLAGS - o progname progname.c
Windows set CFLAGS environment variable:
set CFLAGS=-g -Wall -std=c89 -pedantic
Compile on Windows using CFLAGS
gcc %CFLAGS% - o progname progname.c
You can even setup a temporary compile string at a variable and call it to compile as you're testing.
set BUILD=gcc -g -Wall -std=c89 -pedantic - o progname progname.c
and call it like...
%BUILD%
One thing to remember when setting and using the variables on Linux (as most programmers know), the variables are case sensitive so $cflags would simply be ignored. On Windows case doesn't matter.
On both systems the above only works until the terminal (or command prompt) session is terminate. To make them permanent you need to set the variables in their respective settings files.

Related

How to change the default-search-path values for GNU GCC for regular usage?

GNU GCC Compiler Environment Variables Default-Search-Path — I am trying to change default values of GCC environment variables to new custom values so that the default search path will contain any needed additional libraries or include header files that I would like to use on a regular basis.
My version of GNU GCC is: gcc (MinGW.org GCC Build-2) 9.2.0
Include directories for .h header files for this <…> not "…" which would be in the same directory as .c file extension.
Include Header Directories:
CPATH
C_INCLUDE_PATH
CPLUS_INCLUDE_PATH
OBJC_INCLUDE_PATH
Library File Directories:
LIBRARY_PATH
I realized that these are Windows Environment Variables.
And That I could Simply just create Windows User Environment Variables.
Here is a command which will show default search paths for GNU GCC Compiler.
cpp -v
This shows include directory default search path.
gcc -print-search-dirs
This shows library directory default search path.
This Command Prompt Command tells me the default-search-paths which are set during installation of GNU GCC Compiler I assume these are considered Environment Variables and I am looking to see if anyone on the web could give me any urls in regards to changing this default search path value.
Here are a few links related to what I am doing. I used that information although I was still unable to accomplish what I was intending to accomplish.
GCC environment variables
C Preprocessor search path
C preprocessor environment variables
GCC configuration
Recent GCC compilers have some (optional) .spec files.
You could edit yours, and that file drives the actual compilation processes. As you know, gcc is mostly starting some cc1 / cc1plus internal program (then ld)
But I recommend to not edit your .spec file.
Instead of that, configure your build procedure, e.g. edit your Makefile for GNU make or your build.ninja file (actually, the generator of that file) for ninja builder.
Of course, read the chapter about Invoking GCC.
BTW, GNU make has a lot of built-in rules. Use make -p to understand them.
You could also take inspiration from GNU autoconf.
You could also code your own GCC plugin, implementing your own #pragma which would customize the behavior of gcc. I am not sure it is a good idea.
How to change the default-search-path values?
don't do that, learn to use GCC instead
You might want, from time to time, to compile your code with Clang, to check that your code base is not tied to one particular compiler.
You could use Frama-C or the Clang static analyzer on your C code. In some cases, some bugs could be found at compile time. You certainly want to pass explicitly both -Wall and -Wextra to gcc (and notice that clang accepts them also)
PS. This is from a GNU/Linux perspective. Adapt that to your proprietary operating system. Or consider getting the permission to switch to Linux (see also this draft report funded by the CHARIOT European project).

arm gcc by default compiling its libc

I am trying to compile an SDK with the an embedded arm gcc compiler in cygwin. It is a makefile based SDK. My target is a cortex m3 device. My problem is, the SDK has a custom libc implementation for the target, and when I compile with the arm compiler (arm-none-eabi-gcc) it looks to pick up the gnu arm libc, not the SDK libc. This is resulting in a compilation error. I am positive the makefiles are correct (I copy and pasted the entire SDK from a computer where this was working). I no longer have access to that computer to try and verify / compare settings. I don't know how to prevent the arm gcc compiler from looking for its own implementation of the libc and instead point it to the correct implementation. Any help is greatly appreciated.
There are perhaps two solutions:
Create an environment specific to your tool - the GNU toolchain uses a number of environment variables to define default behaviour. For a custom toolchain, you will need to set all necessary variables to override the system defaults.
Use the -nostdlib linker option and explicitly link your desired library and C Runtime start-up code, so your linker command line might include the following:
-nostdlib -L/usr/myarmtools/gcc/lib -lc crt0.o
Note that -nostdlib suppresses the default linking of libc libstdc++ and crt0.o, so you must provide search path (-L) to the libraries, or explicitly link them by their full path and file name and link the C runtime object code for your target.
I use option 2 for preference as it will work in any environment. However if you wish to use common makefiles for building for multiple targets, option 1 may be useful.

passing CC/CFLAGS/LDFLAGS from Makefile to ./configure of Tk/Tcl

I'm trying to compile one library (xcrysden, based on Make file) which during its compilation execute ./configure of an external dependencies - Tk and Tcl 8.5 - and compiles them.
So, the structure is roughly like this:
The main Makefile:
...
cd external/src; make;
external dependencies (pre-)makefile (Tk):
include ../Make.sys
cd /unix
./configure
make
make install
Make.sys included by external makefile:
...
CFLAGS =...
CC =...
The configure, obviously, produces another makefile in /external/src/unix to be used by Tk.
In Tk documentation it is written:
If you wish to specify a particular compiler, set the CC environment variable before calling configure. You can also specify CFLAGS prior to configure and they will be used during compilation.
But from the resulting Makefile i definitely see that neither the defined compiler (CC) nor flags (CFLAGS) are used. Does it qualify as 'environment variable' when it is set in another make file?
I actually have problems compiling Tk, so i try to pass not only compiler but linking info
LDFLAGS = -L/opt/local/lib -lfontconfig .
I want to do it in a neat way (that is, modifying only Make.sys of the library dependent on Tk). But then i face the problem that not only don't i know how to pass LDFLAGS to Tk configure, but even CC/CFLAGS are not there. I'm not sure if this is specific to particular library (Tk) using ./configure or I misunderstand the general usage of ./configure.
p/s/ i'm compiling on OS-X using gnu compilers.
The problem is that the variables you define in ../Make.sys are currently local to the shell that processes the include; the configure and make are run in subprocesses and don't find out that you've got any preferences. The right thing to do is to add:
export CFLAGS CC
between the include and the call to ./configure.
You could also put it inside Make.sys, or invoke configure as CFLAGS=$CFLAGS CC=$CC ./configure. You probably shouldn't set the values directly in the invocation of make though; setting the compiler can mean that different other flags are required as well.

How to compile for a freestanding environment with GCC?

The code I'm working on is supposed to be possible to build for both hosted and freestanding environments, providing private implementations for some stdlib functions for the latter case.
Can I reliably test this with just GCC on a normal workstation/build server? Compile for freestanding environment with GCC
The "-ffreestanding" option looked promising, but it seems that it "only" disables built-ins and sets the STDC_HOSTED macro properly, it still provides all system headers.
The option "-nostdinc" is too restrictive; I still want to use the headers required for a freestanding implementation (in particular stddef.h and limits.h).
What am I missing here?
Oh, and I'm using GCC 4.4.3 for the moment, will upgrade to 4.5.0 "soon".
Well, since no answer is given yet I'd might as well describe how I made this work. It's pretty simple although depending on the target system it can be tedious.
Using "-nostdinc" means that the standard system include paths will be skipped; other include-paths given with "-I" will of course still be searched for headers.
So, for the freestanding build target I create a folder 'include-freestanding-c89' and link the relevant system headers -- float.h, iso646.h, limits.h, stdarg.h and stddef.h -- there. Other headers might be included in these, depending on your platform, so you might have to do some research and set up more links (hence the tediousness if you need to do this for several target platforms).
The C89 directory can then be used as base for 'include-freestanding-c99', the extra headers to link are stdbool.h and stdint.h
The command-line to use is then
gcc -std=c89 -nostdinc -nostdlib -ffreestanding -I include-freestanding-c89
or
gcc -std=c99 -nostdinc -nostdlib -ffreestanding -I include-freestanding-c99
This Xen Makefile uses gcc -print-search-dirs to get the directory with stddef.h and similar, adds it with -isystem, then uses -nostdinc to build:
https://github.com/mirage/xen/blob/2676bc915157ab474ee478d929b0928cf696b385/stubdom/Makefile#L35

Passing a gcc flag through makefile

I am trying to build a pass using llvm and I have finished building llvm and its associated components. However, when I run make after following all the steps to build a pass including the makefile, I get the following
relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
After tyring to find a fix by googling the error message, I came to know that this is not specific to llvm. A few solutions suggested that I should use "--enable-shared" while running configure but that didn't help my case. Now I want to re-build llvm using fPIC, as the error says. But how do I do this using the makefile?
Looks like you could add the -fPIC (for position-independent code, something you want for a shared library that could be loaded at any address) by setting shell variables:
export CFLAGS="$CFLAGS -fPIC"
export CXXFLAGS="$CXXFLAGS -fPIC"
Looking at Makefile.rules, these will be picked up and used. Seems strange that it wasn't there to begin with.
EDIT:
Actually, reading more in the makefiles, I found this link to the LLVM Makefile Guide. From Makefile.rules, setting either SHARED_LIBRARY=1 or LOADABLE_MODULE=1 (which implies SHARED_LIBRARY) in Makefile will put -fPIC in the compiler flags.
If you are moderately convinced that you should use '-fPIC' everywhere (or '-m32' or '-m64', which I need more frequently), then you can use the 'trick':
CC="gcc -fPIC" ./configure ...
This assumes a Bourne/Korn/POSIX/Bash shell and sets the environment variable CC to 'gcc -fPIC' before running the configure script. This (usually) ensures that all compilations are done with the specified flags. For setting the correct 'bittiness' of the compilation, this sometimes works better than the various other mechanisms you find - it is hard for a compilation to wriggle around it except by completely ignoring the fact you specified the C compiler to use.
Another option is to pass -fPIC directly to make in the following way:
make CFLAGS='-fPIC' CXXFLAGS='-fPIC'

Resources