function mergeVariables (pluginInfo, cfg, opts) {
    // Validate top-level required variables
    var pluginVariables = pluginInfo.getPreferences();
    opts.cli_variables = opts.cli_variables || {};
    var pluginEntry = cfg.getPlugin(pluginInfo.id);
    // Get variables from config.xml
    var configVariables = pluginEntry ? pluginEntry.variables : {};
    // Add config variable if it's missing in cli_variables
    Object.keys(configVariables).forEach(function (variable) {
        opts.cli_variables[variable] = opts.cli_variables[variable] || configVariables[variable];
    });
    var missingVariables = Object.keys(pluginVariables)
        .filter(function (variableName) {
            // discard variables with default value
            return !(pluginVariables[variableName] || opts.cli_variables[variableName]);
        });

    if (missingVariables.length) {
        events.emit('verbose', 'Removing ' + pluginInfo.dir + ' because mandatory plugin variables were missing.');
        fs.removeSync(pluginInfo.dir);
        var msg = 'Variable(s) missing (use: --variable ' + missingVariables.join('=value --variable ') + '=value).';
        throw new CordovaError(msg);
    }
    return opts.cli_variables;
}