Repository: conan-io/conan

Issue:
Make temp props file used by MSBuild helper file persistent
This came out of slack discussion.  There is currently a temporary props file used to force MT/MD into projects during build when the MSBuild helper is used.  It would be preferable if the file were generated in the build directory and left behind for packaging, both for debugging, and so that the build is reproducible without Conan.  

Also related to this request: 

https://github.com/conan-io/conan/issues/4073

- [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:

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
@@ -11,7 +11,7 @@
 from conans.model.conan_file import ConanFile
 from conans.model.version import Version
 from conans.util.env_reader import get_env
-from conans.util.files import decode_text, tmp_file
+from conans.util.files import decode_text, save
 
 
 class MSBuild(object):
@@ -29,23 +29,25 @@ def __init__(self, conanfile):
 
     def build(self, project_file, targets=None, upgrade_project=True, build_type=None, arch=None,
               parallel=True, force_vcvars=False, toolset=None, platforms=None, use_env=True,
-              vcvars_ver=None, winsdk_version=None, properties=None, output_binary_log=None):
+              vcvars_ver=None, winsdk_version=None, properties=None, output_binary_log=None,
+              property_file_name=None):
 
+        property_file_name = property_file_name or "conan_build.props"
         self.build_env.parallel = parallel
 
         with tools.environment_append(self.build_env.vars):
             # Path for custom properties file
             props_file_contents = self._get_props_file_contents()
-            with tmp_file(props_file_contents) as props_file_path:
-                vcvars = vcvars_command(self._conanfile.settings, force=force_vcvars,
-                                        vcvars_ver=vcvars_ver, winsdk_version=winsdk_version)
-                command = self.get_command(project_file, props_file_path,
-                                           targets=targets, upgrade_project=upgrade_project,
-                                           build_type=build_type, arch=arch, parallel=parallel,
-                                           toolset=toolset, platforms=platforms,
-                                           use_env=use_env, properties=properties, output_binary_log=output_binary_log)
-                command = "%s && %s" % (vcvars, command)
-                return self._conanfile.run(command)
+            save(property_file_name, props_file_contents)
+            vcvars = vcvars_command(self._conanfile.settings, force=force_vcvars,
+                                    vcvars_ver=vcvars_ver, winsdk_version=winsdk_version)
+            command = self.get_command(project_file, property_file_name,
+                                       targets=targets, upgrade_project=upgrade_project,
+                                       build_type=build_type, arch=arch, parallel=parallel,
+                                       toolset=toolset, platforms=platforms,
+                                       use_env=use_env, properties=properties, output_binary_log=output_binary_log)
+            command = "%s && %s" % (vcvars, command)
+            return self._conanfile.run(command)
 
     def get_command(self, project_file, props_file_path=None, targets=None, upgrade_project=True,
                     build_type=None, arch=None, parallel=True, toolset=None, platforms=None,
diff --git a/conans/util/files.py b/conans/util/files.py
--- a/conans/util/files.py
+++ b/conans/util/files.py
@@ -155,23 +155,6 @@ def mkdir_tmp():
     return tempfile.mkdtemp(suffix='tmp_conan')
 
 
-@contextmanager
-def tmp_file(contents):
-    """ Usage:
-
-    with tmp_file("mycontents") as filepath:
-        # Here exists filepath tmp file with "mycontents" inside
-
-    """
-    try:
-        tmp_dir = mkdir_tmp()
-        path = os.path.join(tmp_dir, "t")
-        save(path, contents)
-        yield path
-    finally:
-        rmdir(tmp_dir)
-
-
 def to_file_bytes(content):
     if six.PY3:
         if not isinstance(content, bytes):


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
@@ -9,6 +9,7 @@
 from conans.client import tools
 from conans.client.build.msbuild import MSBuild
 from conans.errors import ConanException
+from conans.model.ref import PackageReference
 from conans.model.version import Version
 from conans.paths import CONANFILE
 from conans.test.utils.conanfile import MockConanfile, MockSettings
@@ -115,6 +116,18 @@ def package(self):
         self.assertIn("Debug|x86", client.user_io.out)
         self.assertIn("Copied 1 '.exe' file: MyProject.exe", client.user_io.out)
 
+        # Try with a custom property file name
+        files[CONANFILE] = conan_build_vs.replace('msbuild.build("MyProject.sln")',
+                                                  'msbuild.build("MyProject.sln", '
+                                                  'property_file_name="myprops.props")')
+        client.save(files, clean_first=True)
+        client.run("create . 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)
+        pref = PackageReference.loads("Hello/1.2.1@lasote/stable:b786e9ece960c3a76378ca4d5b0d0e922f4cedc1")
+        build_folder = client.client_cache.build(pref)
+        self.assertTrue(os.path.exists(os.path.join(build_folder, "myprops.props")))
+
     def custom_properties_test(self):
         settings = MockSettings({"build_type": "Debug",
                                  "compiler": "Visual Studio",