Exemple #1
0
def install_python(dir, sources):
    basedir = dir
    scons.Mkdir(basedir)
    for file in sources:
        pyc = basedir + '/' + os.path.splitext(
            os.path.basename(file))[0] + '.pyc'
        scons.Command(pyc, file, _python_compile)
Exemple #2
0
    def Flex(self, flex_file):
        """Runs flex to convert a .l file into .cpp and .h files. This has the
        same issues as Lemon when it comes to variant dirs and such - see the
        docs on that method."""
        assert os.path.basename(flex_file) == flex_file
        src_file = os.path.join(self.cur_src_dir, flex_file)
        # Make a copy of the src and variant dirs so they get copied into the
        # closure below
        src_dir = self.cur_src_dir
        var_dir = self.cur_var_dir

        # name of the flex file without the ".l"
        flex_file_base = os.path.splitext(flex_file)[0]
        generated_cpp_file = os.path.join(self.cur_var_dir,
                                          flex_file_base + '.yy.cpp')
        generated_h_file = os.path.join(self.cur_var_dir,
                                        flex_file_base + '.yy.h')

        # Flex puts its output in it's current working directory. Thus we need
        # to change dirs before running it and change back after. We don't want
        # to do that unless we actually need to do the build so we use the
        # closure/command trick that's used in the Lemon rule above. Thus the
        # build process is:
        # 1) cd to variant_dir
        # 2) Run flex over the .l file in the source dir
        # 3) cd back to where we started
        def run_flex(target, source, env):
            start_dir = os.getcwd()
            os.chdir(var_dir)
            res = scons.Execute('flex  ' + src_file, chdir=var_dir)
            if res != 0:
                scons.Exit(1)
            os.chdir(start_dir)

        scons.Command([generated_cpp_file, generated_h_file], src_file,
                      run_flex)
        # Here we return a File node that points to the generated file as if it
        # were generated in the non-variant dir. This is because scons knows
        # it's a build output and so automatically appends the variant dir.
        return [
            generated_cpp_file,
        ]
Exemple #3
0
    def Lemon(self, src):
        """Run lemon to compile a .y file into a .cc and a .h file. The genrated
        files have the same base name as src but end with .cc or .h.

        Args:
            src: the name of the source file. Assumed to be in the same
            directory as the SConscript file from which builder.Lemon() was
            called.

        Returns:
            scons node object for the .cc file generated. This can then be used
            as input to other build rules. This does not return the .h file as
            that is typically not used in build rules. The single file is
            returned in a list as that is scons convention.

        The output files will be put into a variant subdirectory (e.g. ./debug
        for a debug build). We could put the files into the same directory as
        the .y file but that clutters the directory. More importantly, lemon has
        some command line flags that allows us to build optimized parsers. We're
        not using the currently, but in the future the generated source for a
        release build might be different from the source generate for a debug
        build.
        """

        assert os.path.basename(src) == src
        # We need a 3-step build process here:
        # 1) Lemon always puts the generated .c and .h file in the same
        #    directory as the source so we first copy the source file into the
        #    variant dir.
        # 2) Run lemon to generate the the .c and .h files
        # 3) rename the .c file to a .cc file so scons realizes it's C++ and
        #    builds it with g++ instead of gcc.
        # However, we don't want to do any of these things unless the .y file
        # has changed. So we create a single command with a single dependancy.
        # Scons will then run our function only if necessary.

        src_path = os.path.join(self.cur_src_dir, src)
        var_path = os.path.join(self.cur_var_dir, src)
        variant_dir = os.path.join(os.path.dirname(src_path), self.build_dir)

        # The name of the source file without the ".y"
        src_base_filename = os.path.splitext(src)[0]
        # The path to the generated .c file
        generated_c_path = os.path.join(self.cur_var_dir,
                                        src_base_filename + '.c')
        # The path to the generated .h file
        generated_h_path = os.path.join(self.cur_var_dir,
                                        src_base_filename + '.h')
        # Where we should copy the .c file to get a .cc file.
        desired_cc_path = os.path.join(self.cur_var_dir,
                                       src_base_filename + '.cc')
        # Copy self.cur_var_dir, which may refer to a different string by the
        # time run_lemon gets invoked by scons, into a new varible so it gets
        # copy into the run_lemon closure
        var_dir = self.cur_var_dir

        # Closure that will be run to generate the .cc and .h files if
        # necessary
        def run_lemon(target, source, env):
            """The targets, source, and environment are passed by scons but we
            can ignore them as we don't need them."""
            # Copy the .y file into the variant dir
            shutil.copy(src_path, var_dir)
            ret = scons.Execute('lemon ' + var_path)
            if ret != 0:
                scons.Exit(1)
            # now rename the .c file to a .cc file
            shutil.move(generated_c_path, desired_cc_path)

        # This command indicates that the .cc and .h files are generated from
        # the .y file by running run_lemon. Scons will then call that function
        # if and only if the .y file has changed.
        res = scons.Command([desired_cc_path, generated_h_path], src_path,
                            run_lemon)
        return [
            desired_cc_path,
        ]