text = bump(permission): nameservice - version v0.0.20
Example, I have a string like the above text variable. I want to get a sub word from text such as:
word 1: permission, it is a word in pattern bump(%s)
word 2: nameservice, it is a word in pattern : %s -
word 3: v0.0.20, it is a word last of string.
I want to write a Makefile to get substring as required above. Please help me with this problem.
Thanks so much.
GNU make has several text processing functions that can help. But as your problem is not completely specified it's difficult to propose solutions. I will assume that your text matches regular expression ^bump\((\S+)\): +(\S+) +-.* (\S+)$ and that the 3 words you are interested in are \1, \2 and \3. If it is not the case, please edit your question and provide a complete specification.
text = bump(permission): nameservice - version v0.0.20
word1 := $(patsubst bump(%),%,$(word 1,$(text)))
word2 := $(word 2,$(text)))
word3 := $(lastword $(text))
The GNUmake table toolkit is, despite its name, also able to split strings in the way you want:
include gmtt/gmtt.mk
text = bump(permission): nameservice - version v0.0.20
text_list = $(call glob-match,$(text),bump(*): * - version *)
$(info original text: <<$(text)>>)
$(info after glob-match: <<$(text_list)>>)
$(info specific parts: $(word 2,$(text_list)))
$(info $(word 4,$(text_list)))
$(info $(word 6,$(text_list)))
Output:
$ make
original text: <<bump(permission): nameservice - version v0.0.20>>
after glob-match: <<bump( permission ):§ nameservice §-§version§ v0.0.20>>
specific parts: permission
nameservice
v0.0.20
The § characters are space characters in the original string; the latter don't play well with GNUmake lists, so during internal operations they need to be kept replaced and in some circumstances it is best to even return them to the user in this form. Most of the time one can safely ignore them or you get rid of them with $(call spc-unmask,...) if they would get in the way later.
Related
I have a makefile somewhat like this.
I need to generate a file and move that as abc.cpp (Basically get rid of anything after underscore including underscore
xyz:= abc_def
$(xyz):
(some commands here which generates a file)
mv file /tmp/$(patsubst _%,"",$#)
However this does not work. In fact it doesn't ever match the underscore "_" in $#
mv file /tmp/abc.cpp is what i want
How does the "%" wildcard work in patsusbst?
The patsubst function won't work for you, because it can match only ONE pattern. You want to match two patterns: anything before the _ and anything after the _. $(patsubst _%,...) only matches words that begin with _, and your word abc_def doesn't begin with _, so the patsubst is a no-op.
To do what you want using GNU make functions you need to play a trick; something like:
mv file /tmp/$(firstword $(subst _, ,$#))
This splits the string into words by changing the _ to space, then takes the first word.
If you don't shy away from using helper code (i.e. include a GNUmake library) then the GNUmake table toolkit surely can do the trick:
include gmtt.mk
xyz:= abc_def
$(xyz):
(some commands here which generates a file)
mv file /tmp/$(firstword $(call glob-match,$#,*_*)).cpp
The glob-match function splits a string in streaks of matching elements, where every glob character (*,?,[...]) and verbatim string portions (in your case just the _) constitute one match. Or simply said, $(call glob-match,this_is_a_string,*_is_a_*) splits this_is_a_string into a list this _is_a_ string (notice the spaces).
I'm trying to print out the perforce file version of the make file when it's executed. I'm using the $Id$ tag, which expands to $Id: //repository/path/check.make#6 $ or the like and I want to print //repository/path/check.make#6 to a file (currently using echo). I can't figure out how to get make to take the # as part of the string and not the beginning of a comment. I tried:
str1 = $(subst \#,\\\#,'$Id: //repository/path/check.make#6 $')
and other variations but I keep getting:
unterminated call to function `subst': missing `)'. Stop.
It would help if you provided a full example of what you want. I don't really understand why you're trying to subst a hash with a backslash hash. If you showed us a full example, including how you get the string and also what you want to do with the variable ar1, we could actually give you advice.
But, the way to use hashes in GNU make is to put them into a variable:
HASH := \#
$(info HASH = $(HASH))
That's all I can say without more info.
ETA
Yes, I'm very familiar with keyword expansion... it originated with SCCS/RCS back in the day :).
I see, you mean, you want to put the $Id$ into your makefile, then when your makefile is checked out the value will be replaced. That wasn't clear to me.
I'm sorry to say that what you want to do is close to impossible. The problem is that you can't escape the value in the makefile because you're not writing the value into the makefile, Perforce is. And Perforce is not escaping it.
You have only two options that I can see:
First, don't try to put this into a make variable. There are many ways to do this, depending on what you really want. One way is to create a header file that contains const char* foo = "$Id$"; and let that be replaced. If you really want the ID of the makefile, but you only need it within a certain recipe, you can put it directly into that recipe:
myrecipe: ; echo '$$Id$$'
(I'm not actually sure the $$ trick here will work, it depends on how Perforce replaces things... if it doesn't you can use echo '$Id$x' you'll lose the dollar signs but keep the rest).
The only other option is to upgrade your version of GNU make to the latest (4.3). In that release, some broken handling of hash characters in the $(shell ...) function was fixed, which means you can use:
var1 := $(shell echo '$$Id$$')
and it will work (same caveats, and solutions, for $$ here as above).
Maybe I didn't get you correctly but the following works for an outside actor replacing $Id$ without escaping:
define PERFORCE_ID
$Id$
endef
PERFORCE_ID := $(word 2,$(value PERFORCE_ID))
$(info $(PERFORCE_ID))
As a test, I simply put in the text substitution from Perforce myself:
define PERFORCE_ID
$Id: //repository/path/check.make#6 $
endef
PERFORCE_ID := $(word 2,$(value PERFORCE_ID))
$(info Perforce id is: $(PERFORCE_ID))
Output:
Perforce id is: //repository/path/check.make#6
You can't have an unescaped literal # in a make assignment and not have it be interpreted as a comment character. But as a hack, you can have the shell extract this token from the current Makefile.
# $Id: //repository/path/check.make#6 $
str1 := $(shell sed '/[$$]Id[$$:]/!d;s/^\# [$$]Id: \(.*\) [$$].*/\1/' Makefile)
The sed script looks for the $Id$ or $Id: token in the Makefile itself by way of a regex which doesn't match itself; the doubled dollar sign is how you put a literal dollar sign in a Makefile. It extracts the contents of the field, and make assigns the output to str1. Because there is no literal # in the code which assigns the variable, no further escaping is necessary.
Demo: https://ideone.com/hWjnCp
This requires GNU Make, but that's apparently what you are using already. (Please tag such questions explicitly as gnu-make.)
I have 3 dirs and want to link an executable against the libraries
I already have the directory list:
DIRS=Math Graph Test
I want to get the library list like this:
LIBS=Math/libMath.a Graph/libGraph.a Test/libTest.a
If I use this:
$(DIRS:%=%/%.a)
I get:
Math/%.a Graph/%.a Test/%.a
GNU Makefile says:
Only the first ‘%’ in the pattern and replacement is treated this way; any subsequent ‘%’ is unchanged.
Here I need 2 occurrences to be replaced, not just the first one.
You'll have to use a loop:
LIBS := $(foreach D,$(DIRS),$D/lib$D.a)
eventually I used:
LIBS := $(join $(DIRS), $(DIRS:%=/lib%.a))
I found the following lines in a makefile tutorial, but I have some problem with the bold lines.
In 1 line, if I write
program_C_SRCS:=$(*.c)
it does not work. So please tell me what is
wildcard word in doing here. Is this word is specific to the makefile only?
In tutorial it is written that second line will perform the test substitution. Can anyone tell me something about this text substitution?
Please excuse me if my questions are very basic because I am new to make filestuff.
link of tutorial
CC:=g++
program_NAME:=myprogram
**program_C_SRCS:=$(wildcard *.c)** # 1 line
program_CXX_SRCS:=$(wildcard *.cc)
**program_C_OBJ:=$(program_C_SRCS:.c=.o)** # 2 line
program_CXX_OBJ:=$(program_CXX_SRCS:.c=.o)
program_OBJ:= $(program_C_OBJ) $(program_CXX_OBJ)
Suppose you have two source files. foo.c and bar.c.
program_C_SRCS:=$(wildcard *.c) # 1 line
The wildcard function is Make syntax. The variable program_C_SRCS will now have the value foo.c bar.c (maybe not in that order).
program_C_OBJ:=$(program_C_SRCS:.c=.o) # 2 line
This is a substitution reference. It transforms text, replacing one substring with another. The variable program_C_OBJ now has the value foo.o bar.o.
The use of wildcard card function in make file is to list all the source files with a particular extension. For example:
program_C_SRCS:=$(*.c) // In this the variable program_C_SRCS will have all the files with ".c" extension.
Suppose if you want to convert .c files to .o files then the following syntax may be useful:
program_C_OBJS:=$(patsubst %.c,%.o,$(wildcard *.c))
I am trying to figure out what the following two lines in a .mk file mean
include $(ROOTDIRECT)/target/$(MYSUBDIR)/defs.mk
include $(ROOTDIRECT)/target/$(dir $(patsubst %/,%,$(MYSUBDIR)))/defs.mk
For clarity let ROOTDIRECT be "/home/me" and MYSUBDIR be "platform"
The first line I guess is straight forward and includes "/home/me/target/platform/defs.mk"
The second line I dont understand and my guess from my environment is that it includes "/home/me/target/defs.mk"
Am I right/wrong and could could someone help me to understand the second line
$(patsubst %/,%,$(MYSUBDIR)) will substitute anything matching the pattern %/ by %, where % can be anything.
In other words, it will remove the trailing / of $(MYSUBDIR).
See GNU Make Manual 8.2 Functions for String Substitution and Analysis