แนวปฏิบัติที่ดีที่สุดสำหรับ“ Copy Local” และการอ้างอิงโครงการคืออะไร


154

ฉันมีไฟล์โซลูชัน c # ขนาดใหญ่ (ประมาณ 100 โครงการ) และฉันพยายามปรับปรุงเวลาสร้าง ฉันคิดว่า "Copy Local" เป็นเรื่องสิ้นเปลืองในหลาย ๆ กรณีสำหรับเรา แต่ฉันสงสัยเกี่ยวกับแนวทางปฏิบัติที่ดีที่สุด

ใน. sln ของเราเรามีแอปพลิเคชัน A ขึ้นอยู่กับแอสเซมบลี B ซึ่งขึ้นอยู่กับแอสเซมบลี C ในกรณีของเรามี "B" และ "C" เพียงไม่กี่อย่าง เนื่องจากสิ่งเหล่านี้รวมอยู่ใน. sln เราจึงใช้การอ้างอิงโครงการ ชุดประกอบทั้งหมดในปัจจุบันสร้างเป็น $ (SolutionDir) / Debug (หรือ Release)

โดยค่าเริ่มต้น Visual Studio ทำเครื่องหมายการอ้างอิงโครงการเหล่านี้เป็น "Copy Local" ซึ่งส่งผลให้ทุก "C" ถูกคัดลอกลงใน $ (SolutionDir) / Debug หนึ่งครั้งสำหรับ "B" ทุกครั้งที่สร้าง ดูเหมือนว่าสิ้นเปลือง เกิดอะไรขึ้นถ้าฉันเพิ่งปิด "คัดลอกท้องถิ่น" คนอื่นที่มีระบบขนาดใหญ่ทำอะไรได้บ้าง

ติดตาม:

คำตอบมากมายแนะนำให้ทำการ build เป็นไฟล์. sln ที่มีขนาดเล็กกว่า ... ในตัวอย่างข้างต้นฉันจะสร้างคลาสพื้นฐาน "C" ก่อนตามด้วยกลุ่มของโมดูล "B" และจากนั้นแอปพลิเคชั่นสองสามตัว " A" ในรุ่นนี้ฉันต้องมีการอ้างอิงที่ไม่ใช่โครงการไปยัง C จาก B ปัญหาที่ฉันพบคือนั่นคือ "Debug" หรือ "Release" ถูกอบเข้าสู่เส้นทางคำใบ้และฉันจบการสร้าง Release build ของ "B" กับการแก้ปัญหาการสร้างของ "C"

สำหรับบรรดาของคุณที่แบ่งการสร้างเป็นไฟล์. sln หลายไฟล์คุณจะจัดการปัญหานี้ได้อย่างไร


9
คุณสามารถทำให้คำแนะนำเส้นทางของคุณอ้างอิงไดเรกทอรี Debug หรือ Release โดยแก้ไขไฟล์โครงการโดยตรง ใช้ $ (การกำหนดค่า) แทน Debug หรือ Release เช่น <HintPath> .. \ output \ $ (Configuration) \ test.dll </HintPath> นี่เป็นความเจ็บปวดเมื่อคุณมีการอ้างอิงจำนวนมาก (แม้ว่ามันจะไม่ยากสำหรับคนที่จะเขียน Add-in ไป จัดการสิ่งนี้)
ultravelocity

4
'Copy Local' ใน Visual Studio เหมือนกับ<Private>True</Private>csproj หรือไม่
พันเอก Panic

แต่แยกขึ้น.slnเป็นคนเล็กแบ่งการคำนวณพึ่งพา VS ของ automagic ของ<ProjectReference/>s ฉันย้ายจากเล็ก ๆ น้อย.slnๆ ไปเป็นใหญ่.slnเพียงตัวเดียวเพราะ VS ทำให้เกิดปัญหาน้อยลงเช่นนั้น ... ดังนั้นบางทีการติดตามอาจถือว่าเป็นทางออกที่ไม่จำเป็นที่สุดสำหรับคำถามเดิม ;-)
binki

เพิ่งออกมาจากความอยากรู้ ทำไมต้องทำสิ่งที่ซับซ้อนและมี 100+ โครงการตั้งแต่แรก? นี่เป็นการออกแบบที่ไม่ดีหรือเปล่า
UsefulBee

@ColonelPanic ใช่ อย่างน้อยนั่นคือสิ่งที่เปลี่ยนบนดิสก์เมื่อฉันเปลี่ยนสลับใน GUI
Zero3

คำตอบ:


85

ในโครงการก่อนหน้านี้ฉันทำงานกับโซลูชันขนาดใหญ่ที่อ้างอิงโครงการและชนกับปัญหาด้านประสิทธิภาพเช่นกัน คำตอบคือสามเท่า:

  1. ตั้งค่าคุณสมบัติการคัดลอกภายในเครื่องเป็นเท็จเสมอและบังคับใช้ผ่านขั้นตอน msbuild ที่กำหนดเอง

  2. ตั้งค่าไดเรกทอรีผลลัพธ์สำหรับแต่ละโครงการเป็นไดเรกทอรีเดียวกัน (โดยเฉพาะที่สัมพันธ์กับ $ (SolutionDir)

  3. เป้าหมาย cs เริ่มต้นที่มาพร้อมกับเฟรมเวิร์กคำนวณชุดการอ้างอิงที่จะคัดลอกไปยังไดเรกทอรีผลลัพธ์ของโครงการที่กำลังสร้าง เนื่องจากต้องมีการคำนวณการปิดสกรรมกริยาภายใต้ความสัมพันธ์ 'การอ้างอิง' จึงอาจมีราคาแพงมาก วิธีแก้ปัญหาของฉันสำหรับการนี้คือการสร้างนิยามGetCopyToOutputDirectoryItemsเป้าหมายในไฟล์เป้าหมายร่วมกัน (เช่น. Common.targets) Microsoft.CSharp.targetsที่นำเข้าในทุกโครงการหลังจากนำเข้าของ ทำให้ไฟล์โครงการทุกไฟล์มีลักษณะดังนี้:

    <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <PropertyGroup>
        ... snip ...
      </ItemGroup>
      <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
      <Import Project="[relative path to Common.targets]" />
      <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
           Other similar extension points exist, see Microsoft.Common.targets.
      <Target Name="BeforeBuild">
      </Target>
      <Target Name="AfterBuild">
      </Target>
      -->
    </Project>

สิ่งนี้ลดเวลาการสร้างของเราในเวลาที่กำหนดจากสองสามชั่วโมง (ส่วนใหญ่เนื่องจากข้อ จำกัด ของหน่วยความจำ) เป็นสองถึงสามนาที

GetCopyToOutputDirectoryItemsสามารถสร้างนิยามใหม่ได้โดยการคัดลอกบรรทัด 2,438–2,450 และ 2,474–2,524 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Microsoft.Common.targetsเข้าCommon.targetsมา

เพื่อความสมบูรณ์ของการกำหนดเป้าหมายผลลัพธ์ที่ได้จะกลายเป็น:

<!-- This is a modified version of the Microsoft.Common.targets
     version of this target it does not include transitively
     referenced projects. Since this leads to enormous memory
     consumption and is not needed since we use the single
     output directory strategy.
============================================================
                    GetCopyToOutputDirectoryItems

Get all project items that may need to be transferred to the
output directory.
============================================================ -->
<Target
    Name="GetCopyToOutputDirectoryItems"
    Outputs="@(AllItemsFullPathWithTargetPath)"
    DependsOnTargets="AssignTargetPaths;_SplitProjectReferencesByFileExistence">

    <!-- Get items from this project last so that they will be copied last. -->
    <CreateItem
        Include="@(ContentWithTargetPath->'%(FullPath)')"
        Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='Always' or '%(ContentWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"
            >
        <Output TaskParameter="Include" ItemName="AllItemsFullPathWithTargetPath"/>
        <Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectoryAlways"
                Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
        <Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectory"
                Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
    </CreateItem>

    <CreateItem
        Include="@(_EmbeddedResourceWithTargetPath->'%(FullPath)')"
        Condition="'%(_EmbeddedResourceWithTargetPath.CopyToOutputDirectory)'=='Always' or '%(_EmbeddedResourceWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"
            >
        <Output TaskParameter="Include" ItemName="AllItemsFullPathWithTargetPath"/>
        <Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectoryAlways"
                Condition="'%(_EmbeddedResourceWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
        <Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectory"
                Condition="'%(_EmbeddedResourceWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
    </CreateItem>

    <CreateItem
        Include="@(Compile->'%(FullPath)')"
        Condition="'%(Compile.CopyToOutputDirectory)'=='Always' or '%(Compile.CopyToOutputDirectory)'=='PreserveNewest'">
        <Output TaskParameter="Include" ItemName="_CompileItemsToCopy"/>
    </CreateItem>
    <AssignTargetPath Files="@(_CompileItemsToCopy)" RootFolder="$(MSBuildProjectDirectory)">
        <Output TaskParameter="AssignedFiles" ItemName="_CompileItemsToCopyWithTargetPath" />
    </AssignTargetPath>
    <CreateItem Include="@(_CompileItemsToCopyWithTargetPath)">
        <Output TaskParameter="Include" ItemName="AllItemsFullPathWithTargetPath"/>
        <Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectoryAlways"
                Condition="'%(_CompileItemsToCopyWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
        <Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectory"
                Condition="'%(_CompileItemsToCopyWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
    </CreateItem>

    <CreateItem
        Include="@(_NoneWithTargetPath->'%(FullPath)')"
        Condition="'%(_NoneWithTargetPath.CopyToOutputDirectory)'=='Always' or '%(_NoneWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"
            >
        <Output TaskParameter="Include" ItemName="AllItemsFullPathWithTargetPath"/>
        <Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectoryAlways"
                Condition="'%(_NoneWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
        <Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectory"
                Condition="'%(_NoneWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
    </CreateItem>
</Target>

ด้วยวิธีการแก้ปัญหาในสถานที่นี้ฉันพบว่าสามารถทำงานได้มากถึง> 120 โครงการในโซลูชันเดียวสิ่งนี้มีประโยชน์หลักที่การสร้างลำดับของโครงการยังสามารถกำหนดได้โดย VS แทนที่จะทำด้วยมือโดยแยกโซลูชันของคุณ .


คุณสามารถอธิบายการเปลี่ยนแปลงที่คุณทำและทำไม? ดวงตาของฉันเหนื่อยเกินไปหลังจากวันที่ยาวนานในการเขียนโค้ดเพื่อพยายามที่จะทำวิศวกรรมย้อนกลับด้วยตัวเอง :)
Charlie Flowers

ลองคัดลอกและวางใหม่อีกครั้งดังนั้นทำให้เกิดความสับสนถึง 99% ของแท็ก
ZXX

@Charlie Flowers, @ZXX แก้ไขข้อความเป็นคำอธิบายไม่สามารถทำให้ xml เป็นแบบได้
Bas Bossink

1
จาก Microsoft.Common.targets: GetCopyToOutputDirectoryItems รับรายการโครงการทั้งหมดที่อาจต้องโอนไปยังไดเรกทอรีผลลัพธ์ ซึ่งรวมถึงรายการกระเป๋าสัมภาระจากโครงการอ้างอิงที่มีการเปลี่ยนแปลง ดูเหมือนว่าเป้าหมายนี้จะคำนวณการปิดรายการเนื้อหาสำหรับโครงการอ้างอิงทั้งหมด อย่างไรก็ตามนั่นไม่ใช่กรณี
Brans Ds

2
มันจะรวบรวมไอเท็มเนื้อหาจากลูกของมันทันทีไม่ใช่จากลูก ๆ เหตุผลนี้เกิดขึ้นได้ว่ารายการ ProjectReferenceWithConfiguration ที่ถูกใช้โดย _SplitProjectReferencesByFileExistence จะมีเฉพาะในโครงการปัจจุบันและว่างเปล่าในเด็ก ๆ รายการที่ว่างเปล่าทำให้ _MSBuildProjectReferenceExference เป็นค่าว่างและยกเลิกการสอบถามซ้ำ ดังนั้นจึงดูเหมือนว่าไม่มีประโยชน์
Brans Ds

32

ฉันขอแนะนำให้คุณอ่านบทความของ Patric Smacchia ในหัวข้อนั้น:

โครงการ CC.Net VS พึ่งพาตัวเลือกชุดประกอบการอ้างอิงสำเนาโลคัลที่ตั้งค่าเป็นจริง [... ] ไม่เพียงเพิ่มการรวบรวมอย่างมีนัยสำคัญ (x3 ในกรณีของ NUnit) เท่านั้น แต่ยังทำให้สภาพแวดล้อมการทำงานของคุณยุ่งเหยิง ท้ายสุด แต่ไม่ท้ายสุดการทำเช่นนี้จะแนะนำความเสี่ยงสำหรับปัญหาที่อาจเกิดขึ้นกับเวอร์ชัน Btw, NDepend จะส่งคำเตือนหากพบ 2 แอสเซมบลีใน 2 ไดเรกทอรีต่าง ๆ ที่มีชื่อเดียวกัน แต่ไม่ใช่เนื้อหาหรือเวอร์ชันเดียวกัน

สิ่งที่ต้องทำคือการกำหนด 2 ไดเรกทอรี $ RootDir $ \ bin \ Debug และ $ RootDir $ \ bin \ Release และกำหนดค่าโครงการ VisualStudio ของคุณเพื่อปล่อยแอสเซมบลีในไดเรกทอรีเหล่านี้ การอ้างอิงโครงการทั้งหมดควรอ้างอิงแอสเซมบลีในไดเรกทอรี Debug

คุณสามารถอ่านบทความนี้เพื่อช่วยลดจำนวนโครงการและปรับปรุงเวลารวบรวมของคุณ


1
ฉันหวังว่าฉันจะสามารถแนะนำวิธีปฏิบัติของ Smacchia ที่มีมากกว่าหนึ่ง upvote! การลดจำนวนโครงการเป็นกุญแจสำคัญไม่แยกการแก้ปัญหา
Anthony Mastrean

23

ฉันขอแนะนำให้มีการคัดลอก local = false สำหรับโครงการเกือบทั้งหมดยกเว้นโครงการที่อยู่ด้านบนของแผนภูมิการพึ่งพา และสำหรับการอ้างอิงทั้งหมดในอันเดียวที่ด้านบน set copy local = true ฉันเห็นคนจำนวนมากแนะนำให้แชร์ไดเรกทอรีผลลัพธ์ ฉันคิดว่านี่เป็นความคิดที่น่ากลัวจากประสบการณ์ หากโครงการเริ่มต้นของคุณมีการอ้างอิงถึง dll ที่โครงการอื่น ๆ ถือการอ้างอิงถึงคุณในบางจุดจะมีการละเมิดการเข้าถึง \ sharing แม้ว่าการคัดลอก local = false ในทุกสิ่งและการสร้างของคุณจะล้มเหลว ปัญหานี้น่ารำคาญมากและยากที่จะติดตาม ฉันขอแนะนำให้อยู่ห่างจากไดเรกทอรีเอาท์พุทชาร์ดและแทนที่จะให้โครงการที่ด้านบนของห่วงโซ่การพึ่งพาเขียนส่วนประกอบที่จำเป็นไปยังโฟลเดอร์ที่เกี่ยวข้อง หากคุณไม่มีโครงการที่ "ด้านบน" จากนั้นฉันจะแนะนำสำเนาโพสต์บิลด์เพื่อให้ได้ทุกอย่างในที่ที่เหมาะสม นอกจากนี้ฉันจะพยายามจำให้ง่ายในการดีบัก โครงการ exe ใด ๆ ที่ฉันยังคงคัดลอก local = true ดังนั้นประสบการณ์การดีบัก F5 จะทำงานได้


2
ฉันมีความคิดแบบเดียวกันนี้และหวังว่าจะหาคนอื่นที่คิดแบบเดียวกันที่นี่ แต่ฉันอยากรู้ว่าทำไมโพสต์นี้ไม่มี upvotes มากขึ้น คนที่ไม่เห็นด้วย: ทำไมคุณถึงไม่เห็นด้วย?
bwerks

ไม่ไม่สามารถเกิดขึ้นได้เว้นแต่โครงการเดียวกันกำลังสร้างสองครั้งทำไมมันถึงถูกเขียนทับ \ access \ sharing การละเมิดถ้าสร้างขึ้นครั้งเดียวและไม่คัดลอกไฟล์ใด ๆ
paulm

นี้. หากเวิร์กโฟลว์การพัฒนาต้องการสร้างโครงการหนึ่งของ sln ในขณะที่อีกโซลูชันที่คาดการณ์ได้ของโซลูชันกำลังทำงานอยู่การมีทุกอย่างในไดเรกทอรีผลลัพธ์เดียวกันจะยุ่งเหยิง ดีกว่าการแยกโฟลเดอร์เอาต์พุตที่สามารถเรียกใช้งานได้ในกรณีนี้
Martin Ba

10

คุณถูก. CopyLocal จะฆ่าเวลาสร้างของคุณอย่างแน่นอน หากคุณมีต้นกำเนิดที่มีขนาดใหญ่คุณควรปิดการใช้งาน CopyLocal น่าเสียดายที่มันไม่ง่ายอย่างที่ควรจะเป็นการปิดการใช้งานอย่างหมดจด ฉันได้ตอบคำถามตรงนี้เกี่ยวกับการปิดใช้งาน CopyLocal ที่ฉันจะแทนที่การตั้งค่า CopyLocal (ส่วนตัว) สำหรับการอ้างอิงใน. NET จาก MSBUILDได้อย่างไร ลองดูสิ รวมถึงแนวปฏิบัติที่ดีที่สุดสำหรับโซลูชันขนาดใหญ่ใน Visual Studio (2008)

นี่คือข้อมูลเพิ่มเติมเกี่ยวกับ CopyLocal ตามที่ฉันเห็น

CopyLocal ถูกนำมาใช้จริง ๆ เพื่อสนับสนุนการดีบักในเครื่อง เมื่อคุณเตรียมใบสมัครของคุณสำหรับบรรจุภัณฑ์และการปรับใช้คุณควรสร้างโครงการของคุณไปยังโฟลเดอร์ผลลัพธ์เดียวกันและตรวจสอบให้แน่ใจว่าคุณมีการอ้างอิงทั้งหมดที่คุณต้องการ

ผมได้เขียนเกี่ยวกับวิธีการจัดการกับการสร้างแหล่งต้นไม้ขนาดใหญ่ในบทความMSBuild: Best Practices สำหรับการสร้างความน่าเชื่อถือสร้างส่วนที่ 2


8

ในความคิดของฉันการแก้ปัญหาด้วย 100 โครงการเป็นความผิดพลาดครั้งใหญ่ คุณอาจแบ่งโซลูชันของคุณออกเป็นหน่วยเล็ก ๆ ที่ใช้ได้ซึ่งทำให้การบำรุงรักษาและสร้างง่ายขึ้น


1
บรูโน่, โปรดดูคำถามที่ตามมาของฉันด้านบน - ถ้าเราแบ่งเป็นไฟล์. sln ที่มีขนาดเล็กลง, คุณจะจัดการด้าน Debug vs. Release ได้อย่างไร, ซึ่งจะถูกอบเข้าสู่เส้นทางคำใบ้ของการอ้างอิงของฉัน?
Dave Moore

1
ฉันเห็นด้วยกับประเด็นนี้วิธีแก้ปัญหาที่ฉันทำงานด้วยมีประมาณ 100 โครงการเพียงไม่กี่แห่งเท่านั้นที่มีมากกว่า 3 คลาสการสร้างเวลาน่าตกใจและด้วยเหตุนี้ผู้บุกเบิกของฉันจึงแยกโซลูชันออกเป็น 3 อย่างสมบูรณ์ การอ้างอิงทั้งหมดและการสร้างใหม่ สิ่งทั้งหมดสามารถพอดีกับโครงการจำนวนหนึ่งซึ่งจะสร้างในไม่กี่วินาที!
Jon M

เดฟเป็นคำถามที่ดี ที่ที่ฉันทำงานเรามีสคริปต์สร้างที่ทำสิ่งต่าง ๆ เช่นสร้างการอ้างอิงสำหรับโซลูชันที่กำหนดและวางไบนารีไว้ที่ใดที่โซลูชันที่เป็นปัญหาสามารถรับได้ สคริปต์เหล่านี้เป็นพารามิเตอร์สำหรับทั้งการดีบักและปล่อยบิลด์ ข้อเสียคือเพิ่มเวลาพิเศษในการสร้างสคริปต์ดังกล่าว แต่สามารถนำไปใช้ซ้ำในแอปได้ วิธีนี้ใช้ได้ผลดีตามมาตรฐานของฉัน
jyoungdev

7

ฉันประหลาดใจที่ไม่มีใครพูดถึงการใช้ลิงก์ แทนที่จะเป็นการคัดลอกไฟล์มันจะสร้างฮาร์ดลิงก์ไปยังไฟล์ต้นฉบับ สิ่งนี้จะช่วยประหยัดพื้นที่ดิสก์และช่วยเร่งการสร้างได้อย่างมาก สิ่งนี้สามารถเปิดใช้งานบนบรรทัดคำสั่งด้วยคุณสมบัติต่อไปนี้:

/ p: CreateHardLinksForAdditionalFilesIfPossible = true; CreateHardLinksForCopyAdditionalFilesIfPossible = true; CreateHardLinksForCopyFilesToOutputDirectoryIfPossible = true; CreateHardLinksForCopyLocalIfPossible = true; CreateHardLinksForPublishFilesIfPossible = true

คุณยังสามารถเพิ่มสิ่งนี้ลงในไฟล์นำเข้าส่วนกลางเพื่อให้โครงการของคุณทั้งหมดได้รับประโยชน์นี้ด้วย


5

หากคุณมีโครงสร้างการพึ่งพาที่กำหนดไว้ผ่านการอ้างอิงโครงการหรือผ่านการพึ่งพาระดับโซลูชันมันปลอดภัยที่จะเปลี่ยนเป็น "Copy Local" ฉันยังบอกได้ว่ามันเป็นสิ่งที่ต้องปฏิบัติที่ดีที่สุดเพราะจะทำให้คุณใช้ MSBuild 3.5 เพื่อสร้างบิลด์ ผ่าน / maxcpucount) โดยไม่มีกระบวนการที่แตกต่างกันซึ่งกันและกันเมื่อพยายามคัดลอกชุดประกอบที่อ้างอิง


4

"แนวปฏิบัติที่ดีที่สุด" ของเราคือการหลีกเลี่ยงโซลูชันที่มีหลายโครงการ เรามีไดเรกทอรีชื่อ "matrix" พร้อมชุดประกอบรุ่นปัจจุบันและการอ้างอิงทั้งหมดมาจากไดเรกทอรีนี้ หากคุณเปลี่ยนโครงการและคุณสามารถพูดว่า "ตอนนี้การเปลี่ยนแปลงเสร็จสมบูรณ์" คุณสามารถคัดลอกแอสเซมบลีลงในไดเรกทอรี "เมทริกซ์" ดังนั้นโครงการทั้งหมดที่ขึ้นอยู่กับแอสเซมบลีนี้จะมีเวอร์ชันปัจจุบัน (= ล่าสุด)

หากคุณมีโครงการไม่กี่โครงการที่แก้ปัญหากระบวนการสร้างจะเร็วกว่ามาก

คุณสามารถทำขั้นตอน "การประกอบสำเนาไปยังไดเรกทอรีเมทริกซ์" โดยอัตโนมัติโดยใช้มาโครสตูดิโอหรือด้วยเมนู "- เครื่องมือ -> เครื่องมือภายนอก ... "


3

คุณไม่จำเป็นต้องเปลี่ยนค่า CopyLocal สิ่งที่คุณต้องทำคือกำหนด $ ทั่วไป (OutputPath) ล่วงหน้าสำหรับโครงการทั้งหมดในโซลูชันและตั้งค่า $ (UseCommonOutputDirectory) ให้เป็นจริง ดูสิ่งนี้: http://blogs.msdn.com/b/kirillosenkov/archive/2015/04/04/using-a-common-intermediate-and-output-directory-for-your-solution.aspx


ฉันไม่แน่ใจว่ามันพร้อมใช้งานได้ในปี 2552 แต่ดูเหมือนจะใช้งานได้ดีในปี 2558 ขอบคุณ!
Dave Moore

2

ตั้งค่า CopyLocal = false จะลดเวลาการสร้าง แต่อาจทำให้เกิดปัญหาที่แตกต่างกันระหว่างการปรับใช้

มีหลายสถานการณ์เมื่อคุณจำเป็นต้องคัดลอก Local 'เหลือเป็น True เช่น

  • โครงการระดับบน
  • การพึ่งพาระดับที่สอง
  • ที่กำลังเรียกโดยสะท้อน

ปัญหาที่เป็นไปได้ที่อธิบายไว้ในคำถาม SO
" เมื่อใดควรตั้งค่าการทำสำเนาภายในเครื่องเป็นจริงและไม่ควรทำเมื่อใด ",
" ข้อความแสดงข้อผิดพลาด" ไม่สามารถโหลดประเภทที่ขอหนึ่งประเภทขึ้นไปได้ "
และ   คำตอบของaaron-stainback  สำหรับคำถามนี้

ประสบการณ์ของฉันกับการตั้งค่า CopyLocal = false ไม่สำเร็จ ดูโพสต์บล็อกของฉัน"อย่าเปลี่ยน" คัดลอก Local "โครงการอ้างอิงถึงเป็นเท็จเว้นแต่จะเข้าใจองค์ประกอบ

เวลาในการแก้ไขปัญหาน้ำหนักเกินประโยชน์ของการตั้งค่า copyLocal = false


การตั้งค่าCopyLocal=Falseจะทำให้เกิดปัญหาบางอย่าง แต่มีวิธีแก้ไขปัญหาเหล่านั้น นอกจากนี้คุณควรแก้ไขการจัดรูปแบบของบล็อกของคุณซึ่งแทบจะไม่สามารถอ่านได้และบอกว่า "ฉันได้รับคำเตือนจาก <random consulting> จาก <random company> เกี่ยวกับข้อผิดพลาดที่อาจเกิดขึ้นระหว่างการปรับใช้" ไม่ใช่ข้อโต้แย้ง คุณต้องพัฒนา
Suzanne Dupéron

@ GeorgesDupéronเวลาในการแก้ไขปัญหาน้ำหนักเกินประโยชน์ของการตั้งค่า copyLocal = false การอ้างอิงถึงที่ปรึกษาไม่ใช่ข้อโต้แย้ง แต่เป็นเครดิตและบล็อกของฉันอธิบายว่าปัญหาคืออะไร ขอบคุณสำหรับคำติชมของคุณ การจัดรูปแบบฉันจะแก้ไข
Michael Freidgeim

1

ฉันมักจะสร้างไดเรกทอรีทั่วไป (เช่น .. \ bin) ดังนั้นฉันจึงสามารถสร้างโซลูชันทดสอบขนาดเล็กได้


1

คุณสามารถลองใช้โฟลเดอร์ที่ชุดประกอบทั้งหมดที่แชร์ระหว่างโครงการจะถูกคัดลอกจากนั้นสร้างตัวแปรสภาพแวดล้อม DEVPATH และตั้งค่า

<developmentMode developerInstallation="true" />

ในไฟล์ machine.config บนเวิร์กสเตชันของนักพัฒนาแต่ละคน สิ่งเดียวที่คุณต้องทำคือการคัดลอกเวอร์ชั่นใหม่ในโฟลเดอร์ของคุณที่มีตัวแปร DEVPATH

แบ่งโซลูชันของคุณออกเป็นโซลูชันเล็ก ๆ น้อย ๆ ถ้าเป็นไปได้


น่าสนใจ ... มันจะทำงานอย่างไรกับ debug vs. release builds?
เดฟมัวร์

ฉันไม่แน่ใจว่ามีวิธีแก้ปัญหาที่เหมาะสมหรือไม่สำหรับการโหลด debug / release assemblies ผ่าน DEVPATH มันมีจุดประสงค์เพื่อใช้สำหรับ assembly ที่ใช้ร่วมกันเท่านั้นฉันไม่แนะนำให้สร้าง build ปกติ โปรดทราบด้วยว่าแอสเซมบลีรุ่นและ GAC จะถูกเขียนทับเมื่อใช้เทคนิคนี้
Aleksandar

1

นี่อาจไม่ใช่การฝึกหัดที่ดีที่สุด แต่นี่คือวิธีที่ฉันทำงาน

ฉันสังเกตเห็นว่า Managed C ++ ทิ้งไบนารีทั้งหมดลงใน $ (SolutionDir) / 'DebugOrRelease' ดังนั้นฉันก็ทิ้งโปรเจ็กต์ C # ทั้งหมดของฉันที่นั่นด้วย ฉันยังปิด "คัดลอก Local" ของการอ้างอิงทั้งหมดไปยังโครงการในโซลูชัน ฉันมีการปรับปรุงเวลาสร้างที่น่าสังเกตในโซลูชันโครงการขนาดเล็ก 10 ตัวของฉัน โซลูชันนี้เป็นส่วนผสมของ C #, C ++ ที่มีการจัดการ, C ++ ดั้งเดิม, C # webservice และโครงการตัวติดตั้ง

อาจจะมีบางอย่างผิดปกติ แต่เนื่องจากนี่เป็นวิธีเดียวที่ฉันทำงานฉันจึงไม่สังเกตเห็น

มันจะน่าสนใจที่จะค้นหาสิ่งที่ฉันแตกหัก


0

โดยปกติคุณจะต้องคัดลอก Local หากคุณต้องการให้โครงการของคุณใช้ DLL ที่อยู่ใน Bin ของคุณเทียบกับที่อื่น (GAC โครงการอื่น ๆ ฯลฯ )

ฉันมักจะเห็นด้วยกับคนอื่น ๆ ที่คุณควรลองด้วยหากเป็นไปได้เพื่อเลิกแก้ปัญหานั้น

คุณยังสามารถใช้เครื่องมือจัดการการกำหนดค่าเพื่อทำให้การกำหนดค่าบิลด์ที่แตกต่างกันภายในโซลูชันเดียวที่จะสร้างเฉพาะชุดโครงการที่กำหนด

มันจะดูแปลก ๆ หากโครงการทั้งหมด 100 โครงการพึ่งพากันดังนั้นคุณควรจะสามารถแยกมันออกหรือใช้เครื่องมือจัดการการกำหนดค่าเพื่อช่วยตัวเอง


0

คุณสามารถให้การอ้างอิงโครงการของคุณชี้ไปที่เวอร์ชันการดีบักของ dll ได้ นอกเหนือจากสคริปต์ msbuild ของคุณคุณสามารถตั้งค่าได้/p:Configuration=Releaseดังนั้นคุณจะมีแอปพลิเคชันรุ่นที่วางจำหน่ายและชุดดาวเทียมทั้งหมด


1
บรูโน่ - ใช่สิ่งนี้ใช้ได้กับการอ้างอิงโครงการซึ่งเป็นหนึ่งในเหตุผลที่เราใช้โซลูชั่นโครงการ 100 รายการตั้งแต่แรก มันใช้งานไม่ได้กับการอ้างอิงที่ฉันเรียกดูรุ่น Debug ที่สร้างไว้ล่วงหน้า - ฉันปิดท้ายด้วยแอป Release ที่สร้างขึ้นจากชุดประกอบ Debug ซึ่งเป็นปัญหา
Dave Moore

4
แก้ไขไฟล์โครงการของคุณในโปรแกรมแก้ไขข้อความและใช้ $ (การกำหนดค่า) ใน HintPath ของคุณเช่น <HintPath> .. \ output \ $ (การกำหนดค่า) \ test.dll </HintPath>
ultravelocity


0

หากไม่มีการอ้างอิงอยู่ใน GAC เราจะต้องตั้งค่า Copy Local เป็นจริงเพื่อให้แอปพลิเคชันทำงานหากเรามั่นใจว่าการอ้างอิงนั้นจะถูกติดตั้งไว้ใน GAC แล้วก็สามารถตั้งค่าเป็นเท็จได้


0

แน่นอนว่าฉันไม่รู้วิธีแก้ปัญหา แต่ฉันได้ติดต่อกับโซลูชันบิลด์ที่ช่วยตัวเองในการสร้างไฟล์ทั้งหมดที่วางไว้บน ramdiskด้วยความช่วยเหลือของการเชื่อมโยงสัญลักษณ์

  • c: \ solution folder \ bin -> ramdisk r: \ solution โฟลเดอร์ \ bin \
  • c: \ solution folder \ obj -> ramdisk r: \ solution โฟลเดอร์ \ obj \

  • นอกจากนี้คุณยังสามารถบอกต่อว่าสตูดิโอภาพที่ไดเรกทอรีชั่วคราวที่สามารถใช้สำหรับการสร้าง

จริงๆแล้วนั่นไม่ใช่ทั้งหมดที่มันทำ แต่มันก็ทำให้ฉันเข้าใจการแสดงมากขึ้น
การใช้โปรเซสเซอร์ 100% และโครงการขนาดใหญ่ภายในไม่ถึง 3 นาทีพร้อมการพึ่งพาทั้งหมด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.