In my makefile for a C project, I have set the CFLAGS variable as follows -
CFLAGS=-ansi -pedantic -Wall -Wextra -O2 -isystem $(SQLITEDIR)
I expected this variable to be used in the rule for building object files since the flags affect the compilation step
However, in the GNU make manual
https://www.gnu.org/software/make/manual/make.html#Using-Implicit
I see the following example -
foo : foo.o bar.o
cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
I think this is a rule for the linking step so I understand it why it include LDFLAGS, but what is the purpose CFLAGS here?
(I am guessing that you are using GNU make on some Linux system)
You are right in your use of CFLAGS (but I would add -g there). But I am not sure you need -isystem $(SQLITEDIR), it probably can be -I $(SQLITEDIR) instead. The -isystem directory option to GCC is rarely useful.
Read first the documentation about Invoking GCC, assuming you are using the GCC compiler. BTW, you could have CC= gcc in your Makefile. If your compiler is not GCC but something else (e.g. Clang/LLVM) read its documentation.
Then, run make -p to understand the builtin rules of your GNU make (there are many of them). You'll find out that many builtin rules are using CFLAGS etc. And that is why it is simpler to have a CFLAGS variable in your Makefile; if possible, take advantage of some builtin rules known to make.
BTW, you could avoid using any builtin rules and variables, but that is poor taste.
The POSIX standard defines some options understood by cc and by make (and some minimal rules for make). Both GCC and GNU make have much more. Read documentation of GNU make.
CFLAGS usually contain some (optimization or other) flags (e.g. -O or -g, or -pthread) which are also relevant at the linking step (assuming you link with gcc, which will invoke ld). That is why you usually link using gcc (as $(CC) in your recipe) with both LDFLAGS and CFLAGS.
You could use make --trace or even remake (as remake -x) to debug your Makefile.
Related
I want to activate c99 mode in gcc compiler to i read in other post in this forum that -std should be equal to -std=c99 but i don't know how to set it to this value using command line so please help.
Compile using:
gcc -std=c99 -o outputfile sourcefile.c
gcc --help lists some options, for a full list of options refer to the manuals. The different options for C dialect can be found the section "Options Controlling C Dialect" in any gcc version's manual (e.g., here).
As you are using make you can set the command line options for gcc using CFLAGS:
# sample makefile
CC = gcc
CFLAGS = -Wall -std=c99
OUTFILE = outputfile
OBJS = source.o
SRCS = source.c
$(OUTFILE): $(OBJS)
$(CC) $(CFLAGS) -o $(OUTFILE) $(OBJS)
$(OBJS): $(SRCS)
$(CC) $(CFLAGS) -c $(SRCS)
Addendum (added late 2016): C99 is getting kind of old by now, people looking at this answer might want to explore C11 instead.
You may try to use the -std=c99 flag.
Try to complile like this:
gcc -Wall -std=c99 -g myProgram.c
Also note that -g is for debugging option(Thanks Alter Mann for pointing that).
Based on the comments under another answer, perhaps you are using the implicit make rules and don't have a Makefile. If this, then you are just runing make tst to generate tst binary from tst.c. In that case you can specify the flags by setting the environment variable CFLAGS. You can set it for the current shell, or add it to your ~/.bashrc to have it always, with this:
export CFLAGS='-Wall -Wextra -std=c99'
Or specifying it just for the single command:
CFLAGS='-Wall -Wextra -std=c99' make tst
(Note: I added warning flags too, you should really use them, they will detect a lot of potential bugs or just bad code you should write differently.)
Is there a way of telling gcc to use the c99 standard when compiling c files as a default?
I want to avoid giving it the -std=c99 parameter all the time.
I assume I can do this by creating an alias in the .bashrc file, but seems to be rather inelegant.
You may call c99 instead of gcc (wrapper for gcc, if it's available on your system) or try to modify your gcc spec file. More information here: http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Spec-Files.html
Here's an unexpected answer. Use a Makefile!
Pros:
Simply type make to build
All options are automatically handled in the build process.
While you're at it, go ahead and enable all warnings, as is good to do. See this.
Easy to scale up to multiple source files
Can handle multi-step builds involving different tools
Cons:
Another tool to learn, another thing to get wrong.
Consider this source:
#include <stdio.h>
int main() {
printf("Hello!\n");
int x = 4;
printf("%d\n", x);
return 0;
}
You could make a Makefile like this:
(Disclaimer, I don't actually know how to write them)
CC=gcc
CFLAGS=-Wall -pedantic -std=c99
LDFLAGS=
SOURCES=$(wildcard *.c)
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello
.PHONY: clean
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
clean:
rm -f *.o $(EXECUTABLE)
And it builds for me.
Likewise, if you remove the -std=c99, it shouldn't be valid C89 code, and indeed, typing make brings up the build error.
Custom compilation suggests you have at a working knowledge of compilers, standards, and basic flags / options. For that reason, I suggest you set shell variables in your .bashrc, .tcshrc, etc., and use them on the command line.
Since the choice of dialect can have an effect on linking: CC="gcc -std=c99", lets you invoke separate compilation commands using $CC -c -O2 ... foo.c, and is also picked up as the default for configure scripts, etc. Of course, you can always override a configure script with CC="gcc -std=c90" or CC="clang". The same applies to a preferred CFLAGS value, e.g.,
CFLAGS="-pipe -W -Wall -O2 -march=core2"
Allows for $CC $CFLAGS -c foo.c commands, and both environment variables are used by default with configure scripts, unless you explicitly override them. I think this is more useful than aliases. But perhaps I've just grown used to my own setup:)
Both of the proposed solutions are, in my opinion, almost what you want, but neither quite gets there.
Makefile solution
As seen here, by defining variables in your Makefile but not defining targets, you can use the make command like a customized pass-through to GCC. So if you create a Makefile in your "sandbox" directory (or wherever you're compiling outside of a real build system) and define the C*FLAGS vars, you'll essentially get what you want. An example Makefile:
CFLAGS=-Wall -std=c99
CXXFLAGS=-Wall -std=c++14
Now, make foo will turn foo.c into an executable called foo.
If you want to do this trick in multiple directories, put your makefile in a known location--say, ~/sandbox--and create the following alias (or something like it) in your .bashrc:
alias usestdmake="ln -s ~/sandbox/Makefile"
Then you can quickly compile a single file anywhere on your machine:
usestdmake
make foo
This has the added advantage of giving the output executable an appropriate name (foo in this case). It has the disadvantage of disabling tab-completion for your compile command (make fo<tab> does nothing, at least on my system).
Pure bashrc solution
The CC/CFLAGS variables mentioned in Brett Hale's answer are fairly standard, so it might be a good idea to define them in your bashrc. You can then use these variables inside of aliases.
In your .bashrc:
CFLAGS="-Wall -std=c99"
CC=gcc
# Use single-ticks to ensure that the variables are evaluated when the alias is evaluated.
alias mycc='$CC $CFLAGS'
On the command line:
cc foo.c # Compile with default CFLAGS
CFLAGS="$CFLAGS -O2" cc foo.c # Compile with modified CFLAGS
I have a simple Autotools C project (not C++).
CFLAGs (by inspection) seem to be -g -O2.
I want all of the generated make files to also have -std=gnu99 appended to the CFLAGs, because I use for (int i = 0; i < MAX; i++) and similar.
I can obviously hack the Makefile, but this gets overwritten on ./configure.
Where is the correct place to add (or change) CFLAGs which are required by the code (as opposed to those CFLAGs which the user might want to change)?
(Note this is partial duplicate of Where to add a CFLAG, such as -std=gnu99, into an (Eclipse CDT) autotools project as I was getting Eclipse-specific answers which I didn't want.)
#DevSolar's answer has not helped yet. A configure.ac file (below) generates the configure script (also below).
configure.ac:
dnl Process this file with autoconf to produce a configure script.
CFLAGS="$CFLAGS -std=gnu99"
AC_PREREQ(2.59)
AC_INIT(tuntest, 1.0)
AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE()
AC_PROG_CC
AC_CONFIG_FILES(Makefile src/Makefile)
AC_OUTPUT
$ grep CFLAGS configure
CFLAGS
CFLAGS
To assign environment variables (e.g., CC, CFLAGS...), specify them as
CFLAGS C compiler flags
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_test_CFLAGS=${CFLAGS+set}
ac_save_CFLAGS=$CFLAGS
CFLAGS="-g"
CFLAGS=""
CFLAGS="-g"
if test "$ac_test_CFLAGS" = set; then
CFLAGS=$ac_save_CFLAGS
CFLAGS="-g -O2"
CFLAGS="-g"
CFLAGS="-O2"
CFLAGS=
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
autoconf has a macro for this:
Just put:
AC_PROG_CC_STDC
after your AC_PROG_CC and everything will be right.
Especially when you use other compilers that do not have -std=gnu99 but operate in C99 mode by default (or have a different option hpcc's -AC99 springs to mind).
I would NOT use CFLAGS for that kind of thing.
From the docs:
-- Macro: AC_PROG_CC_STDC
If the C compiler cannot compile ISO Standard C (currently C99),
try to add an option to output variable `CC' to make it work. If
the compiler does not support C99, fall back to supporting ANSI
C89 (ISO C90).
After calling this macro you can check whether the C compiler has
been set to accept Standard C; if not, the shell variable
`ac_cv_prog_cc_stdc' is set to `no'.
Although using a macro like AC_PROG_CC_STDC is preferable to adding compiler options to CFLAGS, autoconf currently has no macros enabling C11 compiler support -- there is no AC_PROG_CC_C11 yet, and AC_PROG_CC_STDC only adds the -std=gnu99 option for gcc instead of -std=gnu11 or -std=c11.
You can add compiler flags simply by putting
CFLAGS="$CFLAGS -std=c11"
in the configure.ac.
Alternatively, it might be better to check first if the compiler supports the added option, and print a warning otherwise, telling the user to manually add an equivalent option to CFLAGS that works for their compiler:
AX_CHECK_COMPILE_FLAG([-std=c11],
[AX_APPEND_FLAG([-std=c11])],
[AC_MSG_WARN([-std=c11 not supported, you may have to set CFLAGS to enable C11 support.])
])
This uses the AX_CHECK_COMPILE_FLAG and AX_APPEND_FLAG macros found in the GNU Autoconf Archive. To use them, put them into an m4 subdirectory and add AC_CONFIG_MACRO_DIR([m4]) to configure.ac
This topic is covered in the Automake manual, 27.6 Flag Variables Ordering. There an interaction between configure.ac and Makefile.am, and its more than just setting a well known shell variable used in implicit make rules.
The short of it is, you should set it in a new variable called something like mumble_CFLAGS discussed in the Automake manual. mumble is just the name of your program, and it is often foo or bar in other examples. Later, when your makefile is created, the recipe for your program (mumble or foo or bar) will use $(mumble_CFLAGS) $(CFLAGS) to build the target.
Here is an example of how it might look. Instead of using mumble or foo or bar, it uses my_prog as a artifact name.
configure.ac:
# Perform a compile test using -std=gnu99, set has_gnu99
if test "$has_gnu99" -eq "1"; then
AC_SUBST([MY_GNU99], [-std=gnu99])
fi
Makefile.am:
bin_PROGRAMS = my_prog
my_prog_CFLAGS = $(MY_GNU99) $(MY_ANOTHER_FLAG) $(MY_YET_ANOTHER_FLAG) ...
Later, when the makefile is generated, it will have a recipe similar to the following, where $(MY_PROG_CFLAGS) is applied to all the objects that build my_prog:
my_prog :
$(CC) $(CPPFLAGS) $(MY_PROG_CFLAGS) $(CFLAGS) -c $< -o $#
The extra indirections of my_prog_CFLAGS allows you to have multiple flags for different targets. For example, you could have a my_prog_CFLAGS, a my_archive_CFLAGS and a my_sharedobj_CFLAGS.
And its not limited to my_prog_CFLAGS. You could also have my_prog_CPPFLAGS, my_prog_CXXFLAGS and other variables used implicitly in makefiles.
This is from the Automake manual:
Compile Flag Variables
This section attempts to answer all the above questions. We will
mostly discuss CPPFLAGS in our examples, but actually the answer holds
for all the compile flags used in Automake: CCASFLAGS, CFLAGS,
CPPFLAGS, CXXFLAGS, FCFLAGS, FFLAGS, GCJFLAGS, LDFLAGS, LFLAGS,
LIBTOOLFLAGS, OBJCFLAGS, OBJCXXFLAGS, RFLAGS, UPCFLAGS, and YFLAGS.
CPPFLAGS, AM_CPPFLAGS, and mumble_CPPFLAGS are three variables that
can be used to pass flags to the C preprocessor (actually these
variables are also used for other languages like C++ or preprocessed
Fortran). CPPFLAGS is the user variable (see User Variables),
AM_CPPFLAGS is the Automake variable, and mumble_CPPFLAGS is the
variable specific to the mumble target (we call this a per-target
variable, see Program and Library Variables).
Automake always uses two of these variables when compiling C sources
files. When compiling an object file for the mumble target, the first
variable will be mumble_CPPFLAGS if it is defined, or AM_CPPFLAGS
otherwise. The second variable is always CPPFLAGS.
In the following example,
bin_PROGRAMS = foo bar
foo_SOURCES = xyz.c
bar_SOURCES = main.c
foo_CPPFLAGS = -DFOO
AM_CPPFLAGS = -DBAZ
xyz.o will be compiled with ‘$(foo_CPPFLAGS) $(CPPFLAGS)’, (because
xyz.o is part of the foo target), while main.o will be compiled with
‘$(AM_CPPFLAGS) $(CPPFLAGS)’ (because there is no per-target variable
for target bar).
The difference between mumble_CPPFLAGS and AM_CPPFLAGS being clear
enough, let’s focus on CPPFLAGS. CPPFLAGS is a user variable, i.e., a
variable that users are entitled to modify in order to compile the
package. This variable, like many others, is documented at the end of
the output of ‘configure --help’.
For instance, someone who needs to add /home/my/usr/include to the C
compiler’s search path would configure a package with
./configure CPPFLAGS='-I /home/my/usr/include'
and this flag would be propagated to the compile rules of all
Makefiles.
To clarify things, let's suppose I'm compiling a program (prg) with 3 files, main.c, person.h and person.c.
If I use a concise way of writing the makefile, like this (more specifically the two last lines):
prg : main.o person.o
gcc -Wall -o prg -c $^
main.o : person.h
person.o : person.h
Will the -Wall be applied to main.o and person.o automatically? Or that doesn't even matter?
I know that, as the file says, if person.o needs to be re-compiled, prg will need a re-build too. But, I don't know if specifying -Wall only in the main goal is enough to enable it the other targets so warnings are emitted as the others are compiled.
Maybe I'm missing something really important, or I'm saying something that makes no sense; but take it easy, I'm just a beginner :P
Since you apply the -Wall to the link phase (when collecting the object files into an executable), but the option applies to the compilation phase (converting the source files into object files), it provides no benefit where it is written.
You should modify the compilation by setting macros.
Normally, the rule for compiling an C source file to an object file looks something like:
${CC} ${CFLAGS} -c $*.c
There could be other bits in there, and the notation might use something other than $*.c to identify the source file - there are similar (roughly equivalent) methods for specifying that, but it is tangential to the point I'm making. The $(CC) notation is equivalent to ${CC} too.
So, to change the compiler, you specify 'CC=new_c_compiler' and to change to compilation options, you (cautiously) specify 'CFLAGS=-Wall'.
This can be done in the makefile, or on the command line. The command line overrides the makefile.
Hence:
CFLAGS = -Wall
prg : main.o person.o
${CC} ${CFLAGS} -o prg -c $^
main.o : person.h
person.o : person.h
Why cautiously? Because in more complex situations, there may be a complex definition of CFLAGS which build it up from a number of sources, and blithely setting CFLAGS = -Wall may lose your include paths, macro definitions, and all sorts. In your case, it looks like you can simply set it as shown.
If you use GNU Make, you can simply add -Wall to CFLAGS:
CFLAGS += -Wall
This does not necessarily work with all varieties of make.
Your link line may eventually need to collect some library-related options too.
No, the flags will not magically be applied to other targets.
Add a line like this to the top of your Makefile, above the rules:
CFLAGS=-Wall
Then try without the explicit line for prg.
We are required to compile C source codes using gcc in this manner:
gcc -ansi -pedantic -Wall program.c
I'm wondering how can I 'automate' this so when I enter:
gcc program.c
It will automatically compile with the 3 switches. Is this possible?
You can also use the implicit rules of make, so that you don't have to write a makefile for every program. Make will automatically call the compiler if you say make foo and there exists a foo.c file in the current directory. To add flags to this define the variable CFLAGS in your environment, e.g. in bash add export CFLAGS="-Wall -pedantic -ansi" to .bashrc.
If your program depends on multiple files however you'll have to create a makefile, but for C compilation you can get away with just listing dependancies so long as one of them has the same base name as a target.
For example for this makefile:
# Makefile
foo:foo.o bar.o
running make will execute the commands
gcc $CFLAGS -c -o foo.o foo.c
gcc $CFLAGS -c -o bar.o bar.c
gcc -o foo foo.o bar.o
without you having to add any rules.
To automate the build of any number of build steps / complex parameters, you should use a makefile.
Once you have a makefile you simply need to type: make
alias gcc="gcc -ansi -pedantic -Wall"
But as #Brian said, you really should use a makefile, or better, a build system like CMake or SCons.
A makefile would be the traditional way, especially as part of a larger build process.
If you frequently want to build without a makefile, you could define an alias in your .bashrc or equivalent: alias gcc=gcc -ansi -pedantic -Wall.
You can use a shell script that takes some cues by how its called and invokes make after setting CFLAGS appropriately for the occasional one-off build.
Lets say you have /usr/bin/compile , which is a shell script that looks at $0 to see what name actually invoked it. You then make symbolic links to it named pedantic, fullwarn, etc.
In the shell script itself, something like:
OLDCFLAGS=$CFLAGS
WHATAMI=$(basename $0)
case "$WHATAMI" in
pedantic)
export CFLAGS="-Wall -pedantic -ansi"
make $#
exit $?
;;
c99)
export CFLAGS="-std=c99 ... ... ..."
....
Then, to compile foo.c with the extra naggy flags:
pedantic foo
This is handy, as I said for one-off builds, e.g trying to compile code that someone posted in a question, or working out how to use a new library, etc.
For anything else, just use a makefile, as others have said.