What does the g++ -D flag do? - linux

I am looking at a CFLAGS of -
CFLAGS=-g -w -D LINUX -O3 -fpermissive
in a Makefile. What does the -D flag do? I see on the man page that
-D name
Predefine name as a macro, with definition 1.
but I don't know how to interpret that. My interpretation is...its making LINUX a macro and only doing -03 and -fpermissive when in a linux environment. Is that right? If not, then what? Thanks for any help

It is equivalent to adding the statement #define LINUX 1 in the source code of the file that is being compiled. It does not have any effect on other compilation flags. The reason for this is it's an easy way to enable #ifdef statements in the code. So you can have code that says:
#ifdef LINUX
foo;
#endif
It will only be enabled if that macro is enabled which you can control with the -D flag. So it is an easy way to enable/disable conditional compilation statements at compile time without editing the source file.

It doesn't have anything to do with -O3. Basically, it means the same as
#define LINUX 1
at the beginning of the compiled file.

Related

conditional compilation in makefile so that command-line arguments are ignored

Using gcc compiler on linux, I have a C program that used command-line argument (one argument) like
./myprog 0
I want to write a makefile that uses conditional compilation so that if I compile like
make SPECIAL=1
then command-line argument is used.
if I compile without SPECIAL like
make
then command-line argument is ignored even if we enter it.
How to make it possible.
I am using following compilation command
gcc -o myprog myprog.c prog2.c prog3.c
The makefile can be trivial but the real work has to happen in the C code. Something like this, as a minimal example:
#include <stdio.h>
int main(int argc, char **argv, char **envp) {
int i;
#ifndef SPECIAL
argc=1;
argv[1] = NULL;
#endif
for(i=1; i<argc; ++i) {
printf(">>%s<<\n", argv[i]);
}
}
Now, you don't even really need a Makefile for this simple program.
bash$ make CFLAGS=-DSPECIAL=1 -f /dev/null myprog
cc -DSPECIAL=1 myprog.c -o myprog
Having said that, making your build nondeterministic by introducing variations which depend on ephemeral build-time whims is a recipe for insanity. Have two separate targets which create two separate binaries, one with the regular behavior, and the other with the foot-gun semantics.
DEPS := myprog.c prog2.c prog3.c # or whatever your dependencies are
myprog: $(DEPS)
myprog-footgun: CLAGS+=-DSPECIAL=1
myprog-footgun: $(DEPS) # same dependencies, different output file
$(CC) $(CFLAGS) -o $# $^
See Target-specific Variable Values in the GNU Make documentation for details of this syntax.
(Notice that Stack Overflow renders tabs in the Markdown source as spaces, so you will not be able to copy/paste this verbatim.)
I would perhaps in fact reverse the meaning of SPECIAL so that it enables the foot-gun version, rather than the other way around (the original version of this answer had this design, just because I had read your question that way originally).

Does gcc have any options to add version info in ELF binary file?

I mean whether gcc can insert some source code version infor into ELF binary as section or something similar. I do not want to change my source file, but add some info with gcc option in Makefile.
If you don't mind changing your source file just once, add something like this:
const volatile static char version[] = VERSION;
and compile with:
gcc -c -DVERSION='"1.2.3"'
The volatile keeps gcc from removing the string at higher optimization levels.
As written, this won't compile if you forget the -D option, which may be either good or bad depending on your requirements.
You can emit your version info into a text file, then turn that text file into an object file which you then statically link into your executable.
The first step is simple but you have to write some code: a script or something to write your version info in any format you like as a plain text file. Then write a makefile rule to produce say version.o from version.txt, using objcopy. Now you'll have an object file with two useful symbols defined in it: the beginning and end of the textual version info. Add that generated object to your executable, and you'll be able to access the version two ways: by running strings on the binary, or by writing code in the application to print the version string (you'll need to declare the start and end symbols as variables in some header file).
Even if you don't have access to your source anymore, you can link the object with this option:
gcc -Wl,--defsym,VERSION_1_2_3=0 prog.o -o prog
You can check it with hexdump -C prog | less and look for VERSION
Add this to your makefile and be sure to always know when a program was compiled:
BUILD = $(shell date +"%Y%m%d_%H%M%S")
LDLIBS = -Wl,--defsym,BUILD_$(BUILD)=0
With the GNU linker ld You can use
--version-script=version-scriptfile
Read more about the command-line options at:
Using LD, the GNU linker - Options
Read more about creating version scripts at:
Using LD, the GNU linker - Version Script
Let me warn you though, that it is not for the weak-hearted!

How to make a 'makefile' in c

I can't understand how I can produce a makefile for C code
I have the following .c file which normally I execute in the following manner:
gcc server.c -o server.out -lpthread
Once compiled, I run the .out file like this:
./server.out 4000
EDITED
I only need the make files to compile the program rather than running it too..
If naming your executable file server will do for you, then just
LDLIBS=-lpthread
all: server
in a file called Makefile will do. The you can just type
make
to build it.
Ortherwise your Makefile should contain:
server.out: server.c
gcc server.c -o server.out -lpthread
Except that it is a tabulation, not spaces before the text “gcc”.
To start , you can create a project in eclipse and it would create a makefile for you. And then you can start going into the details about what all is added and this can trim out things you understand are not necessary.
https://github.com/ChrisLundquist/OpenCL-Compiler/blob/master/Makefile
Is an example of a simple make file.

cmake include_directories order AFTER/BEFORE

I have a file in source tree which name is "time.h", exactly as system "time.h". This cannot be changed. I have encountered a problem with cmake that when I use include_library option it is translated to -I flag which means that my custom "time.h" takes prcedence over system time.h even for <> includes. This is a definiti no-no.
I tried using include_directories (AFTER dir1 dir2) but it still generate -I option instead of expected -idirafter.
I don't think this is a problem with CMake; I believe gcc will always find your "time.h" before the system one, regardless of whether you use quotes or brackets in the #include and regardless of the various options in include_directories. See the entries for -I and -isystem in the gcc documentation
The AFTER option of CMake's include_directories relates only to the order of the directories as listed in the gcc command, it doesn't relate to gcc's -idirafter flag.
It's not a great plan to have your own files with identical names to system files, but if your hands are tied, you could avoid this issue without renaming time.h by qualifying the path for your own includes more fully, so rather than e.g.
CMakeLists.txt: include_directories(${PROJECT_SOURCE_DIR}/src)
header file: #include <time.h> // we want but don't get system one
#include "time.h" // we want and get own custom one
something more like
CMakeLists.txt: include_directories(${PROJECT_SOURCE_DIR})
header file: #include <time.h> // we want and get system one
#include "src/time.h" // we want and get own custom one
An alternative option would be to stick with your current #include setup (using angle brackets for the system time.h and quotes for your own) and not use include_directories at all in the CMakeLists.txt. Instead I think you could replace it with something like:
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -iquote ${PROJECT_SOURCE_DIR}/src")
Using -iquote is probably a better option than -idirafter since the directory specified by -idirafter is (in this case incorrectly) treated as a system directory, and as such has warnings suppressed, etc.
If you do go for this choice, it's probably worth commenting the CMakeLists.txt to explain why there is no include_directories to avoid future refactoring reverting back to use the more normal include_directories command.
All in all, your best option if at all possible would be to rename your "time.h" file though.

Simple makefile for C/C++ targets used with arm-linux-gcc

I would like to cross-compile a simple program for ARM architecture using the arm-linux-gcc suite of compilers [arm-linux-gcc (Buildroot 2011.08) 4.3.6]. I've attempted to use a simple makefile for compiling C code, and another simple makefile for compiling C++ code. For example, my makefile for C code is reproduced below, but it does not create an ELF binary for running on my embedded system. The host system is x64 GNU Linux.
Here is the listing of my very simple makefile for a C program:
CC=arm-linux-gcc
CFLAGS=-Wall
main: test.o
clean:
rm -f test test.o
The makefile reproduced above only creates an object file with extension .o, and does not create an ELF binary.
I've Googled for a good solution, but I can't seem to find one webpage showing example cross-compile ARM makefiles for both C and C++ programs. Perhaps an answer to this post could show such examples.
Have a look at the GNU make manual (info make), Section 10.2. It has a catalogue of the implicit rules, i.e. the rules where you don't need to explicitly state the commands. Like #GregHewgill thought, the "Linking a single object file" implicit rule builds N from N.o, but the name must match. Therefore, you can either name your executable like your object file, in which case
test:
or (more standard because it defines the all target)
all : test
completely suffice. You can also write out the rule explicitly, like Greg Hewgill also described. In this case, the standard rule is:
$(CC) $(LDFLAGS) N.o $(LOADLIBES) $(LDLIBS)
Include the LDFLAGS and LDLIBS in your Makefile, it makes life easier for users.
(sic: I think LOADLIBES is really LOADLIBS, and the author missed the -o).
Overall, I'd recommend autoconf and automake instead of hand-rolling makefiles. Gives you a bunch of Makefile features for very little work.
I tried your Makefile and changed the following:
test: test.o
It worked after this changed and created a binary called test. It seems that there is some implicit rule that knows how to link whatever if one of its dependencies is whatever.o.
Another way is to list the rule explicitly:
main: test.o
$(CC) -o $# $$
This uses the special macros $# (which means target) and $$ (which means dependencies).

Resources