Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/osqp/codegen/pywrapper/setup.py.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ class CmdCMakeBuild(build_ext):
build_args += [f'--config={cfg}']

if system() == "Windows":
cmake_args += ['-G', 'Visual Studio 17 2022']
generator = os.environ.get('CMAKE_GENERATOR', 'Visual Studio 17 2022')
cmake_args += ['-G', generator]
cmake_args += ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir)]
if sys.maxsize > 2 ** 32:
cmake_args += ['-A', 'x64']
build_args += ['--', '/m']
if generator.startswith('Visual Studio'):
platform = {'win32': 'Win32', 'win-amd64': 'x64', 'win-arm64': 'ARM64'}[self.plat_name]
cmake_args += ['-A', platform]
build_args += ['--parallel', '2']
else:
cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg]
build_args += ['--', '-j2']
Expand Down
63 changes: 63 additions & 0 deletions src/osqp/tests/codegen_platform_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import os
from pathlib import Path
import tempfile
import unittest
from unittest.mock import Mock, patch
from typing import Any

from setuptools import Distribution


class codegen_platform_tests(unittest.TestCase):
def configure(self, platform, generator=None):
template = Path(__file__).parents[1] / 'codegen' / 'pywrapper' / 'setup.py.jinja'
namespace: dict[str, Any] = {'__file__': str(template)}
source = template.read_text().replace('{{extension_name}}', 'test_ext').replace('{{embedded_mode}}', '1')
with patch('setuptools.setup'):
exec(compile(source, str(template), 'exec'), namespace)
command = namespace['CmdCMakeBuild'](Distribution())
command.plat_name = platform
command.debug = False
extension = namespace['CMakeExtension']('test_ext')
env = dict(os.environ)
env.pop('CMAKE_GENERATOR', None)
if generator is not None:
env['CMAKE_GENERATOR'] = generator
with tempfile.TemporaryDirectory() as directory:
command.build_temp = str(Path(directory) / 'build')
command.build_lib = str(Path(directory) / 'lib')
with patch.dict(os.environ, env, clear=True), patch.dict(namespace, {'system': lambda: 'Windows'}):
with patch.dict(namespace, {'check_call': Mock()}) as mocked:
command.build_extension(extension)
return [call.args[0] for call in mocked['check_call'].call_args_list]

def test_native_arm64_visual_studio(self):
configure, build = self.configure('win-arm64')
self.assertEqual(configure[configure.index('-A') + 1], 'ARM64')
self.assertNotIn('/m', build)

def test_emulated_amd64_interpreter(self):
configure, _ = self.configure('win-amd64')
self.assertEqual(configure[configure.index('-A') + 1], 'x64')

def test_win32_interpreter(self):
configure, _ = self.configure('win32')
self.assertEqual(configure[configure.index('-A') + 1], 'Win32')

def test_explicit_visual_studio_generator(self):
configure, _ = self.configure('win-arm64', 'Visual Studio 18 2026')
self.assertEqual(configure[configure.index('-G') + 1], 'Visual Studio 18 2026')
self.assertEqual(configure[configure.index('-A') + 1], 'ARM64')

def test_ninja_does_not_receive_visual_studio_options(self):
for generator in ('Ninja', 'Ninja Multi-Config'):
with self.subTest(generator=generator):
configure, build = self.configure('win-arm64', generator)
self.assertEqual(configure[configure.index('-G') + 1], generator)
self.assertNotIn('-A', configure)
self.assertNotIn('/m', build)
self.assertIn('--parallel', build)


if __name__ == '__main__':
unittest.main()