Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Distinguish config and component #1364

Closed
xq114 opened this issue Apr 26, 2021 · 3 comments
Closed

Distinguish config and component #1364

xq114 opened this issue Apr 26, 2021 · 3 comments

Comments

@xq114
Copy link
Contributor

xq114 commented Apr 26, 2021

你在什么场景下需要该功能?

现在组件的管理是用config管理的。我先安装了boost{configs={filesystem=true,system=true,regex=true,....}}然后一个包需求是boost{configs={filesystem=true,system=true}},则这个包不会使用现有的boost而是重新安装仅含两个组件的boost,考虑到boost组件众多、安装时间比较长、占用空间也比较大,这样的管理方式缺乏效率

描述可能的解决方案

add_configs("...", {description=..., type="component"(currently boolean), ...})

对components,每一个component视为独立的组件,在匹配的时候只要匹配上需要的components同时其他设置都一样,那就可以复用。

on_fetch里面也要处理找到的component,暂时没想到好的处理方式

描述你认为的候选方案

add_components("...", {description=...})

on_fetch(function (package, opt)
	...
	for _, comp in ipairs(comps) do
		if find... then
			table.insert(result.components, ...)
		end
	end
end)

同时因为component只有有/没有或者需要/不需要两种状态,指定时不需要和config一样麻烦,对于component可以采用更方便的处理方式

add_requires("boost|filesystem,system,regex,program_options,graph")
or add_requires("boost", {components={"filesystem","system","regex","program_options","graph"}})
-- currently add_requires("boost", {configs = {filesystem = true, system = true, regex = true, program_options = true, graph = true}})
@waruqi
Copy link
Member

waruqi commented Apr 27, 2021

这个之前也有人提过,内部还区分子模块,这么搞法,过于复杂,会把 package 的内部逻辑越整越复杂,不好维护,也容易出更多的问题。。

尽量复用现有的包结构,可以把子模块展开成独立的 package ,既可以保证每个包还是现有的模式处理,也方便维护。。

通过子模块主要是为了解决下面几个问题:

  1. 重复下载
  2. 重复编译
  3. 冗余存储

问题1, 现有版本通过 add_requires("boost~context", {configs = {context = true}}) 方式,clone 出一个 package ,就能解决,内部会去复用 cache directory,避免重复下载,但是还是会去重复编译

既然之前已经支持了 private = true 模式,#1313 (comment)

可以采用类似的方式解决,比如下面这样:

package("boost-context")
    add_deps("boost", {private = true, configs = {all = true}})
    on_fetch(function (package, opt)
        local boost = package:dep("boost"):fetch()
        if boost then
            return table.join(boost, {links = "boost_context-mt"})
        end
    end)
package_end()

add_requires("boost-context")

target("test")
    set_kind("binary")
    add_files("src/*.cpp")
    add_packages("boost-context")

通过 add_deps("boost", {private = true, configs = {all = true}}) 确保仅仅只编译安装一次,里面启用了所有模块,并且设置为 private,不对外导出 links,仅用于其他包二次安装使用。。

然后,你自己项目定义需要的子模块包,复用 boost/all 里面的 linkdirs/includedirs,在 fetch 阶段,仅仅开启部分 links 就行了。。

完全复用之前安装的所有文件,并不会重复安装。

你可以分成多个 package("boost-xxx") 来拆分,也可以在一个 package("boost-components") 里面 根据 configs ,开启不同的 links 。。

比如:

add_requires("boost-components", {context = true})
add_requires("boost-components", {system = true})

都不会重复编译安装。

注:需要最新 dev 版本,依赖一些 patch 修复。

@xq114
Copy link
Contributor Author

xq114 commented Apr 27, 2021

感谢回复,还有两个问题:

  1. 如果我安装了全组件的boost,同时依赖两个xmake-repo里面依赖boost不同组件的包,如何让他们共用boost库?
  2. 如何在on_fetch里面返回找到哪些组件?

@waruqi
Copy link
Member

waruqi commented Apr 27, 2021

如果我安装了全组件的boost,同时依赖两个xmake-repo里面依赖boost不同组件的包,如何让他们共用boost库?

就按我刚说的方式,实际上都是共用的 boost all那一个包

如何在on_fetch里面返回找到哪些组件?

也通过 add_configs 和 package:config 判断

另外,也可以直接改进boost package定义,如果走 all,就直接装,如果走部分配置,就加private all 的boost deps,走切片fetch,既不会deadloop,而且一个包就能搞定,对用户完全透明,前提是 得用最新的 xmake 版本,得根据版本兼容下

@waruqi waruqi closed this as completed May 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants