~lattis/muon

b9445e6453def2fe7556b1b13c07628ca5300f03 — Stone Tickle a month ago 354d545
support is_system include directories
M include/coerce.h => include/coerce.h +1 -0
@@ 14,4 14,5 @@ bool coerce_requirement(struct workspace *wk, struct args_kw *kw_required, enum 
bool coerce_files(struct workspace *wk, uint32_t node, obj val, obj *res);
bool coerce_dirs(struct workspace *wk, uint32_t node, obj val, obj *res);
bool coerce_output_files(struct workspace *wk, uint32_t node, obj val, obj *res);
bool coerce_include_dirs(struct workspace *wk, uint32_t node, obj val, bool is_system, obj *res);
#endif

M include/compilers.h => include/compilers.h +1 -0
@@ 64,6 64,7 @@ struct compiler {
		compiler_get_arg_func_0 werror;
		compiler_get_arg_func_1s set_std;
		compiler_get_arg_func_1s include;
		compiler_get_arg_func_1s include_system;
	} args;
	enum compiler_deps_type deps;
	enum linker_type linker;

M include/lang/object.h => include/lang/object.h +5 -0
@@ 36,6 36,7 @@ enum obj_type {
	obj_module,
	obj_install_target,
	obj_environment,
	obj_include_directory,

	obj_type_count,



@@ 168,6 169,10 @@ struct obj {
		struct {
			obj env; /* dict */
		} environment;
		struct {
			str path;
			bool is_system;
		} include_directory;
	} dat;
};


M src/backend/common_args.c => src/backend/common_args.c +9 -4
@@ 126,9 126,11 @@ struct setup_compiler_args_includes_ctx {
};

static enum iteration_result
setup_compiler_args_includes(struct workspace *wk, void *_ctx, obj v_id)
setup_compiler_args_includes(struct workspace *wk, void *_ctx, obj v)
{
	const char *dir = get_cstr(wk, v_id);
	struct setup_compiler_args_includes_ctx *ctx = _ctx;
	struct obj *inc = get_obj(wk, v);
	const char *dir = get_cstr(wk, inc->dat.include_directory.path);

	if (!fs_dir_exists(dir)) {
		return ir_cont;


@@ 142,8 144,11 @@ setup_compiler_args_includes(struct workspace *wk, void *_ctx, obj v_id)
		dir = rel;
	}

	struct setup_compiler_args_includes_ctx *ctx = _ctx;
	push_args(wk, ctx->args, compilers[ctx->t].args.include(dir));
	if (inc->dat.include_directory.is_system) {
		push_args(wk, ctx->args, compilers[ctx->t].args.include_system(dir));
	} else {
		push_args(wk, ctx->args, compilers[ctx->t].args.include(dir));
	}
	return ir_cont;
}


M src/coerce.c => src/coerce.c +79 -0
@@ 5,6 5,7 @@

#include "coerce.h"
#include "lang/interpreter.h"
#include "log.h"
#include "platform/filesystem.h"
#include "platform/path.h"



@@ 268,3 269,81 @@ coerce_dirs(struct workspace *wk, uint32_t node, uint32_t val, uint32_t *res)
{
	return _coerce_files(wk, node, val, res, "directory", fs_dir_exists, mode_input);
}

struct include_directories_iter_ctx {
	uint32_t node;
	obj res;
	bool is_system;
};

static enum iteration_result
include_directories_iter(struct workspace *wk, void *_ctx, obj v)
{
	struct include_directories_iter_ctx *ctx = _ctx;
	struct obj *d = get_obj(wk, v);

	if (d->type == obj_include_directory) {
		obj_array_push(wk, ctx->res, v);
		return ir_cont;
	} else if (d->type != obj_string) {
		interp_error(wk, ctx->node, "unable to coerce %o to include_directory", v);
		return ir_err;
	}

	str path = d->dat.str;
	char buf1[PATH_MAX], buf2[PATH_MAX];
	const char *p = get_cstr(wk, path);

	if (!path_is_absolute(p)) {
		if (!path_join(buf1, PATH_MAX, get_cstr(wk, current_project(wk)->cwd), p)) {
			return ir_err;
		}

		path = wk_str_push(wk, buf1);
	}

	p = get_cstr(wk, path);

	if (!fs_dir_exists(p)) {
		interp_error(wk, ctx->node, "directory '%s' does not exist", get_cstr(wk, path));
		return ir_err;
	}

	obj inc;
	d = make_obj(wk, &inc, obj_include_directory);
	d->dat.include_directory.path = path;
	d->dat.include_directory.is_system = ctx->is_system;
	obj_array_push(wk, ctx->res, inc);

	if (path_is_subpath(wk->source_root, p)) {
		if (!path_relative_to(buf1, PATH_MAX, wk->source_root, p)) {
			return ir_err;
		} else if (!path_join(buf2, PATH_MAX, wk->build_root, buf1)) {
			return ir_err;
		}

		d = make_obj(wk, &inc, obj_include_directory);
		d->dat.include_directory.path = wk_str_push(wk, buf2);
		d->dat.include_directory.is_system = ctx->is_system;
		obj_array_push(wk, ctx->res, inc);
	}

	return ir_cont;
}

bool
coerce_include_dirs(struct workspace *wk, uint32_t node, obj val, bool is_system, obj *res)
{
	struct include_directories_iter_ctx ctx = {
		.node = node,
		.is_system = is_system,
	};

	make_obj(wk, &ctx.res, obj_array);
	if (!obj_array_foreach_flat(wk, val, &ctx, include_directories_iter)) {
		return false;
	}

	*res = ctx.res;
	return true;
}

M src/compilers.c => src/compilers.c +13 -0
@@ 257,6 257,16 @@ compiler_posix_args_include(const char *dir)
/* gcc compilers */

static const struct args *
compiler_gcc_args_include_system(const char *dir)
{
	COMPILER_ARGS({ "-isystem", NULL });

	argv[1] = dir;

	return &args;
}

static const struct args *
compiler_gcc_args_deps(const char *out_target, const char *out_file)
{
	COMPILER_ARGS({ "-MD", "-MQ", NULL, "-MF", NULL });


@@ 403,6 413,7 @@ build_compilers(void)
			.werror       = compiler_arg_empty_0,
			.set_std      = compiler_arg_empty_1s,
			.include      = compiler_arg_empty_1s,
			.include_system = compiler_arg_empty_1s,
		}
	};



@@ 412,6 423,7 @@ build_compilers(void)
	posix.args.optimization = compiler_posix_args_optimization;
	posix.args.debug = compiler_posix_args_debug;
	posix.args.include = compiler_posix_args_include;
	posix.args.include_system = compiler_posix_args_include;
	posix.linker = linker_posix;

	struct compiler gcc = posix;


@@ 420,6 432,7 @@ build_compilers(void)
	gcc.args.warning_lvl = compiler_gcc_args_warning_lvl;
	gcc.args.werror = compiler_gcc_args_werror;
	gcc.args.set_std = compiler_gcc_args_set_std;
	gcc.args.include_system = compiler_gcc_args_include_system;
	gcc.deps = compiler_deps_gcc;
	gcc.linker = linker_gcc;


M src/external/libpkgconf.c => src/external/libpkgconf.c +3 -1
@@ 188,7 188,9 @@ apply_and_collect(pkgconf_client_t *client, pkgconf_pkg_t *world, void *_ctx, in
		switch (frag->type) {
		case 'I':
			if (!pkgconf_fragment_has_system_dir(client, frag)) {
				make_obj(ctx->wk, &str, obj_file)->dat.file = wk_str_push(ctx->wk, frag->data);
				struct obj *o = make_obj(ctx->wk, &str, obj_include_directory);
				o->dat.include_directory.path = wk_str_push(ctx->wk, frag->data);
				o->dat.include_directory.is_system = false;
				obj_array_push(ctx->wk, ctx->info->includes, str);
			}
			break;

M src/functions/default.c => src/functions/default.c +14 -35
@@ 353,46 353,26 @@ func_find_program(struct workspace *wk, obj _, uint32_t args_node, obj *res)
	return true;
}

static enum iteration_result
include_directories_iter(struct workspace *wk, void *_ctx, obj v)
{
	obj *res = _ctx;

	obj_array_push(wk, *res, v);

	const char *p = get_cstr(wk, get_obj(wk, v)->dat.file);

	if (path_is_subpath(wk->source_root, p)) {
		char path[PATH_MAX], tmp[PATH_MAX];
		if (!path_relative_to(tmp, PATH_MAX, wk->source_root, p)) {
			return ir_err;
		} else if (!path_join(path, PATH_MAX, wk->build_root, tmp)) {
			return ir_err;
		}

		obj f;
		make_obj(wk, &f, obj_file)->dat.file = wk_str_push(wk, path);
		obj_array_push(wk, *res, f);
	}

	return ir_cont;
}

static bool
func_include_directories(struct workspace *wk, obj _, uint32_t args_node, obj *res)
{
	struct args_norm an[] = { { ARG_TYPE_GLOB }, ARG_TYPE_NULL };
	if (!interp_args(wk, args_node, an, NULL, NULL)) {
	enum kwargs {
		kw_is_system,
	};
	struct args_kw akw[] = {
		[kw_is_system] = { "is_system", obj_bool },
		0
	};
	if (!interp_args(wk, args_node, an, NULL, akw)) {
		return false;
	}

	obj dirs;
	if (!coerce_dirs(wk, an[0].node, an[0].val, &dirs)) {
		return false;
	}
	bool is_system = akw[kw_is_system].set
		? get_obj(wk, akw[kw_is_system].val)->dat.boolean
		: false;

	make_obj(wk, res, obj_array);
	if (!obj_array_foreach(wk, dirs, res, include_directories_iter)) {
	if (!coerce_include_dirs(wk, an[0].node, an[0].val, is_system, res)) {
		return false;
	}



@@ 526,9 506,8 @@ tgt_common(struct workspace *wk, uint32_t args_node, obj *res, enum tgt_type typ
	LOG_I("added target %s", get_cstr(wk, tgt->dat.tgt.build_name));

	if (akw[kw_include_directories].set) {
		uint32_t inc_dirs;

		if (!coerce_dirs(wk, akw[kw_include_directories].node, akw[kw_include_directories].val, &inc_dirs)) {
		obj inc_dirs;
		if (!coerce_include_dirs(wk, akw[kw_include_directories].node, akw[kw_include_directories].val, false, &inc_dirs)) {
			return false;
		}


M src/functions/default/dependency.c => src/functions/default/dependency.c +2 -3
@@ 286,9 286,8 @@ func_declare_dependency(struct workspace *wk, uint32_t _, uint32_t args_node, ob
	}

	if (akw[kw_include_directories].set) {
		uint32_t inc_dirs;

		if (!coerce_dirs(wk, akw[kw_include_directories].node, akw[kw_include_directories].val, &inc_dirs)) {
		obj inc_dirs;
		if (!coerce_include_dirs(wk, akw[kw_include_directories].node, akw[kw_include_directories].val, false, &inc_dirs)) {
			return false;
		}


M src/functions/dependency.c => src/functions/dependency.c +2 -5
@@ 14,12 14,9 @@ enum iteration_result
dep_args_includes_iter(struct workspace *wk, void *_ctx, obj inc_id)
{
	struct dep_args_ctx *ctx = _ctx;
	assert(get_obj(wk, inc_id)->type == obj_file);

	obj path;
	make_obj(wk, &path, obj_string)->dat.str = get_obj(wk, inc_id)->dat.file;
	obj_array_push(wk, ctx->include_dirs, path);
	assert(get_obj(wk, inc_id)->type == obj_include_directory);

	obj_array_push(wk, ctx->include_dirs, inc_id);
	return ir_cont;
}


M src/lang/object.c => src/lang/object.c +1 -0
@@ 39,6 39,7 @@ obj_type_to_s(enum obj_type t)
	case obj_module: return "module";
	case obj_install_target: return "install_target";
	case obj_environment: return "environment";
	case obj_include_directory: return "include_directory";

	case obj_type_count:
	case ARG_TYPE_NULL: