static int bz_pacman_add_install_scripts(struct bz_env *env, struct cork_buffer *pkgbuild_buf) { struct cork_buffer install_buf = CORK_BUFFER_INIT(); /* Copy each kind of script into install_buf, if present. */ rii_check(bz_pacman_add_install_script (env, &install_buf, "pre_install_script", "pre_install")); rii_check(bz_pacman_add_install_script (env, &install_buf, "post_install_script", "post_install")); rii_check(bz_pacman_add_install_script (env, &install_buf, "pre_remove_script", "pre_remove")); rii_check(bz_pacman_add_install_script (env, &install_buf, "post_remove_script", "post_remove")); /* If any of them added content to the install script, save that to a file * and reference it in the PKGBUILD. */ if (install_buf.size > 0) { struct cork_path *install; const char *install_base; rip_check(install = bz_env_get_path(env, "pacman.install", true)); rip_check(install_base = bz_env_get_string(env, "pacman.install_base", true)); rii_check(bz_create_file(cork_path_get(install), &install_buf, 0640)); cork_buffer_append_printf(pkgbuild_buf, "install=%s\n", install_base); } cork_buffer_done(&install_buf); return 0; }
static int write_header_v1(struct save_data *save_data, struct ipset_node_cache *cache, ipset_node_id root) { /* Output the magic number for an IP set, and the file format * version that we're going to write. */ rii_check(cork_stream_consumer_data(save_data->stream, NULL, 0, true)); rii_check(write_string(save_data->stream, MAGIC_NUMBER)); rii_check(write_uint16(save_data->stream, 0x0001)); /* Determine how many reachable nodes there are, to calculate the * size of the set. */ size_t nonterminal_count = ipset_node_reachable_count(cache, root); size_t set_size = MAGIC_NUMBER_LENGTH + /* magic number */ sizeof(uint16_t) + /* version number */ sizeof(uint64_t) + /* length of set */ sizeof(uint32_t) + /* number of nonterminals */ (nonterminal_count * /* for each nonterminal: */ (sizeof(uint8_t) + /* variable number */ sizeof(uint32_t) + /* low pointer */ sizeof(uint32_t) /* high pointer */ )); /* If the root is a terminal, we need to add 4 bytes to the set * size, for storing the terminal value. */ if (ipset_node_get_type(root) == IPSET_TERMINAL_NODE) { set_size += sizeof(uint32_t); } rii_check(write_uint64(save_data->stream, set_size)); rii_check(write_uint32(save_data->stream, nonterminal_count)); return 0; }
static int bz_autotools__stage(void *user_data) { struct bz_env *env = user_data; const char *package_name; struct cork_path *build_dir; struct cork_path *staging_dir; bool verbose; struct cork_env *exec_env; struct cork_exec *exec; rii_check(bz_stage_message(env, "autotools")); rip_check(package_name = bz_env_get_string(env, "name", true)); clog_info("(%s) Stage using autotools", package_name); rip_check(build_dir = bz_env_get_path(env, "build_dir", true)); rip_check(staging_dir = bz_env_get_path(env, "staging_dir", true)); rie_check(verbose = bz_env_get_bool(env, "verbose", true)); /* Create the staging path */ rii_check(bz_create_directory(cork_path_get(staging_dir), 0750)); /* $ make install */ exec = cork_exec_new("make"); cork_exec_add_param(exec, "make"); cork_exec_add_param(exec, "install"); cork_exec_set_cwd(exec, cork_path_get(build_dir)); exec_env = cork_env_clone_current(); cork_env_add(exec_env, "DESTDIR", cork_path_get(staging_dir)); cork_exec_set_env(exec, exec_env); return bz_subprocess_run_exec(verbose, NULL, exec); }
static int save_visit_node(struct save_data *save_data, ipset_node_id node_id, serialized_id *dest) { /* Check whether we've already serialized this node. */ struct cork_hash_table_entry *entry; bool is_new; entry = cork_hash_table_get_or_create (save_data->serialized_ids, (void *) (uintptr_t) node_id, &is_new); if (!is_new) { *dest = (intptr_t) entry->value; return 0; } else { if (ipset_node_get_type(node_id) == IPSET_TERMINAL_NODE) { /* For terminals, there isn't really anything to do — we * just output the terminal node and use its value as the * serialized ID. */ ipset_value value = ipset_terminal_value(node_id); DEBUG("Writing terminal(%d)", value); rii_check(save_data->write_terminal(save_data, value)); entry->value = (void *) (intptr_t) value; *dest = value; return 0; } else { /* For nonterminals, we drill down into the node's children * first, then output the nonterminal node. */ struct ipset_node *node = ipset_node_cache_get_nonterminal(save_data->cache, node_id); DEBUG("Visiting node %u nonterminal(x%u? %u: %u)", node_id, node->variable, node->high, node->low); /* Output the node's nonterminal children before we output * the node itself. */ serialized_id serialized_low; serialized_id serialized_high; rii_check(save_visit_node(save_data, node->low, &serialized_low)); rii_check(save_visit_node(save_data, node->high, &serialized_high)); /* Output the nonterminal */ serialized_id result = save_data->next_serialized_id--; DEBUG("Writing node %u as serialized node %d = (x%u? %d: %d)", node_id, result, node->variable, serialized_low, serialized_high); entry->value = (void *) (intptr_t) result; *dest = result; return save_data->write_nonterminal (save_data, result, node->variable, serialized_low, serialized_high); } } }
static int write_nonterminal_v1(struct save_data *save_data, serialized_id serialized_node, ipset_variable variable, serialized_id serialized_low, serialized_id serialized_high) { rii_check(write_uint8(save_data->stream, variable)); rii_check(write_uint32(save_data->stream, serialized_low)); rii_check(write_uint32(save_data->stream, serialized_high)); return 0; }
int vrt_producer_eof(struct vrt_producer *p) { struct vrt_value *v; rii_check(vrt_producer_claim_raw(p->queue, p)); clog_debug("<%s> EOF %d", p->name, p->last_produced_id); v = vrt_queue_get(p->queue, p->last_produced_id); v->id = p->last_produced_id; v->special = VRT_VALUE_EOF; rii_check(vrt_producer_publish(p)); return vrt_producer_flush(p); }
static int cork_copy_once_slice__copy(struct cork_slice *dest, const struct cork_slice *src, size_t offset, size_t length) { struct cork_managed_buffer *mbuf = cork_managed_buffer_new_copy(src->buf, src->size); rii_check(cork_managed_buffer_slice(dest, mbuf, offset, length)); rii_check(cork_managed_buffer_slice ((struct cork_slice *) src, mbuf, 0, src->size)); cork_managed_buffer_unref(mbuf); return 0; }
/* Waits for the slot given by the producer's last_claimed_id to become * free. (This happens when every consumer has finished processing the * previous value that would've used the same slot in the ring buffer. */ static int vrt_wait_for_slot(struct vrt_queue *q, struct vrt_producer *p) { bool first = true; vrt_value_id wrapped_id = p->last_claimed_id - vrt_queue_size(q); if (vrt_mod_lt(q->last_consumed_id, wrapped_id)) { clog_debug("<%s> Wait for value %d to be consumed", p->name, wrapped_id); vrt_value_id minimum = vrt_queue_find_last_consumed_id(q); while (vrt_mod_lt(minimum, wrapped_id)) { clog_trace("<%s> Last consumed value is %d (wait)", p->name, minimum); p->yield_count++; rii_check(vrt_yield_strategy_yield (p->yield, first, q->name, p->name)); first = false; minimum = vrt_queue_find_last_consumed_id(q); } p->batch_count++; q->last_consumed_id = minimum; clog_debug("<%s> Last consumed value is %d", p->name, minimum); } return 0; }
static int bz_pacman__package__is_needed(void *user_data, bool *is_needed) { struct bz_env *env = user_data; const char *package_name; bool force = false; rip_check(package_name = bz_env_get_string(env, "name", true)); rie_check(force = bz_env_get_bool(env, "force", true)); if (force) { *is_needed = true; clog_info("(%s) Force creation of binary package", package_name); return 0; } else { struct cork_path *package_file; rip_check(package_file = bz_env_get_path (env, "pacman.package_file", true)); clog_info("(%s) Check whether binary package %s exists", package_name, cork_path_get(package_file)); rii_check(bz_file_exists(cork_path_get(package_file), is_needed)); *is_needed = !*is_needed; return 0; } }
int vrt_producer_flush(struct vrt_producer *p) { struct vrt_value *v; if (p->last_produced_id == p->last_claimed_id) { /* We don't have any queue entries that we've claimed but haven't used, * so there's nothing to flush. */ return 0; } /* Claim a value to fill in a FLUSH control message. */ rii_check(vrt_producer_claim_raw(p->queue, p)); clog_trace("<%s> Flush %d", p->name, p->last_produced_id); v = vrt_queue_get(p->queue, p->last_produced_id); v->special = VRT_VALUE_FLUSH; /* If we've claimed more value than we've produced, fill in the * remainder with holes. */ if (vrt_mod_lt(p->last_produced_id, p->last_claimed_id)) { vrt_value_id i; clog_trace("<%s> Holes %d-%d", p->name, p->last_produced_id + 1, p->last_claimed_id); for (i = p->last_produced_id + 1; vrt_mod_le(i, p->last_claimed_id); i++) { struct vrt_value *v = vrt_queue_get(p->queue, i); v->id = i; v->special = VRT_VALUE_HOLE; } p->last_produced_id = p->last_claimed_id; } /* Then publish the whole chunk. */ return p->publish(p->queue, p, p->last_claimed_id); }
static int clog_stream_handler__annotation(struct clog_handler *vself, struct clog_message *msg, const char *key, const char *value) { struct clog_stream_handler *self = cork_container_of(vself, struct clog_stream_handler, parent); if (clog_stream_handler_claim(self)) { /* Just claimed the lock; clear the buffer */ rii_check(clog_formatter_start(self->fmt)); } rii_check(clog_formatter_annotation(self->fmt, key, value)); return CLOG_CONTINUE; }
static int vrt_publish_multi_threaded(struct vrt_queue *q, struct vrt_producer *p, vrt_value_id last_published_id) { bool first = true; vrt_value_id expected_cursor; vrt_value_id current_cursor; /* If there are multiple publisherthen we have to wait until all * of the values before the chunk that we claimed have been * published. (If we don't, there will be a hole in the sequence of * published records.) */ expected_cursor = last_published_id - p->batch_size; current_cursor = vrt_queue_get_cursor(q); clog_debug("<%s> Wait for value %d to be published", p->name, expected_cursor); while (vrt_mod_lt(current_cursor, expected_cursor)) { clog_trace("<%s> Last published value is %d (wait)", p->name, current_cursor); rii_check(vrt_yield_strategy_yield (p->yield, first, q->name, p->name)); first = false; current_cursor = vrt_queue_get_cursor(q); } clog_debug("<%s> Last published value is %d", p->name, current_cursor); clog_debug("<%s> Signal publication of value %d (multi-threaded)", p->name, last_published_id); vrt_queue_set_cursor(q, last_published_id); return 0; }
static int write_header_dot(struct save_data *save_data, struct ipset_node_cache *cache, ipset_node_id root) { /* Output the opening clause of the GraphViz script. */ rii_check(cork_stream_consumer_data(save_data->stream, NULL, 0, true)); return write_string(save_data->stream, GRAPHVIZ_HEADER); }
static int bz_git__load(void *user_data, struct bz_env *env) { struct bz_git_repo *repo = user_data; struct cork_path *repo_base_dir; rip_check(repo_base_dir = bz_env_get_path(env, "repo.base_dir", true)); rii_check(bz_git_clone(repo->url, repo->commit, repo_base_dir)); return bz_filesystem_repo_load(repo->repo); }
static int cork_read_pipe_read(struct cork_read_pipe *p, char *buf, bool *progress) { if (p->fds[0] == -1) { return 0; } do { DEBUG("[read] Reading from pipe %d\n", p->fds[0]); ssize_t bytes_read = read(p->fds[0], buf, BUF_SIZE); if (bytes_read == -1) { if (errno == EAGAIN) { /* We've exhausted all of the data currently available. */ DEBUG("[read] No more bytes without blocking\n"); return 0; } else if (errno == EINTR) { /* Interrupted by a signal; return so that our wait loop can * catch that. */ DEBUG("[read] Interrupted by signal\n"); return 0; } else { /* An actual error */ cork_system_error_set(); DEBUG("[read] Error: %s\n", cork_error_message()); return -1; } } else if (bytes_read == 0) { DEBUG("[read] End of stream\n"); *progress = true; rii_check(cork_stream_consumer_eof(p->consumer)); rii_check_posix(close(p->fds[0])); p->fds[0] = -1; return 0; } else { DEBUG("[read] Got %zd bytes\n", bytes_read); *progress = true; rii_check(cork_stream_consumer_data (p->consumer, buf, bytes_read, p->first)); p->first = false; } } while (true); }
int vrt_producer_claim(struct vrt_producer *p, struct vrt_value **value) { struct vrt_value *v; rii_check(vrt_producer_claim_raw(p->queue, p)); v = vrt_queue_get(p->queue, p->last_produced_id); v->id = p->last_produced_id; v->special = VRT_VALUE_NONE; *value = v; return 0; }
/* Claims the next ID that this producer can fill in. The new value's * ID will be stored in p->last_produced_id. You can get the value * itself using vrt_queue_get. */ static int vrt_producer_claim_raw(struct vrt_queue *q, struct vrt_producer *p) { if (p->last_produced_id == p->last_claimed_id) { rii_check(p->claim(q, p)); } p->last_produced_id++; clog_trace("<%s> Claimed value %d (%d is available)\n", p->name, p->last_produced_id, p->last_claimed_id); return 0; }
static int clog_stream_handler__message(struct clog_handler *vself, struct clog_message *msg) { struct clog_stream_handler *self = cork_container_of(vself, struct clog_stream_handler, parent); if (clog_stream_handler_claim(self)) { /* Just claimed the lock; clear the buffer */ rii_check(clog_formatter_start(self->fmt)); } rii_check(clog_formatter_finish(self->fmt, msg, &self->buf)); cork_buffer_append(&self->buf, "\n", 1); rii_check(cork_stream_consumer_data (self->consumer, self->buf.buf, self->buf.size, self->first_chunk)); self->first_chunk = false; clog_stream_handler_release(self); return CLOG_CONTINUE; }
static int bz_git__update(void *user_data, struct bz_env *env) { struct bz_git_repo *repo = user_data; struct cork_path *repo_base_dir; struct cork_path *repo_git_dir; rip_check(repo_base_dir = bz_env_get_path(env, "repo.base_dir", true)); rip_check(repo_git_dir = bz_env_get_path(env, "repo.git_dir", true)); rii_check(bz_git_update (repo->url, repo->commit, repo_git_dir, repo_base_dir)); return 0; }
static int bz_pacman_add_install_script(struct bz_env *env, struct cork_buffer *buf, const char *var_name, const char *func_name) { struct cork_path *install_script; rie_check(install_script = bz_env_get_path(env, var_name, false)); if (install_script != NULL) { cork_buffer_append_printf(buf, "%s () {\n", func_name); rii_check(bz_load_file(cork_path_get(install_script), buf)); cork_buffer_append_string(buf, "\n}\n"); } return 0; }
int vrt_consumer_next(struct vrt_consumer *c, struct vrt_value **value) { do { unsigned int producer_count; struct vrt_value *v; rii_check(vrt_consumer_next_raw(c->queue, c)); v = vrt_queue_get(c->queue, c->current_id); switch (v->special) { case VRT_VALUE_NONE: *value = v; return 0; case VRT_VALUE_EOF: producer_count = cork_array_size(&c->queue->producers); c->eof_count++; clog_debug("<%s> Detected EOF (%u of %u) at value %d", c->name, c->eof_count, producer_count, c->current_id); if (c->eof_count == producer_count) { /* We've run out of values that we know can been * processed. Notify the world how much we've * processed so far. */ clog_debug("<%s> Signal consumption of %d", c->name, c->current_id); vrt_consumer_set_cursor(c, c->current_id); return VRT_QUEUE_EOF; } else { /* There are other producers still producing values, * so we should repeat the loop to grab the next * value. */ break; } case VRT_VALUE_HOLE: /* Repeat the loop to grab the next value. */ break; case VRT_VALUE_FLUSH: /* Return the FLUSH control message. */ return VRT_QUEUE_FLUSH; default: cork_unreachable(); } } while (true); }
static int bz_pacman__uninstall(void *user_data) { struct bz_env *env = user_data; const char *package_name; rii_check(bz_uninstall_message(env, "pacman")); rip_check(package_name = bz_env_get_string(env, "name", true)); clog_info("(%s) Uninstall using pacman", package_name); return bz_subprocess_run (false, NULL, "sudo", "pacman", "-R", "--noconfirm", package_name, NULL); }
static int bz_pacman__install__is_needed(void *user_data, bool *is_needed) { struct bz_env *env = user_data; struct bz_value *ctx = bz_env_as_value(env); const char *package_name; struct bz_version *package_version; bool force; rii_check(bz_install_dependency_string("pacman", ctx)); rip_check(package_name = bz_env_get_string(env, "name", true)); rie_check(force = bz_env_get_bool(env, "force", true)); if (force) { *is_needed = true; clog_info("(%s) Force installation of package", package_name); return 0; } else { struct bz_version *installed; clog_info("(%s) Check whether pacman package is installed", package_name); rip_check(package_version = bz_env_get_version(env, "version", true)); ee_check(installed = bz_arch_native_version_installed(package_name)); if (installed == NULL) { clog_info("(%s) Package is not installed", package_name); *is_needed = true; return 0; } else { *is_needed = (bz_version_cmp(installed, package_version) < 0); clog_info("(%s) Installed version %s is %s than %s", package_name, bz_version_to_string(installed), *is_needed? "older": "newer", bz_version_to_string(package_version)); bz_version_free(installed); return 0; } } error: bz_version_free(package_version); return -1; }
static int bz_pacman__install(void *user_data) { struct bz_env *env = user_data; const char *package_name; struct cork_path *package_file; rii_check(bz_install_message(env, "pacman")); rip_check(package_name = bz_env_get_string(env, "name", true)); rip_check(package_file = bz_env_get_path(env, "pacman.package_file", true)); clog_info("(%s) Install %s using pacman", package_name, cork_path_get(package_file)); return bz_subprocess_run (false, NULL, "sudo", "pacman", "-U", "--noconfirm", cork_path_get(package_file), NULL); }
static int save_bdd(struct save_data *save_data, struct ipset_node_cache *cache, ipset_node_id root) { /* First, output the file header. */ DEBUG("Writing file header"); rii_check(save_data->write_header(save_data, cache, root)); /* The serialized node IDs are different than the in-memory node * IDs. This means that, for our nonterminal nodes, we need a * mapping from internal node ID to serialized node ID. */ DEBUG("Creating file caches"); save_data->serialized_ids = cork_pointer_hash_table_new(0, 0); save_data->next_serialized_id = -1; /* Trace down through the BDD tree, outputting each terminal and * nonterminal node as they're encountered. */ DEBUG("Writing nodes"); serialized_id last_serialized_id; ei_check(save_visit_node(save_data, root, &last_serialized_id)); /* Finally, output the file footer and cleanup. */ DEBUG("Writing file footer"); ei_check(save_data->write_footer(save_data, cache, root)); DEBUG("Freeing file caches"); cork_hash_table_free(save_data->serialized_ids); return 0; error: /* If there's an error, clean up the objects that we've created * before returning. */ cork_hash_table_free(save_data->serialized_ids); return -1; }
int cork_consume_file(struct cork_stream_consumer *consumer, FILE *fp) { char buf[BUFFER_SIZE]; size_t bytes_read; bool first = true; while (true) { while ((bytes_read = fread(buf, 1, BUFFER_SIZE, fp)) > 0) { rii_check(cork_stream_consumer_data (consumer, buf, bytes_read, first)); first = false; } if (feof(fp)) { return cork_stream_consumer_eof(consumer); } else if (errno != EINTR) { cork_system_error_set(); return -1; } } }
int cork_consume_fd(struct cork_stream_consumer *consumer, int fd) { char buf[BUFFER_SIZE]; ssize_t bytes_read; bool first = true; while (true) { while ((bytes_read = read(fd, buf, BUFFER_SIZE)) > 0) { rii_check(cork_stream_consumer_data (consumer, buf, bytes_read, first)); first = false; } if (bytes_read == 0) { return cork_stream_consumer_eof(consumer); } else if (errno != EINTR) { cork_system_error_set(); return -1; } } }
static int bz_autotools__test(void *user_data) { struct bz_env *env = user_data; const char *package_name; struct cork_path *build_dir; bool verbose; struct cork_exec *exec; rii_check(bz_test_message(env, "autotools")); /* $ make check */ rip_check(package_name = bz_env_get_string(env, "name", true)); clog_info("(%s) Test using autotools", package_name); rip_check(build_dir = bz_env_get_path(env, "build_dir", true)); rie_check(verbose = bz_env_get_bool(env, "verbose", true)); exec = cork_exec_new("make"); cork_exec_add_param(exec, "make"); cork_exec_add_param(exec, "check"); cork_exec_set_cwd(exec, cork_path_get(build_dir)); return bz_subprocess_run_exec(verbose, NULL, exec); }
static int bz_pacman__uninstall__is_needed(void *user_data, bool *is_needed) { struct bz_env *env = user_data; struct bz_value *ctx = bz_env_as_value(env); const char *package_name; struct bz_version *installed; rii_check(bz_install_dependency_string("pacman", ctx)); rip_check(package_name = bz_env_get_string(env, "name", true)); clog_info("(%s) Check whether pacman package is installed", package_name); rie_check(installed = bz_arch_native_version_installed(package_name)); if (installed == NULL) { clog_info("(%s) Package is not installed", package_name); *is_needed = false; } else { clog_info("(%s) Version %s is installed", package_name, bz_version_to_string(installed)); *is_needed = true; bz_version_free(installed); } return 0; }
static int bz_autotools__build(void *user_data) { struct bz_env *env = user_data; struct bz_value *ctx = bz_env_as_value(env); const char *package_name; struct cork_path *build_dir; struct cork_path *source_dir; struct cork_path *configure; struct bz_value *configure_args; const char *pkgconfig_path; bool exists; bool verbose; struct cork_exec *exec; struct cork_env *exec_env; struct cork_buffer buf = CORK_BUFFER_INIT(); rii_check(bz_install_dependency_string("autoconf", ctx)); rii_check(bz_install_dependency_string("automake", ctx)); rii_check(bz_build_message(env, "autotools")); rip_check(package_name = bz_env_get_string(env, "name", true)); rip_check(build_dir = bz_env_get_path(env, "build_dir", true)); rip_check(source_dir = bz_env_get_path(env, "source_dir", true)); rip_check(configure = bz_env_get_path(env, "autotools.configure.configure", true)); rie_check(pkgconfig_path = bz_env_get_string(env, "pkgconfig.path", false)); rie_check(verbose = bz_env_get_bool(env, "verbose", true)); /* Create the build path */ rii_check(bz_create_directory(cork_path_get(build_dir), 0750)); clog_info("(%s) Configure using autotools", package_name); /* $ autoreconf -i */ rii_check(bz_file_exists(cork_path_get(configure), &exists)); if (!exists) { exec = cork_exec_new("autoreconf"); cork_exec_add_param(exec, "autoreconf"); cork_exec_add_param(exec, "-i"); cork_exec_set_cwd(exec, cork_path_get(source_dir)); ei_check(bz_subprocess_run_exec(verbose, NULL, exec)); } #define add_dir(buzzy_name, param_name) \ do { \ struct cork_path *value; \ ep_check(value = bz_env_get_path(env, buzzy_name, true)); \ cork_buffer_printf(&buf, "--" param_name "=%s", cork_path_get(value)); \ cork_exec_add_param(exec, buf.buf); \ } while (0) /* $ ./configure ... */ exec = cork_exec_new(cork_path_get(configure)); exec_env = cork_env_clone_current(); cork_exec_set_env(exec, exec_env); cork_exec_add_param(exec, cork_path_get(configure)); add_dir("prefix", "prefix"); add_dir("exec_prefix", "exec-prefix"); add_dir("bin_dir", "bindir"); add_dir("sbin_dir", "sbindir"); add_dir("lib_dir", "libdir"); add_dir("libexec_dir", "libexecdir"); add_dir("share_dir", "datadir"); add_dir("man_dir", "mandir"); /* Add custom configure arguments, if given. */ configure_args = bz_env_get_value(env, "autotools.configure.args"); if (configure_args != NULL) { struct bz_configure_add_arg state = { exec, env }; switch (bz_value_kind(configure_args)) { case BZ_VALUE_SCALAR: ei_check(bz_configure_add_arg(&state, configure_args)); break; case BZ_VALUE_ARRAY: ei_check(bz_array_value_map (configure_args, &state, bz_configure_add_arg)); break; case BZ_VALUE_MAP: bz_bad_config("autotools.configure.args cannot be a map"); goto error; default: cork_unreachable(); } } cork_exec_set_cwd(exec, cork_path_get(build_dir)); if (pkgconfig_path != NULL) { cork_env_add(exec_env, "PKG_CONFIG_PATH", pkgconfig_path); } ei_check(bz_subprocess_run_exec(verbose, NULL, exec)); /* $ make */ clog_info("(%s) Build using autotools", package_name); exec = cork_exec_new("make"); cork_exec_add_param(exec, "make"); cork_exec_set_cwd(exec, cork_path_get(build_dir)); ei_check(bz_subprocess_run_exec(verbose, NULL, exec)); cork_buffer_done(&buf); return 0; error: cork_buffer_done(&buf); return -1; }