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

windows上使用msvc编译器,将软件版本定义到头文件宏定义中,rc文件引用宏定义,必须要重新编译windows软件版本信息才会更新 #4893

Closed
supf1994 opened this issue Mar 28, 2024 · 14 comments
Labels
Milestone

Comments

@supf1994
Copy link

Xmake 版本

2.8.9

操作系统版本和架构

windows10

描述问题

为了实现软件版本信息更新时,在多个操作系统下编译文件的版本信息同步更新,我将版本号定义到头文件中
image
windows下编译时在rc文件中引用 APP_VERSION_STRING 宏定义
image
编译之后打印软件的版本信息,同时通过windows的文件管理器查看软件版本
image
当我修改版本信息后再次编译,打印的版本信息改变了,但windows文件管理器查看软件版本依然没变
image
每次修改版本信息宏定义之后必须要重新编译整个项目,文件的版本信息才会改变,项目比较大时重新编译需要花费很长的时间,也容易忘记
image

测试工程,使用vs2022编译
rc_test.zip

期待的结果

不需要重新编译整个项目,改头文件中的宏定义,就能实现文件版本信息更新

工程配置

...

附加信息和错误日志

...

@supf1994 supf1994 added the bug label Mar 28, 2024
@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


Title: Use the msvc compiler on Windows and define the software version into the header file macro definition. The rc file references the macro definition. You must recompile the Windows software version information before it can be updated.

@waruqi
Copy link
Member

waruqi commented Mar 28, 2024

这个没啥好办法,这要怪 msvc 的 rc.exe 压根不支持提供 include 等依赖信息,目前只能通过借助 cl.exe -E 预处理,勉强解析出一些 include 信息,才能够部分增量编译,但不完全精准

你可以调下

local cl = self:toolchain():tool("cxx")
如果能改进,你可以提个 pr 过来

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


There is no good way to do this. This is because msvc's rc.exe does not support providing include and other dependency information. Currently, we can only partially increment it by parsing out some include information with the help of cl.exe -E preprocessing. Compiles, but is not entirely accurate

You can adjust

local cl = self:toolchain():tool("cxx")
. If it can be improved, you can submit a PR.

@star-hengxing
Copy link
Contributor

local ok = try {function () os.execv(cl, {"-E", sourcefile}, {stdout = outfile, stderr = errfile, envs = self:runenvs()}); return true end}
if ok and os.isfile(outfile) then

cl 返回值是 2,所以没有去解析。如果进入了解析逻辑,获取了 rc include 的头文件,可以试试生成一个 cpp 文件并引入该头文件,再获取级联依赖

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


local ok = try {function () os.execv(cl, {"-E", sourcefile}, {stdout = outfile, stderr = errfile, envs = self:runenvs()}); return true end}
if ok and os.isfile(outfile) then

The return value of cl is 2, so it is not parsed. If you enter the parsing logic and obtain the header file of rc include, you can try to generate a cpp file and introduce the header file, and then obtain the cascade dependencies

@waruqi
Copy link
Member

waruqi commented Mar 28, 2024

local ok = try {function () os.execv(cl, {"-E", sourcefile}, {stdout = outfile, stderr = errfile, envs = self:runenvs()}); return true end}
if ok and os.isfile(outfile) then

cl 返回值是 2,所以没有去解析。如果进入了解析逻辑,获取了 rc include 的头文件,可以试试生成一个 cpp 文件并引入该头文件,再获取级联依赖

这就要看下为啥cl为啥预处理失败了,不确定它一定能完全支持所有res文件的预处理,另外除了 includes,还有icon image等资源文件路径 也要提取的

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


local ok = try {function () os.execv(cl, {"-E", sourcefile}, {stdout = outfile, stderr = errfile, envs = self:runenvs()}); return true end}
if ok and os.isfile(outfile) then

The return value of cl is 2, so it is not parsed. If you enter the parsing logic and obtain the header file of rc include, you can try to generate a cpp file and introduce the header file, and then obtain the cascade dependencies

This depends on why cl preprocessing failed. I am not sure it can fully support the preprocessing of all res files. In addition to includes, there are also resource file paths such as icon images that need to be extracted.

@Wzshun
Copy link

Wzshun commented Mar 29, 2024

现阶段可以通过编译前移除rc.obj,来达到重新编译rc文件,而不需要全体重新编译。

before_build(function(target)
        -- workaround 让每次build,rc文件都重新编译
        -- 目前xmake 对rc文件内引用的信息(如头文件) 无法很好的跟踪变更
        --print("target object:", target:objectfile("app.rc")) -- 这个路径返回的不对...
        local rcObjFile = path.join(target:objectdir(), "src/App", "app.rc.obj")        
        if os.exists(rcObjFile) then 
            if not os.tryrm(rcObjFile) then 
                print("Failed to remove rc object file, the application info may be wrong")
            end
        end
    end)

这里的路径你自己适配下,target:objectfile("xxx.rc")返回的路径似乎没法很好的对应具体的obj文件。

waruqi added a commit that referenced this issue Mar 29, 2024
@supf1994
Copy link
Author

现阶段可以通过编译前移除rc.obj,来达到重新编译rc文件,而不需要全体重新编译。

before_build(function(target)
        -- workaround 让每次build,rc文件都重新编译
        -- 目前xmake 对rc文件内引用的信息(如头文件) 无法很好的跟踪变更
        --print("target object:", target:objectfile("app.rc")) -- 这个路径返回的不对...
        local rcObjFile = path.join(target:objectdir(), "src/App", "app.rc.obj")        
        if os.exists(rcObjFile) then 
            if not os.tryrm(rcObjFile) then 
                print("Failed to remove rc object file, the application info may be wrong")
            end
        end
    end)

这里的路径你自己适配下,target:objectfile("xxx.rc")返回的路径似乎没法很好的对应具体的obj文件。

这种方法目前可以保证版本信息更新,但是我使用vs写代码,每次运行的时候都会先去编译,当.rc.obj文件被删除之后,需要重新link,对于比较大的工程,link的时间很长,有没有办法监控 version.h头文件是否有修改,如果修改我就把.rc.obj文件删除,这样当运行软件时不需要重新link

@waruqi
Copy link
Member

waruqi commented Mar 29, 2024

两个问题导致,1. 根本原因是你 res/resource.h 里路径压根没配置对,怎么可能找到 src/version.h 呢。。

res\resource.h(16): fatal error C1083: 无法打开包括文件: “src/version.h”: No such file or directory
  1. rc 里走 cl.exe -E 没有设置 includes flags,所以头文件没找到。

解决方式

  1. add_includedirs(".") 配置上正确路径
  2. 更新 xmake,追加相关 flags improve rc deps #4893 #4897
xmake update -s dev

waruqi added a commit that referenced this issue Mar 29, 2024
@waruqi waruqi added this to the v2.9.1 milestone Mar 29, 2024
@star-hengxing
Copy link
Contributor

这里有一个小问题,既然 cl 没返回 0,应该把 error 信息打印出来才对

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


There is a small problem here. Since cl does not return 0, the error information should be printed out.

@waruqi
Copy link
Member

waruqi commented Mar 29, 2024

这里有一个小问题,既然 cl 没返回 0,应该把 error 信息打印出来才对

这是内部 includes 信息的解析,对用户应该是无感知的,不属于编译错误,原本就不应该对用户显示出来,否则反而误导用户,会让用户觉得很纳闷,明明在用 rc.exe 编译资源文件,怎么会报出 cl.exe 的错误。。

即使 includes 不对,应该得让 rc.exe 编译资源时候报错,而不是让 cl.exe -E 去报错。

但现在 rc.exe 没爆出来,我也没办法。

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


There is a small problem here. Since cl does not return 0, the error message should be printed out.

This is the analysis of internal includes information. It should be imperceptible to users. It is not a compilation error and should not be displayed to users. Otherwise, it will mislead users and make users feel very confused. They are obviously using rc.exe to compile resources. file, why does it report a cl.exe error? .

Even if includes is wrong, you should let rc.exe report an error when compiling resources instead of cl.exe -E.

But now that rc.exe has not exploded, there is nothing I can do.

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

No branches or pull requests

5 participants