2011-01-26 11 views
6

Tôi không quan tâm một sự lặp lại thường xuyên của một cái gì đó khi nó là cần thiết, nhưng trong MSBuild tôi thực sự không biết làm thế nào để bao giờ tránh lặp lại. Nó không cung cấp "chức năng" theo nghĩa thông thường; một mục tiêu chỉ có thể được gọi một lần, thậm chí thông qua CallTarget<Import> chỉ hoạt động ở mức Project.Làm thế nào để tránh lặp lại trong MSBuild?

Dưới đây là một ví dụ cụ thể tôi đang cố gắng để De- "repetize":

<Target Name="Tgt1"> 
    <PropertyGroup><Conf1>Twiddle</Conf1><Conf2>Thing</Conf2></PropertyGroup> 

    <PropertyGroup><xxxxxxxxxxExePath>$(xxxxxxxBuildRoot)\$(Conf1)Console-xxxxxxxxed</xxxxxxxxorExePath></PropertyGroup> 
    <MSBuild Projects="$(BuildSingleProj)" Targets="Build;Merge" 
      Properties="Configuration=$(Conf1)$(Conf2);Platform=$(Platform);CompiledFileName=$(CompiledFileName);ProjectName=$(ProjectName);SolutionFile=$(SolutionFile);Root=$(Root);Caller=$(MSBuildProjectFullPath)"/> 
    <MakeDir Directories="$(xxxxxxxxorExePath)" /> 
    <WriteLinesToFile File="$(xxxxxxxxorExePath)\xxxxxxx.IsPortable.txt" /> 
    <WriteLinesToFile File="$(xxxxxxxxorExePath)\xxxxxxx.Global.Settings.xml" Lines="@(xxxxxxxLicense)" Overwrite="true" /> 
    <Exec Command='$(xxxxxxxxorExePath)\xxxxxxx.exe -a "$(xxxxxxxBuildRoot)\$(Conf1)$(Conf2)-Merged\xxxxxxx.exe" "$(xxxxxxxBuildRoot)\$(Conf1)$(Conf2)-xxxxxxxxed\xxxxxxx.exe"'/> 
</Target> 

Tôi có bốn mục tiêu như vậy, Tgt1, Tgt2, Tgt3, Tgt4. Chỉ chỉ điều khác biệt giữa bốn mục tiêu này là dòng đầu tiên, dòng đầu tiên xác định Conf1Conf2.

Ý tưởng sao chép nhiều hơn hoặc ít khả thi hơn mà tôi biết là bằng cách di chuyển mã được chia sẻ sang một mục tiêu mới và gọi nó qua nhiệm vụ MSBuild. Điều này, thật không may, yêu cầu một chuỗi thuộc tính loooooong được truyền theo cách thủ công và tác vụ này sử dụng khá ít (tôi đã đếm 11 thuộc tính và 1 nhóm mặt hàng).

Yêu cầu bổ sung là tôi có thể gọi tập lệnh bằng một tập hợp con tùy ý của các mục tiêu này, ví dụ: \t:Tgt2,Tgt3.

Có bất kỳ giải pháp thay thế hợp lý nào để chỉ sao chép/dán đoạn mã này - không liên quan đến việc sao chép quanh danh sách lớn các thuộc tính thay thế không?

Trả lời

8

Đây là kịch bản hoàn hảo để sử dụng Batching.

Bạn sẽ cần tạo Items tùy chỉnh với siêu dữ liệu thích hợp và sau đó tạo một Mục tiêu duy nhất để tham chiếu Mặt hàng mới.

Bạn có thể quấn mỗi Item trong mục tiêu riêng của nó như sau:

<Target Name="Tgt1"> 
    <ItemGroup> 
    <BuildConfig Include="Tgt1"> 
     <Conf1>Twiddle</Conf1> 
     <Conf2>Thing</Conf2> 
    </BuildConfig> 
    </ItemGroup> 
</Target> 

<Target Name="Tgt2"> 
    <ItemGroup> 
    <BuildConfig Include="Tgt2"> 
     <Conf1>Twaddle</Conf1> 
     <Conf2>Thing 1</Conf2> 
    </BuildConfig> 
    </ItemGroup> 
</Target> 

<Target Name="Tgt3"> 
    <ItemGroup> 
    <BuildConfig Include="Tgt3"> 
     <Conf1>Tulip</Conf1> 
     <Conf2>Thing 2</Conf2> 
    </BuildConfig> 
    </ItemGroup> 
</Target> 

Sau đó bạn sẽ cần một mục tiêu cốt lõi để gọi đó sẽ thực hiện tất cả các công việc như sau:

<Target Name="CoreBuild" Outputs="%(BuildConfig.Identity)"> 
    <Message Text="Name : %(BuildConfig.Identity)" /> 
    <Message Text="Conf1 : %(BuildConfig.Conf1)" /> 
    <Message Text="Conf2 : %(BuildConfig.Conf2)" /> 
</Target> 

Thêm Outputs="%(BuildConfig.Identity)" vào mục tiêu sẽ đảm bảo bạn có hàng loạt ở cấp mục tiêu thay vì ở cấp nhiệm vụ.

Bạn có thể thực hiện điều này từ msbuild bằng cách chuyển các kết hợp tùy ý của các mục tiêu miễn là mục tiêu cuối cùng là mục tiêu cốt lõi của bạn. Ví dụ thực hiện lệnh này MSBuild.exe test.msbulid /t:Tgt1,Tgt3,CoreBuild sẽ cung cấp cho bạn kết quả sau:

Name : Tgt1 
Conf1 : Twiddle 
Conf2 : Thing 

Name : Tgt3 
Conf1 : Tulip 
Conf2 : Thing 2 
+0

Nhưng điều này có nghĩa là tôi không còn có thể xây dựng chỉ một hoặc hai trong số chúng, đúng không? Bất kỳ cách nào để bảo tồn khả năng đó? –

+0

Bạn có thể đặt điều kiện vào các mục. Tôi sẽ cập nhật câu trả lời với một ví dụ. –

+0

Cảm ơn bạn, mặc dù tôi có thể thấy các điều kiện trở nên khá phức tạp nếu tôi muốn bao gồm bất kỳ _two_ bản dựng nào. Tôi hiện đang hướng tới việc giữ sự lặp lại bởi vì tôi muốn giữ khả năng chỉ định '/ t: Tgt1, Tgt2' - tập lệnh thực sự có thêm một vài mục tiêu, và chúng ta dựa vào khả năng chọn các tập con tùy ý như thế này. –

5

DRY không phải là nguyên lý của MSBuild. Với điều đó đang được nói rằng nó không tốt để lặp lại chính mình trong mọi trường hợp, khi nó là hợp lý tránh được. Câu trả lời mà Aaron đưa ra liên quan đến việc xếp hàng là một câu trả lời hay. Đây là một phương tiện để ngăn chặn trùng lặp.

Một điều mà tôi muốn chỉ ra là ở cấp độ cao hơn có vẻ như bạn đang nghĩ về MSBuild như một ngôn ngữ thủ tục (tức là có các chức năng mà bạn có thể gọi và những gì không). MSBuild là nhiều hơn declarative hơn mặc dù thủ tục.Nếu bạn đang tạo các kịch bản MSBuild và bạn có suy nghĩ 'Tạo hàm X để tôi có thể gọi nó tại điểm Y', thì bạn đang bước vào một thế giới đau đớn. Thay vào đó bạn nên nghĩ về MSBuild như là các giai đoạn. Ví dụ; Khi bạn nghĩ về nó theo cách này thì nó có ý nghĩa tổng thể tại sao các mục tiêu bị bỏ qua sau khi chúng được thực thi một lần (mà bạn đã thấy rõ ràng trong các thử nghiệm của bạn).

Cũng sau khi đã làm việc với MSBuild miễn là tôi đã tìm ra rằng nó thực sự có thể là một PITA để làm mọi thứ theo cách chung/có thể tái sử dụng. Nó có thể được thực hiện, nhưng tôi sẽ dự trữ loại nỗ lực đó cho các tệp .targets mà bạn biết chắc chắn sẽ được sử dụng lại nhiều lần lần. Bây giờ một ngày thay vì đi qua đó tôi thực tế hơn nhiều và tôi hạ cánh ở đâu đó giữa các kịch bản hack hoàn toàn & làm những việc theo cách tôi đã từng làm. Tôi có một tập hợp các tập lệnh mà tôi sử dụng lại, nhưng bên cạnh những tập lệnh tôi cố gắng và giữ mọi thứ đơn giản. Một lý do lớn cho điều này là có rất nhiều người biết làm thế nào cơ bản của MSBuild, nhưng rất ít người có kiến ​​thức rất sâu sắc về nó. Việc tạo các kịch bản lệnh chung tốt đòi hỏi kiến ​​thức sâu về MSBuild, vì vậy khi bạn rời khỏi dự án, người đứng sau bạn sẽ không biết bạn đang làm gì (có lẽ tốt nếu bạn là nhà thầu? Lol).

Trong bất kỳ trường hợp nào, tôi có một loạt tài nguyên theo đợt tại: http://sedotech.com/Resources#Batching.

+0

Cảm ơn thông tin chi tiết này; hy vọng sẽ giúp tôi cố gắng hết sức. Tôi đã cố gắng để xem MSBuild là khai báo, nhưng chắc chắn ngay cả những ngôn ngữ khai báo cũng cần một cơ chế để tạo ra các trừu tượng hóa. Xin lỗi vì đã đề xuất tên "chức năng", đó chắc chắn là thuật ngữ sai. –

+0

Tôi đã bí mật hi vọng có một số cơ chế tuyệt vời mà tôi không biết. Có lẽ một số cách để giảm bớt nỗi đau khi vượt qua bộ _same_ gồm 10 thuộc tính cho một số tác vụ MSBuild? Tôi gần như đã có thực sự, chỉ có các tài sản đã được đánh giá quá sớm, và tôi không thể tìm thấy bất cứ điều gì như "eval" để đánh giá chúng chỉ khi chúng được chuyển đến MSBuild ... –

+0

Nếu bạn muốn "eval" mục, sau đó bạn cần phải đặt ItemGroup bên trong của một mục tiêu mà bạn sẽ thực hiện. ItemGroup elmenets bên ngoài của các mục tiêu được đánh giá trước khi bất kỳ exectues mục tiêu, nhưng ItemGroup yếu tố bên trong của các mục tiêu được đánh giá tại thời điểm mục tiêu thực hiện. –