2009-02-05 9 views
8

मेरे पास कुछ बिल्ड आउटपुट कॉपी करने के लिए एमएसबिल्ड में पोस्ट-बिल्ड लक्ष्य है।जब एक csproj नहीं बनाया गया है तो बिल्डबिल्ड लक्ष्य को दबाकर

<Target Name="AfterBuild" DependsOnTargets="InstallUtil;CopyPostBuildFiles" /> 

वहाँ किसी भी तरह से फ़ाइलें यदि निर्माण वास्तव में फिर से निर्माण नहीं किया प्रतिलिपि बनाई जा रही से बचने के लिए है:

यह AfterBuild लक्ष्य (Microsoft.CSharp.targets द्वारा उजागर) के लिए एक निर्भरता के रूप में में जुड़ा हुआ है?

उदाहरण के लिए, जब एमएसबिल्ड निर्भरता विश्लेषण का दावा है कि परियोजना को बनाने की आवश्यकता नहीं है क्योंकि इसकी कोई भी स्रोत फाइल अपडेट नहीं की गई है, यह निर्माण नहीं करती है, लेकिन फिर भी मेरी प्रतिलिपि लक्ष्य निष्पादित करती है। क्या इसे रोकने का कोई तरीका है?

उत्तर

7

के बारे में अधिक जानकारी के लिए इस पेज देखें। यह पुनर्निर्माण या सामान्य निर्माण के मामले में है। यदि आप पुनर्निर्माण (और निर्माण नहीं) के बाद कुछ क्रियाएं करना चाहते हैं तो आपको पुनर्निर्माण लक्ष्य के लिए निर्भरता संपत्ति का विस्तार करना चाहिए। तो अपने मामले में लक्ष्य एक के पुनर्निर्माण के अपने प्रोजेक्ट फाइल होने के बाद कुछ ऐसा दिखाई देगा सुई:

<Project ...> 
    <!-- some content here --> 

    <Import Project="... Microsoft.Csharp.targets" /> 


    <PropertyGroup> 
     <RebuildDependsOn> 
      $(RebuildDependsOn); 
      InstallUtil; 
      CopyPostBuildFiles 
     </RebuildDependsOn> 
    </PropertyGroup> 
</Project> 

इस विधि संपत्ति जो लक्ष्य के पुनर्निर्माण की घोषणा करने के क्या लक्षित करता है उस पर निर्भर करता है फैली हुई है। मैंने लेख Inside MSBuild में विस्तृत किया है, अनुभाग देखें प्रक्रिया का विस्तार करना।

इसके अलावा, आप क्या हासिल करना AfterBuild लक्ष्य से प्राप्त किया जा सकता है कि तुम क्या क्या फ़ाइलें "ट्रिगर" एक अद्यतन होने के लिये हैं निर्दिष्ट कर सकते हैं कोशिश कर रहे हैं। दूसरे शब्दों में आप लक्ष्य में "इनपुट" का एक सेट और "आउटपुट" का एक सेट निर्दिष्ट कर सकते हैं जो दोनों फाइलें हैं। यदि सभी आउटपुट सभी इनपुट के बाद बनाए गए थे तो लक्ष्य को अद्यतित माना जाएगा और छोड़ दिया जाएगा। इस अवधारणा को वृद्धिशील भवन के रूप में जाना जाता है और मैंने लेख MSBuild Best Practices Part 2 में इसे कवर किया है। इसके अलावा मैंने अपनी पुस्तक, Inside the Microsoft Build Engine: Using MSBuild and Team Foundation Build में इसका विस्तार किया है।

संपादित करें: यदि आप केवल निष्पादित जब फ़ाइलें वास्तव में निर्माण कर रहे हैं करने के लिए लक्ष्य चाहते हैं और जब पुनर्निर्माण लक्ष्य निष्पादित किया जाता है नहीं तो BuildDependsOn उदाहरण

जोड़ा जा रहा है।

<Project ...> 
    <!-- some content here --> 

    <Import Project="... Microsoft.Csharp.targets" /> 


    <PropertyGroup> 
     <BuildDependsOn> 
      $(BuildDependsOn); 
      CustomAfterBuild; 
     </BuildDependsOn> 
    </PropertyGroup> 
    <Target Name="CustomAfterBuild" Inputs="$(MSBuildAllProjects); 
      @(Compile);        
      @(_CoreCompileResourceInputs); 
      $(ApplicationIcon); 
      $(AssemblyOriginatorKeyFile); 
      @(ReferencePath); 
      @(CompiledLicenseFile); 
      @(EmbeddedDocumentation); 
      $(Win32Resource); 
      $(Win32Manifest); 
      @(CustomAdditionalCompileInputs)" 
    Outputs="@(DocFileItem); 
      @(IntermediateAssembly); 
      @(_DebugSymbolsIntermediatePath);     
      $(NonExistentFile); 
      @(CustomAdditionalCompileOutputs)"> 

    <!-- Content here --> 

    </Target> 

</Project> 

मैं बस की नकल की इनपुट और Microsoft.CSharp.targets के अंदर CoreCompile लक्ष्य (मैं अपने यहां सी # का उपयोग कर रहे संभालने कर रहा हूँ से आउटपुट: तो फिर आप निम्नलिखित की तरह बनना अपनी परियोजना बनाना चाहिए) और इसे यहां चिपकाया। इसका अर्थ यह है कि जब भी कोरकंपाइल लक्ष्य निष्पादित किया जाता है तो लक्ष्य छोड़ा जाएगा। चूंकि मैंने BuildDepends को बढ़ाया है, हम जानते हैं कि एमएसबिल्ड परियोजना के निर्माण के दौरान इसे आजमाएगा और निष्पादित करेगा।

+0

ऐसा प्रतीत होता है कि "RebuildDependsOn" लक्ष्य अपडेट करने से केवल अतिरिक्त चरणों को ट्रिगर करने का कारण बन जाएगा यदि आप स्पष्ट रूप से "पुनर्निर्माण" लक्ष्य का आह्वान करते हैं। यदि आप "बिल्ड" का आह्वान करते हैं तो वे ट्रिगर नहीं करेंगे। –

+0

मैंने अभी इस मामले को कवर करने के लिए इसे संपादित किया है। मैं जो चाहता था उसके बारे में उलझन में था। क्या यह काम करता है? –

+0

इनपुट और आउटपुट का उपयोग करने के लिए मेरे लिए काम किया। मेरे मामले में मैं परियोजना की मुख्य आउटपुट फ़ाइल का उपयोग करने में सक्षम था - यानी $ (लक्ष्यपैथ) - अन्य सभी निर्भरताओं के लिए प्रॉक्सी के रूप में। – yoyo

0

बिल्ड लक्ष्य परिभाषा है:

<Target Name = "Build" DependsOnTargets="BeforeBuild;CoreBuild;AfterBuild"/> 

मुझे लगता है कि CoreBuild निष्पादित नहीं है, तो अपनी फ़ाइलें नहीं बदला है, तो आप AfterBuild के बजाय AfterCompile उपयोग करने की कोशिश कर सकता है।

<Target Name="AfterCompile" DependsOnTargets="InstallUtil;CopyPostBuildFiles" /> 
+0

अच्छा विचार है, लेकिन ऐसा लगता है कि यह बहुत अंतर नहीं है। AfterBuild को AfterCompile में बदलने के बाद भी प्रतिलिपि हर बार निष्पादित होती है। –

+0

ओह क्षमा करें, मेरा टेस्ट केस क्रैपी ^^ होना चाहिए। –

0

इसके बारे में क्या।

  • BuildBreak। संकलन त्रुटि होने पर सत्य पर सेट करें, अन्यथा झूठी। निर्माण ब्रेक लक्ष्य का उपयोग यह निर्धारित करने के लिए किया जा सकता है कि वे संकलन त्रुटि या सामान्य रूप से निष्पादित करने के बाद निष्पादित हैं या नहीं।

http://blogs.msdn.com/aaronhallberg/archive/2008/02/12/team-build-2008-property-reference.aspx

मैं इसे करने की कोशिश नहीं की है, लेकिन यह काफी आशाजनक लगता है।

+0

हाय मार्क, यह संपत्ति एक अच्छी खोज है, हालांकि मैं कुछ ऐसा करने के बाद हूं जो मुझे "नोप बिल्ड" के बाद कॉपी कार्यों को दबाएगा, जहां वास्तव में कुछ भी नहीं बनाया गया है क्योंकि सभी आउटपुट को अद्यतित माना जाता है। –

6

इनपुट और आउटपुट लक्ष्य के गुणों का उपयोग करने के बारे में क्या है जैसे संकलन लक्ष्य में किया गया है।

<PropertyGroup> 
    <PostBuildDir>CopiedFilesDirectory</PostBuildDir> 
</PropertyGroup> 

<Target Name="AfterBuild" DependsOnTargets="InstallUtil;CopyPostBuildFiles" /> 

<Target Name="CopyPostBuildFiles" 
     Inputs="@(PostBuildFiles)" 
     Outputs="@(PostBuildFiles -> '$(PostBuildDir)%(Filename)%(Extension)'"> 
    <Copy SourceFiles="@(PostBuildFiles)" 
      DestinationFolder="PostBuildDir"/> 
</Target> 

आप इस्तेमाल किया हो सकता है कि CopyPostBuildFiles और InstallUtil या सीधे पर पर AfterBuild। आप AfterBuild को लक्षित यह हमेशा का निर्माण होता है के बाद निष्पादित करेंगे अधिभावी कर रहे हैं के बाद से

Targets Inputs Outputs

8

मैंने अभी इसे गुगल किया और इस साल का पुराना जवाब पाया। मुझे मुख्य लक्ष्य से आइडिया चुराकर, थोड़ा आसान करने के लिए एक रास्ता मिला। दोनों BeforeBuild और AfterBuild ओवरराइड और की तरह कुछ कार्य करें:

<Target Name="BeforeBuild"> 
    <PropertyGroup> 
     <MyBeforeCompileTimestamp>%(IntermediateAssembly.ModifiedTime) 
       </MyBeforeCompileTimestamp> 
    </PropertyGroup> 
    </Target> 

    <Target Name="AfterBuild"> 
    <CallTarget Condition="$(MyBeforeCompileTimestamp) != 
      %(IntermediateAssembly.ModifiedTime)" Targets="MyTarget" /> 
    </Target> 
+0

धन्यवाद! यह मेरे लिए बिल्कुल समाधान था। – fmuecke

-1

मैं MSBuild के बारे में ज्यादा पता नहीं है, लेकिन सी # के लिए दृश्य स्टूडियो के द्वारा प्रयोग किया MSBuild परियोजनाओं के मामले में एक सरल दिमाग दूसरा रास्ता नहीं है: का प्रयोग करें एक आफ्टरबिल्ड लक्ष्य के बजाय पोस्ट-बिल्ड बिल्ड इवेंट।

आप तीसरे टैब "बिल्ड इवेंट्स" पर विजुअल स्टूडियो प्रोजेक्ट गुण संवाद के माध्यम से एक पोस्ट-बिल्ड बिल्ड इवेंट सेट अप कर सकते हैं। कुछ स्थितियों के लिए इस संवाद पर कुछ आदेश दर्ज करना एक विचार हो सकता है, और उसके बाद यह निर्धारित करने के बाद सीधे .csproj फ़ाइल को संपादित करें कि यह कैसे काम करता है।

डायल द्वारा अनुरोध की गई कार्यक्षमता प्राप्त करने की कुंजी है - "इस पोस्ट-बिल्ड इवेंट को चलाएं: जब बिल्ड प्रोजेक्ट आउटपुट अपडेट करता है" का चयन करना याद रखें।

जैसा कि मैंने कहा, मुझे एमएसबिल्ड के बारे में बहुत कुछ पता नहीं है, और हो सकता है कि पोस्ट-बिल्ड बिल्ड इवेंट कुछ चीजों के लिए लागू न हो जो AfterBuild लक्ष्य कर सकता है। लेकिन मैंने इसे फाइलों की प्रतिलिपि बनाने और बीएटी स्क्रिप्ट चलाने के लिए उपयोग किया है, और इसके लिए यह ठीक काम करता है।

संपादित करें:

मैं कैसे मैं आमतौर पर मेरी सी # परियोजनाओं में होने वाली घटनाओं के बाद निर्माण का उपयोग के बारे में कुछ नोट्स जोड़ देंगे।

कार्यक्षमता के विभिन्न क्षेत्रों को अलग करने के लिए मैं आमतौर पर PostBuildEvent.bat नामक एक बीएटी स्क्रिप्ट तैयार करता हूं, और इसे .csproj फ़ाइल के समान फ़ोल्डर में रखता हूं।

cd $(ProjectDir) 
PostBuildEvent.bat 

तब मैं आदेशों मैं PostBuildEvent.bat फ़ाइल में मनचाहे स्थान: फिर मेरी पोस्ट-निर्माण घटना केवल दो पंक्तियों में शामिल है।यहाँ एक उदाहरण है:

copy "..\..\..\..\..\Shared Bin\Merlinia.CommonClasses.NamedPipesNative.dll" bin 
copy "..\..\..\..\..\Shared Bin\Merlinia.CommonClasses.NamedPipesNative.pdb" bin 

cd Packed-NonObfuscated 
call PackForWindowsSystem32-NonObfuscated.bat 
cd ..\ 

cd Packed-Obfuscated 
call PackForWindowsSystem32-Obfuscated.bat 
cd ..\ 

pause 

याद रखें कि एक बैट स्क्रिप्ट आप स्पष्ट रूप से "कॉल" निर्दिष्ट से एक बैट स्क्रिप्ट कॉल करने के लिए। नोट "रोकें" का उपयोग भी करें - इससे बीएटी फ़ाइल पर डबल-क्लिक करके स्क्रिप्ट का परीक्षण करना संभव हो जाता है और फिर आप cmd विंडो में कोई त्रुटि संदेश देख सकते हैं। जब एमएसबिल्ड के माध्यम से स्क्रिप्ट चलाया जाता है तो "रोकें" को अनदेखा किया जाता है।

0

यह AfterBuild लक्ष्य लागू करेगा यदि और केवल यदि परियोजना लक्ष्य फ़ाइल फिर से बनाया गया है:

<Target Name="AfterBuild" 
    DependsOnTargets="InstallUtil;CopyPostBuildFiles" 
    Inputs="$(TargetPath)" 
    Outputs="$(DeployPath)\$(TargetFileName)" /> 

यह मानता है कि आप एक संपत्ति $(DeployPath) उस फ़ोल्डर जहाँ आप लक्ष्य आउटपुट फ़ाइल की नकल की पहचान करता है परिभाषित किया है।