I have 3 questions about compiling and linking my project in fewer steps...
First, my project looks like: ( I use Watcom C to compile//link my project )
Directory 'MyProject' contains 3 sub directories for different modules and some files:
directory 'A' ( a.h and a.c included )
directory 'B' ( b.h and b.c included )
directory 'C' ( c.h and c.c included )
my.c and my.h
my.lnk
makefile
And within each sub directory there is one corresponding makefile...
[Q1] Assume I update a.h in directory A and a.h is referenced by b.c in directory B, then my original steps will be:
compile in directory A ( obj and lib generated...)
compile in directory B ( obj and lib generated...)
back to directory MyProject then compile and link
Can I just take one step to cover above ?
[Q2] If I want to ignore all existing obj/lib and rebuild all, how to do it ?
I know this takes time but sometimes "kill and rebuild" will be better...
[Q3] If my.h is updated and it is referenced by a.c,b.c, and c.c...
Can I just take one step to cover above ?
[My makefile in sub directory looks like]
INCLUDE1 = -ic:\watcom\h
OBJECTS1 = a.obj
CFLAGS = -zq -mf -oxsbl $(INCLUDE1)
DEST = a.exe
COMPILER = wpp386
.erase # special cmd, tell wmake to "erase" target if make is not successful
.cpp.obj: .AUTODEPEND
$(COMPILER) $(CFLAGS) $<
$(DEST) : $(OBJECTS1) makefile
[My makefile in main directory looks like]
INCLUDE1 = -i=c:\myproj\my -i=c:\watcom\h
OBJECTS1 = my.obj
CFLAGS = -zq -fp6 -mf -6r -s -oxsbl $(INCLUDE1)
DEST = my.exe
COMPILER = wpp386
LINKER = wlink
LNK_FILE = my.lnk
.erase # special cmd, tell wmake to "erase" target if make is not successful
.cpp.obj: .AUTODEPEND
$(COMPILER) $(CFLAGS) $<
$(DEST) : $(OBJECTS1) makefile my.lnk
$(LINKER) #$(LNK_FILE)
[Update 1]
I use wpp386 as compiler and it is watcom c++ tool.
To build the target I use one batch file to compile cpp file:
#echo off
del a1.lib
del *.err
wmake -h
wlib -q a1.lib + a.obj
del *.obj
I can successfully compile cpp file and everything is fine.
In directory B, I use the same way(batch file+makefile) to compile b.cpp
To sum up my project works and the reason why I ask is to find "faster compiling/linking sequence" if I just update some header file...
I tried add the command ehco hello to the rule $(DEST) and found it was ok. Then use echo $(MAKE) and got:
...
echo C:\WATCOM\BINW\WMAKE.EXE
C:\WATCOM\BINW\WMAKE.EXE
...
Thanks !
I'm not familiar with your compiler, so I can't see how these makefiles work, so we'll have to take this one step at a time.
1) when you go into a subdirectory A, what command do you use to build the targets? Does it work? How about in subdirectory B?
2) In the main makefile, can you add a command, like echo hello to the $(DEST) rule? If that works, try echo $(MAKE).
EDIT:
Non-GNU versions of Make are troublesome, but we'll see what we can do.
Try editing the makefile in subdir A:
INCLUDE1 = -ic:\watcom\h
OBJECTS1 = a.obj
CFLAGS = -zq -mf -oxsbl $(INCLUDE1)
DEST = a1.lib # NOTE THIS CHANGE
COMPILER = wpp386
.erase # special cmd, tell wmake to "erase" target if make is not successful
.cpp.obj: .AUTODEPEND
$(COMPILER) $(CFLAGS) $<
$(DEST) : $(OBJECTS1) makefile
wlib -q $# + $(OBJECTS1)
del $(OBJECTS1)
Instead of the batch file, just run make -h. This should rebuild the library (if the library needs rebuilding). If it works, try moving up into MyProject and running make -h -C A. This should execute the makefile in A and rebuild the library there (unless WMAKE has some other syntax).
If that works, try making the same changes in B, then editing the $(DEST) rule in the main makefile:
$(DEST) : $(OBJECTS1) makefile my.lnk
$(MAKE) -h -C A
$(MAKE) -h -C B
$(LINKER) #$(LNK_FILE)
Cross your fingers and run make -h. This should rebuild both libraries, compile, link, and solve Q1...
Related
I'm trying to include Eclipse Mosquitto library sample mosquitto example from here
I'm trying to use a Makefile to build and compile the code.
I'm facing an issue where the compiler/linker/whatsoever cannot find the mosquitto library located at C:\Program Files\Mosquitto\devel.
Here's the error:
mqtt-hostlink> make
gcc -Wall -o main main.c -LC:\\Program ,_,Files\\Mosquitto\\devel\mosquitto.lib
gcc: error: ,_,Files\Mosquitto\devel\mosquitto.lib: No such file or directory
make: *** [Makefile:11: make] Error 1
Here's my Makefile:
CC = gcc
null :=
SPACE := $(null) $(null)
LIBS = -LC:\\Program$(SPACE),_,Files\\Mosquitto\\devel\mosquitto.lib
%.o: %.c
$(CC) -c -o $# $<
make: main.c
$(CC) -Wall -o main $^ $(LIBS)
.PHONY: clean
The "space" method I referred from : How to escape spaces inside a Makefile
You can just use the short name for tar directory. List the directories with /X option as below
C:\>dir /X p*
Directory of C:\
09/06/2021 02:24 PM <DIR> PROGRA~1 Program Files
09/06/2021 01:29 PM <DIR> PROGRA~2 Program Files (x86)
0 File(s) 0 bytes
Then just use PROGRA~1 instead of Program Files
There's some confusion here. That post is about how to escape spaces from make functions. You are not trying to invoke any make functions here, you are just trying to use a variable in a command line. There's no need to escape anything from make.
What you need to do is escape the spaces from the shell, not from make. You can do that easily, just using quotes. No need for fancy make operations. I recommend you also use forward-slashes, not backslashes. Almost all Windows programs accept both forward and backslashes. Only cmd.exe built-ins don't.
LIBS = "-LC:/Program Files/Mosquitto/devel/mosquitto.lib"
I am working on project, where i use couple of .c and .h files.
I created Makefile where i actualize executable program based on changes in all of these files.
Problem is, when i use make, program is compiled, but when i execute program, it runs without any change. I need to save ( working in vim so :w ) all included files, even when i changed only one.
If i don't save all these files, program is compiled, but executes the same thing as it did before change.
Could someone explain me why is that ?
Makefile code :
CC=gcc
CFLAGS=-WALL
execFile: execFile.o functions.h newDataTypes.h
Thank you.
The reason you are not getting execFile updated is because you're NOT updating it. Or at least you don't seem to be in this particular case.
There are many ways to get about doing this. However since you are using gcc and I assume you're using gnu make the following is probably the best solution you can execute1.
Given the files:
-rw-r--r-- 1 user sudo 73 Nov 4 22:54 exeFile.c
-rw-r--r-- 1 user sudo 74 Nov 4 22:54 exeFile.h
-rw-r--r-- 1 user sudo 90 Nov 4 22:55 hello_world.c
-rw-r--r-- 1 user sudo 888 Nov 4 23:03 Makefile
cat exeFile.c
#include <stdio.h>
#include "exeFile.h"
int main()
{
hello_world();
}
exeFile.h
#ifndef _EXEFILE_H
#define _EXEFILE_H
extern void hello_world();
#endif
hello_world.c
#include <stdio.h>
#include "exeFile.h"
void hello_world()
{
printf("Hello World\n");
}
you can set up a make file that generates dependencies and ensures that the program will always be compiled correctly:
CC=gcc
CFLAGS=-Wall
SOURCES=exeFile.c hello_world.c
EXE=exeFile
OBJ=$(SOURCES:%.c=%.o)
DEPDIR := .deps
$(shell mkdir -p $(DEPDIR) >/dev/null)
DEPFLAGS = -MT $# -MMD -MP -MF $(DEPDIR)/$*.Td
COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
COMPILE.cc = $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
POSTCOMPILE = #mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d && touch $#
%.o: %.c
%.o: %.c $(DEPDIR)/%.d
$(COMPILE.c) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
%.o : %.cc
%.o : %.cc $(DEPDIR)/%.d
$(COMPILE.cc) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
%.o : %.cxx
%.o : %.cxx $(DEPDIR)/%.d
$(COMPILE.cc) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
$(DEPDIR)/%.d: ;
.PRECIOUS: $(DEPDIR)/%.d
$(EXE): $(OBJ)
$(CC) -o $# $(OBJ) $(LDFLAGS)
clean:
$(RM) $(OBJ) $(EXE)
dev-clean: clean
$(RM) -r $(DEPDIR)
include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SOURCES))))
Let's go over the relevant parts about dependencies
DEPDIR =
This implementation places dependency files into a subdirectory named .deps .
$(shell mkdir -p $(DEPDIR) 2>/dev/null)
GCC does not create subdirectories for output, this line ensures that the DEPDIR directory always exists.
DEPFLAGS = ...
These are GCC-specific flags which tell the compiler to generate dependency info.
-MT $#
Set the name of the target in the generated dependency file.
-MMD
Generate dependency information in addition to compiling. -MMD omits system headers from the generated dependencies: if you prefer to preserve system headers as prerequisites, use -MD instead.
-MP
Adds a make target for each prerequisite in the list, this avoids errors when deleting files.
-MF $(DEPDIR)/$*.Td
Write the generated dependency file to a temporary file $(DEPDIR)/$*.Td e.g. hello_world.c will generate hello_world.Td as temp dependency content for use in Makefile.
POSTCOMPILE = ...
First rename the generated temporary dependency file to the real dependency file. We do this in a separate step to side-step compile errors. Next we explicitly touch the files to avoid a gcc bug.
%.o : %.c
Delete the built-in rules for building object files from .c files, so that our rule is used instead. Do the same for the other built-in rules.
... $(DEPDIR)/%.d
Declare the generated dependency file as a prerequisite of the target, so that if it’s missing the target will be rebuilt.
$(DEPDIR)/%.d: ;
Create a pattern rule with an empty recipe, so that make won’t fail if the dependency file doesn’t exist.
.PRECIOUS: $(DEPDIR)/%.d
Mark the dependency files precious to make, so they won’t be automatically deleted as intermediate files.
include ...
Include the dependency files that exist: translate each file listed in SOURCES into its dependency file. Use wildcard to avoid failing on non-existent files.
1 See Auto-Dependencies Generation for details.
Fix:
Tell make that the executable depends only on the object file and the object file depends on the header files:
execFile: execFile.o
execFile.o: functions.h newDataTypes.h
Explanation:
In order to build your executable two steps are needed:
compilation of C source files (that include header files) to produce object files,
linking of the object files to produce the executable.
So, when changing your header files you must re-compile, that is re-built the object files, not just re-link that would produce the same executable from the same object files.
In your Makefile the dependencies are not properly defined. You did not tell make that the object file (execFile.o) shall be rebuilt when your header files change. Instead, you told it that the executable (execFile) shall be rebuilt.
First of all, your dependencies are mistaken. Your executable does not depend on the .h header files, as they are using only at compilation time. The dependencies are normally between .o files and .h files, as when you modify one .h file, the including .c file must be compiled to generate the .o file. so in case you have execFile.o (which, on lack of complete information, I'll suppose it depends on execFile.c, which #includes functions.h and newDataTypes.h, the rule should be:
execFile.o: execFile.c functions.h newDataTypes.h
As it has been pointed out in other responses, there's no need to write the command to build the .o file, as there is a default rule like this:
.c.o:
$(CC) $(CFLAGS) -o $# -c $<
(observe there's a -c option to the compiler indicating to compile only and don't link, we'll return here below) which means that once you detect the .o is outdated (as the dependencies on .c and .hs mark) it will be compiled with the above command, which result in:
gcc -Wall -o execFile.o -c execFile.c
making the appropiate compilation.
Other thing is the dependencies of the executable file. These have to be included, as make(1) doesn't know which object files form your final executable. In this case, assuming you have your program execFile depend on execFile.o and a.o, b.o and c.o, I normally use to write:
execFile_objs = execFile.o a.o b.o c.o
execFile: $(execFile_objs)
$(CC) $(LDFLAGS) -o $# $(execFile_objs)
so any of the .os is changed (because an indirect change in a source file) the whole program is linked again (but only the touched files are compiled)
NOTE
In the case (not normal) that you have a Makefile to create a program that has only one source file and several include files you can compile each time the whole thing each time you modify one source file, in this way:
execFile: execFile.c functions.h newDataTypes.h
$(CC) $(CFLAGS) $(LDFLAGS) -o $# execFile.c
This will execute
gcc -Wall -o execFile execFile.c
Observe that there is no -c (compile only, don't link) option in this command.
There's no mention of the include files (they are included because of the #include directives in the code... and you only state here that the executable depends also (and have to be built) in case any of the .h files are modified.
Automatic dependency rules are a little confusing at first, as they induce you to think there are such rules to make any kind of file from any other kind of file (well, there are for .c -> .o files, and .c -> <nothing> to compile directly to an executable) normally you have to include dependencies in such cases when your target depends on more files than the automatic rule states. In such cases, it is very important not to include any command, so the compiler selects the automatic rule (when you don't include a command to generate the target, the make(1) program tries to use a default rule for it, or nothing at all if you have not included commands, it only assumes your dependencies are indirect through this fake target --- and, as this fake target is not built in the process, it will fail always and be followed)
Usually if I want to compile a C program called number_input.c I would type
cc -o number_input number_input.c
I want to use my mac terminal to make a script so that I don't have to type that extra word. Originally I did this to save myself 1 sec of programming but ironically I've spent over 2 hrs trying to get this to work.
a= echo "$1" | rev | cut -c3- | rev
echo $a
cc -o $a $1
echo $1
This is my output:
number_input
clang: error: no input files
number_input.c
I can tell that the names are being inputted correctly but for some reason the cc command isn't taking in the value of $1? I am assuming that somehow the $1 isn't directly converted into a string or something like that but I am not sure.
Your error is on the first line, since you're not assigning anything to a:
a=$(echo "$1" | rev | cut -c3- | rev)
Would fix the problem (for well-behaved filenames, at least, since you're missing quotes further down in your script). A space after a means you're assigning an empty string to it and then running the commands in the pipeline.
Instead of going to all the effort of reversing the twice, just remove the last two characters with ${1%??}:
cc -o "${1%??}" "$1"
The most common tool to do this is make. It reads the recipes from a file named Makefile in the directory it is run, and performs any tasks necessary. It is smart enough to check the file timestamps to detect if or which parts of your projects need to be re-compiled. Here is an example Makefile:
CC := gcc
CFLAGS := -Wall -O2
LDFLAGS := -lm
PROGS := number_input
.PHONY: all clean
all: $(PROGS)
clean:
rm -f $(PROGS)
$(PROGS): %: %.c
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $#
Note that indentation in a Makefile must use tabs, not spaces. If you copy the above, and paste to a file, you will need to run sed -e 's|^ *|\t|' -i Makefile to fix the indentation.
The first three lines name the compiler used, the compiler options, and the linking options. The -lm linking option is not needed for your particular use case; I just included it because you will sooner or later want to use <math.h>, and then you do need to include the -lm linking option.
The PROGS line names your programs. You can specify more than one, just separate them by spaces.
The .PHONY: line tells make that targets all and clean are "phony", that they do not generate files of that name.
The all recipe, as the first recipe in a Makefile, is the default recipe that is followed, when you run make. This one tells that all programs listed in PROGS should be built.
The clean recipe (run make clean) removes all temporary files and compiled files from the directory -- essentially cleaning it.
The last recipe is a tricky one. It says that all the files listed in PROGS are each built from a file having the same name plus a .c suffix. The $^ refers to the .c file name, and $# to the file name without the suffix.
If this Makefile were used for returning exercises via email to a teacher, I'd also add a new .PHONY target, tarball:
CC := gcc
CFLAGS := -Wall -O2
LDFLAGS := -lm
PROGS := number_input
TAR := $(notdir $(CURDIR)).tar
.PHONY: all clean tarball
all: $(PROGS)
clean:
rm -f $(PROGS)
tarball: clean
rm -f ../$(TAR)
tar -cf ../$(TAR) $(notdir $(CURDIR))/
$(PROGS): %: %.c
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $#
Running make will compile number_input, if number_input.c has been modified after the last time number_input was compiled, or if number_input does not exist yet.
Running make TAR=myname-ex01.tar tarball removes the compiled files from the current directory, then creates a tarball of the current directory (and its subdirectories, if any) in the parent directory as myname-ex01.tar. If you run just make tarball, the tar file name will be the same as the name of the current directory, but with a .tar suffix.
I hope you can see why writing a Makefile is so useful.
I have a project with files in different directories. Directory A contains two directories B and C, and C contains a directory D. Files are in B, C and D. I have written makefiles to compile that, with the main makefile in C.
C Makefile contains the following line :
export LDFLAGS = -I ../B -I . -I ../C/D -lm
(At first instead of "../C/D" I had written just "./D" but then I changed because of the error I got, just to be sure the path is valid also for B. However it doesn't changed anything)
The makefile in B contains the following rule :
%.o : %.c
$(CC) $(CFLAGS) -o $# -c $< $(LDFLAGS)
When I run "make", there is an error because a file in B has an include of a file in D, and it doesn't find this file. Why ? Thanks for your help !
edit : As I got exactly the same error (same missing file included on the same B header file) when I added the directory with the -I option, and then when I had the LDFLAGS on my B makefile, I didn't notice the file generating this error change : Now it is a .cpp file that include the B header including the D header that provoke the error.
(Don't ask me why there is one cpp file among c files by the way, it's not me that developed that...)
The lines for the cpp file in the B makefile are :
%.o : %.cpp
g++ $(CFLAGS) -o $# -c $< $(LDFLAGS)
But the .o of this .cpp file is not on the all rule (it call $(OBJS), define as OBJS = $(SRC:.c=.o)). I guess this is my mistake. Because when I run make, it first go on B directory and compile my c file with the options, and then leave directory, because of the rule :
b :
#(cd $(BDIR) && $(MAKE))
So, when make realise that myccpfile.o is needed, he magically call the line
g++ -c -o ../B/myccpfile.o ../B/mycppfile.cpp
So now I really don't understand where this call come from, that's really odd because the only rule using g++ have the CFLAGS and LDFLAGS, I don't understand why they disappeared...
Its CFLAGS that requires the -I options for the compilation phase of the build. Check the B makefile has CFLAGS set with the appropriate -I options.
LDFLAGS will only affect linker options.
I am modifying an old makefile in order to build a C extension for postgreSQL. The Makefile currently looks like this:
PGLIB = /usr/lib/postgresql/8.4/lib
PQINC = /usr/include/postgresql/8.4/server
CC=gcc
override CFLAGS+= $(CFLAGS_SL) -DPG_AGGREGATE
SHLIB = pg_myextlib
SRC = foo.c \
foobar.c
OBJS = foo.o \
foobar.o
all: $(OBJS)
$(CC) -shared -o $(SHLIB)$(DLSUFFIX) $(OBJS) -I$(PQINC)
cp *.so $(PGLIB)
clean:
rm -f $(SHLIB) $(OBJS)
The error I get when I run make is:
common.h:58:22: error: postgres.h: No such file or directory
Which suggests that the include path is not being added (the file exists in $PQINC).
Its a long time since I wrote the Makefile - and I haven't written many since. As an aside, I am pretty sure that 'shared' is not the gcc flag to build shared libs on Ubuntu (my current dev box) - I think the flag should be 'fPIC' - can someone confirm this?
I am runing gcc v4.4.3 on Ubuntu 10.0.4 and compiling for use with PG 8.4
Try moving the -I$(PQINC) from target all to the end of line that starts with override CFLAGS.
Placing -Isomething on the compiler line which turns object files, like those in $(OBJS), into executable will have no effect whatsoever.
You need to do it when you compile the source files.
Since your makefile doesn't explicitly show the rule for processing source files, it may well be using a default one, which is incredibly unlikely to know about PQINC.
You seem to be using the default rules to build foo.o from foo.c, which doesn't have your -I. Try adding the following rule to your Makefile:
.c.o:
$(CC) $(CFLAGS) -c $< -o $# -I$(PQINC)