def generate_makefile()

in python/treelite/contrib/__init__.py [0:0]


def generate_makefile(dirpath, platform, toolchain, options=None):
  """
  Generate a Makefile for a given directory of headers and sources. The
  resulting Makefile will be stored in the directory. This function is useful
  for deploying a model on a different machine.

  Parameters
  ----------
  dirpath : :py:class:`str <python:str>`
      directory containing the header and source files previously generated
      by :py:meth:`Model.compile`. The directory must contain recipe.json
      which specifies build dependencies.
  platform : :py:class:`str <python:str>`
      name of the operating system on which the headers and sources shall be
      compiled. Must be one of the following: 'windows' (Microsoft Windows),
      'osx' (Mac OS X), 'unix' (Linux and other UNIX-like systems)
  toolchain : :py:class:`str <python:str>`
      which toolchain to use. You may choose one of 'msvc', 'clang', and 'gcc'.
      You may also specify a specific variation of clang or gcc (e.g. 'gcc-7')
  options : :py:class:`list <python:list>` of :py:class:`str <python:str>`, \
            optional
      Additional options to pass to toolchain
  """
  if not os.path.isdir(dirpath):
    raise TreeliteError('Directory {} does not exist'.format(dirpath))
  try:
    with open(os.path.join(dirpath, 'recipe.json')) as f:
      recipe = json.load(f)
  except IOError:
    raise TreeliteError('Failed to open recipe.json')

  if 'sources' not in recipe or 'target' not in recipe:
    raise TreeliteError('Malformed recipe.json')
  if options is not None:
    try:
      _ = iter(options)
      options = [str(x) for x in options]
    except TypeError:
      raise TreeliteError('options must be a list of string')
  else:
    options = []

  # Determine file extensions for object and library files
  if platform == 'windows':
    lib_ext = '.dll'
  elif platform == 'osx':
    lib_ext = '.dylib'
  elif platform == 'unix':
    lib_ext = '.so'
  else:
    raise ValueError('Unknown platform: must be one of {windows, osx, unix}')

  _toolchain_exist_check(toolchain)
  if toolchain == 'msvc':
    if platform != 'windows':
      raise ValueError('Visual C++ is compatible only with Windows; ' + \
                       'set platform=\'windows\'')
    from .msvc import _obj_ext, _obj_cmd, _lib_cmd
  else:
    from .gcc import _obj_ext, _obj_cmd, _lib_cmd
  obj_ext = _obj_ext()

  with open(os.path.join(dirpath, 'Makefile'), 'w') as f:
    objects = [x['name'] + obj_ext for x in recipe['sources']] \
              + recipe.get('extra', [])
    f.write('{}: {}\n'.format(recipe['target'] + lib_ext, ' '.join(objects)))
    f.write('\t{}\n'.format(_lib_cmd(objects=objects,
                                     target=recipe['target'],
                                     lib_ext=lib_ext,
                                     toolchain=toolchain,
                                     options=options)))
    for source in recipe['sources']:
      f.write('{}: {}\n'.format(source['name'] + obj_ext,
                                source['name'] + '.c'))
      f.write('\t{}\n'.format(_obj_cmd(source=source['name'],
                                       toolchain=toolchain,
                                       options=options)))