Merge pull request #1605 from juj/mingw32make_nmake_cmake

Mingw32make nmake cmake
This commit is contained in:
Alon Zakai 2013-09-10 14:30:47 -07:00
Родитель 690a9e16e8 48b79570de
Коммит ea729bea8c
2 изменённых файлов: 110 добавлений и 59 удалений

Просмотреть файл

@ -275,71 +275,77 @@ f.close()
# TODO: deprecate llvm optimizations, dlmalloc, etc. in emscripten.py.
def test_cmake(self):
# On Windows, we want to build cmake-generated Makefiles with mingw32-make instead of e.g. cygwin make, since mingw32-make
# understands Windows paths, and cygwin make additionally produces a cryptic 'not valid bitcode file' errors on files that
# *are* valid bitcode files.
# Test all supported generators.
if WINDOWS:
generators = ['MinGW Makefiles', 'NMake Makefiles']
else:
generators = ['Unix Makefiles']
make_commands = { 'MinGW Makefiles': ['mingw32-make'], 'NMake Makefiles': ['nmake', '/NOLOGO'], 'Unix Makefiles': ['make'] }
if os.name == 'nt':
make_command = 'mingw32-make'
generator = 'MinGW Makefiles'
emconfigure = path_from_root('emconfigure.bat')
else:
make_command = 'make'
generator = 'Unix Makefiles'
emconfigure = path_from_root('emconfigure')
cmake_cases = ['target_js', 'target_html']
cmake_outputs = ['hello_world.js', 'hello_world_gles.html']
for i in range(0, 2): # Test both JS and HTML build outputs from CMake.
for configuration in ['Debug', 'Release']:
# CMake can be invoked in two ways, using 'emconfigure cmake', or by directly running 'cmake'.
# Test both methods.
for invoke_method in ['cmake', 'emconfigure']:
for generator in generators:
if generator == 'NMake Makefiles' and not Building.which('nmake'):
print >> sys.stderr, 'Skipping NMake test for CMake support, since nmake was not found in PATH. Run this test in Visual Studio command prompt to easily access nmake.'
continue
# Create a temp workspace folder
cmakelistsdir = path_from_root('tests', 'cmake', cmake_cases[i])
tempdirname = tempfile.mkdtemp(prefix='emscripten_test_' + self.__class__.__name__ + '_', dir=TEMP_DIR)
try:
os.chdir(tempdirname)
make = make_commands[generator]
cmake_cases = ['target_js', 'target_html']
cmake_outputs = ['hello_world.js', 'hello_world_gles.html']
for i in range(0, 2):
for configuration in ['Debug', 'Release']:
# CMake can be invoked in two ways, using 'emconfigure cmake', or by directly running 'cmake'.
# Test both methods.
for invoke_method in ['cmake', 'emconfigure']:
verbose_level = int(os.getenv('EM_BUILD_VERBOSE')) if os.getenv('EM_BUILD_VERBOSE') != None else 0
# Run Cmake
if invoke_method == 'cmake':
# Test invoking cmake directly.
cmd = ['cmake', '-DCMAKE_TOOLCHAIN_FILE='+path_from_root('cmake', 'Platform', 'Emscripten.cmake'),
'-DCMAKE_BUILD_TYPE=' + configuration, '-G', generator, cmakelistsdir]
else:
# Test invoking via 'emconfigure cmake'
cmd = [emconfigure, 'cmake', '-DCMAKE_BUILD_TYPE=' + configuration, '-G', generator, cmakelistsdir]
# Create a temp workspace folder
cmakelistsdir = path_from_root('tests', 'cmake', cmake_cases[i])
tempdirname = tempfile.mkdtemp(prefix='emscripten_test_' + self.__class__.__name__ + '_', dir=TEMP_DIR)
try:
os.chdir(tempdirname)
ret = Popen(cmd, stdout=None if verbose_level >= 2 else PIPE, stderr=None if verbose_level >= 1 else PIPE).communicate()
if len(ret) > 1 and ret[1] != None and len(ret[1].strip()) > 0:
logging.error(ret[1]) # If there were any errors, print them directly to console for diagnostics.
if len(ret) > 1 and ret[1] != None and 'error' in ret[1].lower():
logging.error('Failed command: ' + ' '.join(cmd))
logging.error('Result:\n' + ret[1])
raise Exception('cmake call failed!')
assert os.path.exists(tempdirname + '/Makefile'), 'CMake call did not produce a Makefile!'
verbose_level = int(os.getenv('EM_BUILD_VERBOSE')) if os.getenv('EM_BUILD_VERBOSE') != None else 0
# Run Cmake
if invoke_method == 'cmake':
# Test invoking cmake directly.
cmd = ['cmake', '-DCMAKE_TOOLCHAIN_FILE='+path_from_root('cmake', 'Platform', 'Emscripten.cmake'),
'-DCMAKE_BUILD_TYPE=' + configuration, '-G', generator, cmakelistsdir]
else:
# Test invoking via 'emconfigure cmake'
cmd = [emconfigure, 'cmake', '-DCMAKE_BUILD_TYPE=' + configuration, '-G', generator, cmakelistsdir]
# Build
cmd = [make_command] + (['VERBOSE=1'] if verbose_level >= 3 else [])
ret = Popen(cmd, stdout=None if verbose_level >= 2 else PIPE).communicate()
if len(ret) > 1 and ret[1] != None and len(ret[1].strip()) > 0:
logging.error(ret[1]) # If there were any errors, print them directly to console for diagnostics.
if len(ret) > 0 and ret[0] != None and 'error' in ret[0].lower() and not '0 error(s)' in ret[0].lower():
logging.error('Failed command: ' + ' '.join(cmd))
logging.error('Result:\n' + ret[0])
raise Exception('make failed!')
assert os.path.exists(tempdirname + '/' + cmake_outputs[i]), 'Building a cmake-generated Makefile failed to produce an output file %s!' % tempdirname + '/' + cmake_outputs[i]
ret = Popen(cmd, stdout=None if verbose_level >= 2 else PIPE, stderr=None if verbose_level >= 1 else PIPE).communicate()
if len(ret) > 1 and ret[1] != None and len(ret[1].strip()) > 0:
logging.error(ret[1]) # If there were any errors, print them directly to console for diagnostics.
if len(ret) > 1 and ret[1] != None and 'error' in ret[1].lower():
logging.error('Failed command: ' + ' '.join(cmd))
logging.error('Result:\n' + ret[1])
raise Exception('cmake call failed!')
assert os.path.exists(tempdirname + '/Makefile'), 'CMake call did not produce a Makefile!'
# Run through node, if CMake produced a .js file.
if cmake_outputs[i].endswith('.js'):
ret = Popen(listify(NODE_JS) + [tempdirname + '/' + cmake_outputs[i]], stdout=PIPE).communicate()[0]
assert 'hello, world!' in ret, 'Running cmake-based .js application failed!'
finally:
os.chdir(path_from_root('tests')) # Move away from the directory we are about to remove.
shutil.rmtree(tempdirname)
# Build
cmd = make + (['VERBOSE=1'] if verbose_level >= 3 else [])
ret = Popen(cmd, stdout=None if verbose_level >= 2 else PIPE).communicate()
if len(ret) > 1 and ret[1] != None and len(ret[1].strip()) > 0:
logging.error(ret[1]) # If there were any errors, print them directly to console for diagnostics.
if len(ret) > 0 and ret[0] != None and 'error' in ret[0].lower() and not '0 error(s)' in ret[0].lower():
logging.error('Failed command: ' + ' '.join(cmd))
logging.error('Result:\n' + ret[0])
raise Exception('make failed!')
assert os.path.exists(tempdirname + '/' + cmake_outputs[i]), 'Building a cmake-generated Makefile failed to produce an output file %s!' % tempdirname + '/' + cmake_outputs[i]
# Run through node, if CMake produced a .js file.
if cmake_outputs[i].endswith('.js'):
ret = Popen(listify(NODE_JS) + [tempdirname + '/' + cmake_outputs[i]], stdout=PIPE).communicate()[0]
assert 'hello, world!' in ret, 'Running cmake-based .js application failed!'
finally:
os.chdir(path_from_root('tests')) # Move away from the directory we are about to remove.
shutil.rmtree(tempdirname)
def test_failure_error_code(self):
for compiler in [EMCC, EMXX]:

Просмотреть файл

@ -820,14 +820,52 @@ class Building:
env['EMSCRIPTEN'] = path_from_root()
return env
# Finds the given executable 'program' in PATH. Operates like the Unix tool 'which'.
@staticmethod
def which(program):
import os
def is_exe(fpath):
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
fpath, fname = os.path.split(program)
if fpath:
if is_exe(program):
return program
else:
for path in os.environ["PATH"].split(os.pathsep):
path = path.strip('"')
exe_file = os.path.join(path, program)
if is_exe(exe_file):
return exe_file
if WINDOWS and not '.' in fname:
if is_exe(exe_file + '.exe'):
return exe_file + '.exe'
if is_exe(exe_file + '.cmd'):
return exe_file + '.cmd'
if is_exe(exe_file + '.bat'):
return exe_file + '.bat'
return None
@staticmethod
def handle_CMake_toolchain(args, env):
# Don't append a toolchain file if the user specified one already.
for arg in args:
if '-DCMAKE_TOOLCHAIN_FILE' in arg:
return args
args.append('-DCMAKE_TOOLCHAIN_FILE=' + path_from_root('cmake', 'Platform', 'Emscripten.cmake'))
def has_substr(array, substr):
for arg in array:
if substr in arg:
return True
return False
# Append the Emscripten toolchain file if the user didn't specify one.
if not has_substr(args, '-DCMAKE_TOOLCHAIN_FILE'):
args.append('-DCMAKE_TOOLCHAIN_FILE=' + path_from_root('cmake', 'Platform', 'Emscripten.cmake'))
# On Windows specify MinGW Makefiles if we have MinGW and no other toolchain was specified, to avoid CMake
# pulling in a native Visual Studio, or Unix Makefiles.
if WINDOWS and not '-G' in args and Building.which('mingw32-make'):
args += ['-G', 'MinGW Makefiles']
return args
@staticmethod
@ -858,6 +896,13 @@ class Building:
logging.error('Executable to run not specified.')
sys.exit(1)
#args += ['VERBOSE=1']
# On Windows prefer building with mingw32-make instead of make, if it exists.
if WINDOWS and args[0] == 'make':
mingw32_make = Building.which('mingw32-make')
if mingw32_make:
args[0] = mingw32_make
try:
process = Popen(args, stdout=stdout, stderr=stderr, env=env)
process.communicate()