How to compile with a .o file that was compiled with other .o files (C99) - c

consider c.c a code that includes a.h and b.h, and main.c a code that includes c.h
i tried to compile it like so
gcc --std=c99 -o a.o -c a.c
gcc --std=c99 -o b.o -c b.c
gcc --std=c99 -o c.o -c c.c a.o b.o
but when I run the last one, gcc yells at me
gcc --std=c99 -o c.o -c c.c a.o b.o
gcc: warning: a.o: linker input file unused because linking not done
gcc: warning: b.o: linker input file unused because linking not done
and then when I try to compile the main.c file using gcc -o main main.c c.o it says that there are a lot of undefined references, which is predictable once the c file was not correctly compiled.
I've seen some similar questions here at stackoverflow, but I couldn't get it to work neither way.
I'm on Arch Linux running gcc v4.9.2-3

First, it is -std=c99 with a single dash.
I guess you are on Linux.
Then, you always should pass -Wall -Wextra -g (especially since you are a newbie) to gcc : -Wall ask for nearly all warnings, -Wextra for even more warnings, -g ask for debug information.
At last, you want to produce an executable myprog (don't name executables as c.o, this is supposed to be an object file) with
gcc -std=c99 -Wall -Wextra -g -o myprog c.c a.o b.o
You need to remove any -c since you want the linking to happen.
If you really mean -but that is very unusual today, better make shared libraries!- to agglomerate several object files into one all.o (to be linked later with other objects) you might try the -r linker option
gcc -std=c99 -Wall -Wextra -g -r c.c a.o b.o -o all.o
But last time I tried it was in the previous century, so details could be wrong.
There are very few reasons to agglomerate objects using the -r linker option. Unless you really know what you are doing, you are very probably wrong (in trying -r).
Perhaps you want to make a software library. These days it is much better to make a shared library. A shared library (technically an ELF shared object) should contain position independent code. So, assuming you have three translation units t1.c, t2.c, t3.c you first compile them as PIC :
gcc -std=c99 -Wall -Wextra -g -fPIC t1.c -c -o t1.pic.o
gcc -std=c99 -Wall -Wextra -g -fPIC t2.c -c -o t2.pic.o
gcc -std=c99 -Wall -Wextra -g -fPIC t3.c -c -o t3.pic.o
then you link all these PIC object files into a shared library libmyt.so
gcc -std=c99 -Wall -Wextra -g -shared \
t1.pic.o t2.pic.o t3.pic.o \
-o libmyt.so
Later you'll use this shared library e.g. as
gcc -std=c99 -Wall -Wextra -g main.o -o myprog -Wl,-rpath . libmyt.so
or as
gcc -std=c99 -Wall -Wextra -g main.o -o myprog -Wl,-rpath . -L. -lmyt
You might consider static linking with ar to make a static library libmyt.a but I don't recommend that.
Of course, you'll debug your program using gdb ./myprog and you could try running it with ./myprog. To use valgrind, try valgrind ./myprog
If you have several translation units, better learn how to use GNU make. Read the Program Library HowTo and this and these hints.

Related

How to create command in bash to compile multiple C program with multiple flags

So my file structure is basically this -
I have a .zshrc file since I'm on OS X
I have a .my_custom_commands.sh file which contains the shortcuts I want
In my .zshrc I source the commands file
Currently, I'm looking for a solution to compile multiple files with flags using the "gcc" command
For example, if I want to compile a.c and b.c
gcc -Wall -Werror -ansi -pedantic -o output.c a.c b.c
However, I don't want to type this out every time, so I was thinking there would be a way to create a custom command say 'gccf' (gcc flags). The thing is that I don't know zsh programming language so I'm just wondering if there is a way to pass multiple args into the function I created in the commands file.
I have something like this right now
function gccf() {
gcc -Wall -Werror -ansi -pedantic -o output.c $1 $2
}
I understand that the args you pass into the command line are represented by $1, $2..., but is there anyway to check how many args have been passed? Because if $2 isn't passed then this won't work I think.
Set CFLAGS as you want and just use the default rules for make. You don't even need a makefile:
$ rm -f Makefile
$ ls a.c
a.c
$ make a
cc a.c -o a
$ rm -f a.o a
$ export CFLAGS=-pedantic
$ make a
cc -pedantic a.c -o a
If you have multiple source files, you'll need a (trivial) makefile:
$ rm -f a *.o output Makefile
$ unset CFLAGS
$ make a
cc a.c -o a
$ export CFLAGS='-Wall -Werror -ansi -pedantic'
$ rm a; make a
cc -Wall -Werror -ansi -pedantic a.c -o a
$ printf 'output: a.o b.o\n\t$(CC) $(LDFLAGS) $^ -o $# $(LDLIBS)\n' > Makefile
$ make output
cc -Wall -Werror -ansi -pedantic -c -o a.o a.c
cc -Wall -Werror -ansi -pedantic -c -o b.o b.c
cc a.o b.o -o output
$ rm -rf *.o output
$ export CC=gcc LDLIBS=-lm
$ make output
gcc -Wall -Werror -ansi -pedantic -c -o a.o a.c
gcc -Wall -Werror -ansi -pedantic -c -o b.o b.c
gcc a.o b.o -o output -lm
In other words, don't try to reinvent the wheel. Your use case has been encountered by many people, and there are long standing conventions and tools in place to enable the work flow.
Note that you may want to include LOADLIBES along with LDLIBS, but the former name should (probably?) no longer be used.
In Bourne-heritage shells (e.g. sh, zsh, bash, ksh), to specify all arguments passed to a program or function, use "$#" (including the double quotes!), which expands to any number of args passed, including none.
But if you follow the Unix philosophy of using the one tool that does just one thing, you want to look at make as suggested in comments and other answers.
PS: you also want -o output, not -o output.c, since your program is not a C source file, but an executable.

Makefile: how to specify library name at the end of command using patsubst

I am new to Makefile, C and Linux. I am using gcc & ubuntu. I encountered a problem while trying to compile the code with a link to a library.
Here is my problem. I have:
a_tests.c & b_tests.c files in "tests" folder
lib.a file in "build" folder
Here is the codes in Makefile related to the problem:
CFLAGS=-g -O2 -Wall -Wextra -Isrc -DNDEBUG $(OPTFLAGS)
TARGET=build/lib.a
TEST_SRC=$(wildcard tests/*_tests.c)
TESTS=$(patsubst %.c,%,$(TEST_SRC))
tests: CFLAGS += $(TARGET)
tests: $(TESTS)
When the tests files are compiled, "undefined reference to 'XXXfunction'"errors will be prompted. Because what executed behind is
gcc -g -O2 -Wall -Wextra -Isrc -DNDEBUG build/lib.a tests/a_tests.c -o test/a_tests
gcc -g -O2 -Wall -Wextra -Isrc -DNDEBUG build/lib.a tests/b_tests.c -o test/b_tests
But "build/lib.a" should be placed after the output file name to solve it (If I manually type in the below commands, the codes would be successfully compiled), ie:
gcc -g -O2 -Wall -Wextra -Isrc -DNDEBUG tests/a_tests.c -o test/a_tests build/lib.a
gcc -g -O2 -Wall -Wextra -Isrc -DNDEBUG tests/b_tests.c -o test/b_tests build/lib.a
But I don't know how to change in the Makefile, I tried -l -L options, they didn't work. It would warn that "cannot find the .a file". Any help would be appreciated. Thank you so much in advance!
Define the library as a dependency, because it is one. It will be appended at the end of the other dependencies, here: the source.
CFLAGS=-g -O2 -Wall -Wextra -Isrc -DNDEBUG $(OPTFLAGS)
TARGET=build/lib.a
TEST_SRC=$(wildcard tests/*_tests.c)
TESTS=$(TEST_SRC:%.c=%)
tests: $(TESTS)
$(TESTS): $(TARGET)
The library does not need to be after the output file, but after the depending input file.
The makefile is further simplified:
Replaced the patsubst with a simpler expression.
Moved the target tests up, so it is found as the first and therefore default target.
Good luck!

gcc g option on compile or build?

I know -g option is used for debugging by putting debug symbols on execute file.
I wonder where to put -g option either compile or build may be both.
If I have 2 .c files to build ab.out, where is the correct place to put -g option and why?
gcc (1) -c -o a.o a.c
gcc (2) -c -o b.o b.c
gcc (3) -o ab.out a.o b.o

scons linking problems depending on CC

I'm compiling a library that comes with a scons script. According to the documentation scons does everything automatically and stuff should just work.
However, the build succeeds or fails, depending on what I set CC to (even though I always invoke the same compiler):
/usr/bin/ld: context.os: relocation R_X86_64_32S against `a local symbol' can not be used when making a shared object; recompile with -fPIC
context.os was built with the following arguments.
env cc -o context.os -c ... -Wall -O2 -DNDEBUG -I. -I/usr/local/include ... context.c
So scons forgets the -fPIC argument. However if I set CC=cc it succeeds:
cc -o context.os -c ... -Wall -O2 -fPIC -DNDEBUG ...
The same if I set CC="ccache cc":
ccache cc -o context.os -c ... -Wall -O2 -fPIC -DNDEBUG ...
And of course, with -fPIC set, linking succeeds in both cases.
So, I wonder how does scons position independent code trigger work and why does it screw up in the CC="env cc" case?

How can I compile with shared library if I use Autotools

I have two C programs named drive.c and mylib.c.
drive.c is main module mylib.c is sub modulle that I want work as shared library .
I can compile them with following step and run.
gcc –fPIC –g –c –Wall mylib.c
gcc -shared -Wl,-soname,libmylib.so.1 -o /c/opt/lib/libmylib.so.1.0.1 mylib.o -lc
gcc -g -Wall -Wextra -pedantic -I./ -L/c/opt/lib -o drive.exe drive.c –l:libmylib.so.1
Now I want know is How can I compile them by autotools as same effect of above way ?
What and how do I have to edit configure.ac and Makefile.am for compile them?

Resources