Support customizing implib path of MinGW/MSVC#6334
Support customizing implib path of MinGW/MSVC#6334SineStriker wants to merge 11 commits intoxmake-io:devfrom
implib path of MinGW/MSVC#6334Conversation
|
还发现一个问题:在 |
I also found a problem: the linkargv in |
其中大部分都是找库的库名处理,linkname 处理,没看到 #3052 和你遇到的问题有什么关系。mingw 下库名很多都是 dll.a ,而不是 .lib 当然得处理下。
安装是安装,构建是构建,构建只需要保证 我只是说 implib 这玩意,暂时没必要单独提供 api 去配置路径,安装的 set_prefixdir ,也不支持,并没有区别对待。
安装和构建,不可能完全一致,目的完全不同,怎么一致,就比如 qt 还有 qtdeploy 了,ios app 安装还要先打包成 .ipa ,android 安装还得先打包成 .apk 。。难道每次构建运行,也得都走一遍 qtdeploy ,导出全部 dll 和资源文件后,再运行?这得多慢,改一行代码,deploy 半天,才能出效果。 编译个 ios app 还得先打包出 .ipa 在运行? 构建阶段,不管用户怎么配置路径,只要保证 安装阶段,根据系统和用户需要,配置实际的安装结构,配置打包格式,配置签名,配置资源打包一堆事情。 |
Most of them are processed by looking for library names and linkname processing. I didn’t see what does #3052 have to do with the problems you are facing. Many of the library names under mingw are dll.a, not .lib, of course, they have to be processed.
Installation is installation, and construction is construction. Construction only requires ensuring that I just said that there is no need to provide the API to configure the path of the implib thing for the time being. The installed set_prefixdir is not supported, and there is no difference.
Installation and construction cannot be completely consistent, the purpose is completely different, how to be consistent, for example, qt and qtdeploy, the installation of ios app must be packaged into .ipa first, and the installation of android must be packaged into .apk first. . Do you have to go through qtdeploy every time you build and run it, export all the dlls and resource files, and then run it? How slow is this? Change a line of code and deploy it for half a day before it can produce an effect. To compile an ios app, you have to package out .ipa first and run it? During the construction stage, no matter how the user configures the path, just ensure that During the installation stage, according to the system and user needs, the actual installation structure is configured, the packaging format is configured, the signature is configured, and the resource is configured to package a lot of things. |
这种有问题,可以单开 issues ,提供复现 case ,到时候调下就行了。 |
If you have any problems, you can open issues alone and provide reproduction case. Then you can adjust it. |
In addition, there is no need to separate the impllib path for #3052 problem, although the library has the same name, it should also be overwritten after the second compilation and generation of .lib to ensure that the link is passed. . I feel that I just didn’t thoroughly investigate and locate the root cause before. |
|
当然,这个 patch 还是可以保留,不过需要做进一步改进,既然有了 target:implibdir(), 那就再加上 其他的地方,我暂时没时间 review 等回头有时间在看。 |
Of course, this patch can still be retained, but further improvements are needed. Since there is target:implidir(), then add Other places, I don’t have time to review. I’m waiting for the time to look back. |
这个 PR 先留着了,我这段时间会测试它跟 xmake 的其他功能是不是有水土不服,会不时添加新的提交的。目前找到的问题就是以下几个:
|
I will keep this PR for now. During this period, I will test whether it is not suitable for the other functions of xmake and will add new submissions from time to time. The questions found are the following:
|
感谢,确实需要做改进,现在这个 api 也是我临时想的而已。 我觉得最理想的情况是能让构建期和安装期有形式相同的 API,以 CMake 举例:
set_target_properties(${PROJECT_NAME} PROPERTIES
PDB_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin # .pdb
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build/bin # .exe, Unix Executable
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build/lib # .so, .dylib
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build/lib # .a, .lib, .dll.a
)
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)从 API 设计之初就考虑了一个目标潜在的多个输出文件并对它们都设置了专用的 output dir,install 的时候 DESTINATION 也能保持一致,但是考虑到 xmake 现在已经有 set_targetdir 这样的 API 了,要跟 set_prefixdir 保持一致感觉还是挺困难的,怎么改进现在我也没想好。 |
Thanks, I do need to make improvements, and now this API is just what I think about temporarily. I think the ideal situation is to have the same API in the build and install periods, taking CMake as an example:
set_target_properties(${PROJECT_NAME} PROPERTIES
PDB_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin # .pdb
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build/bin # .exe, Unix Executable
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build/lib # .so, .dylib
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build/lib # .a, .lib, .dll.a
)
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)Since the beginning of the API design, we have considered multiple potential output files for a target and set a dedicated output dir for them. DESTINATION can also be consistent when installing it, but considering that xmake now has an API like set_targetdir, it feels quite difficult to keep it consistent with set_prefixdir. I haven't thought about how to improve it now. |
我只是举例,我的意思的 qt 项目也压根没必要 build 阶段去 deploy ,即使 win 上快,但相比不去 deploy ,开发调试效率会更高。其他pc项目也是,压根没必要去 copy 各种 dll/so 到指定目录, 尤其是一些依赖大量 dll/so 的程序,每次 build 都会省去一大笔 dll/so copy 的时间。
那你可以自己通过 set_targetdir 配置,一个 target 要么只能是 shared ,要么只能是 static ,原本就是可以自己配置的。 现在仅仅 implib 不支持而已。
after_link 里面,你自己 os.cp 同样可以。机会同样给了。
set_prefixdir 那个是通过设置 dll 路径,implib 也只是跟随 dll 的路径,并不能分离。效果 跟 set_targetdir 一样的,你 set_prefixdir 设置 dll 的路径,对应 implib 也会跟着修改调整。 并没有区别,效果完全一致。
我之前说了,这些平台和编译特有的临时文件,xmake 永远不可能全部去为它们单独开接口。但不代表不能控制他们。现在就可以。。 after_link., after_build 里面你可以通过 os.cp + rule 做你想做的任何事情,想怎么 copy 到指定位置,都可以
implib 至少 mingw/ msvc 以及安装上都也许会对外导出用到,想要通过 implibdir 配置,倒也可以,但是 ilk exp 以及其他乱七八糟的文件 就不要想了,不可能单独加接口的。 |
I'm just giving an example. I mean that there is no need to deploy in the build stage at all. Even if win is fast, it will be more efficient than not deploying. The same is true for other PC projects. There is no need to copy various dll/so to the specified directory at all. Especially some programs that rely on a large number of dll/so, each build will save you a lot of time in dll/so copy.
Then you can configure it yourself through set_targetdir. A target can either be shared or static. It can be configured by yourself. Now only implib is not supported.
In after_link, you can also do so with os.cp. Opportunities are also given.
set_prefixdir is set by setting the dll path, implib only follows the dll path and cannot be separated. The effect is the same as set_targetdir. If you set_prefixdir set the path of the dll, the corresponding implib will also be modified and adjusted. There is no difference, the effect is exactly the same.
I said before that xmake can never open an interface for these platforms and compiling unique temporary files. But it doesn't mean they can't be controlled. It's OK now. . After_link., after_build you can do whatever you want through os.cp + rule, and you can copy it to the specified location.
implib at least mingw/ msvc and installation may be exported to the outside world. If you want to configure it through implibdir, it is OK, but don’t think about ilk exp and other messy files, it is impossible to add an interface separately. |
它也没有分离 implib 和 dll ,只是把 implib 跟随进了 archive 里面而已。 RUNTIME_OUTPUT_DIRECTORY 对应 binary target + set_targetdir 本质上都是相同的,仅仅只是 xmake 目前的设计是跟随 target kind ,而不是直接跟随 library kind,导致 implib 输出路径的部分差异而已。 也就是说 cmake 里面 implib 跟随了 archive 库路径,xmake 里面 implib 跟随了 shared target 的路径 就好比 你让 cmake 去分离 .a 和 .dll.a 的路径,一样分离不开。但是 xmake 里面就能分开。 毕竟不同构建工具设计不同,肯定有部分差异。 |
不是啊,我用mingw和msvc都试过,动态库目标的.lib或者.dll.a都会安装到 |
|
CMake 的做法是,我对一个 target 可以设置很多个 output directory,比如
然后如果这个 target 的构建会输出多个文件,比如输出了.dll和.lib,那么.dll就会被输出到 RUNTIME_OUTPUT_DIRECTORY 里,而 LIBRARY_OUTPUT_DIRECTORY 被输出到 ARCHIVE_OUTPUT_DIRECTORY 里。 xmake 是一个 target 只能设置一个 output directory,就是那个 targetdir,不管这个 target 构建完了输出什么类型的文件都会被输出到 targetdir。
这个你说得不对,是可以分离的。.a 是静态库目标才会输出的文件,.dll.a 是动态库目标输出的文件,它们根本不可能来自同一个目标,那我只要给这两个目标自己的 ARCHIVE_OUTPUT_DIRECTORY 设置成不一样的就行了。 add_library(static_target STATIC ...)
set_target_properties(static_target PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY dir1 # static_target 的 .a 就会被输出到 dir1 里
)
add_library(shared_target SHARED ...)
set_target_properties(shared_target PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY dir2 # shared_target 的 .dll.a 就会被输出到 dir2 里
)如果你只能改全局的那个 CMAKE_ARCHIVE_OUTPUT_DIRECTORY,那当然没法把它们分离开,但是我可以单独设置每个目标的。
至于这些中间文件,要不要单独加接口,其实也不好说,我目前是只有一个 implib 的需求,但是以后会不会有其他人有其他文件的需求就不清楚了。反正 CMake 是给 MSVC 的 PDB 文件的输出路径也提供了一个接口,可能将来会有人提出需求,所以保留一定的扩展性会比较好。至于 ilk、exp 那些应该是真的没必要。 |
|
目前是把 如果 set_targetdir("$(buildir)")如果 set_targetdir("$(buildir)", { bin = "bin", lib = "lib" })那么,exe、dll 以及 unix 可执行文件会输出到 并且保留了一定的扩展性,以后如果要加别的类型的输出(比如 pdb,也不用增加新的 API,直接在上面扩展就行)。 如果我要取不同类型文件的输出路径或者目录,那么通过 |
Currently, If set_targetdir("$(buildir)")If set_targetdir("$(buildir)", { bin = "bin", lib = "lib" })Then, the exe, dll and unix executable files will be output to It also retains a certain degree of expansion. If you want to add another type of output in the future (such as pdb, you don’t need to add a new API, just expand it directly). If I want to take the output path or directory of a different type of file, then I can get it through |
It's OK, I'll add it back |
This is the case now, because now the artifactfile and targetfile have functional intersections. Unless you can think of a better extension interface name, you can only access various other products, but have no intersection with the targetfile. At least it will not be guaranteed to be mixed. |
byproduct is OK, it's too long |
|
|
听上去怪怪的,还不如 artifactfile ,就按 artifactfile 来好了,内部限制下,仅仅处理额外的产物就行了 |
It sounds weird, it's better to use artifactfile. Just press artifactfile. Under internal restrictions, you can just process additional products. |
改成 artifactfile 了 |
Change to artifactfile |
| if verbose then | ||
| -- show the full link command with raw arguments, it will expand @xxx.args for msvc/link on windows | ||
| print(linkinst:linkcmd(objectfiles, targetfile, {linkflags = linkflags, rawargs = true})) | ||
| print(linkinst:linkcmd(objectfiles, targetfile, {linkflags = linkflags, implib = target:artifactfile("implib"), rawargs = true})) |
There was a problem hiding this comment.
不要在这里设置。link 的 opt 里,原本就可以通过 target 取到 implib
xmake/xmake/core/tool/linker.lua
Line 230 in 40bfb6e
|
|
||
| if not dryrun then | ||
| assert(linkinst:link(objectfiles, targetfile, {linkflags = linkflags})) | ||
| assert(linkinst:link(objectfiles, targetfile, {linkflags = linkflags, implib = target:artifactfile("implib")})) |
|
|
||
| -- ensure the implib directory | ||
| if opt and opt.implib then | ||
| os.mkdir(path.directory(opt.implib)) |
There was a problem hiding this comment.
opt.target 里是可以取到的
xmake/xmake/core/tool/linker.lua
Line 230 in 40bfb6e
|
|
||
| -- add `-Wl,--out-implib,outputdir/libxxx.a` for xxx.dll on mingw/gcc | ||
| if targetkind == "shared" and self:is_plat("mingw") then | ||
| local implib = opt.implib or path.join(path.directory(targetfile), path.basename(targetfile) .. ".dll.a") |
| -- add `-Wl,--out-implib,outputdir/libxxx.a` for xxx.dll on mingw/gcc | ||
| if targetkind == "shared" and self:is_plat("mingw") then | ||
| table.insert(flags_extra, "-Wl,--out-implib," .. path.join(path.directory(targetfile), path.basename(targetfile) .. ".dll.a")) | ||
| local implib = opt.implib or path.join(path.directory(targetfile), path.basename(targetfile) .. ".dll.a") |
There was a problem hiding this comment.
opt.target 会很麻烦,因为可能这个 target 是个 package,还得判断 type
There was a problem hiding this comment.
但目前只有这种方式,在 link_objects 这种通用逻辑的地方,不适合加 implib 而且,而且覆盖不全,很多地方 link 不走 link_objects
也就多判断个 type ,一两行代码的事情
|
@waruqi 不对,不能从 opt.target 里获取,我之前试过出问题了。比如说 具体我也搞不懂这是怎么回事,大概说来就是 所以我也能理解了为什么 |
|
假如我在现在代码里的 print("TARGET: ", opt.target:name(), opt.implib or "/")然后用 MSVC 编译的时候: |
不是,那是因为这是早期的接口设计,当初还不支持传递 target,后来才追加的 target 到 opt |
按理不会。可能需要调下,或者部分改进下才行,先放着吧 回头我看下,link_objects 里肯定不能加的 |
No, that's because this is an early interface design. It did not support passing target at the beginning, but later the target was added to opt |
It's not true. It may need to be adjusted or partially improved, let's leave it first. I'll look back and see, it's definitely not added in link_objects. |
这个问题我修复了,可以试下这个 patch #6355 后面也再那个 patch 上继续跟进 |
|
另外,建议开个 issue ,详细描述下当前支持的特性和改动点,以及配置支持的写法和 example ,方便后续更新到文档,以及其他用户查看和使用 |
In addition, it is recommended to open an issue to describe the currently supported features and changes points in detail, as well as the configuration supported writing methods and examples, so as to facilitate subsequent updates to documents, and to view and use by other users. |
测试例子我之后有空去加。 |
Test examples I have time to add. |
#3052
我很久以前问过关于设置一个动态库目标
dll和lib文件输出目录分离的问题,当时作者给的答复是不希望给 MSVC 特有的功能设置新的 API,当时比较忙就没继续跟进。这段时间读了很久源码,大致知道了 xmake 工作流程,发现了一些问题。
.lib或者.dll.a进行了特殊处理,而且工具链 nvcc (mingw)、link (msvc)、gcc (mingw) 都被涉及,而且有多处特殊处理是我上次提 issue 之后添加的,说明不止我一个人遇到了与之相关的问题;set_prefixdir里设置bindir、libdir把dll和lib的安装目录分离了,这个功能是去年添加的,这就会导致一个更加匪夷所思的问题,为什么安装的时候允许分离但构建的时候不允许?我暂且认为这是 xmake 设计之初没有考虑周全,CMake 的构建和安装就统一对一个目标的潜在输出文件分为了 RUNTIME/LIBRARY/ARCHIVE 三种类型(虽然我觉得 ARCHIVE 纯粹没必要),我认为一个目标的构建和安装目录的配置最好有一致性,让项目的构建目录结构和安装目录结构保持相同,可以减少出问题的概率;clean的问题是我上次提的,f40cd6da49ed65067d4c6060fa3605cdbd994499 这个提交只处理了 MSVC 的输出文件,我补充了 MinGW 的;结论,我还是希望作者能考虑一下直接支持构建期
dll和lib输出分离。目前我是通过扩展
set_targetdir实现的,在后面添加一个形如{ implibdir = "$(buildir)/lib" }的 option table 就可以完成,对 msvc/gcc 的 build、clean 和 install 都进行了测试。当然这样一个接口看起来不完美,跟 install 时候的 api 名称不一样,之后名称怎么改可以讨论。如果这个 option 不加,那么整个 xmake 的逻辑与以前完全相同。目前还差一个小问题,就是修改了
implib的输出目录以后,还要对工程里其他所有依赖这个动态库的目标增加一个linkdir,这个暂时还没实现,目测应该加在inherit_link这个模块里。Sample: