Repository: conan-io/conan

Issue:
Multiple calls to msbuild.build fail with TypeError
When using MSBuild to attempt to generate a multi-configuration package, the 2nd call to msbuild.build always fails with the following error on Windows 10 and conan 1.3.2:
```
ERROR: libusb/1.0.0@PROJECT: Error in build() method, line 36
        msbuild.build(sln_file, build_type="Debug")
        TypeError: sequence item 4: expected str instance, NoneType found
```
Switching the order of the debug and release calls does not resolve the problem, however reinitializing the msbuild object with msbuild = MSBuild(self) between calls fixes the problem.

My conan file is below:
```
from conans import ConanFile, AutoToolsBuildEnvironment, MSBuild, tools

class LibusbConan(ConanFile):
    name = "libusb"
    version = "1.0.0"
    license = "LGPL 2.1"
    url = "git@github.com:leapmotion/libusb.git"
    description = "<Description of Libusb here>"
    settings = "os", "compiler", "build_type", "arch"
    options = {"shared": [True, False]}
    default_options = "shared=True"
    generators = "cmake"

    def configure(self):
        if self.settings.compiler == "Visual Studio":
            del self.settings.compiler.runtime #tutorial says this is required, but not why
            del self.settings.build_type

    def source(self):
        branch_name="fix-soname-0"

        if self.settings.os == "Windows":
            branch_name="master"

        self.run("git clone --depth 1 git@github.com:leapmotion/libusb.git -b " + branch_name)

    def build(self):
        #no out of source builds
        print(self.source_folder)
        if self.settings.os == "Windows":
            msbuild = MSBuild(self)
            sln_file = "%s/libusb/msvc/libusb_2017.sln" % (self.source_folder)
            msbuild.build(sln_file, build_type="Release")
            msbuild.build(sln_file, build_type="Debug")

    def package(self):
        self.copy("*.h", dst="include", src="libusb")
        self.copy("*hello.lib", dst="lib", keep_path=False)
        self.copy("*.dll", dst="bin", keep_path=False)
        self.copy("*.so", dst="lib", keep_path=False)
        self.copy("*.dylib", dst="lib", keep_path=False)
        self.copy("*.a", dst="lib", keep_path=False)

    def package_info(self):
        self.cpp_info.libs = ["libusb"]

```

To help us debug your issue please explain:

- [x] I've read the [CONTRIBUTING guide](https://raw.githubusercontent.com/conan-io/conan/develop/.github/CONTRIBUTING.md).
- [x] I've specified the Conan version, operating system version and any tool that can be relevant.
- [x] I've explained the steps to reproduce the error or the motivation/use case of the question/suggestion.




Discussion:
Hi @yeswalrus, thanks a lot for reporting. I was able to reproduce your issue and will add a PR to fix it. I would like to ask you some questions/comments:

- I can see you are following a tutorial to create this recipe. Could you please indicate which one?
I am just asking because maybe it is not clearly explained the deletion of `self.settings.compiler.runtime` in `configure()`

- As you want to create a a multi-config package, make sure you are packaging the right binaries into the right folders and the indicating those paths in `package_info()` for consumers. Something like:

```
def package(self):
    self.copy("*.dll", src="x64/Debug/dll", dst="debug/bin")
    self.copy("*.lib", src="x64/Debug/lib", dst="debug/lib")
    self.copy("*.dll", src="x64/Release/dll", dst="release/bin")
    self.copy("*.lib", src="x64/Release/lib", dst="release/lib")

def package_info(self):
    self.cpp_info.libs = ["libusb"]
    if self.settings.build_type == "Debug":
        self.cpp_info.libdirs = ["debug/lib"]
        self.cpp_info.bindirs = ["debug/bin"]
    elif self.settings.build_type == "Release":
        self.cpp_info.libdirs = ["release/lib"]
        self.cpp_info.bindirs = ["release/bin"]
```

Also note that for this case it would be better to delete the build type information in the `package_id()` method instead of in the `configure()`, to have that setting available in the if clauses (as indicated above) of the recipe. Something like:

```
def package_id(self):
    del self.info.settings.build_type
```

Resolving patch:
diff --git a/conans/client/build/msbuild.py b/conans/client/build/msbuild.py
--- a/conans/client/build/msbuild.py
+++ b/conans/client/build/msbuild.py
@@ -1,3 +1,4 @@
+import copy
 import re
 
 from conans import tools
@@ -110,7 +111,7 @@ def _get_props_file_contents(self):
 
         if self.build_env:
             # Take the flags from the build env, the user was able to alter them if needed
-            flags = self.build_env.flags
+            flags = copy.copy(self.build_env.flags)
             flags.append(self.build_env.std)
         else:  # To be removed when build_sln_command is deprecated
             flags = vs_build_type_flags(self._settings)


Test patch:
diff --git a/conans/test/build_helpers/msbuild_test.py b/conans/test/build_helpers/msbuild_test.py
--- a/conans/test/build_helpers/msbuild_test.py
+++ b/conans/test/build_helpers/msbuild_test.py
@@ -99,3 +99,34 @@ def package(self):
         client.run("install Hello/1.2.1@lasote/stable --build -s arch=x86 -s build_type=Debug")
         self.assertIn("Debug|x86", client.user_io.out)
         self.assertIn("Copied 1 '.exe' file: MyProject.exe", client.user_io.out)
+
+    def reuse_msbuild_object_test(self):
+        # https://github.com/conan-io/conan/issues/2865
+        if platform.system() != "Windows":
+            return
+        conan_build_vs = """
+from conans import ConanFile, MSBuild
+
+class HelloConan(ConanFile):
+    name = "Hello"
+    version = "1.2.1"
+    exports = "*"
+    settings = "os", "build_type", "arch", "compiler", "cppstd"
+
+    def configure(self):
+        del self.settings.compiler.runtime
+        del self.settings.build_type
+
+    def build(self):
+        msbuild = MSBuild(self)
+        msbuild.build("MyProject.sln", build_type="Release")
+        msbuild.build("MyProject.sln", build_type="Debug")
+        self.output.info("build() completed")
+"""
+        client = TestClient()
+        files = get_vs_project_files()
+        files[CONANFILE] = conan_build_vs
+
+        client.save(files)
+        client.run("create . danimtb/testing")
+        self.assertIn("build() completed", client.out)