compile C code with no flag other than -o - c

Im doing an assignment and the requirement instruction say "Your code should compile correctly (no warnings and errors) with no flags other -o. you should compile your code to a debug-able executable without producing any warnings or error messages. (Note that -O and -o are different flags.)"
So Im so confused what does the " no flags other -o " means. As far as I know, "flag is a general tool for rudimentary signalling and identification, especially in environments where communication is similarly challenging.", so does the requirement mean that we can't use any for loop ?

No, the requirement is referring to command-line flags, ie options to the compiler. Eg, assuming gcc, gcc -o foo foo.c.
However, since the program is meant to be debuggable, the requirements are contradictory because creating a debuggable executable requires (for gcc) the -g flag.

On many compilers, you can control the warning level with flags. The requirement here is to not use those flags, yet raise no warning.
Said differently, you are just asked to write neat and clean C code using no specific extension nor any semi valid constructs (code not conforming to the standard but accepted with warnings by a compiler)

Related

Best practices regarding warning outputs when compiling in gcc? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I'm learning c and am compiling all my programs using gcc in linux subsystem for windows.
I learned that I can include some flags by the gcc standards. Some include the basic -o or -lm.
I discovered the -Wall flag and it has outputted some warnings in my shell that I fix.
Right now my usual gcc compilation line usually lies along the lines of cc -Wall -lm -o file.exe file.c.
I recently learned that there are a lot of other flags that can be included, some regarding warnings; one is -w, which is supposed to show even more warnings than -Wall, so my question is -
1- Should I always specify -w? or is there any drawbacks or maybe even incorrect issued warnings?
2- Also, what are the best practices when compiling a program, i.e., what options/flags do you always turn on?
The more professional you become the more warnings you strive to enable. My current favorite set is -Wall -Wextra -pedantic which gives a good average.
If you think you receive a false warning, think again. Almost always the compiler is right. Until you become an intimate expert with the C standard you better ask, for example here on SO.
Some think that -Werror has some value, and for their development process they are probably right. Since I use some kind of build control software (namely "make") I don't need it, because GCC returns non-zero values on warnings, too.
All other flags depend on the purpose of the command. Some examples:
-o is great to define the name of the output file.
(EDIT)-O… sets the optimization level; some years ago -O3 might have some problems but today it should be fine.
-s strips the debug information from the output; good for the release version.
-g includes debug information to the output; there are variants depending on your goal.
-Wl,--wrap… is really sophisticated for special debugging and/or testing; read its documentation.
Another best practise can be considered the often use of -Wfatal-errors
GCC compiler errors can sometimes be several pages long (especially so if you ever have to compile C++ code). There are several reasons for while compiler errors can be so long; a typical example is some missing brackets at the top of the file, which causes the compiler to report errors for many lines of the remainder of the file.
Seasoned developers know to initially direct their attention on the top-most error, and fixing that often solves all the following pages of errors. To help with this working practise, you can add the -Wfatal-errors to tell gcc that you only want to see the first error, and that it should stop trying to compile the rest of the code once a compilation error is detected. Thus you never get the daunting pages of output that you have to scroll through.
Best practice is then switching to and from this -Wfatal-errors mode, or just leave it mostly on, only occasionally turning it off when you would like to see more errors for a particular problem.
Should I always specify -w?
-w removes all warning messages. You should not use -w.
If you meant -W, it's an old flag for -Wextra, has the same meaning as -Wextra.
Also, rules are not absolute. Not always, there are project specific needs and recommendations. If I write a short program, I sometimes use like gcc -ansi -xc - <<<'a;b;main() { printf("%d\n", a * b); } because I'm in a hurry. But usually, if not always, you should enable as many warnings as you can.
or is there any drawbacks or maybe even incorrect issued warnings?
The drawbacks of too many warnings are coming from too many enabled warnings - clutter in compiler output, while irrelevant warnings hide important stuff. The warnings I do not like:
unused functions -Wunused-function
unused function parameters -Wunused-parameter
Although code may be perfectly fine, ton of "unused function" warnings may be issued, while these functions may be used in like different project configuration chosen by different macro definitions.
what are the best practices when compiling a program, i.e., what options/flags do you always turn on?
I recommend for warnings: -Wall -Wextra -Wwrite-strings -Wno-unused-function -Wno-unused-parameter
I also recommend following flags to write safe code and protect against runtime mistakes: -D_FORTIFY_SOURCE=2 -fsanitize=address -fsanitize=undefined -fsanitize=leak -fsanitize=pointer-subtract -fsanitize=pointer-compare -fno-omit-frame-pointer -fstack-protector-all -fstack-clash-protection -fcf-protection
Fun fact: -Wwrite-strings is not enabled with -Wall -Wextra and looks like a valuable warning to me.
See also redhat recommended compiler and linker flags for GCC.
With gcc10 static analyzer options are also worth a look.

Is it possible to pass GCC arguments directly from C source code?

I want to be able to pass arguments to GCC from my C source code, something like this...
// pass the "-ggdb" argument to GCC (I know this won't work!)
#define GCC_DEBUG_ARG -ggdb
int main(void) {
return 0;
}
With this code I'd like to simply run gcc myfile.c which would really run gcc myfile.c -ggdb (as the "-ggdb" argument has been picked up from the C source code).
I'm not interested in using make with the CFLAGS environment variable, I just want to know if its possible to embed GCC options within C source code
What you want to do is not possible in general.
However, recent GCC (e.g. GCC 8 in end of 2018) accepts many options and some of them could be passed by function attributes or by function specific pragmas (However, they don't accept -g but do accept -O2).
Also, you can use -g in every compilation (with GCC, it is mixable with optimization flags such as -O2; so runtime performance won't suffer. Of course the -g will increase compile time and size of produced object file). Notice that (on Linux) the DWARF debug information is visible in the generated assembler file (e.g. try to compile your foo.c with gcc -Wall -g -O -S -fverbose-asm foo.c, look into the generated foo.s, and repeat by removing the -g)
I'd like to simply run gcc myfile.c
That is a very bad habit. You should run gcc -Wall -Wextra -g myfile.c -o myprog to get all warnings (you really want them) and debug info in your executable myprog. Read How to debug small programs before continuing coding your program.
I'm not interested in using make with the CFLAGS environment variable
But you really should. Using make or some other build automation tool (e.g. ninja, omake, rake, etc, etc....) is, in practice, the conventional and usual way of using GCC.
Alternatively, on Linux, write a tiny shell script doing the compilation (this is particularly worthwhile if your program is a single source file; for anything bigger, you really should use some build automation tool). At last, if you use emacs as your source code editor, you could add a few lines of comments (like at end of my manydl.c example) specifying Emacs file variables to tune the compilation (done from emacs)
If these conventions surprise you, read about the Unix philosophy then study -for inspiration- the source code of some existing free software (e.g. on github, gitlab, or in your favorite Linux distribution).
At last, GCC itself is a free software project (but a huge one of more than five millions lines of mostly C++ source code). So you can improve it the way you desire (if you follow its GPLv3+ license), after having studying somehow its source code. That would take you several months (or years) of work (because GCC is very complex to understand).
See also this answer to a related question.
You might also (but I recommend not to, because it is very confusing) play tricks with your PATH variable and have some directory there -e.g. $HOME/bin/, ahead of /usr/bin/ which contains /usr/bin/gcc, with your shell script named gcc; but don't do that, you'll be confused. Instead write some "generic" mygcc shell script which would run /usr/bin/gcc and add appropriate flags to it (I believe it is not worth the effort).

how can there be such a big memory difference with -static compilation command?(C)

I am working on a task for the university, there is a webiste that checks my memory usage and it compiles the .c files with:
/usr/bin/gcc -DEVAL -std=c11 -O2 -pipe -static -s -o program programname.c -lm
and it says my program exceeds the memory limits of 4 Mib which is a lot i think. I was told this command makes it use more memory that the standard compilation I use on my pc, like this:
gcc myprog.c -o myprog
I launched the executable created by this one compilation with:
/usr/bin/time -v ./myprog
and under "maximum resident set size" it says 1708 kilobytes, which should be 1,6 Mibs. So how can it be that for the university checker my program goes over 4 Mibs? I have eliminated all the possible mallocs i have, I just left the essential ones but it still says it goes over the limit, what else should I improve? I'm almost thinking the wesite has an error or something...
From GNU GCC Manual, Page 197:
-static On systems that support dynamic linking, this overrides ‘-pie’ and prevents linking with the shared libraries. On other systems, this
option has no effect.
If you don't know about the pie flag quoted here, have a look at this section:
-pie Produce a dynamically linked position independent executable on targets that support it. For predictable results, you must also
specify the same set of options used for compilation (‘-fpie’,
‘-fPIE’, or model suboptions) when you specify this linker option.
To answer your question: yes is it possible this overhead generated by the static flag, because in that case, the compiler can not do the basic optimization by merging stdlib's code with the one you've produced.
As it was suggested in the comments you shall compile your code with the same flag of the website to have an idea of the real overhead of your program (be sure that your gcc version is the same of the website) and also you shall do some common manual optimization such constant folding, function inlining etc. A good reference to these optimizations could be this one

Optimization setting

In c we can enble the optimization setting by enabling the flag -O for enable all the possible optimization and -O0 will disable all enabled optimization.
My question is that this flags are message to whom?means to compiler or kernel?
All command line arguments you supply are interpreted by the compiler (or compiler driver, in the case of some compilers like gcc). They may then be passed on to other programs that the compiler (or compiler driver) executes to complete particular tasks.
Incidentally, -o is not an optimisation setting with quite a few compilers. It usually specifies the name of an output file. For example, gcc -c file.c -o anotherfile.o compilers file.c and produces an object file named anotherfile.o.
The optimisation setting is usually -O (for example -O3). Note the uppercase O. It won't necessarily be passed to every program executed by the compiler/driver. For example, gcc -O3 file.c -o program compiles file.c with optimisation setting -O3 and produces an output executable named program. To do that, the linker is invoked, as well as various compilation phases (preprocessor, compiler proper, etc). -O3 will not normally be passed to the linker - it is a compilation option which linkers normally do not understand.
The O flags are passed to the compiler, not the kernel. The kernel has nothing to do with compilation. These flags determine how aggressively the optimizer will do it's job. A practical example would be clang -O3 WannabeObjectFile.c.
Edit: I made a mistake, the lower case o flag is used to specify the output file. The uppercase O is used to specify optimization level.

How to compile a Linux kernel module using -std=gnu99?

I've recently learned how to program simple character drivers and while playing around with the code I noticed that I get a lot of the following GCC warnings thrown for my C99 code:
warning: ISO C90 forbids mixed declarations and code
I assume this is because the main Linux kernel Makefile is set to compile using a non-C99 standard. I searched around I found this answer here on stackoverflow: How to use make and compile as C99?
So I naturally tried the following in my Makefile:
ccflags-y := -std=gnu99
Unfortunately this didn't silence the GCC warnings. I checked the verbose output of make and verified that GCC is indeed executed with the -std=gnu99 tacked on at the end; so I'm a bit confused.
How do I properly compile a Linux kernel module using the -std=gnu99 option?
EDIT:
I noticed the GCC output shows this option: -Wdeclaration-after-statement. Is this why I am getting the warnings even with the -std=gnu99 option?
It turns out that -std=gnu99 does in fact work; I began seeing errors regarding C99 features after removing the compiler flag. So that meant something else was causing the warnings to print out besides the -std= option.
After parsing through the verbose output via make V=1, I discovered the -Wdeclaration-after-statement option as part of the GCC execution. This was the cause of the ISO C90 mixed declaration warnings I saw.
To disable the ISO C90 warnings, pass this to GCC: -Wno-declaration-after-statement.
For example:
ccflags-y := -std=gnu99 -Wno-declaration-after-statement
You can also specify the flag in your Makefile, if you have one:
FLAGS=-std=gnu99

Resources