Do I need to use -o when I run g++? - c++

I have a very small c++ program that consists of two files: main.cpp and something.cpp. I'd like to compile my program using g++ in the OS X Terminal. Here's what I've tried:
> g++ main.cpp something.cpp
> ./a.out
Is this correct? I've come across examples that use the -o flag. I'm not sure if that's necessary.

Does it work? That's a pretty good indication of correctness! The -o flag allows you to specify a file name so the executable is not named a.out

-o option is not required. If not specified, the default behavior is to put an executable file in "a.out":
-o file
Place output in file file. This applies regardless to whatever sort of output is being produced, whether it be an executable
file, an object file, an assembler
file or preprocessed C code.
If -o is not specified, the default is to put an executable file in a.out, the object file for source.suffix in source.o, its
assembler file in source.s, a
precompiled header file in source.suffix.gch, and all preprocessed C source on standard output.
So yes, this is correct.

Related

Compiling C files along with C++ file in g++

I'm having a custom C header file that I have created. There are several files in my directory as follows.
lib1/
-lib1.h
-lib1.c
lib2/
-lib2.h
-lib2.c
-lib_main.c
-lib_main.h
-main.c
-main.cpp
-Makefile
Now, for testing the header file with a test file called main.c, I will be giving the following command in the terminal,
gcc lib_main.c lib1/lib1.c lib2/lib2.c main.c -o ./main
Now, how could I test the same header files with main.cpp instead of main.c, how do I change it?
You should (and most probably must) compile separately the c and c++ sources into a object file, and then link together.
As an example
gcc -c -o lib1.o lib1/lib1.c
gcc -c -o lib2.o lib2/lib1.c
gcc -c -o lib_main.o lib_main.c
g++ -c -o main.o main.cpp
g++ -o main lib1.o lib2.o lib_main.o main.o
The first four commands create a series of object files, with extension .o. The last command link together the object files into an executable.
Obviously you need to add the relevant compiler options for each source.
Two important points to notice:
Order of files in the linking is important. See discussion here and here.
To mix c and c++ code with each other, for example if a c++ code calls a c function, you need to follow specific guidelines.

Why I cannot run an object file?

When I want to run a source code why this works :
gcc test.c -o test.o
then
./test.o
but this does not work :
gcc -c test.c
then
./test.o
and get this message
bash: ./test.o: Permission denied
First of all, you are not creating an object file but an executable file. Object files are an intermediate file used as input file for the linker to create the executable file. That you name it with an .o suffix doesn't matter.
Secondly, due to tradition if you do not specify an output filename with the -o option the compiler frontend program and linker will create an executable named a.out.
But that's not all, because with the second example you are actually creating a real object file, and those are not executable. Like mentioned above, those needs to be passed to a separate linking step to create the executable file.
You either need to create an executable file:
gcc test.c
./a.out
Or you should link the object file into an executable file:
gcc -c test.c # Create object file
gcc test.o -o test # Use object file to create executable file
./test # Run the executable file
You get that message because the compiler doesn't set the executable bit on object files, because - well, because they are not executable. If you set the executable bit manually and try to run it, you'll get something like "unknown executable format".
Now, it's not just a format problem - the point is that an object file is just half of the work to get something that can actually be executed. In particular, it's missing the linking step, where the linker finds unresolved references and patches them with the addresses from other object files - including the ones you don't specify explicitly, like the standard library - and generates a proper executable file, that the kernel knows how to load and execute.
In the first case you just name the resulting file test.o by using -o, it has been compiled assembled and linked.
In the second case you merely compiled and assemble, it can't run without being linked. See gcc --h or Overall options for gcc for -c:
-c
Compile or assemble the source files, but do not link. The linking stage simply is not done. The ultimate output is in the form of an object file for each source file.
By default, the object file name for a source file is made by replacing the suffix ‘.c’, ‘.i’, ‘.s’, etc., with ‘.o’.
Unrecognized input files, not requiring compilation or assembly, are ignored.
(Emphasis mine)
You need to link it and then execute it:
gcc -o a.out test.o
You cannot run an object file. This is not executable and need to be linked to become executable.
Try
gcc -o test test.c and run using ./test.out
This is a fundamental question in gcc. Note that never using parameter -c when you want to get an executable file in single command such as
gcc -c xx.c yy.c -o new
.But you can get an executable file with -c in following commands
gcc -c xx.c yy.c
gcc xx.o yy.o -o new
It's equivalent to
gcc xx.c yy.c -o new

how to run c++ file if header, class, and main are not in the same folder?

The code::block IDE generates the following files:
./main.cpp
./include/class.h
./src/class.cpp It include class.h with #include "class.h"
How can I run this set of files, with the three files in three different folders?
First, this program can be run by clicking IDE "build and run" button.
This program need to take some arguments, like ./a.out arg[1] arg[2]. So I cannot input arguments by clicking "build and run" button, and thus I have to use g++ to compile an output first.
But g++ is not smart enough as the IDE in finding the three files(I try g++ -I./include main.cpp, it seems that it has no problem with class.h file, but cannot find class.cpp file)
So how can I compile the three files in three different locations?
BTW, how could the class.h file find the class.cpp file in IDE/g++(scan all the files in the directory to see which contains the definition of the class functions?)?
It's a bad idea to #include source files. But this will do it:
g++ -I./include -Isrc main.cpp
Normally one would expect that the IDE has some function to just build the application, especially when there's a function to build-and-run. In addition there are those that have the possibility to supply command line arguments for the program so build-and-run will run with supplied arguments.
You have to supply the source files and the search path for includes, normally one would write:
g++ -o exec-file-name -I./include main.cpp src/class.cpp
but that may depend a bit on how you include the header file. Another note is that you normally don't compile the header file separately - it's included when you compile the .cpp files that includes it.
If on the other hand you actually want to do what you write (compile the .h file that includes the .cpp file - which is higly unorthodox) you would do:
g++ -c -I./src include/class.h
g++ -c main.cpp
g++ -o exec-file-name main.o class.o
where you need to replace the .o extension if your platform uses another extension. Note that in this case you should probably not include class.h from main.cpp since that could lead to duplicate symbols.

how to compile c/cpp code in such a way that it gives preprocessed assembled and object file after compilation in linux?

if source file is source.cpp then compiler output should have source.i source.s
source.o in my directory not only .o file.
where
preprocessed = source.i
assembly = source.s
object = source.o
i know first two files are being created but later on they got deleted only .o file is
shown so that linker can link object file but i want to see those two files also.
for linux any flag or something?.
According to the gcc man pages
-save-temps
-save-temps=cwd
Store the usual "temporary" intermediate files permanently; place them in the current directory and name them based on the source file. Thus, compiling foo.c with -c -save-temps would produce files foo.i and foo.s, as well as foo.o. This creates a
preprocessed foo.i output file even though the compiler now normally uses an integrated preprocessor.
so you should compile your code like this
g++ -save-temps source.cpp
You can create individual file for each stage of compiler.
Preprocessor :
g++ -E file.cpp -o file.i
Translator :
g++ -S file.i -o file.s
Assembler :
g++ -c file.s -o file.o
linker :
g++ file.o -o file

Makefile syntax using -o and -c in c++

It's been a while since I've done a makefile. I have inherited some code that is built with the following line in a makefile
$(CC) $(FLAGS) -c -o $*.o $*.cpp
Why would you use -c and -o in the same line. Doesn't the -c make it so that you build the objects without linking?
EDIT Here is the complete makefile, now I get an error saying cpp.cpp No such file or directory
.SUFFIXES: .o .cpp
CC=g++
MAIN_OBJS = \
main.o \
f1.o \
f2.o \
all:
$(CC) -c -o $*.o $*.cpp
$(CC) $(MAIN_OBJS) -o final
Shouldn't the $*.cpp find all the .cpp files in my current path (and they are there)
As you say, -c means make object files without linking.
-o means you want to override the default output file name and specify your own. So -o $.o means the output file name would be the same as the input file name but with .o on the end.
You might do this if you were planning to have this Makefile rule usable with a number of different compilers, some of which might have a different default output file name for object files.
The man page for gcc describes -o like this:
-o file
Place output in file file. This applies regardless to whatever sort of output is being produced, whether it be an executable file, an
object file, an assembler file or preprocessed C code. If -o is not
specified, the default is to put an executable file in a.out, the
object file for source.suffix in source.o, its assembler file in
source.s, a precompiled header file in source.suffix.gch, and all
preprocessed C source on standard output.
Yes, what you said makes sense.
As we know,-c will compile the source files and produce the assembly files.
After that, we normally use -o to link all those assembly files and produce a executable file.
What follows -o is the name of the output executable file.
And if the -c and -o are used in the same line, it means the output assembly file produced by -c is named what follows -o.