Currently I am setting RPATH using following syntax:
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:$ORIGIN/../lib")
It is working for the binary build using CMake.
The problem is that it is not working for a third party binary I am building using CMake using their auto-configure script. I am using the following command for configure:
add_custom_target(
third_party_bin ALL
COMMAND ./configure
--with-ld-opt=\"-Wl,-rpath,${CMAKE_INSTALL_RPATH}\"
--prefix=${CMAKE_INSTALL_PREFIX}
)
The Makefile generated by third path configure look like:
" -Wl,-rpath,':RIGIN/../lib' -lstdc++"
I think I need to escape ${CMAKE_INSTALL_RPATH} correctly.
I also tried using options like:
add_custom_target(
third_party_bin ALL
COMMAND ./configure
--with-ld-opt=\"-Wl,-rpath,\$\$ORIGIN/../lib\"
--prefix=${CMAKE_INSTALL_PREFIX}
)
and
add_custom_target(
third_party_bin ALL
COMMAND ./configure
--with-ld-opt=\"-Wl,-rpath,\\$\$ORIGIN/../lib\"
--prefix=${CMAKE_INSTALL_PREFIX}
)
but nothing works.
What is the correct way to escape values?
add_custom_target accepts a VERBATIM argument. According to the documentation:
If VERBATIM is given then all arguments to the commands will be
escaped properly for the build tool so that the invoked command
receives each argument unchanged. Note that one level of escapes is
still used by the CMake language processor before add_custom_target
even sees the arguments. Use of VERBATIM is recommended as it enables
correct behavior. When VERBATIM is not given the behavior is platform
specific because there is no protection of tool-specific special
characters.
If I am reading this correctly, you are looking to escape the shell from interpreting the $ variables... If so, use single quotes (') instead of doubles ("). The shell doesn't interpret variables wrapped in single quotes.
Related
I need to execute "rm -rf" on remote machine running Ubuntu in order to clear specified folder.
If I use command like following everything goes fine.
rm -rf "home/blahblah/blah"/*
But if I run the same command in Linux PowerShell I would get ALL files removed.
Is there any way to specify path to be handled the same way in bash and PS? Thank you!
tl;dr
Unfortunately, as of PowerShell 7.0, you must do the following (if you want to use the external rm utility):
sh -c "rm -rf 'home/blahblah/blah'/*"
Note that I've switched to single-quoting ('...') around the path, so I could use it inside a double-quoted ("...") string. While the reverse ('... "..."/*') should work as-is, it currently requires additional escaping ('... \"...\"/*') - see this answer.
However, if the path preceding the /* doesn't actually need quoting - notably if it doesn't contain spaces - you can simply call:
rm -rf home/blahblah/blah/*
You're seeing a very unfortunate difference between PowerShell (as of 7.0) and POSIX-like shells such as Bash with respect to the handling of string arguments composed of both quoted and unquoted parts.
PowerShell parses "home/blahblah/blah"/* as two arguments:
home/blahblah/blah becomes the first argument, as-is in this case.
/* is interpreted as the second argument, which, due to being unquoted and due to an external utility being called, triggers PowerShell's emulation of the globbing (filename expansion) behavior of POSIX-like shells, which means that all files and directories in the root directory are being passed as individual arguments.
Therefore, the arguments that the rm utility actually receives are: -rf, home/blahblah/blah, /bin, /boot, /dev, ... - which is clearly not the intent.
This problematic behavior is discussed in this GitHub issue.
Passing the command to sh, the default shell on Unix-like platforms, instead, bypasses the problem.
I found in a makefile the following commands:
$(var):
mkdir -p $(#D)
What is the meaning of this command?
$(VAR) expands to the value of the variable VAR. This is a Make variable (not a shell etc variable). For example, if earlier in your Makefile you define
VAR=ick/poo
then VAR expands to ick/poo, and #D in your recipe expands to the directory part, ick.
As you seem to be confused about the relationship between shell and make, I should perhaps point out that these are two different languages, though in a Makefile, you will encounter both; the recipes - the parts which are indented by a tab - will be passed to a shell for evaluation (though normally the shell will be /bin/sh, not Bash, unless you specifically override the Make variable SHELL to force it).
In the shell, by the way, the superficially similar construct $(cmd) performs a command substitution; that is, the command cmd will be evaluated and its output will be inserted as text. So for example,
echo Running in $(pwd)
will print
Running in /home/you
if executed in the directory /home/you (the command pwd prints out your current working directory). ... Though in a Makefile, the dollar sign will normally be evaluated and consumed by make itself; so to pass a literal dollar sign to the shell, you have to double it.
test:
echo Running in $$(pwd)
As already explained by #tripleee $(var) expands to the variable. Because it is here listed before a colon it means that it is a target in a Makefile.
For $(#D) see 10.5.3 Automatic Variables in the make manual:
The directory part of the file name of the target, with the trailing slash removed. If the value of ‘$#’ is dir/foo.o then ‘$(#D)’ is dir. This value is . if ‘$#’ does not contain a slash.
NOTE: This is NOT a shell script. This is a makefile. Please use "man make" for a description about what "make" does.
Problem
I am writing an application in rust (for fun) that allows me to use DSL to pretty-print git repository stats into my bash shell prompt.
However, I am having an issue with the library I use to format text in the terminal. It uses an escape I haven't seen before, ^[, in the output. It seems to affect the line wrapping such that the text wraps onto the same line before the end of the terminal.
You can see here a demonstration in gnome shell and in hyper.
Replication
Create a file shell.txt with the following contents:
^[[1;32m\u^[[0m^[[32m#\h^[[0m:^[[1;34m\w^[[0m
Set your prompt command to be the following:
__set_prompt() {
PS1="$(cat shell.txt)"
}
PROMPT_COMMAND=__set_prompt
Question
What is the ^[ escape?
Is there a simple fix to get my shell to recognize the line width-properly?
bash --version 4.4.12(1)-release
It's a representation of a literal escape character (ASCII 0x1b). A simpler way to write shell.txt would be
\e[1;32m\u\e[0m\e[32m#\h\e[0m:\e[1;34m\w\e[0m
To make sure the shell can accurately compute the size of your prompt, you need to wrap the non-printing characters in \[...\].
\[\e[1;32m\]\u\[\e[0m\e[32m\]#\h\[\e[0m\]:\[\e[1;34m\]\w\[\e[0m\]
I have a makefile generated by bakefile which is working fine. To run the executable it needs libraries from a different folder. I found the command rpath used to specify the path to these library. But I have to send it to the makefile as an argument when using the command.
I cannot specify it directly from the bakefile.
I can use the LDFLAGS arguments which is fine. And I found here how to use the $ORIGIN variable.
My question is how does this escaping works?
make LDFLAGS="-Wl,-rpath '-Wl,\$\$ORIGIN'"
Is the single quote to prevent make to interpret the variable?
And why the \$ is here twice?
Yeesh. What a mess.
So, the first set of quotes is removed by the shell, before it starts the make command. Since the outer set of quotes is double-quotes, you have to escape the $ otherwise the shell will treat it as a shell variable (compare to a command like echo "my path is $PWD" and how the PWD variable is expanded). The shell uses backslashes to quote things like $.
So, by the time the shell hands the command line to make, it sees the setting LDFLAGS=-Wl,-rpath '-Wl,$$ORIGIN'
Next in your makefile will be a recipe with a command like this:
$(LD) $(LDFLAGS) ...
Make will expand the LDFLAGS variable as above. For make, any name preceded by a $ is considered a make variable and you escape it from expansion by make by doubling the $ (not using backslashes like the shell), and writing $$. Make will remove one $ during expansion.
So, make will reduce LDFLAGS to the string -Wl,-rpath '-Wl,$ORIGIN' and pass that to the shell.
The shell will strip the next level of quoting, which in this case is the single quotes. Variables are not expanded inside single quotes, so the linker actually gets arguments, literally, -Wl,-rpath and -Wl,$ORIGIN, which is what you want.
Im trying to convert the file paths to/from Linux and Windows on Windows Machine.
unix path to windows works fine.
$ cygpath -w /cygdrive/c/CYGWIN/CYGBuild/build.mak
C:\CYGWIN\CYGBuild\build.mak
But windows path to Linux gives wrong output. i.e Missing '/' and also cygdrive
$ cygpath -u c:\cygwin\cygbuild\build.mak
c:cygwincygbuildbuild.mak
Anyone faced this issue?? Share your experience.
Thanks
I got answer for this question.
cygpath -u 'c:\cygwin\cygbuild\build.mak'
i.e path should be given in single quotation.
Actually as far as I know; you need forward slashes in paths used in cygwin. Single quotations help in cases where there are spaces (and my guess in this case; using backslashes instead of forward slashes) in the path. Otherwise backslashes are like escape characters, while spaces (although not in your case) require escape characters themselves. So quoting the path tends to eliminate such hassles.
Here are links that help me understand this:
This opencv (using cygwin) tutorial, page 4, where there's an example of paths used, with and without quotes, indicating when one might need them.
Also this is
very useful; a list of Cygwin's FAQs, including how to deal with
spaces (or in this case, backslashes in the path where adding quotes would help).
cygpath's -m option is probably the easiest solution. Windows software generally accepts / as well as \. (There may be a few exceptions, but the development tools I work with have all been fine with it.)
$ cygpath -m /cygdrive/c/CYGWIN/CYGBuild/build.mak
C:/Cygwin/CYGBuild/build.mak
No one seems to have explain why, we here is an explanation.
Cygpath will accept slashes, and back-slashes: c:/cygwin/cygbuild/build.mak c:\cygwin\cygbuild\build.mak. However the shell will interpret the back-slashes, therefore you need to stop the shell from interpreting the back-slashes.
You can stop the shell from interpreting back-slashes, in arguments, by preceding them with a back-slash, or by quoting (with single quotes): c:\\cygwin\\cygbuild\\build.mak or 'c:\cygwin\cygbuild\build.mak'.
Double quotes will not help in this case. Double quotes stops argument breaking on space, but does not stop interpretation of escapes (\), or dollar ($) expansion.