coapp / coapp.powershell

ClrPlus Signing
52 stars 43 forks source link

Requested: a command like CopyToOutput, but to an arbitrary folder #20

Open yodantauber opened 11 years ago

yodantauber commented 11 years ago

Files included in the autopackage script with "bin:" are automatically copied to the output folder of the project consuming the package. I suppose this is triggered by this line in PackageScriptTemplate.autopkg:

#add-each-file : ::nuget.[redist]targets.[${condition}].CopyToOutput;

It seems that this CopyToOutput command is defined in C# code and not in an autopackage script, so it cannot be easily overridden in my scripts. What I would like is a command very like CopyToOutput (which still uses the MSBuild Copy task to copy when building, and still uses hard links as I requested in a previous issue), except it will copy the files to an arbitrarily supplied folder instead of the project target folder. This folder may vary by pivots (win32, x64, debug, release...).

What I need to achieve by this: instead of copying 3rd party DLLs to the output folder when building, I have to collect all 3rd party DLLs in one central folder, separated by platform.

yodantauber commented 11 years ago

After some further consideration of this issue, I'm realizing that the decisions of whether the DLLs should be copied somewhere or not, and of whether the destination is the output folder or some other arbitrary folder, are not for the package designer to make. They are for the package consumer to make, because this depends on their specific development environment: in our case, we must collect all 3rd party DLLs in one folder, and all of our own DLLs and EXEs in another folder (both said folders are separated by platform).

Therefore, instead of being able to specify a destination folder in a CopyToOutput-like command in package design time, what I probably really want is a way for the package consumer to specify the destination folder for all package DLLs. When it is unspecified, the DLLs should probably still be copied to the consuming project output folder (assuming it is not a static LIB project). When it is specified, the DLLs should be copied to the specified folder. This setting should depend on project configurations, e.g. to be able to vary by platform.

Note that the package consumer should be able to somehow set this globally (e.g. by a *.props file imported by many projects): in the scenario I described, many projects will use the same destination folder for 3rd party DLLs (varying only by platform), and it wouldn't make sense to specify it manually in each and every project (and in each project configuration).

Implementation idea (just brainstorming with myself): instead of specifying "$(TargetDir)" as the destination of the Copy task, specify a custom property "$(3rdPartyDllDir)". In the .targets file of the package, specify a default value of 3rdPartyDllDir = "$(TargetDir)" on the condition that 3rdPartyDllDir isn't set. Then the project consumer can override this value to whatever, either directly in the project file or through another imported .props / *.targets file. I would also support skipping the copying altogether if this is set to an empty string.

yodantauber commented 11 years ago

Some further refinement, if I may: Other than my request that CopyToOutput will copy to a custom $(3rdPartyDllDir) instead of $(TargetDir) directly, I think I still do also need a separate copy command that will copy to a different folder (perhaps with no destination path explicitly set in the package itself, but only with another MSBuild property which defaults to TargetDir). This is to be used for distribution of content or data files that are needed for the library in the package, but should not reside in the same path as the 3rd party DLLs in the development environment. Perhaps call it "CopyToRedist", "CopyToDataFolder", "CopyToContentFolder" etc.

Also, the actual target folder should be nested under the specified "global content folder" (see the last example here for recursive copying in MSBuild).

fearthecowboy commented 11 years ago

fyi: I'm stuck in out-of-office meetings until Friday; don't panic, I'll be back :D

fearthecowboy commented 10 years ago

I think you guys are right on the money here.

Doing this correctly shouldn't be too tricky. I think I can even generate the XAML property so that this will be overridable in the properties window.

I had an idea how to renovate the copy tasks a bit last night; it involves generating something in the .targets file that looks kinda like this:

    <ItemGroup Condition="**generatedconditionstatement**">
        <CopyToWhereverISay Include="somefile.xyz" />
        <CopyToWhereverISay Include="some_more_files\**\*.abc" />
    </ItemGroup>

    <Target name="AfterBuild" >
        <Copy SourceFiles="@(CopyToWhereverISay)" DestinationFolder="$(WhereverISayDestination)" />
    </Target>

I'm pretty sure I can make all that work, it means we just have do define the destination folder, and way of saying which group the source files are to be combined with.

I'll keep the bin folder as targeting $(TargetDir) -- actually I'll make sure that it uses a folder copy instead of per-file by default, so that it will work naturally with a tree of files.

And then I'll add a way to add files to a collection, which we can associate to a Copy Task with a destination.

Hmm. Most of this would almost work right now if I had the #add-folder metatdata tack on \** to the collection.

gordonwatts commented 10 years ago

You have moved past my knowledge of how the MSBuild system works, but the solution above sounds like it has the flexibility we have been talking about. The only thing that I'm not sure about is the MSBuild CopyTaks. Doesn't the copy task flatten its input list of files into the output directory - so you'd loose the deep folder structure again? Also, would this structure be able to support multiple destination folders? Oh, that is the comment about using $(TargetDir)...

fearthecowboy commented 10 years ago

Live neck deep in this problem for the last five years, and you would quickly learn the deepest, darkest things about MSBuild.

The funniest part is that I wrote a prototype a few year ago of a build automation tool (what eventually became the invoke-build command in CoApp) that internally worked fairly similar to MSBuild . It wasn't very hard to move to using MSBuild for the underlying engine later...

The copy task maintains the folder layout (when used correctly :D )..

And, yeah, this will support multiple, arbitrary destinations.

gordonwatts commented 10 years ago

Sweet! Thanks, and sorry for your pain. :-) (though I live neck deep in makefiles on Linux as part of my work, and I think MSBuild is better). And looking forward to testing what you've got. :-)

fearthecowboy commented 10 years ago

I've got a new Development version posted that supports this.(see the issue #27 thread for the example)

use

  PS > update-coapptools –Development -killallpowershells

To update to my current Dev version (as of this moment, 2.4.164.0 )

As soon as I can get a bit more testing on this to make sure that it's at least fairly stable, and doesn't have any really broken things, I'll promote this to 'Beta'

yodantauber commented 10 years ago

Thanks, I've been able to get this to work much in the same way that gordonwatts has.