def write_conanvcvars(conanfile): """ write a conanvcvars.bat file with the good args from settings """ os_ = conanfile.settings.get_safe("os") if os_ != "Windows": return compiler = conanfile.settings.get_safe("compiler") cvars = None if compiler == "intel": cvars = intel_compilervars_command(conanfile) elif compiler == "Visual Studio" or compiler == "msvc": vs_version = vs_ide_version(conanfile) vcvarsarch = vcvars_arch(conanfile) cvars = vcvars_command(vs_version, architecture=vcvarsarch, platform_type=None, winsdk_version=None, vcvars_ver=None) if cvars: content = textwrap.dedent("""\ @echo off {} """.format(cvars)) save(CONAN_VCVARS_FILE, content)
def check_vs_runtime(artifact, client, vs_version, build_type, architecture="amd64", static_runtime=False): vcvars = vcvars_command(version=vs_version, architecture=architecture) normalized_path = artifact.replace("/", "\\") static = artifact.endswith(".a") or artifact.endswith(".lib") if not static: cmd = ('%s && dumpbin /nologo /dependents "%s"' % (vcvars, normalized_path)) client.run_command(cmd) if static_runtime: assert "KERNEL32.dll" in client.out assert "MSVC" not in client.out assert "VCRUNTIME" not in client.out else: if vs_version in ["15", "16", "17"]: # UCRT debug = "D" if build_type == "Debug" else "" assert "MSVCP140{}.dll".format(debug) in client.out assert "VCRUNTIME140{}.dll".format(debug) in client.out else: raise NotImplementedError() else: # A static library cannot be checked the same client.run_command('{} && DUMPBIN /NOLOGO /DIRECTIVES "{}"'.format( vcvars, artifact)) if build_type == "Debug": assert "RuntimeLibrary=MDd_DynamicDebug" in client.out else: assert "RuntimeLibrary=MD_DynamicRelease" in client.out
def check_vs_runtime(exe, client, vs_version, build_type, static, architecture="amd64"): vcvars = vcvars_command(version=vs_version, architecture=architecture) exe = exe.replace("/", "\\") cmd = ('%s && dumpbin /dependents "%s"' % (vcvars, exe)) client.run_command(cmd) if static: assert "KERNEL32.dll" in client.out, "Error:{}".format(client.out) assert "MSVC" not in client.out, "Error:{}".format(client.out) assert "VCRUNTIME" not in client.out, "Error:{}".format(client.out) else: if vs_version == "15": if build_type == "Debug": assert "MSVCP140D.dll" in client.out, "Error:{}".format( client.out) assert "VCRUNTIME140D.dll" in client.out, "Error:{}".format( client.out) else: assert "MSVCP140.dll" in client.out, "Error:{}".format( client.out) assert "VCRUNTIME140.dll" in client.out, "Error:{}".format( client.out) else: raise NotImplementedError()
def _run(self, cmd): if self._conanfile.settings.get_safe("compiler") == "Visual Studio": vcvars = vcvars_command( self._conanfile.settings.get_safe("compiler.version"), vcvars_arch(self._conanfile)) cmd = '%s && %s' % (vcvars, cmd) self._conanfile.run(cmd)
def test_locally_build_windows(self): """ Ninja build must proceed using default profile and cmake build (Windows Release) """ client = TestClient(path_with_spaces=False) client.save({"conanfile.py": self.conanfile, "main.cpp": self.main_cpp, "CMakeLists.txt": self.cmake}) win_host = textwrap.dedent(""" [settings] os=Windows arch=x86_64 compiler=Visual Studio compiler.version=15 compiler.runtime=MD build_type=Release """) client.save({"win": win_host}) client.run("install . -pr=win") # Ninja is single-configuration vcvars = vcvars_command("15", architecture="amd64") client.run_command('{} && cmake . -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake ' .format(vcvars)) client.run_command("{} && cmake --build .".format(vcvars)) client.run_command("App") self.assertIn("main: Release!", client.out) self.assertIn("main _M_X64 defined", client.out) self.assertIn("main _MSC_VER19", client.out) self.assertIn("main _MSVC_LANG2014", client.out) client.run_command('{} && dumpbin /dependents /summary /directives "App.exe"'.format(vcvars)) self.assertIn("MSVCP140.dll", client.out) self.assertIn("VCRUNTIME140.dll", client.out)
def test_locally_build_windows_debug(self): """ Ninja build must proceed using default profile and cmake build (Windows Debug) """ client = TestClient(path_with_spaces=False) client.save({"conanfile.py": self.conanfile, "main.cpp": self.main_cpp, "CMakeLists.txt": self.cmake}) win_host = textwrap.dedent(""" [settings] os=Windows arch=x86 compiler=Visual Studio compiler.version=15 compiler.runtime=MTd build_type=Debug """) client.save({"win": win_host}) client.run("install . -pr=win") # Ninja is single-configuration # It is necessary to set architecture=x86 here, otherwise final architecture is wrong vcvars = vcvars_command("15", architecture="x86") client.run("install . -pr=win") client.run_command('{} && cmake . -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake ' .format(vcvars)) client.run_command("{} && cmake --build .".format(vcvars)) client.run_command("App") self.assertIn("main: Debug!", client.out) self.assertIn("main _M_IX86 defined", client.out) self.assertIn("main _MSC_VER19", client.out) self.assertIn("main _MSVC_LANG2014", client.out) client.run_command('{} && dumpbin /dependents /summary /directives "App.exe"'.format(vcvars)) self.assertIn("KERNEL32.dll", client.out) self.assertEqual(1, str(client.out).count(".dll"))
def test_use_msbuild_toolchain(self): self.t.save({'profile': self.profile}) self.t.run("new hello/0.1 -s") self.t.run("create . hello/0.1@ -pr:h=profile") app = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) # Prepare the actual consumer package self.t.save( { "conanfile.py": conanfile_py, "MyProject.sln": sln_file, "MyApp/MyApp.vcxproj": myapp_vcxproj, "MyApp/MyApp.cpp": app, 'profile': self.profile }, clean_first=True) # Build in the cache self.t.run("install . -pr:h=profile -if=conan") self.assertIn( "conanfile.py: MSBuildToolchain created conan_toolchain_release_x64.props", self.t.out) self.t.run("build . -if=conan") self.assertIn("Visual Studio 2017", self.t.out) self.assertIn("[vcvarsall.bat] Environment initialized for: 'x64'", self.t.out) exe = "x64\\Release\\MyApp.exe" self.t.run_command(exe) self.assertIn("main __INTEL_COMPILER1910", self.t.out) vcvars = vcvars_command(version="15", architecture="x64") dumpbind_cmd = '%s && dumpbin /dependents "%s"' % (vcvars, exe) self.t.run_command(dumpbind_cmd) self.assertIn("KERNEL32.dll", self.t.out) # Build locally os.unlink(os.path.join(self.t.current_folder, exe)) cmd = vcvars + ' && msbuild "MyProject.sln" /p:Configuration=Release ' \ '/p:Platform=x64 /p:PlatformToolset="Intel C++ Compiler 19.1"' self.t.run_command(cmd) self.assertIn("Visual Studio 2017", self.t.out) self.assertIn("[vcvarsall.bat] Environment initialized for: 'x64'", self.t.out) self.t.run_command(exe) self.assertIn("main __INTEL_COMPILER1910", self.t.out) self.t.run_command(dumpbind_cmd) self.assertIn("KERNEL32.dll", self.t.out)
def test_cmake_toolchain_runtime_types(): # everything works with the default cmake_minimum_required version 3.15 in the template client = TestClient(path_with_spaces=False) client.run("new hello/0.1 --template=cmake_lib") client.run("install . -s compiler.runtime=MTd -s build_type=Debug") client.run("build .") vcvars = vcvars_command(version="15", architecture="x64") lib = os.path.join(client.current_folder, "build", "Debug", "hello.lib") dumpbind_cmd = '{} && dumpbin /directives "{}"'.format(vcvars, lib) client.run_command(dumpbind_cmd) assert "LIBCMTD" in client.out
def command(self, sln): if self.compiler == "intel": cvars = intel_compilervars_command(self._conanfile) else: cvars = vcvars_command(self.version, architecture=self.vcvars_arch, platform_type=None, winsdk_version=None, vcvars_ver=None) cmd = ('%s && msbuild "%s" /p:Configuration=%s /p:Platform=%s ' % (cvars, sln, self.build_type, self.platform)) return cmd
def test_toolchain_win(self): client = TestClient(path_with_spaces=False) settings = { "compiler": "Visual Studio", "compiler.version": "15", "compiler.cppstd": "17", "compiler.runtime": "MT", "build_type": "Release", "arch": "x86" } # Build the profile according to the settings provided settings = " ".join('-s %s="%s"' % (k, v) for k, v in settings.items() if v) client.run("new hello/0.1 -s") client.run("create . hello/0.1@ %s" % (settings, )) # Prepare the actual consumer package client.save( { "conanfile.py": self.conanfile, "MyProject.sln": sln_file, "MyApp/MyApp.vcxproj": myapp_vcxproj, "MyApp/MyApp.cpp": self.app }, clean_first=True) # Run the configure corresponding to this test case client.run("install . %s -if=conan" % (settings, )) self.assertIn( "conanfile.py: MSBuildToolchain created conantoolchain_release_win32.props", client.out) client.run("build . -if=conan") self.assertIn("Visual Studio 2017", client.out) self.assertIn("[vcvarsall.bat] Environment initialized for: 'x86'", client.out) self._run_app(client, "x86", "Release") version = re.search("main _MSC_VER19([0-9]*)", str(client.out)).group(1) version = int(version) self.assertTrue(10 <= version < 20) self.assertIn("main _MSVC_LANG2017", client.out) vcvars = vcvars_command(version="15", architecture="x86") cmd = ('%s && dumpbin /dependents "Release\\MyApp.exe"' % vcvars) client.run_command(cmd) # No other DLLs dependencies rather than kernel, it was MT, statically linked self.assertIn("KERNEL32.dll", client.out) self.assertEqual(1, str(client.out).count(".dll"))
def test_use_cmake_toolchain(self): self.t.save({'profile': self.profile}) self.t.run("new hello/0.1 -s") self.t.run("create . hello/0.1@ -pr:h=profile") app = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) # Prepare the actual consumer package self.t.save( { "conanfile.py": conanfile_py, "main.cpp": app, "CMakeLists.txt": cmakelists_txt, 'profile': self.profile }, clean_first=True) # Build in the cache self.t.run("install . -pr:h=profile") self.assertIn( "conanfile.py: Generator cmake_find_package_multi created helloTargets.cmake", self.t.out) self.t.run("build .") self.assertIn("The CXX compiler identification is Intel 19.1", self.t.out) exe = os.path.join("Release", "MyApp.exe") self.t.run_command(exe) self.assertIn("main __INTEL_COMPILER1910", self.t.out) vcvars = vcvars_command(version="15", architecture="x64") dumpbind_cmd = '%s && dumpbin /dependents "%s"' % (vcvars, exe) self.t.run_command(dumpbind_cmd) self.assertIn("KERNEL32.dll", self.t.out) # Build locally os.unlink(os.path.join(self.t.current_folder, exe)) self.t.run_command('cmake . -G "Visual Studio 15 2017" ' '-DCMAKE_TOOLCHAIN_FILE={}'.format( CMakeToolchainBase.filename)) self.t.run_command('cmake --build . --config Release') self.t.run_command(exe) self.assertIn("main __INTEL_COMPILER1910", self.t.out) self.t.run_command(dumpbind_cmd) self.assertIn("KERNEL32.dll", self.t.out)
def _write_vcvars(self): if self.compiler == "intel": cvars = intel_compilervars_command(self._conanfile) else: cvars = vcvars_command(self.visual_version, architecture=self.vcvars_arch, platform_type=None, winsdk_version=None, vcvars_ver=None) content = textwrap.dedent("""\ @echo off {} """.format(cvars)) save("conanvcvars.bat", content)
def test_toolchain_win_debug(self): client = TestClient(path_with_spaces=False) settings = { "compiler": "Visual Studio", "compiler.version": "15", "compiler.toolset": "v140", "compiler.runtime": "MDd", "build_type": "Debug", "arch": "x86_64" } # Build the profile according to the settings provided settings = " ".join('-s %s="%s"' % (k, v) for k, v in settings.items() if v) client.run("new hello/0.1 -s") client.run("create . hello/0.1@ %s" % (settings, )) # Prepare the actual consumer package client.save( { "conanfile.py": self.conanfile, "MyProject.sln": sln_file, "MyApp/MyApp.vcxproj": myapp_vcxproj, "MyApp/MyApp.cpp": self.app }, clean_first=True) # Run the configure corresponding to this test case client.run("install . %s -if=conan" % (settings, )) self.assertIn( "conanfile.py: MSBuildToolchain created conantoolchain_debug_x64.props", client.out) client.run("build . -if=conan") self.assertIn("Visual Studio 2017", client.out) self.assertIn("[vcvarsall.bat] Environment initialized for: 'x64'", client.out) self._run_app(client, "x64", "Debug") self.assertIn("main _MSC_VER1900", client.out) self.assertIn("main _MSVC_LANG2014", client.out) vcvars = vcvars_command(version="15", architecture="amd64") cmd = ('%s && dumpbin /dependents "x64\\Debug\\MyApp.exe"' % vcvars) client.run_command(cmd) self.assertIn("MSVCP140D.dll", client.out) self.assertIn("VCRUNTIME140D.dll", client.out)
def test_cmake_toolchain_runtime_types_cmake_older_than_3_15(): client = TestClient(path_with_spaces=False) # Setting an older cmake_minimum_required in the CMakeLists fails, will link # against the default debug runtime (MDd->MSVCRTD), not against MTd->LIBCMTD client.run("new hello/0.1 --template=cmake_lib") replace_in_file(os.path.join(client.current_folder, "CMakeLists.txt"), 'cmake_minimum_required(VERSION 3.15)', 'cmake_minimum_required(VERSION 3.1)' , output=client.out) client.run("install . -s compiler.runtime=MTd -s build_type=Debug") client.run("build .") vcvars = vcvars_command(version="15", architecture="x64") lib = os.path.join(client.current_folder, "build", "Debug", "hello.lib") dumpbind_cmd = '{} && dumpbin /directives "{}"'.format(vcvars, lib) client.run_command(dumpbind_cmd) assert "LIBCMTD" in client.out
def test_toolchain_win_multi(self): client = TestClient(path_with_spaces=False) settings = { "compiler": "Visual Studio", "compiler.version": "15", "compiler.cppstd": "17" } settings = " ".join('-s %s="%s"' % (k, v) for k, v in settings.items() if v) client.run("new hello/0.1 -s") configs = [("Release", "x86", True), ("Release", "x86_64", True), ("Debug", "x86", False), ("Debug", "x86_64", False)] for build_type, arch, shared in configs: # Build the profile according to the settings provided runtime = "MT" if build_type == "Release" else "MTd" client.run( "create . hello/0.1@ %s -s build_type=%s -s arch=%s -s compiler.runtime=%s " " -o hello:shared=%s" % (settings, build_type, arch, runtime, shared)) # Prepare the actual consumer package client.save( { "conanfile.py": self.conanfile, "MyProject.sln": sln_file, "MyApp/MyApp.vcxproj": myapp_vcxproj, "MyApp/MyApp.cpp": self.app }, clean_first=True) # Run the configure corresponding to this test case for build_type, arch, shared in configs: runtime = "MT" if build_type == "Release" else "MTd" client.run( "install . %s -s build_type=%s -s arch=%s -s compiler.runtime=%s -if=conan" " -o hello:shared=%s" % (settings, build_type, arch, runtime, shared)) vs_path = vs_installation_path("15") vcvars_path = os.path.join(vs_path, "VC/Auxiliary/Build/vcvarsall.bat") for build_type, arch, shared in configs: platform_arch = "x86" if arch == "x86" else "x64" if build_type == "Release" and shared: configuration = "ReleaseShared" else: configuration = build_type # The "conan build" command is not good enough, cannot do the switch between configs cmd = ('set "VSCMD_START_DIR=%%CD%%" && ' '"%s" x64 && msbuild "MyProject.sln" /p:Configuration=%s ' '/p:Platform=%s ' % (vcvars_path, configuration, platform_arch)) client.run_command(cmd) self.assertIn("Visual Studio 2017", client.out) self.assertIn("[vcvarsall.bat] Environment initialized for: 'x64'", client.out) self._run_app(client, arch, build_type, shared) check_exe_run(client.out, "main", "msvc", "19.1", build_type, arch, "17", { "DEFINITIONS_BOTH": "True", "DEFINITIONS_CONFIG": build_type }) new_cmd = "conan\\%s\\%s\\MyApp.exe" % (arch, configuration) vcvars = vcvars_command(version="15", architecture="amd64") cmd = ('%s && dumpbin /dependents "%s"' % (vcvars, new_cmd)) client.run_command(cmd) if shared: self.assertIn("hello.dll", client.out) else: self.assertNotIn("hello.dll", client.out) self.assertIn("KERNEL32.dll", client.out)