Cannot specify -c with multiple files - c

I've got this problem with my makefile:
gcc -c src/uno.c src/uno.h -o src/uno.o
gcc: fatal error: cannot specify -o with -c, -S or -E with multiple files
How can i create a .o file with multiple files?

The header files (src/uno.h in this case) are referenced from within the files, and should not be named again on the command line:
gcc -c src/uno.c -o src/uno.o
You might have to name the directory where to find them, using the -I flag. But if you #include "uno.h" in your sources, then gcc will find the file already, as it searches for it in the same directory which also contains uno.c.
You can compile multiple fils and link them into a single binary, e.g.
gcc -o myApp myAppMain.c myAppUtil.c myAppStuff.c
But that means you'll have to recompile everything if a single source changes, as the intermediate objects are not kept. If you work with object files, there is always one compiler invocation per translation unit.
There is a feature to precompile headers, but in that case, you'd only compile the header, not the uno.c file. And in any case, this is pretty advanced, so you probably won't need it.

Related

Is the GCC link option truly necessary when linking to a static library?

I've been playing around with GCC lately and have been experimenting with the linking options. I'm somewhat confused why the link option -l is necessary when statically linking to an archive file. It seems like you can just toss the .a file as if it were an ordinary object file.
For example, take the following make file:
test1 : main.c libfunc.a
gcc main.c -L. -lfunc -o main.out
test2 : main.c libfunc.a
gcc main.c libfunc.a -o main.out
libfunc.a : func1.c func2.c
gcc func1.c -c
gcc func2.c -c
ar cr libfunc.a func1.o func2.o
Make target test1 uses GCC's linking options to link to the archive file. Target test2 instead just includes the archive file direct. Building and running each output seem to result in the same executable.
There are several ways you can tell gcc what file(s) to use. An argument of the form -lname (or the two arguments -l name) says “Search for a library named name”. Per the GCC documentation, this argument is passed to the linker (typically the ld command). The linker looks for a file with a name like libname.extension, where extension is one of the known library files extensions such as .a or .so, and it looks for files with those names in a list of library directories it has. You can add directories to search with the -L switch.
When the linker finds the library, it uses it just as if you had specified the path, so the end result is the same whether you specify the library with -l or with its path.
By using the path, you can specify libraries that are not in the known library directories or that have unusual names.
Note that the linker does not process libraries the same way as object files. When the linker processes an object file, it incorporates everything in the object file into the output file being constructed. When the linker processes a library file, it incorporates only those modules within the library that provide a symbol definition for a symbol referenced by a prior module and not yet resolved. For example, if you write a program that uses sqrt but does not use sin, then, when the linker processes libm.a after reading your object module, it will take the sqrt module from the library but not the sin module.

How to let gcc compiler know where a certain file is

I'm trying to compile my C code but I need to tell the GCC compiler where two file are.
The two files are located here
/usr/local/ssl/include/
/usr/local/ssl/lib/
I want to add this to my gcc -o file file.c so that my program can work.
In gcc, the -I option is used for adding a directory to the set of directories to search for header files, and the -L option is used for adding a directory to the set of directories to search for libraries. Since you're not explicitly linking in any libraries, you shouldn't need the -L option in this case.
gcc -I/usr/local/ssl/include -o file file.c
If you were linking in libraries, something like the following format should work, assuming that file.c calls a function in libmyLib.a:
gcc -I/usr/local/ssl/include -o file file.c -L/path/to/my/library -lmyLib
See this question for more details regarding library linking order.

cannot specify -o when generating multiple output files [C error]

I have a question about make file using gcc, below is my code in makefile. I got cannot specify -o when generating multiple output files error, but I just cant see where the problem is. Can someone point out my mistakes? Thanks!
BASE_FILES=bwtsearch.c bwtsearch.h bwttext.c bwttext.h chartable.c chartable.h common.h occtable.c occtable.h plset.c plset.h strbuf.c strbuf.h
BASE_ENCODER_FILES=bwtencoder.h bwtencoder.c
BWTSEARCH_FILES=${BASE_FILES} main_bwtsearch.c
BENCODE_FILES=${BASE_ENCODER_FILES} main_bencode.c
PSEARCH_FILES=${BASE_FILES} main_psearch.c
PSEARCH_NL_FILES=${BASE_FILES} main_psearch_nl.c
PENCODE_FILES=${BASE_ENCODER_FILES} main_pencode.c
PENCODE_NL_FILES=${BASE_ENCODER_FILES} main_pencode_nl.c
DEBUG_FILES=${BASE_FILES} main_debug.c
all: bwtsearch psearch psearch_nl pencode pencode_nl bencode
clean:
rm psearch psearch_nl bwtsearch pencode pencode_nl bencode bwt_debug
bwtsearch: ${BWTSEARCH_FILES}
gcc -o bwtsearch ${BWTSEARCH_FILES}
bencode: ${BENCODE_FILES}
gcc -o bencode ${BENCODE_FILES}
psearch: ${PSEARCH_FILES}
gcc -o psearch ${PSEARCH_FILES}
psearch_nl: ${PSEARCH_NL_FILES}
gcc -o psearch_nl ${PSEARCH_NL_FILES}
pencode: ${PENCODE_FILES}
gcc -o pencode ${PENCODE_FILES}
pencode_nl: ${PENCODE_NL_FILES}
gcc -o pencode_nl ${PENCODE_NL_FILES}
debug: ${DEBUG_FILES}
gcc -o bwt_debug ${DEBUG_FILES}
below is the output of the console :)
gcc -o bwtsearch bwtsearch.c bwtsearch.h bwttext.c bwttext.h chartable.c chartable.h common.h occtable.c occtable.h plset.c plset.h strbuf.c strbuf.h main_bwtsearch.c
clang: error: cannot specify -o when generating multiple output files
make: *** [bwtsearch] Error 1
There should be no need to put header files in the list of files to be compiled, since a stylistically correct header file generates no executable code.
It used to be the case that it was mostly harmless to put header files in the gcc command line, because the compiler would add no executable content to the output file as a result of parsing and compiling a header. However, since gcc version 4 or so, and for roughly the same amount of time for clang, header files on the command-line are compiled into precompiled headers for use in later compile steps.
That means that compiling
gcc x.c y.h
will create two products: an executable generated from x.c and a precompiled header generated from y.h.
Gcc (at least up to version 6.3) lets you specify an explicit output filename in this case, although I believe the consequence is that the precompiled header file is written as x and then overwritten by the executable. (It doesn't let you specify an explicit output name in most other cases, such as when you use the -c, -S or -E options to produce an output for every input.) But clang, possibly more sensibly, produces an error when you an explicit output filename with the -o option and you have more than one output, even when that output is a precompiled header (which you possibly didn't intend to produce).
(Confusingly, on Mac OS X, the command gcc normally invokes the clang compiler. I suppose this is to avoid breaking scripts which incorrectly believe that gcc is the generic name for a C compiler.)
The solution is to remove the header files from the list of files to be compiled.

Makefiles to include multiple headers in c

I originally had this in my makefile:
all:
gcc myFunctions1.h myFunctions1.c myFunctions2.h myFunctions2.c main.c -o main
which worked for some reason until I restarted the terminal. Now I get this error:
clang: error: cannot specify -o when generating multiple output files
So what's the proper way to do this?
You don't specify header files when compiling. You don't need to as they are included in the source files, and can't be used by themselves.
You might also want to learn about translation units, and how they relate to source and header files.

When Linking: use -l flag or just treat archives as input

I had some problems linking the static library stxxl into a shared library as outlined in my question Linking a static library into Boost Python (shared library) - Import Error
The command I was using was
g++ -Wall -pthread -march=i686 -I/home/zenna/Downloads/stxxl-1.3.0/include -include stxxl/bits/defines.h -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -I /home/zenna/local/include/ -I /usr/include/python2.6/ -fPIC -c partition.cpp -o obj/Partition_wrap.o
and to link:
g++ -shared -lboost_python -L/home/zenna/local/lib/ -L/home/zenna/Downloads/stxxl-1.3.0/lib/bk/ -Wall -pthread -L/home/zenna/Downloads/stxxl-1.3.0/lib -lstxxl -o lib/fast_parts.so obj/Partition_wrap.o
Using nm I found the missing symbols was in the final output shared object library, but had type "U" for undefined.
I then changed the linking command to not only use -lstxxl but also add the entire archive file as another input to the linker
such that the new command was (difference at end)
++ -shared -lboost_python -L/home/zenna/local/lib/ -L/home/zenna/Downloads/stxxl-1.3.0/lib/bk/ -Wall -pthread -L/home/zenna/Downloads/stxxl-1.3.0/lib -lstxxl -o lib/fast_parts.so obj/Partition_wrap.o obj/libstxxl.a
This fixed the problem as far as I can tell.
My question is then what is the difference between using the -l flag and adding the archive as an input and why did former method result in undefined symbols?
I think the problem in your case was that you specified -lstxxl before the object files. When you put libstxxl.a at the end, the symbols from it are read again and the undefined symbols are resolved. You could try moving it before obj/Partition_wrap.o and check if it will result in undefined symbols.
From man ld
ld -o /lib/crt0.o hello.o -lc
This tells ld to produce a file called output as the result of linking the file "/lib/crt0.o" with "hello.o" and the library "libc.a",
which will come from the standard search directories. (See the discussion of the -l option below.)
Some of the command-line options to ld may be specified at any point in the command line. However, options which refer to files, such
as -l or -T, cause the file to be read at the point at which the option appears in the command line, relative to the object files and
other file options.
Non-option arguments are object files or archives which are to be linked together. They may follow, precede, or be mixed in with
command-line options, except that an object file argument may not be placed between an option and its argument.
-l namespec
The linker will search an archive only once, at the location where it is specified on the command line. If the archive defines a
symbol which was undefined in some object which appeared before the archive on the command line, the linker will include the
appropriate file(s) from the archive. However, an undefined symbol in an object appearing later on the command line will not cause
the linker to search the archive again.
Although it's not mentioned very clear there doesn't seem to be any difference between the 2 ways of giving the linker the files to link.

Resources