Correctly including (POSIX) libraries in deeply nested source / makefiles - c

Long story short: We have a large SDK containing ~1Gb of hairy code hacked together by Elbonian Code Slaves, duck-taped together by a quivering lattice of RPC's, shared memory, mutex/semaphores, and spit. It's compiled on a Linux machine for an embedded SoC target.
As part of a stab at improving part of the code, I want to add POSIX Semaphores to one of the sources, which gets included by a few RPC routines.
However, just writing some valid code & sticking
#include <semaphore.h>
at the top is of course insufficient to enable compilation.
What is required are special flags in the makefile, depending on what you read it could be any/all of:
-pthread
-lpthread
-lpthreads
-lrt
-rt
I do not have a great deal of experience writing makefiles, and unfortunately due to the size of the codebase there are multiple nested levels of them (upwards of 2,000 makefiles in the SDK) with all sorts of dependencies, all spawning from the One True Makefile in the root folder.
There is a lot of macroification(TM) going on in the makefiles which is not helping my efforts to unravel the correct incantation.
As a glimpse of the structure of the project and the file I'm trying to modify, the folder structure is something like:
/home/project/kernel/... Contains the Linux kernel & PSP / BSP
/home/project/the_system/... Contains the software suite we're building
And the file we're looking at is in:
/home/project/the_system/core_app/interface/src/messaging.c
Which itself is included by maybe 5 other sources, like:
/home/project/the_system/core_app/interface/src/sys-control.c
/home/project/the_system/core_app/interface/src/file-control.c
/home/project/the_system/core_app/interface/src/audio-control.c
... you get the idea. Each of these may then be included/called by other processes wishing to communicate with each other Did I mention it's all horrible?
There are makefiles in pretty much every folder up that chain, the makefile in the local folder
/home/project/the_system/core_app/interface/src/Makefile
is something like this (I removed a few bits for clarity, ignore unreferenced objects):
INCLUDES += -I./ -I$(PUBLIC_INCLUDE_DIR) -I$(LINUXKERNEL_INSTALL_DIR)/include -I$(CMEM_INSTALL_DIR)/packages/ti/sdo/linuxutils/cmem/include -lpthreads
C_FLAGS += -Wall -g -O3
AR_FLAGS += -r
CC = $(MVTOOL_PREFIX)gcc $(INCLUDES) $(C_FLAGS) -c
AR = $(MVTOOL_PREFIX)ar
REL_EXE1 = reboot_me
REL_LIB1 = file-control.a
REL_LIB3 = share_mem.a
REL_LIB4 = sys-control.a
REL_LIB5 = msg_util.a
REL_LIB9 = messaging.a
REL_LIB10 = sysctrl.a
REL_LIB11 = audio-control.a
REL_OBJ1 = file-control.o share_mem.o msg_util.o
REL_OBJ3 = share_mem.o
REL_OBJ4 = sys-control.o share_mem.o msg_util.o
REL_OBJ5 = msg_util.o
REL_OBJ9 = messaging.o
REL_OBJ10 = sysctrl.o sys-control.o share_mem.o msg_util.o messaging.o audio-control.o
REL_OBJ11 = audio-control.o messaging.o share_mem.o msg_util.o
all: $(REL_EXE1) $(REL_LIB9) $(REL_LIB12) $(REL_LIB3) $(REL_LIB1) $(REL_LIB2) $(REL_LIB4) $(REL_LIB5) $(REL_LIB6) $(REL_LIB7) $(REL_LIB8) $(REL_LIB10) $(REL_LIB11) install
$(REL_LIB1): $(REL_OBJ1)
$(AR) $(AR_FLAGS) $(REL_LIB1) $(REL_OBJ1)
$(REL_LIB2): $(REL_OBJ2)
$(AR) $(AR_FLAGS) $(REL_LIB2) $(REL_OBJ2)
$(REL_LIB3): $(REL_OBJ3)
$(AR) $(AR_FLAGS) $(REL_LIB3) $(REL_OBJ3)
$(REL_LIB4): $(REL_OBJ4)
$(AR) $(AR_FLAGS) $(REL_LIB4) $(REL_OBJ4)
$(REL_LIB5): $(REL_OBJ5)
$(AR) $(AR_FLAGS) $(REL_LIB5) $(REL_OBJ5)
$(REL_LIB7): $(REL_OBJ7)
$(AR) $(AR_FLAGS) $(REL_LIB7) $(REL_OBJ7)
$(REL_LIB8): $(REL_OBJ8)
$(AR) $(AR_FLAGS) $(REL_LIB8) $(REL_OBJ8)
$(REL_LIB9): $(REL_OBJ9)
$(AR) $(AR_FLAGS) $(REL_LIB9) $(REL_OBJ9)
$(REL_LIB10): $(REL_OBJ10)
$(AR) $(AR_FLAGS) $(REL_LIB10) $(REL_OBJ10)
$(REL_LIB11): $(REL_OBJ11)
$(AR) $(AR_FLAGS) $(REL_LIB11) $(REL_OBJ11)
$(REL_LIB12): $(REL_OBJ12)
$(AR) $(AR_FLAGS) $(REL_LIB12) $(REL_OBJ12)
file-control.o : file-control.c $(PUBLIC_INCLUDE_DIR)/file-control.h $(PUBLIC_INCLUDE_DIR)/Msg_Def.h\
$(PUBLIC_INCLUDE_DIR)/sys_env_type.h
$(CC) $(C_FLAGS) -o $# $<
audio-control.o : audio-control.c $(PUBLIC_INCLUDE_DIR)/audio-control.h \
$(PUBLIC_INCLUDE_DIR)/Msg_Def.h $(PUBLIC_INCLUDE_DIR)/sys_env_type.h
$(CC) $(C_FLAGS) -o $# $<
share_mem.o: share_mem.c $(PUBLIC_INCLUDE_DIR)/share_mem.h
$(CC) $(C_FLAGS) -o $# $<
sys-control.o : sys-control.c $(PUBLIC_INCLUDE_DIR)/sys-control.h $(PUBLIC_INCLUDE_DIR)/Msg_Def.h\
$(PUBLIC_INCLUDE_DIR)/sys_env_type.h $(PUBLIC_INCLUDE_DIR)/share_mem.h
$(CC) $(C_FLAGS) -o $# $<
msg_util.o: msg_util.c $(PUBLIC_INCLUDE_DIR)/Msg_Def.h
$(CC) $(C_FLAGS) -o $# $<
messaging.o: messaging.c $(PUBLIC_INCLUDE_DIR)/messaging.h
$(CC) $(C_FLAGS) -o $# $<
sysctrl.o: sysctrl.c $(PUBLIC_INCLUDE_DIR)/sysctrl.h $(PUBLIC_INCLUDE_DIR)/sys_env_type.h
$(CC) $(C_FLAGS) -o $# $<
reboot_me:
$(MVTOOL_PREFIX)gcc -g -Wall -static -c -o reboot_me.o reboot_me.c
$(MVTOOL_PREFIX)gcc -o reboot_me reboot_me.o
clean:
-$(RM) -f *.o
-$(RM) -f *.a
-$(RM) -f $(REL_EXE1)
-$(RM) -Rf $(APP_LIB_DIR)
install: $(REL_EXE1) $(REL_LIB3) $(REL_LIB1) $(REL_LIB2) $(REL_LIB4) $(REL_LIB5) $(REL_LIB7)
install -d $(APP_LIB_DIR)
install $(REL_LIB1) $(APP_LIB_DIR)
install $(REL_LIB2) $(APP_LIB_DIR)
install $(REL_LIB3) $(APP_LIB_DIR)
install $(REL_LIB4) $(APP_LIB_DIR)
install $(REL_LIB5) $(APP_LIB_DIR)
install $(REL_LIB7) $(APP_LIB_DIR)
install $(REL_LIB8) $(APP_LIB_DIR)
install $(REL_LIB9) $(APP_LIB_DIR)
install $(REL_LIB10) $(APP_LIB_DIR)
install $(REL_LIB11) $(APP_LIB_DIR)
install $(REL_LIB12) $(APP_LIB_DIR)
install $(REL_EXE1) $(EXEC_DIR)
Anyway, having added
#include <semaphore.h>
to the top of
/home/project/the_system/core_app/interface/src/messaging.c
what do I need to do to allow this to compile properly?
As a bonus question, is there any way to determine which one of:
-pthread
-lpthread
-lpthreads
-lrt
-rt
Is the correct one for our particular build environment?
Edit to add (also TL;DR):
I seem to be encountering an exact duplicate of the scenario mentioned in this question.
However, no matter where I stick the -lpthread and -lrt arguments I get errors.
For example, I tried to add a call to pthread_mutex_trylock, and it fails to compile:
undefined reference to 'pthread_mutex_trylock'
...even though existing functions calling pthread_mutex_lock compile OK.

I am not sure exactly what you mean by the first question. I will attempt to cover all possibilities.
The answer to the second question was pretty much covered by Joachim.
Your system will attempt to build messaging.o if you change messaging.c, for example, if you add a header file to the top.
If you want to know, how to succeed that attempt, well, you need to provide the proper location of the file semaphore.h in the INCLUDES variable. It is a "system" file, in one of the "system" include directories.
If you want to ensure, that you rebuild messaging.o when semaphore.h changed, you would need to read the section on advanced auto-dependency generation in the GNU Make Manual or on MadScientist's site http://mad-scientist.net/make/autodep.html
Or, use the ElectricAccelerator, that EricMelski talks about all the time. That fantastic software, has automatic dependency generation built-in for free. You don't have to do a thing.
Also, as you already know, the Makefile you are showing is very poorly written, very "naiive". And it sounds like you have a recursive system of several thousand of similarly poor Makefiles. Yes, it is terrible.
And it sounds like you personally do not want to fix this build system as such, you are just interested to add some functionality to the software itself.
So, I think you need to hire an expert consultant to write your company a state-of-the-art system, perhaps using ElectricAccelerator, or plain old GNU Make. Do you get the hint? Ehm, , if Eric can put plugs here all the time and he gets away with it, then so can I :)

Well, I finally got the hateful thing to build, unfortunately more through brute force & ignorance than some elegant master-stroke of coding genius.
However, should it help some future generation, the route I followed was this:
Add -lrt -lpthread to C_FLAGS in my example makefile, and then tried to make
When make failed, look at the location where it failed, load the makefile from that place and add -lrt -lpthread in a similar fashion in that makefile.
Lather, rinse, repeat until make succeeds.
It now seems to work OK, of course there are now 100 other bugs to fix, but at least I got it to compile in the end.
Nurse, the screens!

Related

Makefile not generating debugging information with -g flag

I recently moved from working in the terminal to VScode and am needing to generate debugging information to use with the debugger in vscode.
My makefile is:
SRCS = src/ft_argcheck.c \
src/ft_operations.c \
src/ft_stcutils.c \
src/push_swap.c
NAME = push_swap
INCS = inc/push_swap.h
OBJS = $(SRCS:c=o)
CC = gcc
CFLAGS = -g -Wall -Wextra -Werror
RM = rm -f
LIBFT = libft/libft.a
LIBFT_DIR = libft
.PHONY: all bonus clean fclean re
all: $(NAME)
$(NAME): $(OBJS)
#make -C $(LIBFT_DIR) --silent
#$(CC) $(CFLAGS) -I$(INCS) -o $(NAME) $(OBJS) -L $(LIBFT_DIR) -lft
clean:
#$(RM) $(OBJS)
#make -s clean -C $(LIBFT_DIR)
fclean: clean
#$(RM) $(NAME)
#make -s fclean -C $(LIBFT_DIR)
re: fclean all
But despite adding the -g flag, no debugging information is generated. on which I can run lldb.
A good proposal is to remove the #s in front of the command names to see what commands make is executing.... To make a program debuggable, you need to check that all the compilation steps are done using the -g flag and that the linking step has also included the -g flag. Also a good option is to specify no optimization so you will not get to problems with breakpoints you cannot fix because the compiler has eliminated or changed the final code, and has broken the correspondence between source lines and points in the code.
If you take off all the #s there, you will see the commands as make is executing them, think you don't see now. I think there's a command (berkeley make has it) to make make to print the commands even though the #s remain in place.
By the way, as you are telling you are using vscode it should be fine if you execute make on the command line alone, to see the output of the commands, and try to see if it is some problem with make or with vscode itself.
As you have not provided your complete project, I'm sorry to say that I can only test it with dumb/fake files and no program can be made to test it with gdb.
I guess that the problem is that you have put your project sources in a different directory than where the program is built, and the sources cannot be found by gdb and so, no source debugging can be done because gdb cannot find the source files. Gdb has some way to specify the path to the source files... You should look at gdb documentation.
Thanks for all your answers (Removing # didn't really give me much more information, as it did show the -g flag and I already tried remaking everything with fclean). I seem to have figured out an easy fix with the help of a friend:
add a rule "debug"
debug:
$(CC) -g $(CFLAGS) -I$(INCS) $(LIBFT) $(SRCS) -o $(NAME)
which we can run just when we want to generate the debugging information and run this directly with $(SRCS) instead of running it on the $(OBJS) as in the normal command.

Write proper Ansi C makefile for Windows [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I'm really desperate when trying to write a C makefile for windows for my school project. I already have my makefile written and used for ubuntu and it works perfectly like this:
all: clean install
install: dynarr.o broadcaster.o main.o
gcc -o freq dynarr.o broadcaster.o main.o
clean:
rm -f *.o
dynarr.o:
gcc -c dynarr.c
broadcaster.o:
gcc -c broadcaster.c
main.o:
gcc -c main.c
I've already tried just about 10 tutorials on various sites and it is getting on my nerve.
I need to compile dynarr.c broadcaster.c main.c in this particular order and the output should be freq.exe. Compiler on the school server is gcc for both versions(linux and windows).
Please help me.
Edit: For some reason our teacher's online validator required freq.exe for both windows and linux and he did not bother to mention it anywhere. Everything I had to edit was freq to freq.exe. Thanks for support.
On Windows, you expect the compiler to produce a file named freq.exe (or the test system does, anyway) but the command you issue tells GCC to emit a file named just freq, instead. The latter seems natural for Linux, so it is not surprising that your build works as expected there.
It is tricky to support different OS families with the same makefile, which is why utilities such as the Autotools and CMake were invented. Supposing that you only need a Makefile for Windows, this variation should suffice:
all: clean install
install: dynarr.o broadcaster.o main.o
gcc -o freq.exe dynarr.o broadcaster.o main.o
clean:
rm -f *.o
dynarr.o:
gcc -c dynarr.c
broadcaster.o:
gcc -c broadcaster.c
main.o:
gcc -c main.c
With that said, I have some suggestions for further improvement:
A rule for building a specific output file should name that file as its target.
Conversely, targets of rules that do not correspond to a file created by that rule should be declared "phony" by naming them as prerequisites of a target named .PHONY.
By convention, an "install" target copies built files from their build location to a permanent system location. Neither your install rule nor anything else in your makefile does that, so you probably don't need an "install" target.
It is perhaps intentional that your rule for the default target cleans before it builds, but that is abnormal, as it defeats one of the major reasons for using make in the first place: to avoid needless work.
It is good form and it protects against errors to use Make's automatic variables to avoid repeating yourself in rules.
There is some divergence of opinion, but I think the general consensus is that a clean target should clean up all built objects, not just intermediate ones.
Applying all those would yield a makefile such as this:
all: freq.exe
freq.exe: dynarr.o broadcaster.o main.o
gcc -o $# $^
clean:
rm -f freq.exe *.o
dynarr.o:
gcc -c dynarr.c
broadcaster.o:
gcc -c broadcaster.c
main.o:
gcc -c main.c
.PHONY: all clean
Personally, I would also suggest introducing variables for the executable target (which would make it easier to adapt the makefile between Windows and Linux / macOS) and for the required object files (which is typical, and which would allow the clean target to be more precise). You could also consider relying on Make's built-in rules for building .o files from .c files, as the explicit rules you're using don't do anything that the is not also done by the built-in one. The result might be:
PROG = freq.exe
OBJS = dynarr.o broadcaster.o main.o
all: $(PROG)
$(PROG): $(OBJS)
gcc -o $# $^
clean:
rm -f $(PROG) $(OBJS)
# Relies on the built-in rules for building object files from C sources
.PHONY: all clean

Makefile dependencies on multiple files

I have created a Makefile for unit tests which uses GCC with arguments to create profiling files (gcno) during compiling. Here's a similified part of it where compiling and linking takes place:
UTEXE = $(UTOBJSDIR)\$(UTUNIT).exe
UTOBJS = $(UTUUTSRC:.c=.o) $(UTUTSRC:.c=.o) $(UTCSRC:.c=.o)
UTOBJSFULL = $(addprefix $(UTOBJSDIR)\,$(UTOBJS))
UTOBJSGCNO = $(addprefix $(UTOBJSDIR)\,$(UTOBJS:.o=.gcno))
$(UTOBJS): %.o: %.c $(UTMAKEDEP)
$(call report,Compiling $(*F).c)
$(MKDEP) $(MKDFLAGS) -o.o -f$(UTOBJSDIR)\$(*F).dep $(subst /,\,$<)
$(CC) -c $(CFLAGS) $(subst /,\,$<) -o $(UTOBJSDIR)/$#
$(UTOBJSGCNO): $(UTOBJS) $(UTMAKEDEP)
utbuild: $(UTEXE) $(UTOBJSGCNO) $(UTOBJS) $(UTMAKEDEP)
$(UTEXE): $(UTOBJSGCNO) $(UTOBJS) $(UTMAKEDEP)
$(call report,Linking to $(UTUNIT).exe)
$(LINK) $(UTOBJSFULL) $(LNKFLAGS) -o $(UTEXE)
It compiles all the object and profile files and links together a binary. However when i delete some profile file (gcno) and call "utbuild" again it won't re-compile to restore the .gcno file. It tries to do linking again because gcno is a prequisite to it, but it wont do the compiling.
I don't know how to name this case so couldn't find solution from internet. Basically one recipe creates two files and i don't know how to write the rule that re-run's recipe even when only one file needs to re-created.
I would appreciate some links or hints.
thanks for all the comments. I've tried no-op ";" and ":=" with same outcome.
I think i need to take one step back and explain why i asked this question. It's not just about deleting or not-deleting gcno files manually, it's about general understanding how to write such a Makefile which restores any missing or out-of-date file. My Makefile has similar cases in few places and it's using parallel build so when some file goes missing it gives lot of weird errors. Usually it's solved by "clean" and "all", but i'd like the Makefile to be perfect and handle the missing file issues nicely.
As the example above is not so clear without all the rest of the Makefile then i made a new simple test.
hello.c
#include <stdio.h>
int main()
{
printf("Hello world\n");
}
Makefile
CCDIR = C:\tools\MinGW
CCBINDIR = $(CCDIR)\bin
CCINCDIR = $(CCDIR)\include;$(CCDIR)\lib\gcc\mingw32\4.8.1\include
CCLIBDIR = $(CCDIR)\lib;$(CCDIR)\lib\gcc\mingw32\4.8.1
# Overcome "missing dll file" messages on Windows
CC = set PATH=%PATH%;$(CCBINDIR)& $(CCBINDIR)\gcc.exe
LINK = set PATH=%PATH%;$(CCBINDIR)& $(CCBINDIR)\gcc.exe
# Compile and link for code coverage
CFLAGS = -fprofile-arcs -ftest-coverage -g3 -O0 $(addprefix -I,$(CCINCDIR))
LNKFLAGS = -fprofile-arcs -ftest-coverage -static -static-libgcc $(addprefix -L,$(CCLIBDIR))
OBJECTS = hello.o
EXE = hello.exe
$(OBJECTS): %.o: %.c
$(CC) -c $(CFLAGS) $(subst /,\,$<) -o $#
$(EXE): $(OBJECTS)
$(LINK) $(OBJECTS) $(LNKFLAGS) -o $(EXE)
build: $(EXE)
"make build" creates following files:
hello.o
hello.gcno
hello.exe
Now if i delete the "hello.gcno" and run build again it tells me:
mingw32-make: Nothing to be done for 'build'.
The goal is to update Makefile so that the make re-creates the "hello.gcno". It would probably re-create "hello.o" and "hello.exe" also during that process but that's not a problem.
Edit:
Just to be clear: in real Makefile i really-really need the .gcno files. It's not just an additional information or something which to avoid or do optionally. The Makefile builds the unit test executables, runs them and executes gcov to generate code coverage information and gcovr creates a report of all the .gcov files. If .gcno file is missing it won't work. Also - as it's parallel build then dependencies shall be absolutely correct to avoid some process starting earlier and it's tricky because coverage report has dependencies coming from two "branches" - .gcno files from compile stage and .gcda files from execute stage. So that's why i need it to be correct.
your only option here is this :
(if you can change the rule)
$(EXE): $(OBJECTS)
$(LINK) $(OBJECTS) $(LNKFLAGS) -o $(EXE)
to this:
%.exe %.gnco: $(OBJECTS)
$(LINK) $(OBJECTS) $(LNKFLAGS) -o $(EXE)
$(GENERATE_GNCO) $<
Here is a very simple solution of one thing dependig on two other things
compile:./src/main.c ./src/error.c
gcc ./src/error.c ./src/main.c -o ./exe/calc
run : ./exe/calc
./exe/calc
The correct answer in my opinion, is, don't delete any .gcno files by themselves. If you have to "clean", use make clean, but don't just go about deleting files.
The "build" is a state machine, with all the files constituting a "state". Don't corrupt the state!
Some people say, one should be able to delete arbitrary files and the build should recover. My answer is, what about if you corrupt some .o file by hand, say, add some 0's and 1's, making it unusable (thank you user3629249 for pointing that needs to be clarified, that I am talking about corruption, not intentional editing). Should the build also recover from that? Obviously no - no build system in the world will recover if you touch the .o file this way. Then why allow deleting a file, but not allow modifying it?? Where do you draw the line?
Simply put, any corruption should not be allowed. Use make clean only, or better yet, write your Makefile properly, so you never need to clean period.
The whole Makefile has a number of problems, here is how it should look like (I am assuming this is on Windows/DOS):
.SUFFIXES:
UTEXE := $(UTOBJSDIR)\$(UTUNIT).exe
UTOBJSFULL := $(addprefix $(UTOBJSDIR)\,$(subst /,\, $(UTUUTSRC:.c=.o) $(UTUTSRC:.c=.o) $(UTCSRC:.c=.o)))
UTOBJSGCNO := $(UTOBJSFULL:.o=.gcno)
.PHONY: utbuild all
all: utbuild
utbuild: $(UTEXE) $(UTOBJSGCNO) $(UTMAKEDEP)
$(UTOBJSGCNO): %.gcno: %.o $(UTMAKEDEP) ;
.SECONDARY: %\.
%\.: Makefile
mkdir $*
.SECONDEXPANSION:
$(UTOBJSFULL): $(UTOBJSDIR)\%.o: %.c $(UTMAKEDEP) | $$(#D)\.
$(call report,Compiling $<)
$(MKDEP) $(MKDFLAGS) -o.o -f$(UTOBJSDIR)\$(*F).dep $<
$(CC) -c $(CFLAGS) $< -o $#
$(UTEXE): $(UTOBJSFULL) $(UTMAKEDEP) | $$(#D)\.
$(call report,Linking to $(#F))
$(LINK) $(UTOBJSFULL) $(LNKFLAGS) -o $#

How to make a makefile for Oracle on Solaris/Linux Server?

I have an application which is running properly for Informix database. But now I want it to compile it for Oracle too. What changes should be made in the makefile shown below which is running properly for Informix?
ESQL:=esql
CFLAGS:=$(CFLAGS) -DSOLARIS
PROCFLAGS:=$(PROCFLAGS) -DSOLARIS
HEADERS= $(HOME)/tmiD/headers
target = $(HOME)
CC=gcc
%.o :%.ec ; $(ESQL) -I$(HEADERS) -c $(CFLAGS) -DINFORMIX -EDINFORMIX -I/usr/local/include $<
%.o :%.c ; $(CC) -I$(HEADERS) -c $(CFLAGS) $<
MAKEC= mv $(target)/$(#F) $(target)/$(#F).old; \
$(ESQL) -DINFORMIX -EDINFORMIX \
$^ $(CFLAGS) -lnsl -L $(target) \
-o $(target)/$(#F)
$(target)/%:%.o $(CLIBFILES); $(MAKEC)
%:%.o $(CLIBFILES); $(MAKEC)
all: a tw_interface clean
tw_interface: tcp.o trace.o global.o rmi.o License.o purge.o libswx.a
ap: tcp.o trace.o global.o rmi.o License.o purge.o
clean:
-rm tcp.o trace.o global.o rmi.o purge.o License.o\
trace.c global.c rmi.c
a:
-rm tw_interface
I am very new to these things. So please help me.
Thank you in advance.
Hmm....you say you're very new to these things.
Re-writing a Makefile is a non-trivial exercise, if you're not an experienced programmer.
But, if you want to give this a try, I recommend starting out by installing the Pro*C demos in your ORACLE_HOME. Once that's done, and you've verified it, by building the sample Pro*C programs, I recommend using the demo_proc.mk makefile, (which will be installed with the demo programs) as a template to convert the makefile.
Also, note, I don't know anything about Informix, but the code itself will probably need to be converted to Pro*C, as I assume Informix has some other precompiler, or alternate set of libraries for database access.
Hope that helps.
I think the Pro*C precompiler is invoked with "proc" so the first line
ESQL:=esql
should become
PRO_C:=proc
It looks like Pro*C files normally have a .pc file extension. Assuming your Pro*C files will be slightly different than your Informix *.es files, and you will create them with a .pc extension, then this line
%.o :%.ec ; $(ESQL) -I$(HEADERS) -c $(CFLAGS) -DINFORMIX -EDINFORMIX -I/usr/local/include $<
would become
%.o :%.pc ; $(PRO_C) CONFIG=proc_c_config.txt -I$(HEADERS) -c $(CFLAGS) -I/usr/local/include $<
The above line has "proc_c_config.txt" which is a file to create to put any desired Pro*C options. That part could be removed if there are no options desired other than defaults.
$(ESQL) -DINFORMIX -EDINFORMIX \
would become
$(PRO_C) CONFIG=pro_c_config.txt \
They talk about Pro*C options here

GNU Make - Dependencies on non program code

A requirement for a program I am writing is that it must be able to trust a configuration file. To accomplish this, I am using several kinds of hashing algorithms to generate a hash of the file at compile time, this produces a header with the hashes as constants.
Dependencies for this are pretty straight forward, my program depends on config_hash.h, which has a target that produces it.
The makefile looks something like this :
config_hash.h:
$(SH) genhash config/config_file.cfg > $(srcdir)/config_hash.h
$(PROGRAM): config_hash.h $(PROGRAM_DEPS)
$(CC) ... ... ...
I'm using the -M option to gcc, which is great for dealing with dependencies. If my header changes, my program is rebuilt.
My problem is, I need to be able to tell if the config file has changed, so that config_hash.h is re-generated. I'm not quite sure how explain that kind of dependency to GNU make.
I've tried listing config/config_file.cfg as a dependency for config_hash.h, and providing a .PHONY target for config_file.cfg without success. Obviously, I can't rely on the -M switch to gcc to help me here, since the config file is not a part of any object code.
Any suggestions? Unfortunately, I can't post much of the Makefile, or I would have just posted the whole thing.
Declaring the file in .PHONY is wrong. Any dependency listed there will not be checked in the filesystem. Just list it as a dependency for the hash header and go from there.
What happened when you added config/config_file.cfg to the dependancies of config_hash.h, and why wasn't it what you expected?
A rule like
config_hash.h:config/config_file.cfg
$(SH) genhash $< > $#
would regenerate config_hash.h if config/config_file.cfg was more recent. Your gcc generated dependancies would then recompile anything depending on config_hash.h.
The $# variable is the target, using this ensures you are creating the file you asked for (In your question, if srcdir is defined the rule says it will generate ./config_hash.h, but will actually create ./$(srcdir)/config_hash.h). Similarly $< and $^ give the first and all prerequisites respectively.
I'm assuming you have a makefile like
CPPFLAGS+=-MMD -MP
all:
# etc.
config_hash.h:config/config_file.cfg
$(SH) genhash $< > $#
%.d %.o:%.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $*.o $<
%.d %.o:%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $*.o $<
-include $(wildcard *.d) /dev/null

Resources