def build_setup_py(dirname): # we want to really build the package by running setup.py # so any code generation would take place (for example, Cython to C code) # we specify the curent directory as the build-temp directory so all the generated sources # will be in the same directory as the other python code with chdir_context(dirname): env = environ.copy() env.update(PYTHONPATH=path.abspath(path.curdir)) cmd = ( [PYTHON_EXECUTABLE, PYTHON_SCRIPT, "setup.py", "build", "--build-temp=."] if name != "nt" else [PYTHON_SCRIPT, "setup.py", "build", "--build-temp=."] ) logger.info(" ".join(cmd)) pid = execute_assert_success(cmd, env=env) logger.debug(pid.get_stdout() + pid.get_stderr())
def build_dependency(filepath): """:returns: base directory""" build_dir = path.abspath(path.join("build", "dependencies")) ensure_directory(path.join(build_dir, "x")) with chdir_context(build_dir): basename = path.basename(filepath) logger.info("building {}".format(basename)) if basename.endswith("egg"): # we assume that all the egg sources are pure-python and don't contain binaries # people obviosuly don't upload binary eggs for POSIX systems to PyPI # but on Windows they do, and therefore we already downloaded their source districutions # in a previous step in the build process of the recipe return path.join(build_dir, _unzip_egg(filepath)) elif basename.endswith("zip"): return path.join(build_dir, _extract_and_build_zip(filepath)) elif basename.endswith("gz"): return path.join(build_dir, _extract_and_build_tgz(filepath)) else: raise RuntimeError()
def scan_for_files_with_setup_py(build_dir, cleanup=False): from . import setup python_files, c_extensions = [], [] with chdir_context(build_dir): setup_py_mock = "_embed_recipe.py" setup_py_mock_json = "_embed_recipe.json" if not path.exists(setup_py_mock_json): with open(setup_py_mock, "w") as fd: fd.write(SETUP_PY_MOCK) env = environ.copy() env.update(PYTHONPATH=path.abspath(path.curdir)) cmd = [PYTHON_EXECUTABLE, PYTHON_SCRIPT, setup_py_mock] if name != "nt" else [PYTHON_SCRIPT, setup_py_mock] logger.info(" ".join(cmd)) pid = execute_assert_success(cmd, env=env) logger.debug(pid.get_stdout() + pid.get_stderr()) with open(setup_py_mock_json) as fd: files = loads(fd.read()) if cleanup: remove(setup_py_mock) remove(setup_py_mock_json) return files
def build_console_script(self, executable, module_name, callable_name, python_source_path): def generate_executable_c_code(): source_filename = '{}.c'.format(executable) with open(source_filename, 'wb') as fd: fd.write(MAIN.format(executable, module_name, callable_name)) return source_filename def generate_buildsystem_for_the_executable(source_filename): # we need to use the same build environment we used to build the embedded python interpreter # and add some stuff on top of it from .environment import write_pystick_variable_file, get_sorted_static_libraries, get_scons_variables from .environment import is_64bit from pprint import pformat from jinja2 import Template variables = get_scons_variables(self.static_libdir, self.options) variables['!LIBPATH' if '!LIBPATH' in variables else 'LIBPATH'].insert(0, self.embedded_python_build_dir) variables['!LIBS' if '!LIBS' in variables else 'LIBS'].insert(0, 'fpython27') # always generate pdb variables['!PDB'] = source_filename.replace('.c', '.pdb') # our generated C code for main uses headers from the Python source code variables.setdefault('CPPPATH', []).append([self.embedded_python_build_dir]) variables.setdefault('CPPPATH', []).append([path.join(python_source_path, 'Include')]) variables.setdefault('CPPDEFINES', []).append(["Py_BUILD_CORE"]) with open('SConstruct', 'w') as fd: fd.write(Template(SCONSTRUCT).render(repr=repr, sorted=sorted, environment_variables=variables, source=source_filename)) def compile_code_and_link_with_static_library(): run_in_another_process(scons, None) def _copy_executable_file_from_build_to_dist(extension): basename = executable + extension src = path.join(build_dir, basename) dst = path.join('dist', basename) ensure_directory(dst) copy(src, dst) return dst def copy_executable_to_dist(): extension = dict(Windows='.exe').get(system(), '') return _copy_executable_file_from_build_to_dist(extension) def copy_pdb_to_dist(): extension = dict(Windows='.pdb').get(system(), '') return _copy_executable_file_from_build_to_dist(extension) build_dir = path.join('build', 'executables', executable) ensure_directory(path.join(build_dir, executable)) with chdir_context(build_dir): source_filename = generate_executable_c_code() generate_buildsystem_for_the_executable(source_filename) compile_code_and_link_with_static_library() run_in_another_process(scons, None) files = [copy_executable_to_dist()] if os_name == 'nt': files.append(copy_pdb_to_dist()) if self.should_sign_files(): self.signtool.sign_executables_in_directory('dist') return files