Add space separated string to cmake `include_directories` - cmake

I have a space separated string that represents include directories I'd like to add, let's call it ${MYSTRING}, and let's say it contains the stringmy/dir1 my/dir2 my/dir3.
Using:
include_directories(${MYSTRING})
Results in an incorrect makefile, as the CXX_FLAGS that is added is:
-Imy/dir1 my/dir2 my/dir3
Rather than:
-Imy/dir1 -Imy/dir2 -Imy/dir3
Is there anyway I can work around this? the string is generated via an external command, and I'd rather not have to depend on external tools such as sed.

Use separate_arguments which takes a space-separated string of values and turns it into a list:
set(MY_LIST ${MYSTRING})
separate_arguments(MY_LIST)
include_directories(${MY_LIST})

Related

Cmake match beginning of string

I am getting some compile definitions from an external library. Unfortunately, they provide a list that sometimes starts with a leading semi-colon. For example:
;-Dfoo;Dbar
I think this is crashing the build command later in the process. I thought that I could simply remove potential leading semi-colons with this regex:
string(REGEX REPLACE "^;" "" stripped_defs ${defs})
but the problem is that Cmake seems to be ignoring the carrot ^ which signifies the start of the string, with the consequence being that all semi-colons are deleted. That is, I am getting the output
-Dfoo-Dbar
when I want
-Dfoo;-Dbar
As Sergei points out, the problem is that my defs variable was being interpreted as a list, not a string. So the regex was acting on each element of the list individually. All I need to do to force the string interpretation is to add quotes. Specifically, instead of
string(REGEX REPLACE "^;" "" stripped_defs ${defs})
I should have had
string(REGEX REPLACE "^;" "" stripped_defs "${defs}")
Rather than using a regular expression in this case, using list operations to delete empty elements would be my preferred approach in this case:
set(stripped_defs ${defs})
list(REMOVE_ITEM stripped_defs "")
This may involve one more command, but it's easier to understand what the snippet does.

Sending an argument to batch file with spaces. VB

I am using a VB to run .bat file and to pass arguments to it.
Right now I managed to run it and to send the arguments to it, but ran into a problem. My arguments might contain spaces inside. I was trying to use quotes, but it didn't seem to work as I expected. So what I am doing:
Running this code: System.Diagnostics.Process.Start("C:\Users\XXXXXXX\Desktop\New.bat", """"+data+"""")
where 'data' is the argument I am sending. For testing it contains the value:
Hel loo
Inside the .bat file I have a code, that opens notepad and writes the argument inside it. With this code I have managed to pass the argument as one with spaces, but the result is:
"Hel loo"
Any ideas how to get rid of the quotes on each side, while still passing the argument as one with spaces?
I cannot escape them or replace with another symbol. This solution needs to pass the argument as one with spaces inside. Is this possible? The program I am working with is not important.
EDIT
This is the content of the .bat file:
set directory_Rexe="C:\Users\XXXXXXX\Desktop\testBat.txt"
set var=%1
echo %var%>%directory_Rexe%
%directory_Rexe%
You have three options here:
Use %~1, which will strip the quotes.
Don't care about putting everything into argument 1 and quoting and use %* instead. You mentioned not wanting that, though.
Don't pass the string as an argument, but as an environment variable instead. This also helps a lot when you have a number of characters in it that need to be escaped.
All options require you to change the batch file, though.
I'd also question the need for a batch file when you have a perfectly capable programming language already at your fingertips. Writing text to a file should actually be easier from VB.

Renaming file via UNC path

I need to have my VB.NET program rename a file over the network.
Microsoft says that My.Computer.FileSystem.RenameFile does not work if the file path starts with two backslashes ("\\"). So, what other way is there of doing this? I just need to rename a file in the domain, for instance:
rename("\\domain\1\exemple.txt", "\\domain\1\exemple2.txt")
The second parameter for rename should be just the file name eg:
My.Computer.FileSystem.RenameFile("C:\Test.txt", "SecondTest.txt")
So try changing your code to this:
My.Computer.FileSystem.RenameFile(#"\\domain\1\exemple.txt", "exemple2.txt")
Also beware of escaping because \ is an escape character, so add a # before any string that contains \. This will cause it to ignore escaping and therefore will treat \ as a normal character

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.