how to escape closing angle bracket symbol in cmake generator expresssions? - cmake

Here is what I am trying to do:
set(BE_QUIET $<$<NOT:$<BOOL:CMAKE_VERBOSE_MAKEFILE>>:&>/dev/null>)
with the aim of using it in add_cusom_command like this:
add_custom_command(
...
COMMAND ... ${BE_QUIET}
)
idea is to suppress custom command output unless user sets CMAKE_VERBOSE_MAKEFILE (or runs make VERBOSE=1).
Problem is that cmake treats that closing angle bracket symbol as end of expression. Is there any way to escape it?
Edit: alas, even though I know about $<ANGLE-R> now, this idea doesn't work -- you need new expression (smth like $<CONFIG_FLAGS:VERBOSE>)
Edit 2: found a solution (inject some make magic):
set(BE_QUIET "$(if" "$(VERBOSE),,&>/dev/null)")

Use $<ANGLE-R> (the documentation is under Output Expressions):
set(BE_QUIET $<$<BOOL:CMAKE_VERBOSE_MAKEFILE>:&$<ANGLE-R>/dev/null>)
Note that it's not possible to detect make VERBOSE=1, though, as there is no generator expression that tells us whether VERBOSE=1 was passed.

Related

what does evaluate expansion means in intellij idea?

I am writing a sh script in Intellij with two loops in there, in one loop
for i in {1..32}
do
some commands
done
intellij is marking the {1..32} as "evaluate expansion"
the other loop:
for text in {'fhv', 'green'}
do
commands
done
is not marking that error, what does the evaluate expansion means?
Your second example, due to the space, is not a brace expansion. It is just two separate words, {'fhv', and 'green'}. (Depending on the shell, it might be a syntax error.) Eliminate the space
for text in {'fhv','green'}
and you'll have a valid (though pointless) brace expansion expression.

Globbing expression in cmake: can I use brackets?

In theory cmake should support globbing expression, a little bit like a glob command.
However, I cannot find a way to match, for example, "a sequence of 3 numbers, or nothing". I would guess it should be something like:
file (GLOB outputVar *theImportantStringIWantedToMatch{[0-9][0-9][0-9],}.dll)
But it does not seem to work. For example:
*opencv_*flann{[0-9][0-9][0-9],}.a
does not match a file called
libopencv_flann.a
(Should also match libopencv_flann462.a for example)
It does not even match even if I put an expression like this:
*opencv_*flann{.,.}a
Escaping the brackets or the comma does not help. Is there any way to get brackets working, or any alternative to the expression I am trying to achieve?
So, for the moment the only solution I can come out with is repeating the expression in the 2 versions, namely:
file (GLOB outputVar *theImportantStringIWantedToMatch[0-9][0-9][0-9].dll
*theImportantStringIWantedToMatch.dll
)

What's the difference between parenthesis $() and curly bracket ${} syntax in Makefile?

Is there any differences in invoking variables with syntax ${var} and $(var)? For instance, in the way the variable will be expanded or anything?
There's no difference – they mean exactly the same (in GNU Make and in POSIX make).
I think that $(round brackets) look tidier, but that's just personal preference.
(Other answers point to the relevant sections of the GNU Make documentation, and note that you shouldn't mix the syntaxes within a single expression)
The Basics of Variable References section from the GNU make documentation state no differences:
To substitute a variable's value, write a dollar sign followed by the
name of the variable in parentheses or braces: either $(foo) or
${foo} is a valid reference to the variable foo.
As already correctly pointed out, there is no difference but be be wary not to mix the two kind of delimiters as it can lead to cryptic errors like in the GNU make example by unomadh.
From the GNU make manual on the Function Call Syntax (emphasis mine):
[…] If the arguments themselves contain other function calls or variable references, it is wisest to use the same kind of delimiters for all the references; write $(subst a,b,$(x)), not $(subst a,b,${x}). This is because it is clearer, and because only one type of delimiter is matched to find the end of the reference.
The ${} style lets you test the make rules in the shell, if you have the corresponding environment variables set, since that is compatible with bash.
Actually, it seems to be fairly different:
, = ,
list = a,b,c
$(info $(subst $(,),-,$(list))_EOL)
$(info $(subst ${,},-,$(list))_EOL)
outputs
a-b-c_EOL
md/init-profile.md:4: *** unterminated variable reference. Stop.
But so far I only found this difference when the variable name into ${...} contains itself a comma. I first thought ${...} was expanding the comma not as part as the value, but it turns out i'm not able to hack it this way. I still don't understand this... If anyone had an explanation, I'd be happy to know !
It makes a difference if the expression contains unbalanced brackets:
${info ${subst ),(,:-)}}
$(info $(subst ),(,:-)))
->
:-(
*** insufficient number of arguments (1) to function 'subst'. Stop.
For variable references, this makes a difference for functions, or for variable names that contain brackets (bad idea)

How do you pass SOME_LIB="-lmylib -lmylib2" in a BUILD_COMMAND for ExternalProject_Add()?

I'm trying to pass a quoted string through BUILD_COMMAND in ExternalProject_Add() and every way I try it's getting mangled. The code is this:
set (mylibs "-lmylib -lmylib2")
ExternalProject_Add(Foo
URL http://foo
BUILD_COMMAND make SOME_LIB=${mylibs}
BUILD_IN_SOURCE 1
...)
I've tried using backslash quotes, double quotes, inlining the whole thing, but every time, either the whole SOME_LIB=... part gets quoted or my injected quotes get escaped. Is it not possible to get quotes through to the command line so they just cover the parameters?
Even though I'm unable to get the resulting make call to look like make SOMELIB="-lmylib -lmylib2", you can make it call make "SOMELIB=-lmylib -lmylib2" which seems to do the same thing.
Have you tried quoting like this?
ExternalProject_Add(
...
BUILD_COMMAND make "SOME_LIB=\"${mylibs}\""
...
)
The outer pair of double quotes says "this is all one argument here", and the inner pair of escaped double quotes says "these are embedded IN the argument".
It may need extra escaping, though. I haven't tried this and I'm not certain it will work. But there should be a way to add escape characters until it does work... Or, worst case, you could write out a script file (bash .sh or batch .bat) that has proper shell syntax for calling make like you want it and then invoke executing the script file as the BUILD_COMMAND.

Using CMake's include_directories command with white spaces

I am using CMake to build my project and I have the following line:
include_directories(${LLVM_INCLUDE_DIRS})
which, after evaluating LLVM_INCLUDE_DIRS, evaluates to:
include_directories(C:\Program Files\LLVM\include)
The problem is that this is being considered two include directories, "C:\Program" and "Files\LLVM\include".
Any idea how can I solve this problem? I tried using quotation marks, but it didn't work.
EDIT: It turned out that the problem is in the file llvm-3.0\share\llvm\cmake\LLVMConfig.cmake. I enclosed the following paths with quotation marks and the problem was solved:
set(LLVM_INSTALL_PREFIX C:/Program Files/LLVM)
set(LLVM_INCLUDE_DIRS ${LLVM_INSTALL_PREFIX}/include)
set(LLVM_LIBRARY_DIRS ${LLVM_INSTALL_PREFIX}/lib)
In CMake,
whitespace is a list separator (like ;),
evaluating variable names basically replaces the variable name with its content and
\ is an escape character (to get the symbol, it needs to be escaped as well)
So, in your example, include_directories(C:\\Pogram Files\\LLVM\\include) is the same as
include_directories( C:\\Program;Files\\LLVM\\include)
that is, a list with two items. To avoid this, either
escape the whitespace as well:
include_directories( C:\\Program\ Files\\LLVM\\include) or
surround the path with quotation marks:
include_directories( "C:\\Program Files\\LLVM\\include")
Obviously, the second option is the better choice as it is
simpler and easier to read and
can be used with variable evaluation like in your example (since the result of the evaluation is then surrounded by quotation marks and thus, treated a single item)
include_directories("${LLVM_INCLUDE_DIRS}")
This works as well, if LLVM_INCLUDE_DIRS is a list of multiple directories because the items in this list will then be explicitly separated by ; so that there is no need for unquoted whitespace as implicit list item separator.
Side note:
When using hard-coded path-names (for whatever reason) in my CMake files, I usually uses forward slashes as directory separators as this works on Windows as well and avoids the need to escape all backslashes.
This is more likely to be an error at the point where LLVM_INCLUDE_DIRS is set rather than a problem with include_directories.
To check this, try calling include_directories("C:\\Program Files\\LLVM\\include") - it should work correctly.
The problem seems to be that LLVM_INCLUDE_DIRS was constructed without using quotation marks. Try for example running this:
set(LLVM_INCLUDE_DIRS C:\\Program Files\\LLVM\\include)
message("${LLVM_INCLUDE_DIRS}")
set(LLVM_INCLUDE_DIRS "C:\\Program Files\\LLVM\\include")
message("${LLVM_INCLUDE_DIRS}")
The output is:
C:\Program;Files\LLVM\include
C:\Program Files\LLVM\include
Note the semi-colon in the first output line. This is a list with 2 items.
So the way to fix this is to modify the way in which LLVM_INCLUDE_DIRS is created.