Version matching in makefile - makefile

I am new to make. Suppose I have a makefile which has atarget, the target will kick off different compile command base on the version: From version 1.x.x to version 3.x.x, it will kick off command 1. While version 4.x.x or above, it will kick off command 2.
run-%: %.txt
<if %.txt is in between 1.x.x and 3.x.x, kick off command 1 with %.txt as input>
<else kick off command 2 with %x.txt as input>
User will run it like this:
make run-2.2.0
Does make provide some sort of pattern matching?

There is nothing like glob's [1-3] if that's what you mean by "pattern matching". All you can do is write multiple rules unfortunately:
run-1.%: 1.%.txt
<command1>
run-2.%: 2.%.txt
<command1>
run-3.%: 3.%.txt
<command1>
run-%: %.txt
<command2>

Related

How to block "make" command in makefile

I write makefile, which structure like following
#... Configure basic flags for compiler
.PHONY: mk_mingw
mk_mingw:
# build with mingw(windows)
.PHONY: mk_gcc_linux
mk_gcc_linux:
# build in gcc(linux)
#... some auxiliary unit such as clear, test ...
Use the following command when building with mingw(windows)
#command 1
$ make mk_mingw
Use the following command when building with gcc(Linux)
#command 2
$ make mk_gcc_linux
I hope the above two commands are legal in my project.
mk_gcc_linux and mk_mingw are environment of compiler(I specified)
But following commands isn't:
#command 3
$ make
Because it's not specify environment of compiler after make command.
I want make to report an error and stop when this situation(command 3) happens.
How do I do in my makefile?
By default, make tries to build the very first target. So you can simply put this on top of your Makefile:
.PHONY: first
first:
#echo Environment not specified!
#false
# the rest of file is following...
But for me it doesn't look quite right. Probably, setting a variable, instead of a dedicated target, is better.

OpenCobol Makefile

I am trying to compile an OpenCobol program using make. I am always getting "make: Nothing to be done for test1.cob". Here is my makefile. I had put a TAB before cobc. But still I am getting that message. Please help.
Thanks.
COBCWARN = -W
%: %.cob
cobc $(COBCWARN) -free -x $^ -o $#
And here is my cobol program.
IDENTIFICATION DIVISION.
PROGRAM-ID. TEST1.
PROCEDURE DIVISION.
DISPLAY 'Hello world!'.
STOP RUN.
Your makefile contains no actual targets. You have defined only a pattern rule which tells make how to build targets that match the pattern. But make doesn't go looking for targets out on the filesystem that could match the pattern, it only checks the pattern against targets that have been specifically requested.
You don't have any specific targets (files) listed in your makefile, so the only way make can know about a target is if you give the target to be built on the command line.
You are running this command from within vim, using the % special token, which expands to the name of the file currently being edited. That means you are running the command:
make test1.cob
because you are editing the file test1.cob. So, you are telling make "please try to create the target (file) test1.cob". But, that file already exists (it's the file you're writing). So make says "nothing to do".
If you run make and ask it to create the target you really want created, it will work:
make test1
Now the file test1 doesn't exist, and make can find a pattern rule that knows how to build it, so make will run that rule.
Alternatively, you can edit your makefile to add the specific target, like this:
COBCWARN = -W
test1: test1.cob
%: %.cob
cobc $(COBCWARN) -free -x $^ -o $#
Then you can run make with no arguments at all. Without any command line arguments, make will look in the makefile for explicit targets and find test1 as the first one. It sees that there is a rule (the pattern rule) that matches that target, so it will build that target.
UPDATE
If you want to allow a simple command make to build multiple programs, write your makefile like this:
COBCWARN = -W
all: test1 test2 test3
.PHONY: all
%: %.cob
cobc $(COBCWARN) -free -x $^ -o $#
Now from vim you can just say :!make and that's it.
If you run make with no arguments then it will find the first explicit target in the makefile and build that. In this example the first target is all, and its prerequisites are the possible programs to build. To build each one make sees that it can apply the pattern rule, and so it will do so (if the .cob file has been modified since the last time the program was built).

Makefile: what is "#-"?

In a makefile I use there is #-, that is not mentioned in any makefile tutorial I could find.. Could you please explain what #- is for?
For example:
#- $(RM) *.o
The at-sign # tells Make to not print the command line before executing it.
(Manual: Recipe echoing)
The minus sign - tells Make to ignore the result of the command and not fail the target if it was unsuccessful.
(Manual: Errors in recipes)
In your case it's just both of them being used, because somebody did not want to pollute the output with the erase command, and did not want to fail the build if anything goes wrong with the deletion either.

Makefile - Deduce targets from sources (on iSeries system)

On an IBM i system, using PASE (AIX emulator), i try to compile RPG sources using a makefile.
I have RPG sources and try to build a PGM program.
Every single source will be compile in a distinct PGM.
Here is the syntax i tried first
VPATH=.
SYSTEM=system -iv
CRTRPGMOD=CRTRPGMOD
BIN_LIB=MR_CH
CURRENT_PATH=/currentPath #${PWD} doesn't work
#With this line active, it works
SRC_RPGLE = src1.rpgle src2.rpgle
#With this line active, it doesn't work
#SRC_RPGLE = $(shell echo *.rpgle) #Should list every sources i want to compile
TARGETS = $(SRC_RPGLE:.rpgle=.rpgleMod) #Should list every program i want to build
.SUFFIXES: .rpgle .rpgleMod
.rpgle.rpgleMod:
$(SYSTEM) "$(CRTRPGMOD) MODULE($(BIN_LIB)/$(*F)) SRCSTMF('$(CURRENT_PATH)/$<')" > $(*F)_1_crtrpgmod.log
ln -fs $(*F).rpgMod
all: $(TARGETS)
I tried to apply GNU shell syntax using AIX make command
Any suggestions ?
I'm not familiar with the AIX implementation of make but assuming that the linked man page is all there is to it, then it looks like a bare-bones implementation of POSIX make (for an older POSIX spec).
Therefore, the only way to do what you want (expand a list of files) is to use recursion, so that you get access to the shell, like this:
SYSTEM=system -iv
CRTRPGMOD=CRTRPGMOD
BIN_LIB=MR_CH
CURRENT_PATH=/currentPath
CURRENT_PATH=/home/CHARLES/Projets/MRSRC/tmp
recurse:
$(MAKE) all SRC_RPGLE="`echo *.rpgle`"
TARGETS = $(SRC_RPGLE:.rpgle=.rpgleMod)
.SUFFIXES: .rpgle .rpgleMod
.rpgle.rpgleMod:
$(SYSTEM) "$(CRTRPGMOD) MODULE($(BIN_LIB)/$(*F)) SRCSTMF('$(CURRENT_PATH)/$<')" > $(*F)_1_crtrpgmod.log
ln -fs $(*F).rpgMod
all: $(TARGETS)
The recurse rule MUST be the first target in the makefile. Also this won't help if you want to run other targets like make foobar; it will only help you run all properly.
Alternatively you can obtain GNU make and build it for your system, and use that. In the end that might be a more straightforward approach.

Adding comments to Makefile

How do I add comments (with echo) in a Makefile so that they're printed when ran?
You should use
target:
#echo "Building!"
Note the #, which tells Make not to display the command itself. Without this the output would look like:
echo "Building!"
Building!
Or, since Make just pushes whatever is in a rule to bash, you could just use a pound to have bash treat it as a comment.
Rule: Dependencies
# Your Comment
Command
Will output
$ make Rule
# Your Comment
Command
all :
echo "Building!"
$(CC) $(OBJECTS) $(LPATH) $(LIBS) -o $(PROGRAM)
Visual C++ nmake has the !message text... preprocessing directive. I have not used GNU make, so I don't if it has it as weel, but quick search shows it has the $(info text...) function.
And inside command blocks you can use echo.
Since a makefile mostly contains commands to be run when building specific targets, I'd say you use just that: echo.

Resources