cmake string begins with a caret(^) and ends with a dollar sign($)? - makefile

I saw a strange cmake line that contains a tring begins with "^" and ends with "$". However, it is not a regular expression, but rather a if statement. It's like this:
if ("^${CMAKE_SOURCE_DIR}$" STREQUAL "^${PROJECT_SOURCE_DIR}$")
Can you tell what does this means? Is it necessary to add the caret and dollar sign to compare the two strings?
Thanks at first.

I see no reason in such string "wrapping" when compare quoted values.
Some languages (e.g. bash) have some problem when compare possibly-empty values, so adding a symbol to both sides of comparison have a sense. But again, CMake has no such problem if argument is quoted.
This is valid:
if("${CMAKE_SOURCE_DIR}" STREQUAL "${PROJECT_SOURCE_DIR}")
Moreover, taking into account nature of given variables:
after project() call both variables exists,
variables are non-empty
variables contain paths, which very unlikely has a ; symbol,
omitting quotes would also be valid in most cases:
if(${CMAKE_SOURCE_DIR} STREQUAL ${PROJECT_SOURCE_DIR})
Finally, the most natural way for compare strings in CMake:
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
In this case, CMake automatically attempts to dereference variables with unquoted names.

Related

Makefile string with spaces

var := 'C:/some/path here' labas
all:
#echo $(words $(var))
This returns 3.
How to make it return 2? Or make does not work the way I think??
Make definitely doesn't work the way you think, if you think that make has any interest in quotes of any type :). Make ignores (i.e., treats as normal characters like any other) both single- and double-quote characters in virtually every situation, and all make functions work in simple whitespace delimiters without regard to quote characters.
In general, it's not practical to use make with any system that requires spaces in target names. It just doesn't work: too much of make is based on whitespace as a separator character and there's no general, common way to escape the whitespace that works everywhere.
In your very particular case you can play a trick like this:
E :=
S := $E $E
path := C:/some/path here
xpath := $(subst $S,^,$(path))
var := $(xpath) labas
all:
#echo $(words $(var))
#echo $(subst ^,$S,$(var))
Basically, this creates a variable $S which contains a space, then it substitutes all spaces in the variable path with some other, non-space character (here I chose ^ but you can pick what you like, just note it has to be a character which is guaranteed to not appear in the path).
Now this path doesn't contain whitespace so you can use it with make functions.
This has major downsides: not only the complexity visible here, but note these paths cannot be used in target names since they won't actually exist on disk.
In general, you should simply not use paths containing whitespace with make. If you must use paths containing whitespace, then very likely make is not the right tool for you to be using.

Variables in makefiles (How to use arrays)

I have compiler flag in a makefile which looks like:
MYVARIABLE1=HELLO 4.5.6
MYVARIABLE2"="{0x95,0x04,0x05,0x06,' ','A','A'}"
CFLAGS+=-DMYVARIABLE2=${MYVARIABLE2}
which works fine. But if I want to use already known info in VARIABLE1 to create VARIABLE2:
MYVARIABLE1=HELLO 4.5.6
MYVARIABLE2"="{0x95,$(MYVARIABLE1[7]},$(MYVARIABLE1[9]},$(MYVARIABLE1[11]},' ','A','A'}"
CFLAGS+=-DMYVARIABLE2=${MYVARIABLE2}
But when I run my makefile with the second option, It stops compile at the c-file using the CFLAG with the error message:
error: expected expression before ',' token
in the C-code:
uint8 OTHERVARIABLE[] = MYVARIABLE2;
Question: Is the really $(MYVARIABLE1[x ]}the correct way of using parts of a variable defined in the makefile?
There is no such thing as an "array" or list variable in make syntax.
There are some GNU make functions which will operate on every word of a string, one at a time, where a word is a space-separated value. This can be thought of as an array, kind of. This is why make has an almost impossible time dealing with paths containing whitespace.
If you're not using GNU make, then none of this will work.
To do what you want you'll have to split the MYVARIABLE1 value into separate words, then you can access individual words using functions. Something like this will work:
MYVARIABLE1 = HELLO 4.5.6
__var1 = $(subst ., ,$(MYVARIABLE1))
MYVARIABLE2 = "{0x95,$(word 2,$(__var1)),$(word 3,$(__var1)),$(word 4,$(__var1)),' ','A','A'}"
The subst function replaces the . with spaces, giving a result of HELLO 4 5 6 so that you can reference the parts of the version individually using the word function.
You can find out more about GNU make functions in the documentation.
Is the really $(MYVARIABLE1[x]} the correct way of using parts of a variable defined in the makefile?
It is valid bash syntax, but not valid GNU make syntax.

How to specify a pathname with space in middle to prefix in a makefile

In a Makefile for a gnu software distribution, I want to change the value of prefix to be a pathname with some whitespaces in the middle. When I do that, make reports error at the assignment to prefix. When I double quote the pathname, make still doesn't work. How shall I assign the pathname with whitespaces to prefix?

can't use variable in Makefile

My main Makefile call config.mk
include $(TOPDIR)/config.mk
then config.mk include some sentences like this:
ifdef CPU
sinclude $(TOPDIR)/cpu/$(CPU)/config.mk
endif
ifdef SOC
sinclude $(TOPDIR)/cpu/$(CPU)/$(SOC)/config.mk
endif
I have prepared these two tree and necessary config.mks. But for "SOC", whose value is "versatile", there is a problem. If I put "versatile" directly here, it could find the file and everything is fine; but when I use $(SOC), il will meet an error, and say
/../../../cpu/arm926ejs/versatile: is a folder, stop
Anyone know what the problem is ??
Are you sure you gave the exact error message? What version of make are you using? That error doesn't look like anything GNU make would print.
Anyway, I'll bet the problem is that your assignment of the SOC variable has trailing whitespace. According to the POSIX definition of make, leading whitespace before a variable value is removed, but trailing whitespace is preserved. That means, for example, if you write your makefile like this:
SOC = versatile # this is the versatile SOC
then make will remove the comment, but keep the space, so the value will be 'versatile' (space at the end). This means when the value is expanded in the sinclude line you get:
sinclude $(TOPDIR)/cpu/$(CPU)/versatile /config.mk
which make interprets as trying to include two different values, the first of which is a directory.
Even if you don't have a comment there, any trailing whitespace will be preserved. When editing makefiles you should try to put your editor into a mode where it flags trailing whitespace, or even better removes it automatically. GNU Emacs, for example, can do this.

Trim an environmental variable in makefile

I maintain a project which provides makefile for Arduino
There is a master (common) makefile and the users create a small makefile where they set certain environmental variables and then include the master makefile.
A typical makefile looks likes this
# Arduino Make file. Refer to https://github.com/sudar/Arduino-Makefile
BOARD_TAG = atmega328
ARDUINO_PORT = /dev/ttyACM*
include $(ARDMK_DIR)/arduino-mk/Arduino.mk
Recently, I was debugging a bug and then found out that if there is an additional space at the end of BOARD_TAG environmental variable, then it results in an error, which is not very intuitive for someone to fix.
My initial thought was to fix it by trimming the environmental variable inside the makefile. But on second thought I was not sure whether that is the correct way to fix this issue.
So my question is what is the recommended way to fix these kind of user input issues in makefile? Should I try to trim it or is there an alternate way to fix this?
To trim the variable "in place", just treat it as a simply expanded variable:
BOARD_TAG = atmega328
BOARD_TAG := $(strip $(BOARD_TAG))
If you use "=", it's a recursive expanded variable, so any expression on the right (e.g. $(strip ...)) will not be expanded until the variable itself is evaluated; if you try to put the variable itself on the right, Make warns you that that expression can't be evaluated because it goes into an infinite loop.
If you use ":=", it becomes a simply expanded variable; Make expands the right-hand side then and there, assigns the result to the variable and that's that.

Resources