Using gcc with multiple files - c

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.

Related

The rm -f command in my Makefile is not working

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.

Clang compiler ignoring the .a library file

This compiling works OK:
$ clang -target x86_64-unknown-freebsd10.0 --sysroot=/opt/cross-freebsd-10/ -l:libconfuse.so main.cpp
This one does not (undefined references on internal functions):
$ clang -target x86_64-unknown-freebsd10.0 --sysroot=/opt/cross-freebsd-10/ -l:libconfuse.a main.cpp
/tmp/main-115bc4.o: En la función `main':
main.cpp:(.text+0x691): referencia a `cfg_init' sin definir
main.cpp:(.text+0x6ab): referencia a `cfg_parse' sin definir
main.cpp:(.text+0x6da): referencia a `cfg_getstr' sin definir
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Same error with these command lines:
$ clang -target x86_64-unknown-freebsd10.0 --sysroot=/opt/cross-freebsd-10/ -L/opt/cross-freebsd-10/usr/lib/ -l:libconfuse.a main.cpp
$ clang -target x86_64-unknown-freebsd10.0 --sysroot=/opt/cross-freebsd-10/ -L/opt/cross-freebsd-10/usr/lib/ -l:libconfuse.a -static main.cpp
The files for the LibConfuse C programming library seem to be at the correct path:
$ ls -la /opt/cross-freebsd-10/usr/lib/libconfuse*
-rwxrwxrwx 1 luis luis 78318 sep 29 2018 /opt/cross-freebsd-10/usr/lib/libconfuse.a
lrwxrwxrwx 1 luis luis 19 sep 29 2018 /opt/cross-freebsd-10/usr/lib/libconfuse.so -> libconfuse.so.2.0.0
lrwxrwxrwx 1 luis luis 19 sep 29 2018 /opt/cross-freebsd-10/usr/lib/libconfuse.so.2 -> libconfuse.so.2.0.0
-rwxr-xr-x 1 luis luis 56616 sep 29 2018 /opt/cross-freebsd-10/usr/lib/libconfuse.so.2.0.0
So, I would say the compiler can not see the .a file. Am I right? How could I solve it?
I need to solve this because I am trying to compile with static linking for the LibConfuse library, as long as I don't need to install that package on destination computers. So, as I have read, the .a library file must be used.
Further Data:
Note that I am cross-compiling to FreeBSD. I don't know if that matters.
When running (on a remote FreeBSD computer) the executable generated by the .so mode above, the program yields «Shared object "libconfuse.so.2" not found, required by [MyExecutableName]». This is why I am trying to perform static link.
Tests performed on Ubuntu Linux v16.04.
New data upon requestion:
Same first line that works OK, but with -### parameter to show extra info:
1$ clang -### -target x86_64-unknown-freebsd10.0 --sysroot=/opt/cross-freebsd-10/ -l:libconfuse.so main.cpp
clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
Target: x86_64-unknown-freebsd10.0
Thread model: posix
InstalledDir: /usr/bin
"/usr/lib/llvm-3.8/bin/clang" "-cc1" "-triple" "x86_64-unknown-freebsd10.0" "-emit-obj" "-mrelax-all" "-disable-free" "-disable-llvm-verifier" "-main-file-name" "main.cpp" "-mrelocation-model" "static" "-mthread-model" "posix" "-mdisable-fp-elim" "-masm-verbose" "-mconstructor-aliases" "-munwind-tables" "-target-cpu" "x86-64" "-dwarf-column-info" "-debugger-tuning=gdb" "-resource-dir" "/usr/lib/llvm-3.8/bin/../lib/clang/3.8.0" "-isysroot" "/opt/cross-freebsd-10/" "-internal-isystem" "/opt/cross-freebsd-10//usr/include/c++/v1" "-fdeprecated-macro" "-fdebug-compilation-dir" "/media/Almacen01/Temporal/CPlusPlus/PruebaCSV01" "-ferror-limit" "19" "-fmessage-length" "83" "-fobjc-runtime=gnustep" "-fcxx-exceptions" "-fexceptions" "-fdiagnostics-show-option" "-fcolor-diagnostics" "-o" "/tmp/main-065e9b.o" "-x" "c++" "main.cpp"
"/usr/bin/ld" "--sysroot=/opt/cross-freebsd-10/" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld-elf.so.1" "--hash-style=both" "--enable-new-dtags" "-o" "a.out" "/opt/cross-freebsd-10//usr/lib/crt1.o" "/opt/cross-freebsd-10//usr/lib/crti.o" "/opt/cross-freebsd-10//usr/lib/crtbegin.o" "-L/opt/cross-freebsd-10//usr/lib" "-l:libconfuse.so" "/tmp/main-065e9b.o" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" "/opt/cross-freebsd-10//usr/lib/crtend.o" "/opt/cross-freebsd-10//usr/lib/crtn.o"
More data requested by Ahmed:
$ clang -### -target x86_64-unknown-freebsd10.0 --sysroot=/opt/cross-freebsd-10/ /opt/cross-freebsd-10/usr/lib/libconfuse.a main.o -o LogManager
clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
Target: x86_64-unknown-freebsd10.0
Thread model: posix
InstalledDir: /usr/bin
"/usr/bin/ld" "--sysroot=/opt/cross-freebsd-10/" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld-elf.so.1" "--hash-style=both" "--enable-new-dtags" "-o" "LogManager" "/opt/cross-freebsd-10//usr/lib/crt1.o" "/opt/cross-freebsd-10//usr/lib/crti.o" "/opt/cross-freebsd-10//usr/lib/crtbegin.o" "-L/opt/cross-freebsd-10//usr/lib" "/opt/cross-freebsd-10/usr/lib/libconfuse.a" "main.o" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" "/opt/cross-freebsd-10//usr/lib/crtend.o" "/opt/cross-freebsd-10//usr/lib/crtn.o"
Change the commandline to:
clang -target x86_64-unknown-freebsd10.0 --sysroot=/opt/cross-freebsd-10/ -c main.cpp -o main.o
clang -target x86_64-unknown-freebsd10.0 --sysroot=/opt/cross-freebsd-10/ /opt/cross-freebsd-10/usr/lib/libconfuse.a main.o -o main
This will allow you to link the libconfuse.a right into the binary with static symbols. Let me know if you run into trouble
If you want to link to the library file libconfuse.a then you can do that by specifying only the filename (without the -l: part), or you can write -lconfuse (the lib and .a parts are then assumed. Writing -l:libconfuse.a will not work, I think.

GCC output file's size seems too big

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.

Why does compiling a header file with a D option result in a much bigger file than using a C wrapper for the header?

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).

How to compile a APR test script

Its a long time since I've used C but now I'm trying to compile a short script that gets server-stats from the Apache-Portable-Runtime (APR).
Header files located at /usr/include/apr-1/apr*.h and libs are located at /usr/lib64/libapr-1.*
Source files can be found on the official APR site http://apr.apache.org/docs/apr/1.3/files.html.
/* test.c */
#include <stdio.h>
#include <stdlib.h>
#include <apr_general.h>
#include <apr_time.h>
int main(int argc, const char *argv[])
{
apr_time_t t;
t = apr_time_now();
printf("The current time: %" APR_TIME_T_FMT "[us]\n", t);
return 0;
}
When I try and compile I get the following error (which I believe is a linking issue):
~> gcc -Wall $(apr-1-config --cflags --cppflags --includes --link-ld) test.c -o test.bin
/tmp/cc4DYD2W.o: In function `main':
test.c:(.text+0x10): undefined reference to `apr_time_now'
collect2: ld returned 1 exit status
My environment is gentoo:
~> uname -a
Linux alister 2.6.32.21-grsec-gt-r2 #1 SMP Tue Sep 7 23:54:49 PDT 2010\
x86_64 Intel(R) Xeon(R) CPU L5640 # 2.27GHz GenuineIntel GNU/Linux`
~> gcc -v
gcc version 4.3.4 (Gentoo 4.3.4 p1.1, pie-10.1.5)
~> emerge --search "%#^dev-lib.*apr"
* dev-libs/apr
Latest version installed: 1.3.9
* dev-libs/apr-util
Latest version installed: 1.3.9
Does anyone with more experience with C on Linux have any suggestions for me to get this working?
As always thanks in advance.
gcc -Wall -I/usr/include/apr-1 -L/usr/lib64 -lapr-1 test.c -o test.bin
-l specifies which shared library to link to, while -L specifies where to look for shared libraries.
APR provides a tool to make this easier, apr-1-config. Something like this should work:
gcc -Wall $(apr-1-config --cflags --cppflags --includes --link-ld) test.c -o test.bin
I finally got around to looking into this.
gcc mentions -l twice in different contexts:
Linker Options
object-file-name -llibrary ...
Directory Options
... -Idir -Ldir ...
so I moved the -llib after the object name (to get the 2nd context) and it compiled!
APR_CFG=$(apr-1-config --cflags --cppflags --includes --link-ld)
gcc -Wall test.c -o test.bin $APR_CFG
./test.bin
The current time: 1332999950442660[us]
I'm not fully sure I understand the linking order and why it didn't work before (if someone could shed some light on that it would be fantastic) but for now I have enough to continue.

Resources