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.
Related
So here's something I don't understand : Every single time you include something in c, you have to do #include "dir/subdir/file.h". Since the .c file is in the exact same place, why do I also have to do gcc main.c dir/subdir/file.c -o main ?
It doesn't seem to make sense, every single other language I've used (arguably not that many, but still, several) was able to make sense of imports on its own. Am I missing something ? Is there a way to tell gcc to "just find them yourself" ?
gcc main.c dir/subdir/file.c -o main is not the typical command form for most projects. It is used only for simple projects, such as student assignments.
Much commercial code consists of dozens, hundreds, or thousands of source files. It is not compiled all at once. Build tools such as make or Xcode are used to manage the project, and they will compile each source file separately to its own object file.
Object files may be grouped by subproject, may be collected into libraries, and may be further processed before being linked into an executable file or other product.
When the project is built, there is no need to compile all of the source files because they have been compiled previously. It is only necessary to compile source files for object files that may change due to source edits that have been made since the last time the project was built. Thus, the build tool may compile only a few of the hundreds of source files in the project, using an individual compile command for each. Having a single command that compiled all of the source files would be wasteful.
In some projects, there may be several variants of the source file for one header file. One header file may declare common interfaces, but several different source files may provide different implementations for those interfaces, to target different types of destination systems or to provide different characteristics, such as prioritizing speed over memory or vice-versa. In such a situation, knowing the header file does not identify which source file is to be compiled.
If you want your project to compile all source files that are implied by header files, you can write your own program that scans the main.c file to find included header files (possibly recursively) and generate commands to compile the associated source files.
C is a product of early 1970s, and this is one of the areas where that really shows. An #include statement simply loads the contents of the specified file before it gets compiled - the path of the included file isn't being analyzed or preserved anywhere. Similarly, gcc isn't preserving the path of any of the files on the command line - it just loads the source from the specified file, translates it, and spits out an object file at the end.
C doesn't specify any kind of package management semantics. Each file on the gcc command line is compiled separately, and gcc doesn't know anything about the environment other than what's specified on the command line.
Yes, you could build a compiler that does all that analysis and tries to be smart about paths and such, but it's a crapload of work, there's no specification for it, no two compilers would do it the same way, and it kind of violates the spirit of C (the programmer is assumed to always know what they're doing, even when they don't).
Having said all that...
With gcc, you can use the -I option to specify additional include paths:
gcc -o main -I /dir/subdir main.c /dir/subdir/file.c
so in your source you don't need to use an explicit path in the #include:
#include "file.h" // no need for /dir/subdir path
Similarly, you can use -L to specify additional directories to search for libraries (linked with -l):
gcc -o main -I /dir/subdir main.c /dir/subdir/file.c -L /anotherdir/subdir/libs -lmylib.a
Like Eric says, if you're having to manage source across multiple directories, you should be using make or a similar tool - doing all this manually on the command line rapidly gets unscalable.
EDIT
I think an example may be helpful. I have a simple C program made up of three files - main.c, foo.c, and bar.c:
/**
* main.c
*/
#include <stdio.h>
/**
* Notice no explicit path on either include
*/
#include "foo.h"
#include "bar.h"
int main( void )
{
printf( "calling foo: " );
foo();
printf( "calling bar: " );
bar();
return 0;
}
/**
* foo.c
*/
#include <stdio.h>
#include "foo.h"
void foo( void )
{
puts( "In function foo" );
}
/**
* bar.c
*/
#include <stdio.h>
#include "bar.h"
void bar( void )
{
puts( "In function bar" );
}
Because I'm insane, I've split the source code up over multiple directories like so:
make_example/
Makefile
build/
include/
package/
src/
main.c
subdir.mk
Makefile
subdir1/
Makefile
foo.c
foo.h
subdir2/
Makefile
bar.c
bar.h
I want to do the following:
Build foo.c and bar.c and write their object files to make_example/build;
Copy foo.h and bar.h to make_example/include;
Build main.c, which includes the headers for foo and bar from make_example/includes, and write its object file to make_example/build;
Build an executable named demo from main.o, foo.o, and bar.o and save it to the make_example/package directory.
IOW, after my build is done, I want the following:
make_example/
Makefile
build/
bar.o
foo.o
main.o
include/
bar.h
foo.h
package/
demo
src/
main.c
subdir.mk
Makefile
subdir1/
Makefile
foo.c
foo.h
subdir2/
Makefile
bar.c
bar.h
I have a Makefile at the top level directory and each of my source directories. Here's the top-level Makefile (make_example/Makefile):
CC=gcc
CFLAGS=-std=c11 -pedantic -Wall -Werror
TARGET=package/demo
SUBDIRS=src
all: $(TARGET)
#
# Makes sure we build all source subdirectories before
# attempting to build the target
#
$(TARGET) : $(SUBDIRS)
$(CC) -o $# $(CFLAGS) $(wildcard build/*.o)
#
# Executes the Makefile in each source subdirectory
# with the current goal (all or clean)
#
$(SUBDIRS):
$(MAKE) -C $# $(MAKECMDGOALS)
clean: $(SUBDIRS)
rm -rf $(TARGET)
.PHONY: $(SUBDIRS) all clean
Here's the Makefile for the top-level source directory (make_example/src/Makefile):
CC=gcc
CFLAGS=-std=c11 -pedantic -Wall -Werror -g
TOPDIR=..
BLDDIR=$(TOPDIR)/build
INCDIR=$(TOPDIR)/include
#
# Look for foo.h and bar.h in the ../include
# subdirectory.
#
CFLAGS += -I $(INCDIR)
SUBDIRS=$(wildcard subdir*/.)
SRCS=main.c
OBJS=$(SRCS:%.c=$(BLDDIR)/%.o)
TARGET=main
#
# Required for the $(OBJS) target - expands
# all of the $$ expressions
#
.SECONDEXPANSION:
all: $(TARGET)
#
# Makes sure the subdirectories are
# built before attempting to build our
# target
#
$(TARGET) : $(SUBDIRS) $(OBJS)
#
# Executes the Makefile in each of the source
# subdirectories with the current goal (all or clean)
#
$(SUBDIRS):
$(MAKE) -C $# $(MAKECMDGOALS)
$(OBJS): $$(patsubst $(BLDDIR)/%.o, %.c, $$#)
$(CC) -c -o $# $(CFLAGS) $<
clean: $(SUBDIRS)
rm -rf $(OBJS)
.PHONY: all $(TARGET) $(SUBDIRS)
Since the Makefile for each of subdir1 and subdir2 is identical except for the file names, I created the subdir.mk file for the stuff that's common between the two:
CC=gcc
CFLAGS=-std=c11 -pedantic -Wall -Werror -g
TOPDIR=../..
BLDDIR=$(TOPDIR)/build
INCDIR=$(TOPDIR)/include
OBJS=$(SRCS:%.c=$(BLDDIR)/%.o)
HDRS=$(SRCS:%.c=$(INCDIR)/%.h)
all: $(OBJS) $(HDRS)
clean:
rm -rf $(OBJS) $(HDRS)
#
# Required for the $(OBJS) and $(HDRS) targets - expands
# all of the $$ expressions
#
.SECONDEXPANSION:
$(OBJS) : $$(patsubst $(BLDDIR)/%.o,%.c,$$#)
$(CC) -c -o $# $(CFLAGS) $<
#
# Copy the header files to the ../../include
# directory
#
$(HDRS) : $$(patsubst $(INCDIR)/%.h,%.h,$$#)
cp $< $#
.PHONY: all clean
Then each of the make_example/src/subdir* Makefiles is
SRCS=foo.c
include ../subdir.mk
and
SRCS=bar.c
include ../subdir.mk
So, at the top level (make_example), we simply type
make
which gives us
$ make
make -C src
make[1]: Entering directory '/home/john/Development/make_example/src'
make -C subdir2/.
make[2]: Entering directory '/home/john/Development/make_example/src/subdir2'
gcc -c -o ../../build/bar.o -std=c11 -pedantic -Wall -Werror -g bar.c
cp bar.h ../../include/bar.h
make[2]: Leaving directory '/home/john/Development/make_example/src/subdir2'
make -C subdir1/.
make[2]: Entering directory '/home/john/Development/make_example/src/subdir1'
gcc -c -o ../../build/foo.o -std=c11 -pedantic -Wall -Werror -g foo.c
cp foo.h ../../include/foo.h
make[2]: Leaving directory '/home/john/Development/make_example/src/subdir1'
gcc -c -o ../build/main.o -std=c11 -pedantic -Wall -Werror -g -I ../include main.c
make[1]: Leaving directory '/home/john/Development/make_example/src'
gcc -o package/demo -std=c11 -pedantic -Wall -Werror build/foo.o build/main.o build/bar.o
And now we have all our build artifacts where we want them:
$ ls -l */*
-rw-rw-r-- 1 john john 5744 Oct 23 16:13 build/bar.o
-rw-rw-r-- 1 john john 5744 Oct 23 16:13 build/foo.o
-rw-rw-r-- 1 john john 5984 Oct 23 16:13 build/main.o
-rw-rw-r-- 1 john john 56 Oct 23 16:13 include/bar.h
-rw-rw-r-- 1 john john 56 Oct 23 16:13 include/foo.h
-rwxrwxr-x 1 john john 21752 Oct 23 16:13 package/demo
-rw-rw-r-- 1 john john 165 Oct 23 12:54 src/main.c
-rw-rw-r-- 1 john john 555 Oct 23 15:50 src/Makefile
-rw-rw-r-- 1 john john 481 Oct 23 15:46 src/subdir.mk
src/subdir1:
total 12
-rw-rw-r-- 1 john john 89 Oct 23 12:29 foo.c
-rw-rw-r-- 1 john john 56 Oct 23 12:07 foo.h
-rw-rw-r-- 1 john john 32 Oct 23 15:16 Makefile
src/subdir2:
total 12
-rw-rw-r-- 1 john john 89 Oct 23 15:03 bar.c
-rw-rw-r-- 1 john john 56 Oct 23 14:49 bar.h
-rw-rw-r-- 1 john john 32 Oct 23 15:17 Makefile
And our program runs as
$ ./package/demo
calling foo: In function foo
calling bar: In function bar
To clean up, all I have to do is type make clean:
$ make clean
make -C src clean
make[1]: Entering directory '/home/john/Development/make_example/src'
make -C subdir2/. clean
make[2]: Entering directory '/home/john/Development/make_example/src/subdir2'
rm -rf ../../build/bar.o ../../include/bar.h
make[2]: Leaving directory '/home/john/Development/make_example/src/subdir2'
make -C subdir1/. clean
make[2]: Entering directory '/home/john/Development/make_example/src/subdir1'
rm -rf ../../build/foo.o ../../include/foo.h
make[2]: Leaving directory '/home/john/Development/make_example/src/subdir1'
rm -rf ../build/main.o
make[1]: Leaving directory '/home/john/Development/make_example/src'
rm -rf package/demo
and all our build artifacts are gone:
$ ls -l */*
-rw-rw-r-- 1 john john 165 Oct 23 12:54 src/main.c
-rw-rw-r-- 1 john john 555 Oct 23 15:50 src/Makefile
-rw-rw-r-- 1 john john 481 Oct 23 15:46 src/subdir.mk
src/subdir1:
total 12
-rw-rw-r-- 1 john john 89 Oct 23 12:29 foo.c
-rw-rw-r-- 1 john john 56 Oct 23 12:07 foo.h
-rw-rw-r-- 1 john john 32 Oct 23 15:16 Makefile
src/subdir2:
total 12
-rw-rw-r-- 1 john john 89 Oct 23 15:03 bar.c
-rw-rw-r-- 1 john john 56 Oct 23 14:49 bar.h
-rw-rw-r-- 1 john john 32 Oct 23 15:17 Makefile
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I'm trying to learn how Makefile works, so I decided to try it with a very simple code. This is what I wrote:
/* justify.c */
#include <stdio.h>
#include "line.h"
#include "word.h"
int main(void) {
printf("I'm in the main.\n");
read_word();
write_line();
}
/* line.h */
void write_line(void);
/* line.c */
#include <stdio.h>
#include "line.h"
void write_line(void) {
printf("write_line\n");
}
/* word.h */
void read_word(void);
/* word.c */
#include <stdio.h>
#include "word.h"
void read_word(void) {
printf("read_word\n");
}
now ... if I do everything from the terminal it works:
> gcc -c justify.c
> gcc -c line.c
> gcc -c word.c
> gcc -o justify justify.c line.c word.c
but if I try to do everything with a Makefile it gives me an error:
# Makefile
justify: justify.o line.o word.o
gcc -o justify.o line.o word.o
justify.o: justify.c line.h word.h
gcc -c justify.c
line.o: line.c line.h
gcc -c line.c
word.o: word.c word.h
gcc -c word.c
> make justify
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
No pun intended, but you are making make a bit harder than it needs to be. In your case with the source and headers all in the same directory, it is quite simple to use wildcards to allow make to handle the rest. For example with three simple variable declartions in your Makefile, you can tell make what your sources are, your includes and how to generate an object file for each of the source files that isn't the application name.
For starters, specify your application name:
# application name
APPNAME := justify
If needed, set your compiler variables, e.g.
# compiler
CC := gcc
CCLD := $(CC)
Now make knows your application name is held in APPNAME which you access like any other variable in a Makefile as $(APPNAME).
Now just use wildcard to collect all sources and includes in variables as well, and let make associate the object file output:
# source/include/object variables
SOURCES := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS := $(SOURCES:%.c=%.o)
Set your compiler/linker/library flags:
# compiler and linker flags
CFLAGS := -Wall -Wextra -pedantic -finline-functions -std=c11 -Wshadow -Ofast
LDFLAGS :=
# libraries
LIBS :=
Now create your default target for make (note: there must be a tab-character '\t' in front of each rule):
all: $(OBJECTS)
$(CCLD) -o $(APPNAME) $(OBJECTS) $(CFLAGS) $(LDFLAGS) $(LIBS)
A rule to compile all sources to objects:
$(OBJECTS): %.o : %.c
$(CC) $(CFLAGS) -c -o $# $<
(see: What do the makefile symbols $# and $< mean? for explanation of the automatic variables used)
And finally a target for clean:
clean:
rm -rf $(APPNAME) *.o
A complete example for your files would be:
# application name
APPNAME := justify
# compiler
CC := gcc
CCLD := $(CC)
# compiler and linker flags
CFLAGS := -Wall -Wextra -pedantic -finline-functions -std=c11 -Wshadow -Ofast
LDFLAGS :=
# libraries
LIBS :=
# source/include/object variables
SOURCES := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS := $(SOURCES:%.c=%.o)
# target for all
all: $(OBJECTS)
$(CCLD) -o $(APPNAME) $(OBJECTS) $(CFLAGS) $(LDFLAGS) $(LIBS)
# strip only if -DDEBUG not set
ifneq ($(debug),-DDEBUG)
strip -s $(APPNAME)
endif
$(OBJECTS): %.o : %.c
$(CC) $(CFLAGS) -c -o $# $<
clean:
rm -rf $(APPNAME) *.o
(note: a rule to strip the executable was also added to the all: target)
Example Build
With your Makefile source and include files in a common directory, e.g.
$ ll
total 24
-rw-r--r-- 1 david david 668 Nov 6 12:38 Makefile
-rw-r--r-- 1 david david 161 Nov 6 12:31 justify.c
-rw-r--r-- 1 david david 106 Nov 6 12:32 line.c
-rw-r--r-- 1 david david 37 Nov 6 12:31 line.h
-rw-r--r-- 1 david david 104 Nov 6 12:32 word.c
-rw-r--r-- 1 david david 36 Nov 6 12:32 word.h
Just type make to have your application built:
$ make
gcc -Wall -Wextra -pedantic -finline-functions -std=c11 -Wshadow -Ofast -c -o word.o word.c
gcc -Wall -Wextra -pedantic -finline-functions -std=c11 -Wshadow -Ofast -c -o line.o line.c
gcc -Wall -Wextra -pedantic -finline-functions -std=c11 -Wshadow -Ofast -c -o justify.o justify.c
gcc -o justify word.o line.o justify.o -Wall -Wextra -pedantic -finline-functions -std=c11 -Wshadow -Ofast
strip -s justify
No errors, you can check all files were created as expected:
$ ll
total 44
-rw-r--r-- 1 david david 668 Nov 6 12:38 Makefile
-rwxr-xr-x 1 david david 6312 Nov 6 13:01 justify
-rw-r--r-- 1 david david 161 Nov 6 12:31 justify.c
-rw-r--r-- 1 david david 1760 Nov 6 13:01 justify.o
-rw-r--r-- 1 david david 106 Nov 6 12:32 line.c
-rw-r--r-- 1 david david 37 Nov 6 12:31 line.h
-rw-r--r-- 1 david david 1496 Nov 6 13:01 line.o
-rw-r--r-- 1 david david 104 Nov 6 12:32 word.c
-rw-r--r-- 1 david david 36 Nov 6 12:32 word.h
-rw-r--r-- 1 david david 1496 Nov 6 13:01 word.o
Test your executable:
$ ./justifiy
I'm in the main.
read_word
write_line
Lastly, clean your build directory with make clean, e.g.
$ make clean
And confirm all build files are removed.
That's about the easiest way to go about writing minimal make files. You can list each object individually and the required includes to support them, but why? the automatic variables will take care of that for you. There is much, much more you can do with Makefiles, but for getting started, this will make your life easier.
You can heavily simplify the Makefile you have. Make provides lots of helpful variables.
$# - target name
$< - first prequisite
$^ - all prequsites
justify: justify.o line.o word.o
gcc -o $# $^ # this one will turn into
# gcc -o justify justify.o line.o word.o
justify.o: justify.c
gcc -c $< # this one will turn into
# gcc -c justify.c
line.o: line.c
gcc -c $<
word.o: word.c
gcc -c $<
it's also a good idea to add clean
clean:
-rm *.o justify
-rm - minus sign at the beginning will not produce error if command fails;
useful in case you expect that something might be missing
There is bug in your make file. The commands for the make target justify: are missing the output file name. It should be like this.
gcc -o justify justify.o line.o word.o
with your current command line the gcc will try to output justify.o by linking line.o and word.o and the it does not find _main which is not defined in line.o and word.o
The make command already knows how to convert a .c file to .o so you do not need to tell this to make again in the make file. Keeping this in mind, the following make file is enough for your test case.
# Makefile
justify: justify.o line.o word.o
gcc -o justify justify.o line.o word.o
You can further simplify this by using make's built-in automatic variables. $# and $^. The $# variable contains the name of the target of rule. and $^ contains the name of all the prerequisites of the rule. So using these two variables your make file will be.
justify: justify.o line.o word.o
gcc -o $# $^
I'm new with makefiles and I'm trying to write one that compiles files from different folders. You can see my files distribution in the output of tree command that I have added to the post:
I want my header files in the includes folder, some library files in srclib, my main source files in src and the generated .o in lib. To start, I have tried recursive makefiles but I'm unable to compile tcp.c because the compiler can't find tcp.h, I'm stuck.
Output tree command
.
|-- includes
| `-- tcp.h
|-- lib
|-- makefile
|-- src
| |-- cliente.c
| `-- servidor_preforked.c
`-- srclib
`-- tcp.c
you need to indicate where to find the header to your compiler, for gcc this is done with the option -I
For instance if you produce a.out in lib your makefile can be :
lib/a.out:
gcc -o lib/a.out -I includes srclib/tcp.c src/cliente.c src/servidor_preforked.c
To also produces objects in lib :
all::lib/a.out
GCC = gcc -ansi -pedantic -Wextra
lib/tcp.o : srclib/tcp.c includes/tcp.h
$(GCC) -c -o lib/tcp.o -I includes srclib/tcp.c
lib/cliente.o : src/cliente.c includes/tcp.h
$(GCC) -c -o lib/cliente.o -I includes src/cliente.c
lib/servidor_preforked.o : src/servidor_preforked.c includes/tcp.h
$(GCC) -c -o lib/servidor_preforked.o -I includes src/servidor_preforked.c
lib/a.out : lib/tcp.o lib/cliente.o lib/servidor_preforked.o
$(GCC) -o lib/a.out -I includes lib/tcp.o lib/cliente.o lib/servidor_preforked.o
Example :
pi#raspberrypi:/tmp/d $ rm lib/*
pi#raspberrypi:/tmp/d $ make
gcc -ansi -pedantic -Wextra -c -o lib/tcp.o -I includes srclib/tcp.c
gcc -ansi -pedantic -Wextra -c -o lib/cliente.o -I includes src/cliente.c
gcc -ansi -pedantic -Wextra -c -o lib/servidor_preforked.o -I includes src/servidor_preforked.c
gcc -ansi -pedantic -Wextra -o lib/a.out -I includes lib/tcp.o lib/cliente.o lib/servidor_preforked.o
pi#raspberrypi:/tmp/d $ ls -l lib
total 24
-rwxr-xr-x 1 pi pi 8208 févr. 23 18:15 a.out
-rw-r--r-- 1 pi pi 956 févr. 23 18:15 cliente.o
-rw-r--r-- 1 pi pi 856 févr. 23 18:15 servidor_preforked.o
-rw-r--r-- 1 pi pi 840 févr. 23 18:15 tcp.o
Yes, you can explicitly add folder names to targets and commands as #bruno, but that's a bit like hardcoding, plus adds a bit of duplication. A way to improve that is to use VPATH or vpath function that fits for that case:
vpath %.h includes
vpath %.c src:srclib
vpath %.o lib
This tells which directory to search for a particular type of files. For .c files it will search both "src" and "srclib".
Now the rules might look simpler like so:
cliente.o : cliente.c tcp.h
$(GCC) -c -o lib/$# -I includes $<
Note the usage of $# and $< automatic variables. In this case $< will expand to the first prerequisite path with directory - "lib/cliente.c", and $# is just the target name - "cliente.o".
If you write the rules like so you might end up that all your rules look the same, and think about refactoring it further to just a single implicit pattern rule %.o: %.c.
I am writing CUDA code and am using the following Makefile to compile and link it together.
DEBUG = TRUE
CUDA_PATH = /usr/local/cuda
INC_DIR = ../include
ICC = -I/usr/include -I$(INC_DIR) -I$(CUDA_PATH)/include
LIB_CUDA = -L$(CUDA_PATH)/lib64
NVCC = $(CUDA_PATH)/bin/nvcc
LINT = cppcheck
LINK = $(NVCC)
CXX = g++
C_SOURCES = main.c
CUDA_SOURCES = cuda_r_lib.cu
EXE = r_lib
OBJS = main.o
CUDA_OBJS = cuda_r_lib.o
HFILES = $(INC_DIR)/r_lib.h
MAKEFILE = Makefile
REBUILDABLES = $(CUDA_OBJS) $(OBJS) r_lib
LFLAGS = -lcuda $(LIB_CUDA)
ifdef DEBUG
CFLAGS = -Wall -ggdb -pthread -fPIC -O3
CDEFINES = $(ICC)
CUDA_FLAGS = -arch=sm_20 $(ICC)
else
CFLAGS = -Wall -pthread -fPIC -O3
CDEFINES = $(ICC) -DNDEBUG=1
CUDA_FLAGS = -arch=sm_20 $(ICC)
endif
$(EXE): $(OBJS) $(CUDA_OBJS)
$(LINK) $(LFLAGS) $(OBJS) $(CUDA_OBJS) -o $(EXE)
$(OBJS): $(C_SOURCES) $(HFILES) $(MAKEFILE)
$(CXX) $(CDEFINES) $(CFLAGS) -c $(C_SOURCES) -o $#
$(CUDA_OBJS): $(CUDA_SOURCES) $(HFILES) $(MAKEFILE)
$(NVCC) $(CUDA_FLAGS) -c $(CUDA_SOURCES) -o $#
clean:
rm -f *~ $(REBUILDABLES) *ii core
lint:
$(LINT) --enable=all --inconclusive --std=posix *.c *.cu
I've got to the point where my code compiles and links cleanly. But the binary ./r_lib doesn't execute. I can't even change its permissions (tried chmod +x ...)
Here's what I get:
rinka#rinka-Desktop:/media/rinka/CUDA/dev/code$ make
g++ -I/usr/include -I../include -I/usr/local/cuda/include -Wall -ggdb -pthread -fPIC -O3 -c main.c -o main.o
/usr/local/cuda/bin/nvcc -arch=sm_20 -I/usr/include -I../include -I/usr/local/cuda/include -c cuda_r_lib.cu -o cuda_r_lib.o
/usr/local/cuda/bin/nvcc -lcuda -L/usr/local/cuda/lib64 main.o cuda_r_lib.o -o r_lib
rinka#rinka-Desktop:/media/rinka/CUDA/dev/code$ ll ./r_lib
-rw------- 1 rinka rinka 552223 Nov 6 19:08 ./r_lib
rinka#rinka-Desktop:/media/rinka/CUDA/dev/code$ file r_lib
r_lib: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=8f2b88bf570a5d74c2c237969a93519f64636b86, not stripped
rinka#rinka-Desktop:/media/rinka/CUDA/dev/code$ ./r_lib
bash: ./r_lib: Permission denied
rinka#rinka-Desktop:/media/rinka/CUDA/dev/code$ chmod +x ./r_lib
rinka#rinka-Desktop:/media/rinka/CUDA/dev/code$ ./r_lib
bash: ./r_lib: Permission denied
rinka#rinka-Desktop:/media/rinka/CUDA/dev/code$ ll ./r_lib
-rw------- 1 rinka rinka 552223 Nov 6 19:08 ./r_lib
I can't for the life of me figure out what I'm doing wrong - maybe I'm just tired. I looked at: gcc compiled binaries give "cannot execute binary file" but I'm not using the -c option while linking...
Also - any feedback on the compiler & linker options for nvcc that will help throw up warnings more rigorously will be very welcome. I'm not really satisfied with the warnings I got so far.
This is not a message from your compiler or build-tool, but from your shell and originates from the OS.
For the path /media/, it seems you have your files on external storage e.g. an USB-stick. That might be mounted with option noexec, so you cannot execute from there. Also, if that is VFAT, there are no permission-flags in the, so you cannot set them. Instead default flags are used by the OS and might also prevent execution a program from that partition. This is a security measure against malware.
Try mount and check options.
If I'm right, you should move the files to a normal filesystem, e.g. your home.
I madeC 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 this step on MINGW
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
Finally I did drive.exe
Then Windows Dialog Message was shown program can start because libmylib.so.1.0.1 is missing.
LD_LIBRARY_PATH is set.
$ set|grep LD
LD_LIBRARY_PATH=:/c/opt/lib
$
And there is libmylib.so.1.0.1
$ ls -la /c/opt/lib
total 98
drwxr-xr-x 2 JAC484 Administrators 4096 Mar 18 14:44 .
drwxr-xr-x 7 JAC484 Administrators 4096 Mar 14 15:47 ..
-rwxr-xr-x 1 JAC484 Administrators 45356 Mar 18 14:23 libmylib.so.1
-rwxr-xr-x 1 JAC484 Administrators 45356 Mar 18 14:23 libmylib.so.1.0.1
If I copied libmylib.so.1.0.1 in same directory of drive.exe,drive.exe can run.
How Can I tell the system where libmylib.so.1.0.1 is?
Windows doesn't use LD_LIBRARY_PATH. Your shared library DLL will need to be in the same directory as drive.exe or in a directory in the PATH.
The full details of Windows' DLL search is documented here:
MSDN: Dynamic-Link Library Search Order