I am using the latest version 2.8.1
I tried project source and binary relative pathes without success. Here is the code: https://github.com/dadhi/LempTest/blob/strong text9ce17d16a8d7c71fc475921e1414e5bc64d72f9d/LibWithEcs/ServiceRegistrations.ecs.include#L3
Also, I am not sure how to pass the directory via --set:key=value. Should I wrap the key or value in quotes, escape the slashes?
And if I succeed in passing, could I #get(key) in compileTime
section and somehow use it for #r?
I have created a simple Test.ecs file to test the --set:key=value
output
compileTime
{
using C = System.Console;
var a = #get(a);
C.WriteLine(a);
}
Here what I found:
lemp Test.ecs --set:a="c:"
returns "Error: Expected a particle (id, literal, {braces} or (parens))."lemp Test.ecs --set:a=@"c:"
returns "c:"lemp Test.ecs --set:a=@"c:\Code"
returns the same "c:"lemp Test.ecs --set:a=@"c:\\Code"
again returns the same "c:"and at least
lemp Test.ecs --set:a="""c:\\Code"""
works and outputs "c:\Code"The final puzzle piece for me was passing the $(ProjectDir)
as a value of the set:key=value
command-line switch.
Here is the final (actually not, see Update below) solution:
<Target Name="LempTransform" BeforeTargets="BeforeBuild">
<PropertyGroup>
<ProjectDirEscaped>$(ProjectDir.Replace('\', '___'))</ProjectDirEscaped>
</PropertyGroup>
<!-- <Message Text="Project with escaped slashes is $(ProjectDirEscaped)" Importance="high"/> -->
<Exec WorkingDirectory="$(ProjectDir)"
Command="dotnet lemp %(EcsFile.Identity) --outext=.Generated.cs --set:ProjectDir=@"$(ProjectDirEscaped)"" />
</Target>
The main problem was even using @"$(ProjectDir)"
was not enough because the ProjectDir
outputs the path with single slashes like c:\foo\bar
. Then there is no way to escape them inside the string literal. So I've ended up replacing slashes manually with string.Replace
and then replacing them back when working with the key in .ecs
file:
compileTime
{
##reference(precompute(System.IO.Path.Combine(#get(ProjectDir).Replace("___", "\\"), @"..\AnotherLib\bin\Debug\netstandard2.0\AnotherLib.dll")));
using AnotherLib;
//...
The comment helped a lot, so I don't need to Replace
escaped value back in consuming template.
First, I am replacing \
with /
instead of ___
which still keeps the path a valid for .NET BCL API:
<PropertyGroup>
<ProjectDirEscaped>$(ProjectDir.Replace('\', '/'))</ProjectDirEscaped>
</PropertyGroup>
Consequently, I don't need to Replace
when using the path in ##reference
:
##reference(precompute(System.IO.Path.Combine(#get(ProjectDir), @"..\AnotherLib\bin\Debug\netstandard2.0\AnotherLib.dll")));
Relative paths in #r
are working for me in the Visual Studio extension. The path should be relative to the source file location.
To find out the input folder where the file "believes" it is, write #get(#inputFolder);
at the top of the file and then look at LeMP's output. If the output says _numget(_numinputFolder)
, something went wrong - the variable is unset, but it would be possible to set its value on the command line: --set:#inputFolder="C:\\Dev\\MyFolder"
.
After --set:
, key=value
is parsed as an assignment expression, so you should wrap the value in quotes and replace backslashes with double-backslashes. (The expression syntax is LES or the current input language if any - --inlang=ecs
for Enhanced C#)
You can use #get(key)
inside compileTime
; however, the #r
directive is parsed in a very dumb way because of the directive's very dumb syntax (which is different from normal C# strings). As a result, macros cannot be used on the #r
line. You probably don't need to hack around this limitation, but if you do, you can replace #r "dir\Foo.dll"
with its equivalent Loyc tree ##reference(@"""dir\\Foo.dll""");
(the extra quotes are optional) and then you can use macros in the modified line.
It did not occur to me that one could use precompute
inside compileTime
, but you can and it works. So for example you can do ##reference(precompute(System.IO.Path.Combine(@"dir", "Foo.dll")));
.