23

I am trying to understand static and shared Libraries.

I want to do the following to create a makefile that does separate compilation and linking such that a static library is created and linked in forming the final static executable.

I have the following code for the Makefile, but I am getting the following error

Makefile:13: *** missing separator. Stop.

But I am also trying to understand how to actually link/create libraries.

If I run the commands after line 12 in the terminal they work, but not in the makefile.

myProgram: main.o addSorted.o freeLinks.o
    gcc -lm -o myProgram main.o addSorted.o freeLinks.o

main.o: main.c
    gcc -O -c -lm main.c main.h

addSorted.o: addSorted.c addSorted.h
    gcc -O -c -lm addSorted.c

freeLinks.o: freeLinks.c freeLinks.h
    gcc -O -c -lm freeLinks.c

ar rc libmylib.a main.o addSorted.o freeLinks.o    //Error Line

ranlib libmylib.a

gcc -o foo -L. -lmylib foo.o

clean:
    rm -f myProgram main.o addSorted.o freeLinks.o

Also, if you can assist in improving the code, I would really appreciate it.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user3337714
  • 663
  • 1
  • 7
  • 25
  • possible duplicate of [Make error: missing separator](http://stackoverflow.com/questions/920413/make-error-missing-separator) – Etan Reisner Jul 15 '15 at 04:48
  • The three `ar`, `ranlib` and `gcc` lines are supposed to be the recipe for what target? – Etan Reisner Jul 15 '15 at 04:48
  • @EtanReisner I am new to C/makefile and libraries. I guess for `myProgram`. That's why I need assistance. Also the line where I am getting error, does not contain `tab` – user3337714 Jul 15 '15 at 04:50
  • 1
    Q: "the line where I am getting error, does not contain tab..." A: That's the problem. You need a "target" (e.g. `mylib.a`, left justified), followed by two lines that begin with a "tab" (`ar rc libmylib.a main.o addSorted.o freeLinks.o`, then `ranlib libmylib.a`). The two lines must be consecutive (no intervening blank lines). Here is a good tutorial: [A Simple Makefile Tutorial](http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/) – paulsm4 Jul 15 '15 at 05:16
  • the gcc linker handles the command line parameters in the order that they are listed. the linker will not include anything from a library unless there is an unresolved name the needs satisfying. therefore, nothing will be linked from the math library. Suggest moving the '-lm' to the end of the linker command line. – user3629249 Jul 16 '15 at 01:28
  • the gcc compiler has absolutely no need for external libraries., so the compile statements should not have '-lm' – user3629249 Jul 16 '15 at 01:29
  • the format of a makefile rule is: 1) destinationFile : sourceFile all other dependencies 2) each command line following the first line must be indented, with a tab. The lines your having a problem with are not formatted correctly – user3629249 Jul 16 '15 at 01:40

2 Answers2

37

Try this:

all: myProgram

myProgram: main.o libmylib.a #libmylib.a is the dependency for the executable
        gcc -lm -o myProgram main.o -L. -lmylib

main.o: main.c
        gcc -O -c main.c main.h

addSorted.o: addSorted.c addSorted.h
        gcc -O -c addSorted.c

freeLinks.o: freeLinks.c freeLinks.h
        gcc -O -c freeLinks.c

libmylib.a: addSorted.o freeLinks.o #let's link library files into a static library
        ar rcs libmylib.a addSorted.o freeLinks.o

libs: libmylib.a

clean:
        rm -f myProgram *.o *.a *.gch #This way is cleaner than your clean

This set of rules first compiles all files, then it makes library (libmylib.a) target and uses it's artifact to link the executable. I also added separate redundant target form making libs only. Needed files:

user@host> ls
addSorted.c  addSorted.h  freeLinks.c  freeLinks.h  main.c  main.h Makefile
Sergey
  • 7,985
  • 4
  • 48
  • 80
  • 1
    So libraries are only made from all the files, except `main`?. And once I have created the library, it is linked to `myProgram`? This helps. – user3337714 Jul 15 '15 at 05:05
  • Would `Shared Libraries` also would work similarly? Or I have to invoke the same from `main` – user3337714 Jul 15 '15 at 05:06
  • @user3337714 Yes, that is. You also may construct a separate library for each non-main file or link one bunch of files into one library and another group of files into another. Just make libraries in the way you want, joining files by their purpose to sustain clarity of your project structure. – Sergey Jul 15 '15 at 05:07
  • 1
    @Dmitri Surely, forgot to remove that. Corrected the answer. – Sergey Jul 15 '15 at 05:19
  • @user3337714 Shared libraries should be build simultaneously from the point of view of Makefile. Just compile `*.o` files with `-fpic` and links with `-shared`. Here is a good explanation (not about makefiles, shared libs only): http://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html – Sergey Jul 15 '15 at 05:23
  • `main.o: main.c gcc -O -fpic -lm main.c main.h`. Would this be correct way of doing for Shared? – user3337714 Jul 15 '15 at 05:26
  • @user3337714 No. I meant `gcc -c -fpic freeLinks.c` and `gcc -c -fpic addSorted.c`. Then `gcc -shared -o libmylib.so freeLinks.o addSorted.o` to craft a shared library. Then you can link an executable with it using `-lmylib`, and don't forget to add it's directory to `$LD_LIBRARY_PATH` of the shell where you're going to run the executable. – Sergey Jul 15 '15 at 05:34
  • @user3337714 You also do NOT need linkning flags (i.e. `-lm`) on compilation steps. I corrected the proposed makefile in the answer. – Sergey Jul 15 '15 at 05:36
  • @user3337714 Obviously, you can not have different files with the same name (`*.o` files with `-fpic` and without it), so to make shared and static libs simultaneously you should use subdirectories or different file naming. – Sergey Jul 15 '15 at 05:39
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/83280/discussion-between-user3337714-and-sergey). – user3337714 Jul 15 '15 at 05:45
  • 'all' 'libs' 'clean' need to be listed as dependences in a 'PHONY : all libs clean' rule. Always place the 'all' target as the first target in the file, so when no specific target is specified, that is the target that is performed first by the make utility – user3629249 Jul 16 '15 at 01:44
  • when calling 'ar', it would be better to include the 's' modifier to create the table rather than calling the ranlib utility. – user3629249 Jul 16 '15 at 01:53
12

A makefile is not a shell script. It's a configuration file for an expert system. Specifically an expert system that knows, if you tell it, how to efficiently create files and their dependencies with a minimum of re-making files that don't need to be remade.

If you look at the first rule you have:

myProgram: main.o addSorted.o freeLinks.o
    gcc -lm -o myProgram main.o addSorted.o freeLinks.o

that tells the system how to make a file called "myProgram" if it decides that it needs to do that. The parts after the colon are files that myProgram needs. If they aren't there, or make decides they are out of date, make will try to find some recipe that can be used to create or update them. Once all that is done, make then executes the "gcc ..." line and assumes that will create or update myProgram.

The ar and ranlib lines you have don't match the needed syntax for a makefile rule. From the look of them, they appear to be a recipe for making libmylib.a. If you put them into the syntax make needs to say that, you get:

libmylib.a: main.o addSorted.o freeLinks.o
    ar rcu libmylib.a main.o addSorted.o freeLinks.o
    ranlib libmylib.a

myProgram should depend on the library itself, rather than the contents of the library, and it is best to put the library options at the end:

myProgram: libmylib.a
    gcc -o myProgram libmylib.a -lm

if you like, you can use an option to tell gcc to look for libraries in the current directory:

gcc -L. -o myProgram main.o -lmylib -lm

There are also makefile variables that can help you not have to repeat so much, so I would write the first rule as:

myProgram: libmylib.a
    gcc -L. -o $@ -lmylib -lm

however, it is unlikely that main.o should actually be part of the library, so:

myProgram: main.o libmylib.a
    gcc -L. -o $@ $< -lmylib -lm

and the library rule as:

libmylib.a: addSorted.o freeLinks.o
    ar rcu $@ $+
    ranlib $@

the $+ here means "all of the dependency file names".

Finally, if you want gcc to make an actual static executable, and not just use the library you made, you need to pass the '-static' option to gcc.

user464502
  • 2,203
  • 11
  • 14
  • Can you also explain me for shared library? – user3337714 Jul 15 '15 at 05:34
  • Shared libraries are highly dependent on what system you are on. On x86 or x86_64 linux, you need to compile the object files with -fpic, among other things. Other systems may vary. – user464502 Jul 15 '15 at 05:45