I'm working on a project with the Dialogic DivaSDK to be able to analyze telephone calls. Since the DivaSDK supports Java via JNI, I wanted to give the samples a try. Unfortunately: the whole Java documentation is not as complete as the C# one is. So it seems to be like fishing in murky waters.
In my first step I wanted to look into the sample ( Link to DivaSDK with Sample Files )files and try them out. Each sample has a makefile which has to be run. The only part within the manual which scratches my problem sounds like this:
For details how to compile and link your application please have a look at any of the samples provided with the Diva SDK. In every sample subdirectory you will find a makefile, that describes the compilation and link process of that application. The evaluation of the makefile requires some knowledge of shell scripting and makefile syntax and is beyond the scope of this document.
My problem right now is that the given makefile doesn't work the way it is supposed to be. I get the error "No Targets" Since I have not that much knowledge of makefiles, I can't figure out what is wrong with that file.
#-------------------------------------------------------------------------------
#
# makefile to geenrate the Diva SDK Java sample "SimpleApp". This makefile
# generate the class files for teh framework and the sample and creates
# a SimpleApp.jar that can be executed via jav -jar SimpleApp
#
# The makefile assumes that the java development enmvironment is installed and
# the java tools are accessable from the command prompt.
#
#-------------------------------------------------------------------------------
FRAMEWORK_PATH=..\..\Framework
FRAMEWORK=$(FRAMEWORK_PATH)\DivaAPI.java $(FRAMEWORK_PATH)\DivaCallBase.java
BIN_DIR=.\bin
SRC_DIR=.\src
TRAGET=SimpleApp
#edited with hint from #Aaron Digulla
all : $(BIN_DIR)\$(TRAGET).jar
SRC=$(SRC_DIR)\SimpleApp.java \
$(SRC_DIR)\AppCall.java
$(BIN_DIR)\$(TRAGET).jar: $(SRC)
#echo #-----------------------------------------------
#echo # Generate class files
#echo #-----------------------------------------------
javac -d $(BIN_DIR) -sourcepath $(FRAMEWORK_PATH) $(FRAMEWORK) $(SRC)
#echo #-----------------------------------------------
#echo # Generate jar files and clean class and manifest
#echo #-----------------------------------------------
copy $(SRC_DIR)\manifest.txt $(BIN_DIR)
cd $(BIN_DIR)
jar -cvfm $(TRAGET).jar manifest.txt *.class > nul
del *.class
del manifest.txt
cd ..
#echo #-----------------------------------------------
#echo # $(BIN_DIR)\$(TARGET).jar successfully created
#echo #-----------------------------------------------
It seems, that the target definition is wrong, but I don't know in which way. Any tips would be very much appreciated.
edit1: With the hint from #Aaron Digulla it works a little bit better. At least the target is recognized. But now there is an error which tells me, that there are no rules to create the jar.
edit2: Well... It seems that the filepaths are wrong. If I replace some of the backslashes ( "\" ) with normal slashes ( "/" ), the compiling starts. It stops at copy though...
The error means there is no target all in the Makefile and make cowardly refuses to continue.
My guess is that this Makefile is supposed to be called from another Makefile.
Add this line to the Makefile:
all : $(BIN_DIR)\$(TRAGET).jar
and it should work. If the error persist, make sure you use GNU make or try make all
Related
i'm working on a project requiring cmake. i'd like to add some custom rules to my makefile, but can't quite get my head around how to do it.
both c source files and header files are in the same directory. also in this same directory are a number of .def files, which are the sources for some of the header files #included in the source during compilation.
if i were to do this in a makefile, i'd use a simple rule like
.SUFFIXES: .def
.def.h:
$(PREPROC) $< > $#
how can i do this with cmake ??
i've tried various permutations of the following, both with and without cmake working directory specifications :
add_custom_command(
OUTPUT vvr_const.h
PRE_BUILD
COMMAND preproc vvr_const.def > vvr_const.h
DEPENDS vvr_const.def
)
add_custom_target(vvr_const.h DEPENDS vvr_const.def)
but the header file isn't generated by the time the c source file is compiled, so the compile fails. i've also tried a variation where i replace the last line above with
set_property(SOURCE main.c APPEND PROPERTY OBJECT_DEPENDS vvr_const.h)
in this case, the header file is correctly generated in advance, but make can't find it, and complains that there's no rule to make the target .h.
ideally this would be a general rule, like the make rule above, but i'm not opposed to making a separate rule for each of the .def files if that's what it takes.
cheers.
There are 2 problems with the add_custom_command approach you present:
You did not specify a working directory; by default the command is run in the build directory, not in the source directory.
You rely on shell functionality here (the redirect to a file). Even though this probably still works. You should go with an approach that does not rely on the shell.
To solve issues 1 and 2 I recommend creating a seperate cmake script file receiving the absolute paths to input and output files and using those in the custom command. This allows you to use execute_process to specify the file to write without relying on the platform.
preprocess_def.cmake
# preprocess def file
# parameters INPUT_FILE and OUTPUT_FILE denote the file to use as source
# and the file to write the results to respectively
# use preproc tool to get data to write to the output file
execute_process(COMMAND preproc "${INPUT_FILE}"
RESULT_VARIABLE _EXIT_CODE
OUTPUT_FILE "${OUTPUT_FILE}")
if (_EXIT_CODE)
message(FATAL_ERROR "An error occured when preprocessing the file ${INPUT_FILE}")
endif()
CMakeLists.txt
set(_INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vvr_const.def")
set(_OUTPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vvr_const.h")
# not necessary to use build event here, if we mark the output file as generated
add_custom_command(OUTPUT "${_OUTPUT_FILE}"
COMMAND "${CMAKE_BUILD_TOOL}" -D "OUPUT_FILE=${_OUTPUT_FILE}" -D "INPUT_FILE=${_INPUT_FILE}" -P "${CMAKE_CURRENT_SOURCE_DIR}/preprocess_def.cmake"
DEPENDS "${_INPUT_FILE}")
add_executable(my_target vvr_const.h ...)
set_source_files_properties(vvr_const.h PROPERTIES GENERATED 1)
Documentation from cmake:
PRE_BUILD
On Visual Studio Generators, run before any other rules are executed within the target. On other generators, run just before PRE_LINK commands.
So possibly your command is just running too late.
I have a verifone terminal (vx520 and vx820).
I whant to crate a makefile for compile app for this terminal.
I have "VRXSDK" version 1.2.0
howto do it?
or how to compile a file like "main.c" or "main.cpp" till have a execute file for verifone POS terminal
Wherever you got your "VRXSDK" from, you should also be able to get some sample project files. You will find a make file in there (likely with a .smk extension). I would recommend you start with that and as you read through it, that should give you more specific questions to ask and things you can look up using your favorite search engine.
A make file is, in essence, a program that invokes the compiler with input parameters you determine based on various factors. It will also invoke the linker to tie it all together. How you go about this varies wildly from one implementation to another, so "How do I create a make file" is just about as broad as "how do I write a program?" which makes answering it here rather challenging. However, to get you started...
I use Visual Studio as my IDE and I am using NMake. I actually have 2 layers of make files. The outer layer is what is called when I say "build" from my IDE and it is very short:
# Pick one of the following (for LOG_PRINTF messages)
#CompileWithLogSys = -DLOGSYS_FLAG
CompileWithLogSys =
all:
$(MAKE) /i /f coreBuild.smk /a TerminalType=$(Configuration) CompileWithLogSys=$(CompileWithLogSys) VMACMode=Multi
$(MAKE) /i /f coreBuild.smk /a TerminalType=$(Configuration) CompileWithLogSys=$(CompileWithLogSys) VMACMode=Single
Lines starting with # are comments.
This outer file makes it really easy for me to toggle a few things when I want to build different variations. You can see that I have turned OFF compliation with LogSys. The more important thing the 2-layer approach gives me is an easy way to compile 2 different versions with a single command to build. This runs nmake with "VMACMode" set to "Multi" and then runs it again with it set to "Single". The inner make file will see that parameter and compile to a different root folder for each so in the end I wind up with 2 folders, each with a different version.
You can do a web search on "nmake parameters" to see what things like /i and /f do, as well as other options I'm not using here. However, I would like to direct your attention to TerminalType=$(Configuration). In Visual Studio, you can select from a dropbox if you want "Debug" or "Release". Those 2 options are the default options, but you can change them; in my case, I have modified them to "eVo" and "Vx". Now I just select in my drop down box which version I want to compile for and that gets passed in. Alternately, I could just hard code both into my outer make file. That's just preference.
My inner make file (which is named "coreBuild.smk") gets much more interesting.
Generally, you start by defining variables, such as "include paths":
# Includes
SDKIncludes = -I$(EVOSDK)\include
ACTIncludes = -I$(EVOACT)include
VCSIncludes = -I$(EVOVCS)include
EOSIncludes = -I$(EOSSDK)\include\ssl2
And/Or libraries:
#Libraries
ACTLibraries = $(EVOACT)OutPut\RV\Files\Static\Release
#Others you may want to include, but I am not using:
#LOGSYSLibraries = $(EVOVMAC)\Output\RV\Lib\Files\Debug
#EOSLibraries = $(EOSSDK)\lib
As well as the path(s) to your files
# App Paths
AppIncludes = .\include
SrcDir = .\source
ObjDir = .\obj
OutDir = .\Output\$(TerminalType)\$(VMACMode)\Files
ResDir = .\Resource
I also like to define my project name here:
ProjectName = MakeFileTest
Note that OutDir uses the TerminalType and VMACMode that we passed in in order to go to a unique folder.
Next, you would generally set your compiler options
# Compiler Options
# Switch based on terminal type
!IF "$(TerminalType)"=="eVo"
CompilerCompatibility=-p
DefineTerminalType = -DEVO_TERMINAL
!ELSE
CompilerCompatibility=
DefineTerminalType = -DVX_TERMINAL
!ENDIF
# Switch based on Multi or Single mode (VMACMode)
!if "$(VMACMode)"=="Multi"
VMACIncludes = -I$(EVOVMAC)include
DefineMulti = -DMULTI_APP_ENABLED
!else
VMACIncludes =
DefineMulti =
!endif
An interesting thing to note above is the -DMULTI_APP_ENABLED. The program I wrote has some blocks that are dependent on #ifdef MULTI_APP_ENABLED. This is not any special name--it's just one I came up with, but the compiler will define it right before it starts compiling my code, so I can turn those code blocks on and off right here.
Next, we are going to kinda' gather everything together. We will start by defining a new var, "Includes" and it will have the flag "-I" (to indicate "include" and then all the things we said above that we wanted to include:
Includes = -I$(AppIncludes) $(SDKIncludes) $(ACTIncludes) $(VMACIncludes) $(VCSIncludes)
Note that you could just type everything long hand here and not go through the extra steps of defining the vars in the first place, but it makes it easier to read, so I think this is pretty normal.
We do pretty much the same thing with compiler options, although note that the specific flags (ex, "-D" "-p") were already included in the original var declarations, so we leave them out here:
COptions =$(CompilerCompatibility) $(CompileWithLogSys) $(DefineTerminalType) $(DefineMulti) -DDEV_TOGGLES_FOR_SYNTAX
Next we set a variable that will tell the linker where the object files are that it needs to stitch together. Note that if you insert new lines, as I have, you need the '\' to tell it that it continues on the next line
# Dependencies
AppObjects = \
$(ObjDir)\$(ProjectName).o \
$(ObjDir)\Base.o \
$(ObjDir)\printer.o \
$(ObjDir)\UI.o \
$(ObjDir)\Comm.o
We will also set one for any libaries we want to link in:
Libs = $(ACTLibraries)\act2000.a
OK, next we have to sign the file(s). We are trying to tell nMake that we also will be creating the resource file and compiling the actual code.
If we are doing a multi-app build, then pseudoOut depends on the .res and the .out files. If not, then it just depends on the .out, because there is no .res. If the the dependent file(s) has/have changed more recently than pseudoOut, then run commands vrxhdr..., filesignature..., and move... NOTE that the indentations seen below are required for nMake to work properly.
!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 *****************************************************************
Note that the "echo" commands are just to help me read my output logs, as needed.
OK, now we link.
"WAIT!" I can hear you saying, "We haven't compiled yet, we already issued a command to sign, and now we are linking? This is totally out of order!" Yes and no. We haven't actually issued the command to sign yet, we have merely told nmake that we may want to do that and how to do it if we decide so to do. Similarly, we aren't issuing the command to link yet, we are just telling nmake how to do it when we are ready.
# Link object files
$(OutDir)\$(ProjectName).out : $(AppObjects)
$(EVOSDK)\bin\vrxcc $(COptions) $(AppObjects) $(Libs) -o $(OutDir)\$(ProjectName).out
Remember that mutli-app programs need a .res file. Single apps don't. The following will actually build the .res file, as needed.
!if "$(VMACMode)"=="Multi"
# compile resource file
$(ResDir)\$(ProjectName).res : $(ResDir)\$(ProjectName).rck
$(EVOTOOLS)rck2 -S$(ResDir)\$(ProjectName) -O$(ResDir)\$(ProjectName) -M
!endif
Remember those AppObjects? We are finally ready to make them. I'm using the following flags
-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 | )
Again, wherever you got your VRXSDK, you should also be able to get some documentation from VeriFone. See "Verix_eVo_volume 3", page 59 for more details on the flags
$(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)\myprinter.o : $(SrcDir)\printer.c
$(EVOSDK)\bin\vrxcc -c $(COptions) $(Includes) -o $(ObjDir)\printer.o $(SrcDir)\printer.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"
Is there a way to let make determine the number of files to be recompiled before actually compiling? The problem is this: Consider having a quite big project with hundreds of source files. It would very convenient to have a rough idea of how long compilation will take, but to know that, one needs to know the number of files to be compiled.
The general answer is no, because your build could generate files which themselves are inputs to other rules which generate more files. And so on. However if a rough answer is good enough you can try the --dry-run flag. From the GNU make documentation...
“No-op”. Causes make to print the recipes that are needed to make the targets up to date, but not actually execute them. Note that some recipes are still executed, even with this flag (see How the MAKE Variable Works). Also any recipes needed to update included makefiles are still executed (see How Makefiles Are Remade).
As you can see, despite its name even the --dry-run flag will change the state of your build.
"make -n" will do the dry run. But you can't get the list of files to be rebuilt. May be you can write shell script to store the last modified time of files and get the list of files.
I think a found a decent solution for unix. Here SRC are your source files, HDR your headers and DEP the dependency files (something like DEP:=$(OBJ:.o=.d) )
isInDepFile+=$(shell grep -q $(modifiedFile) $(depFile) 1>&2 2> /dev/null && echo $(depFile))
COMPFILES=
checkDepFiles=$(foreach depFile,$(DEP), $(eval filesToCompile+=$(isInDepFile))) $(thinOutDepFiles)
thinOutDepFiles=$(foreach fileToCompile,$(filesToCompile),$(eval DEP=$(filter-out $(fileToCompile),$(DEP))))
countFilesToCompile: $(SRC) $(HDR)
$(eval modifiedFiles=$?)
$(foreach modifiedFile,$(modifiedFiles), $(call checkDepFiles))
$(eval numOfFilesToCompile = $(words $(filesToCompile)))
$(eval numDepFiles = $(words $(DEP)))
$(eval NumSRCFiles = $(words $(SRC)))
#echo $(NumSRCFiles) sources
#echo $(numDepFiles) files to leave
#echo $(numOfFilesToCompile) files to compile
#touch $#
This first generates a list of modified files within your source and header files lists. Then for each modified file it checks all dependency files for its filename. If a dependency file contains the current file we are looking at, it is added to the list of filesToCompile. It is also removed from the list of dependency files to avoid duplication.
This can be invoked in the main building rule of your project. The advantage of that over the dry run is that it gives you a simple number to work with.
For some reason make is recompiling the source files that are outside my
project tree every time. I don't normally have such files, but I noticed it while I was testing this Makefile and I would like to understand why. It behaves normally with respect to the source files inside my project tree. Here are my rules. First I have a function
src_to_obj = $(basename $(addprefix $(build_dir)/,$(1))).o
Then I populate the list of program_objects by calling foreach on the list of sources and applying the above function to each one.
$(bin_dir)/$(program_name): $(program_objects)
$(linker) $(link_flags) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH) \
$^ $(OUTPUT_OPTION)
define build_template =
$$(call src_to_obj,$(1)) : $(1) $$(call dependency_file,$(1))
// make dependency and build directories
$$(compile) $$(OUTPUT_OPTION) $$<
// rename dependency
endef
$(foreach source,$(program_sources),\
$(eval $(call build_template,$(source))))
As I said, this works just fine for the source files in the project directory. For example, the Makefile lives in ~/Projects/foo and most of the source code is in ~/Projects/foo/src. But if I pull in a file A.cc from the home directory,then that file is recompiled every time I run make.
EDIT:
Following Mad-Scientists suggestion, I ran make -d and examined the output. That made the problem clear. Basically, if I feed this a source file ~/bad.cc, then the rule looks like:
build/~/bad.o : ~/bad.cc .deps/~/bad.d
...
However, my script for the rule is creating the file .deps/home/jim/bad.d. Therefore, every time I run make the dependency file is "not there" and the object file has to be remade. I am using the exact same expressions to refer to the file name in the script. However I am guessing that the shell is expanding the ~ to /home/jim. So somehow I have to escape the ~ in the recipe. Thanks to Mad Scientist for pointing out the -d option for make.
I don't have time to make a short self contained correct example right now, but if I can't solve this problem I will come up with one and post it here later.
EDIT EDIT:
So I solved the problem with the following hack:
program_sources = $(shell echo $(program_sources))
This pre-expands all names so that they are never different in the shell.
The problem: i want to echo some info when make makefile, the makefile is generated by CMakeLists.txt, and i don't want to echo the info when cmake CMakeLists.txt, what should i do?
In Makefile, the code is like this:
.build-pre:
#echo
#echo "###########################################################"
#echo "######## Welcome to Prosim Build System ###################"
What should i wirte in the CMakeLists.txt so that i can get like these in MakeFile?
You can use add_custom_target function to create a dummy target that has dependencies set to all other targets causing it to be built first.
You can use the ALL option to make it build every time. However, you will still need to use add_dependencies to make it build before every other target.
Finally, use the command-line tool mode of CMake to make it platform independent. (The COMMENT option of add_custom_target may be enough to show the message).
add_custom_target(display_intro ALL COMMAND cmake -E echo Foo)
# ....
add_executable(your_app ...)
add_dependencies(your_app display_intro)
add_library(your_lib ...)
add_dependencies(your_lib display_intro)
For convenience, you could probably wrap the add_executable and add_dependencies in a function or macro.