Can we call a function inside a cmake generator expression? - cmake

Variables like $<TARGET_OBJECTS:myTarget> can contain a list. To pretty-print it I would like to transform like put a dash, or whatever. So the question is simple : can we call a function from a generator expression ?
I know generator expressions are evaluated at the end of the process, but for me it doesn't implies it can't call a function. However, it's not possible to return a value. If this is possible, is there a way to use it inside generator expressions ?

You cannot call a function for the result of a generator expression, because generator expressions are evaluated after the configuration stage, when all CMake functions are executed.
For pretty-printing a list you could use $<JOIN> expression.
For example,
$<JOIN $<TARGET_OBJECTS:myTarget>,$<COMMA> >
will concatenate all objects and paste , between them.

I know generator expressions are evaluated at runtime, so the function should also be [evaluated] at runtime.
What do you mean by "runtime"? That's not a thing in CMake. There's configuration time and generation time, which are different. Functions run during configuration and generator expressions are expanded during generation, so you cannot call a CMake function from a generator expression.
Plus, it's not possible to return a value. If this is possible, is there a way to use it inside generator expressions?
Indeed, functions in CMake do not have return values.

Related

inspect regex made with a variable

sub make-regex {
my $what's-in-the-box = rand > .5 ?? 'x' !! 'y';
/$what's-in-the-box/
}
my $lol-who-knows = make-regex;
$lol-who-knows.gist.say;
How do you see the innards of the regex (i.e. x or y)? Forcing a match is not a solution.
How do you see the innards of the regex (i.e. x or y)?
You:
Statically compile the regex. Doing so will involve use of a raku compiler, i.e. Rakudo.
Dynamically evaluate the regex so that the $what's-in-the-box variable in your regex gets interpolated and turns into x or y. Doing so will involve running the regex as code. That in turn means both using Rakudo and running the regex with a Match object invocant (or sub-class instance or, conceivably, a mock object equivalent).
View the resulting regex. Doing so will involve using compiler (Rakudo) toolchain specific introspection or debug functionality.
Forcing a match is not a solution.
You can run a regex with no input if your concern is just to avoid the need for a successful match:
say Match.new.&$lol-who-knows; # #<failed match>
But it must be run, otherwise the $what's-in-the-box variable won't turn into an x or y. You might think you could cheat on this by writing something that mimics this part of raku regex construction/use but there's good reason to think that's not going to work out[1].
And then you must view its innards, using Rakudo toolchain features, after you've started running it and before it finishes running.
A regex is a method
In raku, a Regex is code, a sub-class of Method.
Until you run it, by using it in a match, that code is just /$what's-in-the-box/ (aka regex { $what's-in-the-box }). It's the equivalent of something like:
method {
...self should be a Match or a sub-class of it
...if self is not an instance, create a new one
...do matching -- compiler evaluates $what's-in-the-box during this
...return updated self / new instance
}
(To see a bit more detail, see Moritz's answer to the SO Can I change the slang inside a method?.)
A routine is a closure
You create your regex inside the closure named make-regex. The compiler spots that you've used $what's-in-the-box and therefore hangs on to the variable even after the make-regex closure returns. Later on, if/when your regex is run, the $what's-in-the-box variable will be replaced by its value at the moment the regex is run.
Footnotes
[1] There are plenty of huge complications you'll encounter if you try to do an end-run around using the compiler. Even something simple like interpolation is non-trivial. To quote Jonathan Worthington, in 2020:
I thought oh I'm only building [a tool that's] not the real compiler. I can ... have a simpler model of the symbol resolution. In the end it turned out that no I couldn't really. That started to create us some problems. When we aligned the way that we resolved symbols with the same algorithms and lookup structures that was being used in the compiler then suddenly it all became a lot simpler.

Distinguish two functions with the same name

I want to use multiple external CMake files in my project. Unfortunately two different files use the same CMake function name foo. I don't want to modify these external files.
Is there a way to call one specific function or will CMake error out? Would it help if one of the functions has a named parameter, i.e., foo(a b c …) and foo(DESTINATION a b c …)?
New function's definition replaces the previous one with the same name. So access to the previous function is lost.
If different functions (but with the same name) are used in different subprojects, you may try to build one subproject as ExternalProject, so function's collision wouldn't occure.
In CMake any function definitions contains the only piece of information for the caller - minimal number of parameters which should be passed to the function. By using this information it is impossible to resolve function's overloading, if it would be implemented.

Why cannot CMake functions return values?

A question for CMake experts out-there.
According to the CMake function documentation a function simply does not return anything. To change variable values one has to pass it to the function, and inside the function set the new value specifying the PARENT_SCOPE option.
Fine, this is a well-known feature of CMake.
My question here is not about the how, rather on why: why CMake functions do not return values? What is the idea behind?
For example, a function cannot be used inside a if expression, or called inside a set command.
If I remember correctly, it is the same with autotools, therefore I do not think it is like this just by chance.
Is there any expert that knows why?
You can find a partial answer by Ken Martin in a message from the CMake's mailing list:
With respect to the general question of functions returning values it
could be done but it is a bit of a big change. Functions and commands
look the same (and should act the same IMO) to the people using them.
So really we are talking about commands returning values. This is
mostly just a syntax issue. Right now we have
command(arg arg arg
)
to support return values we need something that could handle
command (arg command2(arg arg) arg arg
)
or in your case
if(assertdef(foo))
or in another case
set(foo get_property(
))
etc. This hits the parser and the argument processing in CMake but I
think it could be done. I guess I’m not sure if we should do it.
Open to opinions here.

Dynamic casting in SV using $cast function and task

How can we tell if the calling of $cast is of a function or of a task. How would calling of each differ? One thing I understand is that with the function call, I'll be able to use assert(). But other than that, what tells us if the call is of the $cast function or the $cast task? In either case, we'd be doing something like $cast(pkt, pkt1);
LRM gives the syntax of the $cast function as
function int $cast( singular dest_var, singular source_exp );
and of the $cast task as
task $cast( singular dest_var, singular source_exp );
and goes on to explain that
Use of $cast as either a task or a function determines how invalid assignments are handled.
When called as a task, $cast attempts to assign the source expression
to the destination variable. If the assignment is invalid, a run-time
error occurs, and the destination variable is left unchanged.
When called as a function, $cast attempts to assign the source expression
to the destination variable and returns 1 if the cast is legal. If the
cast fails, the function does not make the assignment and returns 0.
When called as a function, no run-time error occurs, and the
destination variable is left unchanged.
Please explain.
Your comment is correct: if $cast is used as part of an expression, it is considered called as a function. That wording is derived from Verilog terminology when functions could only be used in an expression and never could exist as a simple statement like a task call. But once SystemVerilog added functions with void return types, that wording does not fit as well anymore.

Erlang Looping through a list (or set) to process files

I want to create 16 directories in Erlang.
for ( create_dir("work/p" ++ A, where A is an element in a list [0, 1, ... f]) (sixteen number in hex notation).
I could of course write sixteen lines like: mkdir ("work/p0"), mkdir("work/p1") etc.
I have looked at lists:foreach. In the examples fun is used, is possible to define a function outside the loop and call it?
I am new to Erlang and used to C++ etc.
Yes, it's possible to define a (named) function outside the call to lists:foreach/2. Why would you, though? This is a case when an anonymous function is incredibly handy:
lists:foreach(fun(N) ->
file:make_dir(
filename:join("work", "p"++integer_to_list(N, 16)))
end, lists:seq(0, 15)).
The filename:join/2 call will use the appropriate directory separator to construct the string work/pN, where N is an integer in hex representation constructed using integer_to_list/2, which converts an integer to a string (list) in a given base (16).
lists:seq/2 is a friendly little function that returns the list [A,A+1,A+2,...,B-1,B] given A and B.
Note that you could just as well have used the list comprehension syntax here, but since we're applying functions to a list for the side-effects alone, I chose to stick with a foreach.
If you really want to define a separate function -- let's call it foo and assume it takes 42 arguments -- you can refer to it as fun foo/42 in your code. This expression evaluates to a function object that, like an anonymous function defined inline, can be passed to lists:foreach/2.