镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Fix "Clean" build target for xamarin-android repo #1129

Closed

Description

@atsushieno

There is no working "Clean" process. MSBuild is lame by design and does not appropriately resolve dependencies in reverse order so any project whose "Clean" target depends on dependencies's outcome will abort.

We should scrap MSBuild or (insert anything here; I can't think of any reasonable way to achieve this. Any other solution results in external tooling to automatically track dependencies).

Activity

  1. atsushieno commented on Dec 22, 2017

    @atsushieno
    ContributorAuthor

    How to resolve stupid MSBuild solution structure with broken Clean targets

    Current "(simple and?) stupid" MSBuild style

    Target "Build"

    (all.sln)
    
       Project("{project_type_guid}") = "depending" "depending.proj", "{project_guid}"
       EndProject
       Project("{project_type_guid}") = "dependency" "dependency.proj", "{project_guid}"
       EndProject
       Project("{project_type_guid}") = "further_dependency" "further_dependicy.proj", "{project_guid}"
       EndProject
    
    (depending.proj)
    
    	<Reference Project="dependency.proj">
    	  <ReferenceOutputAssembly>False</ReferenceOutputAssembl
    	</Reference>
    
    (dependency.proj)
    
    	<Reference Project="further_dependency.proj">
    	  <ReferenceOutputAssembly>False</ReferenceOutputAssembl
    	</Reference>
    
    • Dependencies are not obvious.
    • Dependencies can be externally inserted that are hard to identify.

    target Clean

    WTF, TELL ME HOW TO DO THIS!

    msbuild /t:Clean all.sln doesn't work fine, as depending.proj could be using artifacts from dependency.proj etc.

    Makefile style

    Target "Build"

    all: depending.dll
    
    depending.dll: dependency.dll
    	msbuild depending.proj
    
    dependency.dll: further_dependency.dll
    	msbuild dependency.proj
    
    further_dependency.dll:
    	msbuild further_dependency.proj
    

    (Remove <Reference>s in the .proj.)

    target Clean

    clean: clean-depending clean-dependency clean-further_dependency
    
    clean-depending:
    	msbuild /t:Clean depending.proj
    
    clean-dependency:
    	msbuild /t:Clean dependency.proj
    
    clean-further-dependency:
    	msbuild /t:Clean further_dependency.proj
    

    Processed in order. It is clean and easy enough to understand.

    Proposed "clever" MSBuild style

    • DO NOT USE <Reference><ReferenceOutputAssembly>True</></>
    • Use <BuildDependsOn> and list things in well-structured order, if necessary.

    Code:

    (all.sln) - unchanged. Do not expect .sln do the right job. It's lame by design.
    
    all.proj
    
    <Target Name="Build">
      <MSBuild Targets="Clean" Projects="depending.proj dependency.proj further_dependency.proj" />
    </Target>
    
    <Target Name="Clean">
      <MSBuild Targets="Clean" Projects="depending.proj dependency.proj further_dependency.proj" />
    </Target>
    

    Bring in cleanliness to this ugly XML land.

    Conclusion

    • Create all.proj for building everything.
    • scrap away Xamarin.Android.sln, automatically generate it from all.csproj.
  2. atsushieno commented on Jan 5, 2018

    @atsushieno
    ContributorAuthor
  3. atsushieno commented on Jan 5, 2018

    @atsushieno
    ContributorAuthor

    The updated solution content analyzer (rev. 2 on the gist) gives more structured solution information. Namely, the output became as simple as https://github.com/proxy/gist.github.com/atsushieno/671667cbe09140862f1081f0e3c196f4 . This is against the fixed solution from PR #1159.

  4. jonpryor commented on Jan 9, 2018

    @jonpryor
    Contributor

    target Clean

    WTF, TELL ME HOW TO DO THIS!

    What do we want out of a Clean target? What is the intention?

    We could create a make clean rule which runs git clean -xdff. Would that be sufficient or adequate?

    Alternatively, we could "fix" our Clean targets to not require use of generated files. For example, src/OpenTK-1.0/OpenTK.csproj could change the Xamarin.Android.CSharp.targets import to be conditional:

      <Import
          Condition="Exists('$(OutputPath)\..\..\..\xbuild\Xamarin\Android\Xamarin.Android.CSharp.targets')"
          Project="$(OutputPath)\..\..\..\xbuild\Xamarin\Android\Xamarin.Android.CSharp.targets"
      />

    which could plausibly result in a "bizarre" error condition on build if the file doesn't already exist (which is already the case! the error message will just be different), but should allow Clean to work (more?) sanely.

  5. atsushieno commented on Jan 10, 2018

    @atsushieno
    ContributorAuthor

    Reflecting internal discussion: there are make clean and make distclean. git clean -xdf is basically distclean, and by asking everyone everytime means you are asking to download any dependencies within the repo every time (which is reportedly not particularly for the mono runtime case anymore).

    Working clean target for every part is important for developers who work on individual part. MSBuild tasks hackers shouldn't be required to clean up Mono.Android.dll at any case.

    We shouldn't keep awkward code quality where Makefile exists and make clean does not work.

  6. jonpryor commented on Jan 10, 2018

    @jonpryor
    Contributor

    The question is, what are the desired semantics for a Clean target?

    Specifically, should running the Clean target in a given directory also clean the dependencies?

    For example, consider mono:

    $ cd mono/mini
    $ make -n clean | grep ^rm
    rm -rf .libs _libs
    rm -rf interp/.libs interp/_libs
    rm -f mono a.out gmon.out *.o buildver-boehm.h buildver-sgen.h test.exe regressionexitcode.out TestResult-op_il_seq_point.xml*
    rm -f *.o
    rm -f ../metadata/*.o
    rm -f interp/*.o
    rm -f interp/*.lo
    rm -f *.lo

    Is it "expected" that running make clean within mono/mini also cleans up mono/metadata?

    Which is in part the problem/question: expectations vary, not only between developers and projects, but between directories as well:

    $ cd mono/metadata
    $ make -n clean | grep ^rm
    rm -rf .libs _libs
    rm -rf ../../support/libm/.libs ../../support/libm/_libs
    rm -f *.o
    rm -f ../../support/libm/*.o
    rm -f ../../support/libm/*.lo
    rm -f *.lo

    (Aside: Mono quickly starts looking bananas: make -C mono/mini removes some files in mono/metadata, but it doesn't do the same things as make -C mono/metadata.)


    I fear that the answer to "what should the Clean target do?" will vary on a project-by-project basis. For some projects we'll want it to also clean @(ProjectReference)s. In others, we won't.

    We'll need to figure out a set of guidelines, and coerce projects to follow them as needed/desired.

  7. jonathanpeppers commented on Apr 16, 2026

    @jonathanpeppers
    Member

    The conversation here is very old, closing for now.

    Related (great explanation of MSBuild Clean target):

  8. locked and limited conversation to collaborators on May 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions