Tuesday, July 17, 2012 5:49 AM
Is it possible to use a user macro before it is defined?
The flow of my props files is such that a user macro defined at the end of the flow should be used at the beginning. But from tests it seems that if I do it like that an empty string (without even a warning!) is used instead of user macro as soon as it is used.
I could redesign the flow but I would find it much more useful if I could somehow "forward declare" a user macro.
Wednesday, July 18, 2012 5:06 AMModerator
I can't know your purpose well. Please post more detail about your issue.
I guess you want to run a macro programming. However what does "before it is defined" mean?
On the other hand, this forum is about msbuild. Is your issue concerned about msbuild?
MSDN Community Support | Feedback to us
Wednesday, July 18, 2012 5:29 AM
In our scenario we have a bunch of props files. They are included in a strict hierarchy. First some common settings/macros then conditional (if exists) inclusions of props files constructed by joining platform, configuration and solution in various ways.
This way common staff like bin/tmpBin folder is kept in a single props file while we still can do some extra/special configuration for various setups (like for example add some extra macros in some configuration or use extra include paths in some solutions/project).
Various solution files are placed in different folders within the entire workbench layout. But we need to know the root folder of the workbench so that the bin/tmpBin folders are located relative to it rather than relative to solution. The solution seemed to be to use the conditionally included props files to define "offset" from $(SolutionDir) to workbench dir. So for each solution X.sln we would have to have and X.props files that would define SolutionToRoot user macro (for example of value ..\..\). Then by joining SolutionDir and that SolutionToRoot we would have the Root.
The issue is however that the X.props file in current hierarchy is included at the end of all props files. While the bin/tmpBin (which require the Root) are defined at the beginning. I have used $(Root) in the first props files knowing that it will be defined to proper value later. But it didn't work because as soon as I used $(Root) it used its current value which was nothing (as the user macro wasn't defined yet).
Obviously I could just include the X.props at the beginning of the hierarchy. But it didn't seem nice enough since it forces me to change the inclusion order (which does have some other consequences) each time I would need to have some early-used late-defined user macro.
If this description is not clear enough I will try to attach some simplified structure of props files.
Friday, July 20, 2012 9:28 AMModerator
I will involve some experts into this issue to see whether they can help you out. There might be some time delay, appreciate for your patience.
Thank you for your understanding and support.
MSDN Community Support | Feedback to us
Friday, July 20, 2012 8:11 PM
I just realized that I can introduce yet another family of props files named (for example): "SolutionToRoot-$(SolutionName).props". Which would contain nothing but definition of user macro "$(SolutionToRoot)" being the relative path from solution folder to workbench root. For example:
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ImportGroup Label="PropertySheets" /> <PropertyGroup Label="UserMacros"> <SolutionToRoot></SolutionToRoot> </PropertyGroup> <PropertyGroup /> <ItemDefinitionGroup /> <ItemGroup> <BuildMacro Include="SolutionToRoot"> <Value>$(SolutionToRoot)</Value> </BuildMacro> </ItemGroup> </Project>
Then at the very begining of the main props file (which imports all the others) I can add:
<ImportGroup Label="PropertySheets"> <Import Project="SolutionToRoot-$(SolutionName).props" />
This way all following files can use "$(SolutionToRoot)" since it is already defined. For example:
<PropertyGroup Label="UserMacros"> <WorkbenchRoot>$(SolutionDir)$(SolutionToRoot)</WorkbenchRoot> <BinRoot>$(WorkbenchRoot)bin</BinRoot> <DocsRoot>$(WorkbenchRoot)docs</BinRoot>
(Please note that although this solution does allow to have solution files in different folders in the workbench it still requires that they have unique names. Probably this could be somehow worked around.)
Its not that I didn't knew about that possibility. After all in the very first post I wrote that "I could redesign the flow". What I didn't realize is that this particular approach has some advantages. Now I can include "SolutionToRoot-$(SolutionName).props" unconditionally and thus have better error detection. Also they are simple and schematic thus easy to maintain.
But still the original issue remains since it seems it would be much better if user macros were resolved once entire file was read so you could use them before they are actually defined.