SEARCH_SOURCE = $(DDODBC_LIB_DIR) ;
InstallBin [ FDirName $(TOP) $(BUILDDIR) lib ] : $(DDODBC_LIBS) ;
InstallBin [ FDirName $(TOP) $(BUILDDIR) datadirect V7 lib ] : $(DDODBC_LIBS) ;
Only in the second directory can I find the copied files from $(DDODBC_LIBS). Why they are not copied to the first directory by InstallBin?
The issue is that InstallBin respectively InstallInto need to define a target (per source file) which represents the installed file and which is made a dependency of the install pseudo target. They do that by simply using the source target name with the grist set to $(INSTALLGRIST). So the second InstallBin invocation defines the same target, resetting the target's location (LOCATE variable on the target). Hence the file is only installed to the second location.
A simple, if not particularly elegant, work-around is to redefine INSTALLGRIST for one of the invocations of InstallBin.
SEARCH_SOURCE = $(DDODBC_LIB_DIR) ;
InstallBin [ FDirName $(TOP) $(BUILDDIR) lib ] : $(DDODBC_LIBS) ;
oldInstallGrist = $(INSTALLGRIST) ;
INSTALLGRIST = $(INSTALLGRIST)2 ;
InstallBin [ FDirName $(TOP) $(BUILDDIR) datadirect V7 lib ] : $(DDODBC_LIBS) ;
INSTALLGRIST = $(oldInstallGrist) ;
In case you need to do that more often, a more elegant solution would be to create a wrapper rule that derives an INSTALLGRIST value from the installation directory:
rule InstallBinSafe
{
local INSTALLGRIST = installed-$(1:G=) ;
InstallBin $(1) : $(2) ;
}
And then simply use that rule instead of InstallBin.
Related
I am trying to build libtorrent using b2 by following libtorrent building with boost build but I am facing this error when I do b2 install --prefix=PRIFIX:
LDFLAGS =
OS = LINUX
Jamfile:944: in install-paths
ERROR: rule "version.boost-build" unknown in module "Jamfile</home/pavan/projects/torrents/libtorrent_install/libtorrent-2.0.7>".
Jamfile:1063: in install-pkg-config
Jamfile:1094: in load-aux
/home/pavan/boost_install/boost_1_80_0/tools/build/src/build/project.jam:378: in load-jamfile
/home/pavan/boost_install/boost_1_80_0/tools/build/src/build/project.jam:64: in load
/home/pavan/boost_install/boost_1_80_0/tools/build/src/build/project.jam:142: in project.find
/home/pavan/boost_install/boost_1_80_0/tools/build/src/build-system.jam:618: in load
/home/pavan/boost_install/boost_1_80_0/tools/build/src/kernel/modules.jam:294: in import
/home/pavan/boost_install/boost_1_80_0/tools/build/src/kernel/bootstrap.jam:135: in module scope
pavan#pavan-B550-GAMING-X-V2:~/projects/torrents/libtorrent_install/libtorrent-2.0.7$ ls
after going through the line number in Jamfile (944) I can see this:
local boost-build-version = [ SPLIT_BY_CHARACTERS [ version.boost-build ] : "-" ] ;
I have followed the same steps on another machine I did not see this error, am I missing something ?
There was a change in boost-build in boost-1.80 where this way of accessing its version number was removed.
It was fixed here (but hasn't been released yet).
You can fix it by applying this patch:
--- a/Jamfile
+++ b/Jamfile
## -22,6 +22,8 ## ECHO "CXXFLAGS =" $(CXXFLAGS) ;
ECHO "LDFLAGS =" $(LDFLAGS) ;
ECHO "OS =" [ os.name ] ;
+jam-version = [ modules.peek : JAM_VERSION ] ;
+
if $(BOOST_ROOT)
{
ECHO "building boost from source directory: " $(BOOST_ROOT) ;
## -163,10 +165,11 ## rule linking ( properties * )
# which only works on ELF targets with gcc
result += <linkflags>-Wl,--export-dynamic <linkflags>-rdynamic ;
}
- else
+ else if [ version.version-less $(jam-version) : 1990 0 ]
{
- # backtraces don't work with visibility=hidden, so we only add that in
- # the else-block
+ # the visibility feature was introduced in boost-1.69. This was close to
+ # when the verisoning scheme changed from year to (low) version numbers.
+ # in boost-1.70
result += <visibility>hidden ;
}
## -941,8 +944,10 ## rule install-paths ( properties * )
# package.paths was introduced in boost-1.70 (2018.02)
# however, boost build's versioning scheme changed in boost-1.71 to version
# 4.0
- local boost-build-version = [ SPLIT_BY_CHARACTERS [ version.boost-build ] : "-" ] ;
- if [ version.version-less [ SPLIT_BY_CHARACTERS $(boost-build-version[1]) : "." ] : 2018 03 ]
+ # so, if versions are 4.0+ we want to use package.paths, but if it's a year,
+ # say 2018, that means it's old and we use the fallback below. Any version <
+ # 1990 is considered the 4.0 and later numbering scheme.
+ if [ version.version-less 1990 0 : $(jam-version) ]
{
import option ;
import property ;
I have the following Makefile target:
target1:
$(eval count_abc := $(shell grep -c "ABC" myFileA))
$(eval count_def := $(shell grep -c "DEF" myFileB))
echo $(count_abc)
echo $(count_def)
ifeq ($(count_abc),$(count_def))
echo "TRUE"
else
echo "FALSE"
endif
But the output is always TRUE, e.g.:
echo 22
22
echo 21
21
echo TRUE
TRUE
What am I doing wrong here? What I want is INSIDE the target do 2 greps and compare their outputs and do something or something else based on the result. Please note that the greps must be done within the target since myFileA and myFileB get created on the target before and don't exist at the beginning when running make.
Thanks,
Amir
The rule file for "make" is declarative in nature - the makefile defines rules and targets, and then the make program evaluate the rules, and decide which action to take based on the target. As a result, execution is not always in the order the lines are entered into the file.
More specifically, the "ifeq" is evaluated at the rule definition stage, but the actions for building the target (eval count_abc ...) are executed when the target is built. As a result, when the ifeq is processed, both count_abc and count_def are still uninitialized, expanded to empty strings.
For the specific case you described - building a target that will compare the grep -c output from the two files, you can try something like below, effectively using shell variables (evaluated when target is evaluated), and not make variables (which are mostly declarative, evaluated when makefile is read)
target1:
count_abc=$(grep -c "ABC" myFileA) ; \
count_def=$(grep -c "DEF" myFileB) ; \
echo $(count_abc) ; \
echo $(count_def) ; \
if [ "$count_abc" -eq "$count_def" ] ; then echo TRUE ; else echo FALSE ; fi
Disclaimer: I did not run the revised makefile, not having access to desktop at this time.
This question already has answers here:
Extract filename and extension in Bash
(38 answers)
Closed 1 year ago.
I'm trying to create a bash script that will move all files recursively from a source folder to a target folder, and simply rename files if they already exist. Similar to the way M$ Windows does, when a file exists it auto-renames it with "<filemame> (X).<ext>", etc. except for ALL files.
I've create the below, which works fine for almost all scenarios except when a folder has a (.) period in its name and a file within that folder has no extension (no period in its name).
eg a folder-path-file such as: "./oldfolder/this.folder/filenamewithoutextension"
I get (incorrectly):
"./newfolder/this (1).folder/filenamewithoutextension"
if "./newfolder/this.folder/filenamewithoutextension" already exist in the target location (./newfolder),
instead of correctly naming the new file: "./oldfolder/this.folder/filenamewithoutextension (1)"
#!/bin/bash
source=$1 ; target=$2 ;
if [ "$source" != "" ] && [ "$target" != "" ] ; then
#recursive file search
find "$source" -type f -exec bash -c '
#setup variables
oldfile="$1" ; osource='"${source}"' ; otarget='"${target}"' ;
#set new target filename with target path
newfile="${oldfile/${osource}/${otarget}}" ;
#check if file already exists at target
[ -f "${newfile}" ] && {
#get the filename and fileextension for numbering - ISSUE HERE?
filename="${newfile%/}" ; newfileext="${newfile##*.}" ;
#compare filename and file extension for missing extension
if [ "$filename" == "$newfileext" ] ; then
#filename has no ext - perhaps fix the folder with a period issue here?
newfileext="" ;
else
newfileext=".$newfileext" ;
fi
#existing files counter
cnt=1 ; while [ -f "${newfile%.*} (${cnt})${newfileext}" ] ; do ((cnt+=1)); done
#set new filename with counter - New Name created here *** Needs re-work, as folder with a period = fail
newfile="${newfile%.*} (${cnt})${newfileext}";
}
#show mv command
echo "mv \"$oldfile\" \"${newfile}\""
' _ {} \;
else
echo "Requires source and target folders";
fi
I suspect the issue is, how to properly identify the filename and extension, found in this line:
filename="${newfile%/}" ; newfileext="${newfile##*.}" which doesn't identify a filename properly (files are always after the last /).
Any suggestion on how to make it work properly?
UPDATED: Just some completion notes - Issues fixes with:
Initially Splitting each full path filename: path - filename - (optional ext)
Reconstructing the full path filename: path - filename - counter - (optional ext)
fixed the file move to ensure directory structure exists with mkdir -p (mv does not create new folders if they do not exist in the target location).
Maybe you could try this instead?
filename="${newfile##*/}" ; newfileext="${filename#*.}"
The first pattern means: remove the longest prefix (in a greedy way) up to the last /.
The second one: remove the prefix up to the first dot (the greedy mode seems unnecessary here) − and as you already noted, in case the filename contains no dot, you will get newfileext == filename…
Example session:
newfile='./oldfolder/this.folder/filenamewithoutextension'
filename="${newfile##*/}"; newfileext="${filename#*.}"
printf "%s\n" "$filename"
#→ filenamewithoutextension
printf "%s\n" "$newfileext"
#→ filenamewithoutextension
newfile='./oldfolder/this.folder/file.tar.gz'
filename="${newfile##*/}"; newfileext="${filename#*.}"
printf "%s\n" "$filename"
#→ file.tar.gz
printf "%s\n" "$newfileext"
#→ tar.gz
I'm wondering if it's possible to override a target in a makefile! The environment I'm working in does not allow me to do this due to auto generation! I was wondering if I coded the same rule above or below the static target would this achieve an override?
%_emul.flist: $(if ${GEN_FLIST},%_synth.flist,) ${rdlh_file_deps}
${QUIET}if test ${SYN_DEBUG} -eq 1 ; then set -xv ; fi; \
$(if ${TOOL_VERILOG},rm -f $#; touch $#,$(if ${TOOL_BBOX_LIBS},echo ${TOOL_BBOX_LIBS} > $#,rm -f $#; touch $#))
/bin/sed -e '/\/libs\//d' -e '/\/place\//d' $(foreach mod,$(filter %.vhd,$^),-e 's%^\(.*\/\)\{0,1\}$(basename $(notdir ${mod}))\.v$$%${mod}%') $*_synth.flist >> $#
Yes , i think that would work .... but you need to be a bit more careful in the way you code things. You don't want to override something that might be useful!
GNU make would take the most recent of the target it encounters. So, the following works (but not as i would have liked it to work :( )
Output: I think you are looking for something like this --
Kaizen ~/make_prac $ make -nf mk.name
mk.name:20: warning: overriding recipe for target `name'
mk.name:17: warning: ignoring old recipe for target `name'
arg1="Kaizen" ;
echo "hello "" ;" ;
hello ;
Code: Here the target "name" appears twice and is overridden.
Kaizen ~/make_prac $ cat mk.name
##
## make to accept name and display hello name
##
arg1="" ;
.PHONY : name \
hello
#.DEFAULT :
# hello
hello : name
+ echo "hello $(arg1)" ;
name :
echo "name given is : $(arg1)" ;
name :
arg1="Kaizen" ;
PS: Take note of the use of : -- if you use :: then both rules get executed.
Explanation for the arg1 .... not showing in the output: The variable arg1, even though it gets assigned in the first parsing, it gets ignored, since its assignment is target dependent. If you would have had a variable declaration elsewhere -- e.g. like arg1 is defined at the start -- there would not be any dereferencing issues.
a:
#echo 1
b:
#echo 2
c:
#if [ ! -d somefolder ]; \
then \
# how do I invoke target b here?
fi;
How can I invoke target b inside target c, based on my condition? Sort of like an antcall, if you're familiar with ant.
Just say make b