I want to create separate executables for each directory named "test" in my project. Test directory has structure like this:
test.mk
test (dir)
|__test.mk
|__testRun.c
|__testRun.h
test.mk contains dependencies for specific test, testRun.c is the test itself.
So hierarchy looks like this:
ROOT
|__Makefile
|__Module1 (dir)
|__some files
|__test (dir)
|__Module2 (dir)
|__some files
|__test (dir)
|__Module3 (dir)
|__some files
|__test (dir)
|__outdir (dir)
|__test1 (exec)
|__test2 (exec)
|__test3 (exec)
I want to run single Makefile in root parent directory. I want it to search for all test directories and create test executables in outdirectory. So far I have this:
Makefile
CFLAGS = -I$(DIRTEST) -I$(DIRTEST)/..
OUTDIR= ./outdirectory
DIRTEST = $(shell find -type d -not -path "$(OUTDIR)/*" -name "test" -prune )
I have no idea how to create rule that creates target executable from sources and headers from separate directories. I was looking for solution for similar problem, but no luck so far.
Note: I do not want to use recursive make. test.mk looks for example like this:
SRCTEST = module1/test/testRun.c \
module1/module1.c
CFLAGS += -Imodule1
You can use bash scripts files for building variables, in case if you are avoiding a recursive build.
cat module1/test/test.sh
export SRCTEST="module1/test/testRun.c
module1/module1.c"
export CFLAGS="$CFLAGS -Imodule1"
cat module2/test/test.sh
export SRCTEST="module2/test/testRun.c
module2/module2.c"
export CFLAGS="$CFLAGS -Imodule2"
Then your Makefile could looks like:
test1:
source module1/test/test.sh && gcc -o $# $$CFLAGS $$SRCTEST
test2:
source module2/test/test.sh && gcc -o $# $$CFLAGS $$SRCTEST
Also you can do something with include instruction. Redefinition could be avoided by checking the build target, but this is not a good way.
Your examples are not clear enough for us to answer.
For one thing, tt's not clear how the name of the test executable is related to the name of the module. Is it really the case that the modules end with a number and the generated test program should also end with that same number (Module1 -> test1)? Or is there some other relationship? There doesn't appear to be any variable containing a test name in the test.mk file so how is the test name computed?.
Second, it will make your life very difficult if you redefine the same variables in every test.mk file. There is no "scoping" in make that will allow you to say "this instance of CFLAGS is used only for this included makefile". Each time you include a different test.mk file it will overwrite the previous settings.
It CAN be done: you'll need to use a combination of define variables to hold rule definitions, then eval to evaluate the rules.
Let's suppose that you added a new variable to test.mk which defined the test name, and you qualified your variables with this name as well; then your life is much easier:
Module1/test/test.mk would contain:
TESTNAME = test1
test1_SRCTEST = module1/test/testRun.c \
module1/module1.c
test1_CFLAGS = -Imodule1
Now in your main makefile you would create a variable holding the rule you wanted to define:
define MAKETEST
include $T
$$(OUTDIR)/$$(TESTNAME): $$(OUTDIR)/% : $$($$(TESTNAME)_SRCTEST)
$$(CC) $$(CPPFLAGS) $$(CFLAGS) $$($$*_CFLAGS) -o $$# $$^
endef
$(foreach T,$(DIRTEST),$(eval $(MAKETEST)))
Note, this is untested.
Related
I want to use makefile to create my app and .out file and use it in my verifone vx520.
I have makeapp.bat for creating .out file but when I run it get this error: NMAKE : fatal error U1073: don't know how to make 'utils.h'
and this is makeapp.bat file:
#goto Begin
:Begin
#set OLDPATH=%PATH%
#rem set VRXSDKS to the Verix V SDK directory
#set VRXSDK=C:\eVoAps\SDK\1.2.0\VRXSDK
#rem Set RVCTDIR to RVDS2.2
#set RVCTDIR=C:\Program Files\ARM\RVCT\Programs\2.2\349\win_32-pentium
#rem or, Set RVCTDIR to RVDS2.1
#rem set RVCTDIR=C:\Program Files\ARM\RVCT\Programs\2.0.1\277\win_32-pentium
#set PATH=%VRXSDK%\bin\;%RVCTDIR%;%OLDPATH%
#rem use app.mak to buid application
nmake /f app.mak
#rem or, use vrxcc directly here to build a simple application
#rem %VRXSDK%\bin\vrxcc app.c
#set PATH=%OLDPATH%
#set RVCTDIR=
pause
how can i solve that error?
So, it looks to me like your bat file here has lots of comments (#rem) and it also sets several variables (#set), but the bulk of the work will be done in the line
nmake /f app.mak
which will reference a different file called app.mak. That's where the magic happens and it's where you will need to edit something to let nmake know how to compile and link utils.h. I suggest you look at c2.com/cgi/wiki?UsingNmake for more details.
As you know, a make file is, for all intents and purposes, a program that you write. When it runs, it builds the VeriFone app (or whatever other program you were working on). As such, there is a multitude of things you can do, some of which you must do if you want nmake to actually build your program. I think the best way to help out would be to share parts of my make file. Note that this started off as just a template from a sample VeriFone project.
Mine starts off just declaring variables, paths, etc., like so:
ProjectName = TestProject
# ****** PATHS ******
# Includes
SDKIncludes = -I$(EVOSDK)\include
ACTIncludes = -I$(EVOACT)include
VCSIncludes = -I$(EVOVCS)include
#Libraries
ACTLibraries = $(EVOACT)OutPut\RV\Files\Static\Release
# App Paths
AppIncludes = .\include
SrcDir = .\source
ObjDir = .\obj
OutDir = .\Output\$(TerminalType)\$(VMACMode)\Files
ResDir = .\Resource
Note that TerminalType is something I have set Visual Studio to pass into NMAKE when it initiates a build and it is based on my solution configuration. Technically, I have 1 make file calling another and the outer one is setting it like this: TerminalType=$(Configuration). You'll see this variable again below as well as a couple others that are similar.
Next, I define some compiler options
# Switch based on terminal type
!IF "$(TerminalType)"=="eVo"
CompilerCompatibility=-p
DefineTerminalType = -DEVO_TERMINAL
!ELSE
CompilerCompatibility=
DefineTerminalType = -DVX_TERMINAL
!ENDIF
The -D flag defines things in my code as if I had done a #define. This is useful for turning parts on or off depending one what I'm compiling for. Unless you plan to do that, you won't need to do it yourself. The important part here for anyone compiling for eVo terminals is the CompilerCompatibility which sets a -p flag (must be off for Verix V, must be on for for eVo terminals).
Now we consolidate everything we've done thus far into 2 variables:
Includes = -I$(AppIncludes) $(SDKIncludes) $(ACTIncludes) $(VMACIncludes) $(VCSIncludes)
COptions =$(CompilerCompatibility) $(DefineTerminalType)
OK, now here's the part I suspect you are tripping up on: we need to define our dependencies, which I do like so:
# Dependencies
AppObjects = \
$(ObjDir)\$(ProjectName).o \
$(ObjDir)\Base.o \
$(ObjDir)\UI.o \
$(ObjDir)\Comm.o
Libs = $(ACTLibraries)\act2000.a
This could all go on one line, if we wanted to. The \ at the end of each line just means we are breaking that single line up which is done here for readability. Otherwise, it would look like this:
AppObjects = $(ObjDir)\$(ProjectName).o $(ObjDir)\Base.o $(ObjDir)\UI.o $(ObjDir)\Comm.o
Libs = $(ACTLibraries)\act2000.a
OK, so this AppObjects will be used when we do our linking. First, however, I also want to tell NMAKE to run the file signing program and then copy the files over where I want them.
# Sign the file(s). Tell nMake that we also
# will be creating the resource file and compiling the actual code...
# NOTE: (the indentations seen below are required for nMake to work properly)
# pseudoOut depends on TestProject.res and TestProject.out.
# If TestProject.res or TestProject.out have changed more recently than pseudoOut,
# then run commands vrxhdr..., filesignature..., and move...
!if "$(VMACMode)"=="Multi"
pseudoOut : $(ResDir)\$(ProjectName).res $(OutDir)\$(ProjectName).out
!else
pseudoOut : $(OutDir)\$(ProjectName).out
!endif
# This calls vrxhdr: the utility program that fixes the executable program’s header required to load and run the program.
# Vrxhdr is needed when you want to move a shared library around on the terminal.
$(EVOSDK)\bin\vrxhdr -s 15000 -h 5000 $(OutDir)\$(ProjectName).out
# do the signing using the file signature tool and the .fst file associated with this TerminalType.
"$(VSFSTOOL)\filesignature" $(TerminalType)$(VMACMode).fst -nogui
#echo __________________ move files to out directory __________________
# rename the .p7s file we just created
move $(OutDir)\$(ProjectName).out.p7s $(OutDir)\$(ProjectName).p7s
!if "$(VMACMode)"=="Multi"
copy $(ResDir)\imm.ini $(OutDir)\imm.ini
copy $(ResDir)\$(ProjectName).INS $(OutDir)\$(ProjectName).INS
copy $(ResDir)\$(ProjectName).res $(OutDir)\$(ProjectName).res
!endif
#echo *****************************************************************
Now let's define how we will do the linking:
# Link object files
$(OutDir)\$(ProjectName).out : $(AppObjects)
$(EVOSDK)\bin\vrxcc $(COptions) $(AppObjects) $(Libs) -o $(OutDir)\$(ProjectName).out
...and build the .res file...
#This will actually build the .res file. (We only said we were going to do it above)
!if "$(VMACMode)"=="Multi"
# compile resource file
$(ResDir)\$(ProjectName).res : $(ResDir)\$(ProjectName).rck
# SET INCLUDE=$(INCLUDE);$(EVOVMAC)\include;$(EVOVMAC)\template --> I put this into my include path for the project, instead
$(EVOTOOLS)rck2 -S$(ResDir)\$(ProjectName) -O$(ResDir)\$(ProjectName) -M
!endif
and now we can actually run the compilation:
# Compile modules --> -c = compile only, -o = output file name, -e"-" => -e redirect error output from sub-tools to... "-" to stdout. (These are all then redirected via pipe | )
# For more details, see Verix_eVo_volume 3, page 59
$(ObjDir)\$(ProjectName).o : $(SrcDir)\$(ProjectName).c
!IF !EXISTS($(OutDir))
!mkdir $(OutDir)
!ENDIF
-$(EVOSDK)\bin\vrxcc -c $(COptions) $(Includes) -o $(ObjDir)\$(ProjectName).o $(SrcDir)\$(ProjectName).c -e"-" | "$(EVOTOOLS)fmterrorARM.exe"
$(ObjDir)\Base.o : $(SrcDir)\Base.c
$(EVOSDK)\bin\vrxcc -c $(COptions) $(Includes) -o $(ObjDir)\base.o $(SrcDir)\Base.c -e"-" | "$(EVOTOOLS)fmterrorARM.exe"
$(ObjDir)\UI.o : $(SrcDir)\UI.c
$(EVOSDK)\bin\vrxcc -c $(COptions) $(Includes) -o $(ObjDir)\UI.o $(SrcDir)\UI.c -e"-" | "$(EVOTOOLS)fmterrorARM.exe"
$(ObjDir)\Comm.o : $(SrcDir)\Comm.c
$(EVOSDK)\bin\vrxcc -c $(COptions) $(Includes) -o $(ObjDir)\Comm.o $(SrcDir)\Comm.c -e"-" | "$(EVOTOOLS)fmterrorARM.exe"
And that's the last line--there is no other fanfare or what-have-you.
I would like to point something out that you may have noticed, but threw me for a loop when I was getting started on all of this: we kinda' do everything backwards. If I were telling a person how to build the project, I would start by telling them how to compile everything to it's .o file first, but that's the last step in a make file. Next, I would tell a person how to do the linking, but that's the 2nd to last step, and so on.
If you still need more info, visit the link I included--it's way more authoritative than I am and includes a lot of details I probably missed. Hopefully this is enough to get you going, though.
From the docs:
The include directive tells make to suspend reading the current
makefile and read one or more other makefiles before continuing. The
directive is a line in the makefile that looks like this:
include FILENAMES...
FILENAMES can contain shell file name patterns.
Now, given a Makefile:
# we define 'include' from the command-line.
ifdef include
# We create the included Makefile
$(shell echo 'all : ;' >makefile.include)
# And we include it.
# The docs say: "FILENAMES can contain shell file name patterns."
include *.include
else
endif
Running, we get:
$ rm -rf makefile.include && make include=1
makefile:6: *.include: No such file or directory
So, what happened here? We clearly had:
Created a Makefile to be included, in:
$(shell echo 'all : ;' >makefile.include)
And later included this makefile, given that we can using "shell file name patterns", as quoted above from the documentation - and thus, we have in the makefile:
include *.include
So, why did Gnu-Make failed to find this newly-created makefile?
The problem you are facing is not of inclusion, but of order of execution.
make is not a procedural language, but instead a declarative one, so order-of-execution sometimes gets a bit tricky.
In your specific case, make will parse the entire Makefile in the first pass, including the include statements, resulting in an erroneous Makefile, since there is no makefile.include yet.
It will then execute the shell command to create the makefile.include (but again it is too late: inclusion would have happened before).
A second run of make will then correctly include the makefile.include.
Note:
The same is true for both directly using include *.include and include $(wildcard *.include) but only the former will result in an error (since the latter will expand the *.include to an empty set which will then (not) be included, whereas the former will try to include the literal *.include - similar to a stray cat *.nonexistent on the shell).
The following is a makefile I encountered in Postgres, I don't understand how it works. I saw some simple Makefile examples where they have commands to compile, but this one seems to be different. Could anyone explain how this makefile works? Basically I need to understand this one before I modify it for my purpose.
subdir = src/backend/access/transam
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
OBJS = clog.o multixact.o \
xlogreader.o xlogutils.o
include $(top_srcdir)/src/backend/common.mk
xlog.o: xlog.c $(top_srcdir)/src/include/catalog/catversion.h
Please let me know if you need more information.
Thanks.
subdir = src/backend/access/transam
top_builddir = ../../../..
Set some variables
include $(top_builddir)/src/Makefile.global
Include a global makefile (presumably uses the two previously set variables in some way).
OBJS = clog.o multixact.o \
xlogreader.o xlogutils.o
Create an OBJS variable for the things to be built in this directory (I assume).
include $(top_srcdir)/src/backend/common.mk
Include another makefile (which presumably uses OBJS and defines rules/flags/etc. for building files).
xlog.o: xlog.c $(top_srcdir)/src/include/catalog/catversion.h
Explicitly handle prerequisites to the xlog.o target file (presumably because putting this in OBJS would do something undesirable).
For more about what subdir or OBJS is used for exactly (or what else you can set in this file) you would need to read and understand src/Makefile.global and src/backend/common.mk.
I have linked a ".c" file to another one. ld doesn't return any error but the compiler can't find included header files in this ".c" file and returns this error:
../libvmi/driver/xen.c:27:20: fatal error: libvmi.h: No such file or directory
Here is the Makefile of my project:
## Source directory
SUBDIRS =
INCLUDES = -I$(top_srcdir) $(top_srcdir)/libvmi
AM_LDFLAGS = -L$(top_srcdir)/libvmi/.libs/ $(top_srcdir)/libvmi/driver $(top_srcdir)/libvmi/libvmi.h
LDADD = -lvmi -lm $(LIBS) $(top_srcdir)/libvmi/driver/xen.c $(top_srcdir)/libvmi/libvmi.h
bin_PROGRAMS = module-list process-list map-symbol map-addr dump-memory
module_list_SOURCES = module-list.c
process_list_SOURCES = process-list.c
map_symbol_SOURCES = map-symbol.c
map_addr_SOURCES = map-addr.c
dump_memory_SOURCES = dump-memory.c
As you see above I thought I should add "$(top_srcdir)/libvmi" to "INCLUDES"; this is the directory that libvmi.h is located.
The original Makefile is:
## Source directory
SUBDIRS =
INCLUDES = -I$(top_srcdir)
AM_LDFLAGS = -L$(top_srcdir)/libvmi/.libs/
LDADD = -lvmi -lm $(LIBS)
c_sources = process-list.c $(top_srcdir)/libvmi/driver/xen.c
bin_PROGRAMS = module-list process-list map-symbol map-addr dump-memory
module_list_SOURCES = module-list.c
process_list_SOURCES = $(c_sources)
map_symbol_SOURCES = map-symbol.c
map_addr_SOURCES = map-addr.c
dump_memory_SOURCES = dump-memory.c
I have modified it to link "libvmi/driver/xen.c" to process-list.c file which are located in different directories.
This is because of something's wrong in Makefile, yes?
Add a -I to the path you added. Note this is a compiler, not linker question
The reason ld doesn't return an error is because it is not invoked. The error message you are getting is coming from the compiler, and the loader is not invoked until the compiler is successful.
Yes, you do need to add $(source_dir)/libvmi to INCLUDES; you just need to do it symmetrically with the existing entry:
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/libvmi
Note the -I preceding the directory name. You have a similar problem in AM_LDFLAGS and LDADD:
AM_LDFLAGS = -L$(top_srcdir)/libvmi/.libs/ -L$(top_srcdir)/libvmi/driver
LDADD = -lvmi -lm $(LIBS)
but you do not want to add the header file $(top_srcdir)/libvmi/libvmi.h to the load flags. Headers are not libraries; headers are not appropriate for sending to the linker/loader. You should only supply the linker/loader with object files, libraries, and options — no source files, no headers.
That more or less deals with the surface issues. What is the real problem you are trying to solve?
If you need to link with code from a library built in libvmi directory, why don't you make the dependency changes in this makefile to pick up the library from the libvmi directory (and separately run the build for the library in the libvmi directory)? Or, if you really want to do the compilation in the current directory (but why?), create links to the libvmi files locally (or copy them; no, on second thoughts, don't copy them), and compile them locally? Mixed directory working is painful at best — and to be avoided when possible, which it almost always is.
I note that the original makefile does in fact include -lvmi on the link line, so what I outlined is what you're expected to use. Why isn't that working for you? This is very much an XY Problem. I recommend reworking the question so that you get a solution to the real problem you started out with, rather than the artificial problem you ran into attempting to solve the real problem in a misguided way.
I have a C project that has the following structure
Main/
Makefile.am
bin/
src/
Makefile.am
main.c
SomeLibrarySource/
SomeFuncs.c
SomeFuncs.h
The main.c contains the main function that uses functions defined in the SomeFuncs.{h/c} files.
I want to use autotools for this project. I read a couple of resources on autotools. But, I was only able to manage using autotools for a single level project where all source, object and other files reside in the same directory.
Then I got some links that talked about using autotools for deep projects like this one and then I got confused.
Right now I have two Makefile.am as follows
Makefile.am
SUBDIRS=src
src/Makefile.am
mainprgdir=../
mainprg_PROGRAMS=main
main_SOURCES=main.c
I am pretty sure that these files should not be as I have them now :P
How do I use autotools for the above project structure? (At least what should be there in those Makefile.am(s) and where should I place them.
EDIT:
One more thing! At the end I would like to have the object files created in the bin directory.
Thanks
mainprogdir=../ does not make a whole lot of sense (you don't know what it is relative to on installation). Probably intended:
# Main/Makefile.am
# .━━ target for `make install`
# |
# ↓ ↓━━ target for compilation
bin_PROGRAMS = bin/main
# ↓━━ based upon compilation target name
bin_main_SOURCES = src/main.c
There are two main approaches. If the functions in SomeLibrarySource are used only by main, then there's no need to build a separate library and you can simply specify the source files in src/Makefile.am
main_SOURCES = main.c SomeLibrarySource/SomeFuncs.c
However, if you actually want to use the functions in other code in your tree, you do not want to compile SomeFuncs.c multiple times but should use a convenience library.
# Assigning main_SOURCES is redundant
main_SOURCES = main.c
main_LDADD = SomeLibrarySource/libSomeFuncs.a
noinst_LIBRARIES = SomeLibrarySource/libSomeFuncs.a
AM_CPPFLAGS = -I$(srcdir)/SomeLibrarySource
(You'll need AC_PROG_RANLIB in configure.ac to use convenience libraries.)
If the source file is named SomeFuncs.c, automake will not need Makefile.am to specify SomeLibrarySource_libSomeFuncs_a_SOURCES, but if the name of the source code file does not match the name specified in noinst_LIBRARIES, SomeLibrarySource_libSomeFuncs_a_SOURCES should be set to the list of files used to build the library. Note that you do not need to specify main_SOURCES, since main.c is the default value if left unspecified (but it's not a bad idea to be explicit.) (In all of this, I am not comfortable use CamlCase names, but the system I'm using uses a case insensitive file system (biggest mistake apple ever made) and the examples I give here are working for me. YMMV)
You could of course do a recursive make, or build the library as a separate project and install it. (I like the final option. Libraries with useful features should exist on their own.)