When compiling multiple files with gcc (i.e: gcc *.c), a large project may take some time to compile and, if no errors are found, the screen remains static for some time. Does gcc have a command line option to display the filename of the c file its currently compiling?
gcc is just a driver program which uses cc1 to actually compile input C files.
That said, you can simply check arguments of gcc child processes to get what gcc is up to. I.e:
> gcc 1.c 2.c & ps -f --forest
[1] 22907
UID PID PPID C STIME TTY TIME CMD
myaut 21963 18153 0 20:21 pts/1 00:00:00 /bin/bash
myaut 22907 21963 0 20:41 pts/1 00:00:00 \_ gcc 1.c 2.c
myaut 22909 22907 0 20:41 pts/1 00:00:00 | \_
/usr/lib64/gcc/x86_64-suse-linux/4.8/cc1 -quiet 1.c -quiet -dumpbase
1.c -mtune=generic -march=x86-64 -auxbase 1 -o
myaut 22908 21963 0 20:41 pts/1 00:00:00 \_ ps -f --forest
In this example I was lucky enough to capture child process which actually compiles 1.c with ps which has started almost simultaneously with gcc
Anyway, using a full fledged building system on top of GCC (make, CMake or SCons) is a much better for compiling project consisting of multiple files.
Related
Referring to the code below, the command rm -f *.o is not removing the realnumsets.o and gestore.o files after the compile process. Do you have any suggestions for how I can remove these *.o files?
~/workspace$ more Makefile
eseguibile : gestore.o realnumsets.o Makefile
gcc -ansi -Wall -O gestore.o realnumsets.o -o myprog
gestore.o : gestore.c realnumsets.h Makefile
gcc -ansi -Wall -O -c gestore.c
realnumsets.o : realnumsets.c realnumsets.h Makefile
gcc -ansi -Wall -O -c realnumsets.c
clean :
rm -f *.o
~/workspace$ make
gcc -ansi -Wall -O -c gestore.c
gcc -ansi -Wall -O -c realnumsets.c
gcc -ansi -Wall -O gestore.o realnumsets.o -o myprog
~/workspace$ ls -la
total 60
drwx------ 2 ubuntu ubuntu 4096 May 20 17:57 ./
drwxrwxr-x 9 ubuntu ubuntu 4096 May 20 14:33 ../
-rw------- 1 ubuntu ubuntu 289 May 20 16:35 Makefile
-rw------- 1 ubuntu ubuntu 6271 May 20 14:45 gestore.c
-rw------- 1 ubuntu ubuntu 4624 May 20 17:57 gestore.o
-rwx------ 1 ubuntu ubuntu 13588 May 20 17:57 myprog*
-rw------- 1 ubuntu ubuntu 5101 May 20 14:44 realnumsets.c
-rw------- 1 ubuntu ubuntu 584 May 20 14:08 realnumsets.h
-rw------- 1 ubuntu ubuntu 3792 May 20 17:57 realnumsets.o
Expected results:
~/workspace$ ls
Makefile gestore.c myprog* realnumsets.c realnumsets.h
Actual result:
~/workspace$ ls
Makefile gestore.c gestore.o myprog* realnumsets.c realnumsets.h realnumsets.o
You have to run make clean to run the clean target. Typing just make runs only the default target (eseguibile) and its dependencies.
The make utility works toward a specific target when it is run. If you specify a target, that will be the one make works toward. By default, the first target (not starting with a period) will be made if you don't specify a target. Thus your simple invocation with just
make
will start work on the target eseguibile. Make pulls in the targets gestore.o and realnumsets.o as those are needed to create eseguibile. The clean target isn't needed for eseguibile, so it doesn't run.
In theory, you could add your clean target to end of the list of targets in eseguibile. However, this would be an unusual way of doing things. More commonly, you just separately call:
make clean
after you run make for the build. If you want to clean before a build is done you could accomplish this with:
make clean eseguibile
The clean will be done first, so you would start building new .o files.
I am trying to generate an executable file test from a c file test.c.
test.c includes the main() function, but I also want to include functions from stuff.c. I was told to declare functions in stuff.h and then run the command gcc -Wall -std=c99 stuff.c stuff.h test.c -o test.
I know what each component of this does, but this is the first time I've tried to use gcc with multiple input files. When I try to run this command, it fails, and I get the error clang: error: cannot specify -o when generating multiple output files.
As far as I'm aware, I'm only trying to generate one output file, so I assume this command is set up incorrectly. How can I fix it?
Here are your errors
you are not suppose to compile .h files in c so try this:
gcc -Wall -std=c99 stuff.c test.c -o test
gcc depends also on environment that you run it on. On my system if I do gcc -Wall -std=c99 stuff.c stuff.h test.c -o test it will work, because compiler is set that way. On some machines it might be different. So if for some strange reason #1 does not work you have to do following:
gcc -Wall -std=c99 -c stuff.c test.c
gcc -Wall -std=c99 stuff.o test.o -o test
./test
But your error clang: error: cannot specify -o when generating multiple output files is due to some code error, perhaps header file problems. So post your code
The difference seems to be due to a difference of behavior between gcc and clang as shown in the following example.
~/test $ ls -ltr
total 4
-rw-rw-r-- 1 arusaha arusaha 0 Apr 3 13:19 b.h
-rw-rw-r-- 1 arusaha arusaha 0 Apr 3 13:19 b.c
-rw-rw-r-- 1 arusaha arusaha 14 Apr 3 13:20 a.c
~/test $ clang -Wall -std=c99 b.c b.h a.c -o ab
clang: error: cannot specify -o when generating multiple output files
~/test $ gcc -Wall -std=c99 b.c b.h a.c -o ab
~/test $ ls -ltr
total 16
-rw-rw-r-- 1 arusaha arusaha 0 Apr 3 13:19 b.h
-rw-rw-r-- 1 arusaha arusaha 0 Apr 3 13:19 b.c
-rw-rw-r-- 1 arusaha arusaha 14 Apr 3 13:20 a.c
-rwxrwxr-x 1 arusaha arusaha 8576 Apr 3 13:21 ab
~/test $
Compiling multiple files is supported in gcc, see http://www.network-theory.co.uk/docs/gccintro/gccintro_11.html
I was curious how gcc command can throw a clang error and that turned out to be a clue :). It is possible that OP's gcc is pointing to clang (and that can be confusing).
From gcc manpage at http://man7.org/linux/man-pages/man1/gcc.1.html
-o file
Place output in file file. This applies 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.
From clang manpage at https://clang.llvm.org/docs/CommandGuide/clang.html
-o <file> Write output to file.
To me, the difference of behavior is not exactly clear by just reading the man page but I could be wrong.
I have the following code(file.c):
int main() {}
I go gcc file.c, and the output file file.exe is 26.5KB
I also tried with -O2, -Ofast, -Os but the size stays the same. I have included no headers, nothing; I even tried putting int main(void) {}.
Shouldn't the output file be roughly 1KB? [I am using Windows 10 - GCC 4.8.1]
Context:
I am trying to understand how PE files work in windows, and so far, I think I have a great grasp of the concept, so I wanted to run some tests because I want to be able to take code from another file, lets say file2.exe, and try to sneak it inside file.exe with OllyDBG. But since this pretty much NULL code yields a freaking 26.5KB, I really dont know what to do...
there are a LOT of items that get added to a file to make it executable.
In the following example, on Linux 16.04
gcc version: gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
I wrote the following source in a
file named untitled2.c
int main(void)
{
}
Then compiled it into untitled2.o
gcc -ggdb -Wall -Wextra -Wconversion -std=gnu11 -pedantic -Wmissing-prototypes -c untitled2.c -o untitled2.o -I.
then linked it into untitleed2
gcc -ggdb -std=gnu11 -o untitled2 untitled2.o
Here are the results.
-rw-r--r-- 1 rkwill root 22 Mar 21 20:41 untitled2.c
-rw-rw-r-- 1 rkwill rkwill 2608 Mar 21 20:41 untitled2.o
-rwxrwxr-x 1 rkwill rkwill 16904 Mar 21 20:41 untitled2
I.E. the original source file is 22 bytes. The compiled file is 2608 bytes (no optimization parameters) the executable file is 16904 bytes
striping the file (removing the debug info) would reduce the file size slightly, but not enough to eliminate the significant difference in size.
I am struggling to set up an MPI cluster, following the Setting Up an MPICH2 Cluster in Ubuntu tutorial. I have something running and my machine file is this:
pythagoras:2 # this will spawn 2 processes on pythagoras
geomcomp # this will spawn 1 process on geomcomp
The tutorial states:
and run it (the parameter next to -n specifies the number of processes to spawn and distribute among nodes):
mpiu#ub0:~$ mpiexec -n 8 -f machinefile ./mpi_hello
With -n 1 and -n 2 it runs fine, but with -n 3, it fails, as you can see below:
gsamaras#pythagoras:/mirror$ mpiexec -n 1 -f machinefile ./mpi_hello
Hello from processor 0 of 1
gsamaras#pythagoras:/mirror$ mpiexec -n 2 -f machinefile ./mpi_hello
Hello from processor 0 of 2
Hello from processor 1 of 2
gsamaras#pythagoras:/mirror$ mpiexec -n 3 -f machinefile ./mpi_hello
bash: /usr/bin/hydra_pmi_proxy: No such file or directory
{hungs up}
Maybe that parameter next to -n specifies the number of machines? I mean the number of processes is stated in the machinefile, isn't it? Also, I have used 2 machines for the MPI cluster (hope this is the case and the output I am getting is not only from the master node (i.e. pythagoras), but also from the slave one (i.e. geomcomp)).
Edit_1
Well I think that the parameter next to -n actually specifies the number of processes, since in the tutorial I linked to, it uses 4 machines and the machine file implies that 8 processes will run. Then why we need that parameter next to -n though? Whatever the reason is, I still can't get why my run fails with -n 3.
Edit_2
Following Edit_1, it -n 3 is logical, since my machinefile implies 3 processes to be spawned.
Edit_3
I think that the problem lies when it tries to spawn a process in the slave node (i.e. geomcomp).
Edit_4
pythagoras runs on Debian 8, while geomcomp runs on Debian 6. The machines are of same architecture. The problem lies in geomcomp, since I tried mpiexec -n 1 ./mpi_hello there and said that no daemon runs.
So, I got, in pythagoras:
gsamaras#pythagoras:~$ mpichversion
MPICH Version: 3.1
MPICH Release date: Thu Feb 20 11:41:13 CST 2014
MPICH Device: ch3:nemesis
MPICH configure: --build=x86_64-linux-gnu --prefix=/usr --includedir=${prefix}/include --mandir=${prefix}/share/man --infodir=${prefix}/share/info --sysconfdir=/etc --localstatedir=/var --libdir=${prefix}/lib/x86_64-linux-gnu --libexecdir=${prefix}/lib/x86_64-linux-gnu --disable-maintainer-mode --disable-dependency-tracking --enable-shared --prefix=/usr --enable-fc --disable-rpath --disable-wrapper-rpath --sysconfdir=/etc/mpich --libdir=/usr/lib/x86_64-linux-gnu --includedir=/usr/include/mpich --docdir=/usr/share/doc/mpich --with-hwloc-prefix=system --enable-checkpointing --with-hydra-ckpointlib=blcr
MPICH CC: gcc -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -O2
MPICH CXX: g++ -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -g -O2 -fstack-protector-strong -Wformat -Werror=format-security
MPICH F77: gfortran -g -O2 -fstack-protector-strong -g -O2 -fstack-protector-strong -O2
MPICH FC: gfortran -g -O2 -fstack-protector-strong -g -O2 -fstack-protector-strong
gsamaras#pythagoras:~$ which mpiexec
/usr/bin/mpiexec
gsamaras#pythagoras:~$ which mpirun
/usr/bin/mpirun
where in geomcomp I got:
gsamaras#geomcomp:~$ mpichversion
-bash: mpichversion: command not found
gsamaras#geomcomp:~$ which mpiexec
/usr/bin/mpiexec
gsamaras#geomcomp:~$ which mpirun
/usr/bin/mpirun
I had installed MPICH2, like the tutorial instructed. What should I do? I am working on /mirror at the master node. It is mounted on the slave node.
1. This relevant question,
mpiexec.hydra - how to run MPI process on machines where locations of hydra_pmi_proxy are different?,
is different from mine, but it might be the case here too.
2. Damn it, the only Hydra I know is a Greek island, what am I missing?
:/
I'd say you've identified a genuine shortcomming of Hydra: there should be some way to tell it the paths on the other nodes are different.
Where is mpich installed on pythagoras? Where is mpich installed on geocomp?
In the simplest configuration, you would have, for example, a common home directory, and you would have installed mpich into ${HOME}/soft/mpich.
Hydra might not be starting a "login shell" on the remote machine. If you add the MPICH installation path to your PATH environment variable, you'll have to do so in a file like .bashrc (or whatever the equivalent for your shell is).
To test this, try 'ssh geocomp mpichversion' and 'ssh pythagoras mpichversion' and plain old 'mpichversion'. That should tell you something about how your environment is set up.
In your case, your environment is really strage! debian 8 and debian 6 and it looks like not even the same versions of MPICH.. I think, thanks to the ABI initiative, that MPICH-3.1 and newer will work with MPICH-3.1, but if you have a version of MPICH that pre-dates the "MPICH2 to MPICH" conversion, there are no such gaurantees.
And setting ABI aside, you've got an MPICH that expects the hydra launcher (the debian 8 version) and an MPICH that expects the MPD launcher. (the debian 6 version)
And even if you do have recent enough packages, the only way things can work is if you have the same architecture on all machines. ABI, as Ken points out, does not mean suppore for heterogeneous environments.
remove the distro packages and build MPICH yourself on both machines.
I have this C file that serves as a wrapper for a header file:
#define SOME_CONTROL_FLAG
#include "thefile.h"
If I compile with this:
gcc -I. -c -o thefile.o thefile.c
I get a 9 kB object file. However, if I do this instead:
gcc -I. -c -D SOME_CONTROL_FLAG -o thefile.o thefile.h
I get a 3 MB object file! That's ~300 times larger. Aren't those two command lines supposed to yield the same thing?
In general, compilation with different symbols compiled different code
Consider the following code. If FOOBAR is defined, then there's more code in the file to compile (after the preprocessor preprocesses it):
#ifdef FOOBAR
int foo(int bar) {
return bar + bar;
}
#endif
int bar(int baz) {
return 1+baz;
}
Compiling with FOOBAR defined changes the size of the output. Without FOOBAR, it's 1232, and with FOOBAR, it's 1328. That's not a huge difference, but it is a difference.
$ gcc -c code.c -o code.o
$ ls -l code.o
-rw-rw-r-- 1 user user 1232 Oct 29 13:19 code.o
$ gcc -DFOOBAR -c code.c -o code.o
$ ls -l code.o
-rw-rw-r-- 1 user 1328 Oct 29 13:19 code.o
If there's lots of conditional code, this could be very significant. For instance, defining symbols might cause lots of platform specific code to be included, and not defining symbols might leave function implementations as stubs.
Compiling different types of code produces different code sizes
Note: this portion is based on Urhixidur's (the OP's) answer. I felt that a bit more elaboration on it was in order.
Another aspect that can lead to different compiled object sizes is what GCC is actually compiling. In your example
gcc -I. -c -D SOME_CONTROL_FLAG -o thefile.o thefile.h
a header file is being compiled, and GCC detects that it's compiling with the c-header language based on the file extension. However, the fact that you're compiling a header file and producing a .o file suggests that you want to compile this as C, in which case you should use GCC's -x option. About it the man page says:
-x language
Specify explicitly the language for the following input files (rather than letting the compiler choose a default based on the file name suffix). This option applies to all
following input files until the next -x option. Possible values for language are:
c c-header cpp-output
c++ c++-header c++-cpp-output
objective-c objective-c-header objective-c-cpp-output
objective-c++ objective-c++-header objective-c++-cpp-output
assembler assembler-with-cpp
ada
f77 f77-cpp-input f95 f95-cpp-input
go
java
-x none
Turn off any specification of a language, so that subsequent files are handled according to their file name suffixes (as they are if -x has not been used at all).
Based on this, and the code I used in the first section, we can observe the drastic size difference that happens when we compile your code as c or as c-header:
$ gcc -c code.h -o code.o # as a header
$ ls -l code.o
-rw-rw-r-- 1 user user 1470864 Oct 29 14:04 code.o
$ gcc -c -x c code.h -o code.o # as c code
$ ls -l code.o
-rw-rw-r-- 1 user user 1232 Oct 29 14:04 code.o
Note that compiling (as a header) doesn't seem to be affected by the symbol definition though:
$ gcc -c code.h -o code.o
$ ls -l code.o
-rw-rw-r-- 1 user user 1470864 Oct 29 14:06 code.o
$ gcc -DFOOBAR -c code.h -o code.o
$ ls -l code.o
-rw-rw-r-- 1 user user 1470864 Oct 29 14:06 code.o
Because gcc decides what to do with the input based on its extension, silly me. The true equivalent compilation line is:
gcc -I. -c -D SOME_CONTROL_FLAG -x c -o thefile.o thefile.h
Where -x c tells gcc to treat the .h as a .c
The resulting object files are identical save for one byte, because the file's name is included (in the debug info, I suppose).