设置依赖于项目的构建系统变量

Set project dependent build system variables

我编写了一个调用 bash 或批处理构建脚本的构建系统。现在我将构建脚本复制并粘贴到任何新项目中并更改项目相关属性。

为了避免每次都修改脚本(或者只使用一个全局设置的脚本),我希望能够在 sublime 项目设置中设置一些变量并在构建系统中获取它们,然后将它们作为参数发送到脚本。

这是否可行而无需定义每个项目的构建系统?

如果相关,这里有一些简化的构建脚本

#!/bin/bash
exe=some_defined_exe

mkdir -p build
cd build
cmake ..
make -j4 
make install
cd ../bin
$exe
cd ..

并构建系统

{
    "cmd": ["build.sh"],
    "working_dir": "${project_path:${folder}}",
    "shell": false,
}

而且我希望它们像

#!/bin/bash
exe=

mkdir -p build
cd build
cmake ..
make -j4 
make install
cd ../bin
$exe
cd ..

{
    "cmd": ["build.sh", "${some_project_defined_variable}"],
    "working_dir": "${project_path:${folder}}",
    "shell": false,
}

由于您已经在使用自定义构建系统,因此您可以使用一些插件代码和对自定义构建系统的一些修改来实现类似的功能。

自定义构建系统允许一个名为 target 的 属性 指定要执行到 运行 构建的命令。当你不提供这个(大多数构建系统不提供)时,默认是 exec 命令。您可以创建自己的自定义命令来为您执行扩展。

作为一个简单的示例,请参阅以下 python 源代码,您可以将其另存为 custom_build.py 之类的内容在 User 包中。这实现了一个名为 my_custom_build 的新命令。执行此命令时,它将通过扩展变量来转换它的参数,然后使用它们执行默认的 exec 命令。

import sublime, sublime_plugin

# List of variable names we want to support
custom_var_list = ["proj_var_1"]

class MyCustomBuildCommand(sublime_plugin.WindowCommand):
    def createExecDict(self, sourceDict):
        global custom_var_list

        # Get the project specific settings
        project_data = self.window.project_data ()
        project_settings = (project_data or {}).get ("settings", {})

        # Get the view specific settings
        view_settings = self.window.active_view ().settings ()

        # Variables to expand; start with defaults, then add ours.
        variables = self.window.extract_variables ()
        for custom_var in custom_var_list:
            variables[custom_var] = view_settings.get (custom_var,
                project_settings.get (custom_var, ""))

        # Create arguments to return by expanding variables in the
        # arguments given.
        args = sublime.expand_variables (sourceDict, variables)

        # Rename the command paramter to what exec expects.
        args["cmd"] = args.pop ("command", [])

        return args

    def run(self, **kwargs):
        self.window.run_command ("exec", self.createExecDict (kwargs))

具体来说,它首先在当前视图指定的设置中查找变量,如果在那里找不到,则在项目特定设置中查找。仍未找到的任何变量默认为空字符串。

您需要指定自定义构建系统,例如:

{
    "target": "my_custom_build",
    "command": ["build.sh", "${proj_var_1}"],

    "working_dir": "${project_path:${folder}}",
    "shell": false
}

请注意,现在有一个 target 字段指定应执行自定义命令以代替 exec。另请注意,我们没有将命令行指定为 cmd,而是在此处将其指定为 command

这是因为 Sublime 似乎会在 运行 执行您的自定义命令之前预先扩展构建系统中已知键的值。因此,它会尝试扩展 cmd 键中的变量,导致 ${proj_var_1} 在我们的命令甚至看到它之前就被扩展为一个空字符串,从而将它剥离给我们。

为了解决这个问题,我们将键的名称更改为 Sublime 会保留的名称,然后在代码中将其换回。

如上所写,上面的代码将尝试扩展它在构建系统中任何地方看到的任何变量,但它只需要特别注意以这种方式保护 cmd 键。例如,如果您想在 working_dir 键中使用自定义变量,则需要执行类似的操作。