make - specify library to link from the command line (without Makefile) - c

For simple program eg, proc.c which has only one source file, it's convenient to compile and link using just make proc, which by default search for proc.c and create proc as output file. There is no need to create a Makefile for that.
If proc.c requires to link with some library such as the math library (defined by <math.h>). Using gcc directly, we can use gcc -c proc.c -o proc -lm. Is there an equivalent make command line option to specify -lm so we can use make command directly without writing a Makefile?
Similar task suggested by Basile Starynkevitch:
Makefile with Multiple Executables

Link library with make without makefile
If your source file is prova.c then you can do the following:
$> export LDFLAGS=-lm; make prova
or:
$> export LDLIBS=-lm; make prova # LDLIBS works on Linux (but LDFLAGS doesn't)
or:
$ make prova LDLIBS=-lm
as Make uses this implicit rule:
%: %.o # Link object file
$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
Make has several implicit rules, you can see all of them with make -p.
For further information see this post.

Related

How to link my C program to a static/dynamic library?

I'm trying to link my C program to both a static and dynamic library to see the difference. How do I do that?
I've made my own Makefile:
# ------ executable rule -----------
app : app.o
-gcc -g app.o -o app
# ------ intermeditate object files rule (.o) -------
app.o : main.c
-gcc -g -c main.c -o app.o
I've only shown you some of my Makefile as I think the rest is unnecessary.
I've tried to write -L. lstatic after -gcc -g app.o -o app but it didn't work.
Read about invoking GCC. Order of arguments to gcc matters a lot!
You could use -static or -Bstatic
You can also explicitly link with static libraries, by giving some /usr/lib/libfoo.a (or some appropriate file path) argument at link time.
You'll better improve your Makefile to use existing builtin rules (try make -p) and conventional variables, e.g. like here. Read the documentation of GNU make.

gcc permanently change c standard

Is there a way of telling gcc to use the c99 standard when compiling c files as a default?
I want to avoid giving it the -std=c99 parameter all the time.
I assume I can do this by creating an alias in the .bashrc file, but seems to be rather inelegant.
You may call c99 instead of gcc (wrapper for gcc, if it's available on your system) or try to modify your gcc spec file. More information here: http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Spec-Files.html
Here's an unexpected answer. Use a Makefile!
Pros:
Simply type make to build
All options are automatically handled in the build process.
While you're at it, go ahead and enable all warnings, as is good to do. See this.
Easy to scale up to multiple source files
Can handle multi-step builds involving different tools
Cons:
Another tool to learn, another thing to get wrong.
Consider this source:
#include <stdio.h>
int main() {
printf("Hello!\n");
int x = 4;
printf("%d\n", x);
return 0;
}
You could make a Makefile like this:
(Disclaimer, I don't actually know how to write them)
CC=gcc
CFLAGS=-Wall -pedantic -std=c99
LDFLAGS=
SOURCES=$(wildcard *.c)
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello
.PHONY: clean
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
clean:
rm -f *.o $(EXECUTABLE)
And it builds for me.
Likewise, if you remove the -std=c99, it shouldn't be valid C89 code, and indeed, typing make brings up the build error.
Custom compilation suggests you have at a working knowledge of compilers, standards, and basic flags / options. For that reason, I suggest you set shell variables in your .bashrc, .tcshrc, etc., and use them on the command line.
Since the choice of dialect can have an effect on linking: CC="gcc -std=c99", lets you invoke separate compilation commands using $CC -c -O2 ... foo.c, and is also picked up as the default for configure scripts, etc. Of course, you can always override a configure script with CC="gcc -std=c90" or CC="clang". The same applies to a preferred CFLAGS value, e.g.,
CFLAGS="-pipe -W -Wall -O2 -march=core2"
Allows for $CC $CFLAGS -c foo.c commands, and both environment variables are used by default with configure scripts, unless you explicitly override them. I think this is more useful than aliases. But perhaps I've just grown used to my own setup:)
Both of the proposed solutions are, in my opinion, almost what you want, but neither quite gets there.
Makefile solution
As seen here, by defining variables in your Makefile but not defining targets, you can use the make command like a customized pass-through to GCC. So if you create a Makefile in your "sandbox" directory (or wherever you're compiling outside of a real build system) and define the C*FLAGS vars, you'll essentially get what you want. An example Makefile:
CFLAGS=-Wall -std=c99
CXXFLAGS=-Wall -std=c++14
Now, make foo will turn foo.c into an executable called foo.
If you want to do this trick in multiple directories, put your makefile in a known location--say, ~/sandbox--and create the following alias (or something like it) in your .bashrc:
alias usestdmake="ln -s ~/sandbox/Makefile"
Then you can quickly compile a single file anywhere on your machine:
usestdmake
make foo
This has the added advantage of giving the output executable an appropriate name (foo in this case). It has the disadvantage of disabling tab-completion for your compile command (make fo<tab> does nothing, at least on my system).
Pure bashrc solution
The CC/CFLAGS variables mentioned in Brett Hale's answer are fairly standard, so it might be a good idea to define them in your bashrc. You can then use these variables inside of aliases.
In your .bashrc:
CFLAGS="-Wall -std=c99"
CC=gcc
# Use single-ticks to ensure that the variables are evaluated when the alias is evaluated.
alias mycc='$CC $CFLAGS'
On the command line:
cc foo.c # Compile with default CFLAGS
CFLAGS="$CFLAGS -O2" cc foo.c # Compile with modified CFLAGS

Where does the default `make` behavior come from?

I'm pretty new to Makefiles; thus, I encountered a question for which I can't come up with a good google search to help answer.
I am running a virtual OS which has a distro of fedora setup by someone else. If I construct my own Makefile in a directory, I can setup my .c files to compile however I like. Yet, if I simply run make test, whereby in my directory exists test.c, I will get the following : clang -ggdb3 -std=c99 -Wall -Werror test.c -lcs50 -lm -o test.
My question following this observation was where does this default, seemingly universal, make behavior come from? In other words, where does this Makefile, if it is one, sit on my file system?
make has several predefined implicit rules. Two of which are:
Compiling C programs
n.o is made automatically from n.c with a recipe of the form ‘$(CC) $(CPPFLAGS) $(CFLAGS) -c’.
Linking a single object file
n is made automatically from n.o by running the linker (usually called ld) via the C compiler. The precise recipe used is ‘$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)’.
Note, make is smart enough to effectively concatenate the above two into one rule when it makes sense:
... could be done by using the ‘.o’ object files as intermediates, but it is faster to do the compiling and linking in one step, so that's how it's done.
You can dump the predefined rules with make -pn. e.g.:
$ make -pn -f /dev/null | grep -A3 '^%: %.c$'
make: *** No targets. Stop.
%: %.c
# commands to execute (built-in):
$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $#
$
This goes for GNU make, which normally is the default make implementation on linux.
There's no default Makefile on your file system containing the default rules.
There are however implicit rules built into make that are in effect whether you supply a makefile or not, and what make does when invoked
is documented here.
These rules knows e.g. how to build an executable from a .c source file. You can learn about those implicit rules here,
e.g make has this default rule when building an executable:
n is made automatically from n.o by running the linker (usually called
ld) via the C compiler. The precise recipe used is ‘$(CC) $(LDFLAGS)
n.o $(LOADLIBES) $(LDLIBS)’
Meaning if you run make test it will try to create an executable test from the file test.o, and you can set the respective CC/LDFLAGS/etc. variables that will be used when linking.
And as another implicit rule it can build a .o file from a .c file, so the above will look for test.o, and try to rebuild that using the rule:
n.o is made automatically from n.c with a recipe of the form ‘$(CC)
$(CPPFLAGS) $(CFLAGS) -c’.
I.e. the implicit rules when running make test will first compile test.c and then link test.o using the compiler you specify with the CC envirnment variable(or the default compiler cc) and the various compiler/linker flags if you set then as environment variables.
.

How to include static library in makefile

I have the following makefile
CXXFILES = pthreads.cpp
CXXFLAGS = -O3 -o prog -rdynamic -D_GNU_SOURCE -L./libmine
LIBS = -lpthread -ldl
all:
$(CXX) $(CXXFILES) $(LIBS) $(CXXFLAGS)
clean:
rm -f prog *.o
I am trying to include the ./libmine library within CXXFLAGS, but it seems like it is not the right way to include a static library, because when I compile the program, I get many undefined references error. So what is actually the right way to include a static library in the makefile?
use
LDFLAGS= -L<Directory where the library resides> -l<library name>
Like :
LDFLAGS = -L. -lmine
for ensuring static compilation you can also add
LDFLAGS = -static
Or you can just get rid of the whole library searching, and link with with it directly.
Say you have main.c, fun.c and a static library libmine.a.
Then you can just do in your final link line of the Makefile
$(CC) $(CFLAGS) main.o fun.o libmine.a
CXXFLAGS = -O3 -o prog -rdynamic -D_GNU_SOURCE -L./libmine
LIBS = libmine.a -lpthread
Make sure that the -L option appears ahead of the -l option; the order of options in linker command lines does matter, especially with static libraries. The -L option specifies a directory to be searched for libraries (static or shared). The -lname option specifies a library which is with libmine.a (static) or libmine.so (shared on most variants of Unix, but Mac OS X uses .dylib and HP-UX used to use .sl). Conventionally, a static library will be in a file libmine.a. This is convention, not mandatory, but if the name is not in the libmine.a format, you cannot use the -lmine notation to find it; you must list it explicitly on the compiler (linker) command line.
The -L./libmine option says "there is a sub-directory called libmine which can be searched to find libraries". I can see three possibilities:
You have such a sub-directory containing libmine.a, in which case you also need to add -lmine to the linker line (after the object files that reference the library).
You have a file libmine that is a static archive, in which case you simply list it as a file ./libmine with no -L in front.
You have a file libmine.a in the current directory that you want to pick up. You can either write ./libmine.a or -L . -lmine and both should find the library.
The -L merely gives the path where to find the .a or .so file. What you're looking for is to add -lmine to the LIBS variable.
Make that -static -lmine to force it to pick the static library (in case both static and dynamic library exist).
Addition: Suppose the path to the file has been conveyed to the linker (or compiler driver) via -L you can also specifically tell it to link libfoo.a by giving -l:libfoo.a. Note that in this case the name includes the conventional lib-prefix. You can also give a full path this way. Sometimes this is the better method to "guide" the linker to the right location.

How do I add my own header file directory to Mac Terminal gcc?

I'm trying to compile a C program (myProgram.c) that includes a custom .h file that is in a specified directory. How can I add the directory to gcc so that I can build myProgram.c anytime using just a command like gcc myProgram (with no flags and what not)
You can do this by altering the C_INCLUDE_PATH environment variable, e.g.
C_INCLUDE_PATH=~/include
export C_INCLUDE_PATH
You can add that to your .bashrc or .bash_profile or whatever to always have the environment variable set properly. Here's a reference on how you can do the same for libraries and C++.
had to use a whole set of flags to get this working on El Capitan:
export DYLD_LIBRARY_PATH=/usr/local/include
export CPPFLAGS="-I/usr/local/include/snappy-c.h"
export CFLAGS="-I/usr/local/include/snappy-c.h"
export CXXFLAGS="-I/usr/local/include/snappy-c.h"
export LDFLAGS="-L/usr/local/lib"
Makefiles would be helpful in this situation, they ease the compilation of multiple file projects.
Assuming you are using these same files and they are in the same directory
main.c
custom.c
custom.h
A sample makefile could look like
all: main.o custom.o
gcc main.o custom.o -o myExecutable
main.o: main.c
gcc -c main.c
custom.o: custom.c custom.h
gcc -c custom.c
clean:
rm -f *.o myExecutable
Or something similar, the general format is
name: dependency
command
So by running make all from the commandline you would be instructing the compiler to compile your source code into object files, and then link those object files together into an executable.
Make should be easily available on any modern system. For more information on basic makefiles and usage refer to this simple tutorial: http://mrbook.org/tutorials/make/

Resources