【发布时间】:2020-03-14 03:24:15
【问题描述】:
我正在创建我的应用程序的纯 x64 版本。为此,我还需要一个 x64 安装程序。我在网上读到 NSIS 代码确实支持 x64,但由于它们不分发我需要从源代码(包括所有插件/等)构建的 x64 构建。
我已经能够使用 Python 2.7/SCons 3.1.1/VS 2012/Zlib 1.2.7 从 x86 的源代码构建 NSIS (v3.0.4)。
scons ZLIB_W32=C:\Source\zlib-1.2.7
但是当我将 TARGET_ARCH=amd64 添加到 scons 命令时,
scons ZLIB_W32=C:\Source\zlib-1.2.7 TARGET_ARCH=amd64
它不起作用。最初它构建但没有链接,因为 zlib 仍然是 x86。
C:\Source\zlib-1.2.7\lib\zdll.lib : warning LNK4272: library machine type 'x86' conflicts with target machine type 'x64'
但是,在将 zlib1.dll(使用 VS2012)重建为 x64 后(dumpbin 确认了这一点)
我现在收到一个找不到 zlib 的错误
scons ZLIB_W32=C:\Source\zlib-1.2.7 TARGET_ARCH=amd64
scons: Reading SConscript files ...
WARNING: VER_PACKED not set, defaulting to 0x03003666!
Delete("nsis-18-Nov-2019.cvs")
Delete(".instdist")
Delete(".test")
Using Microsoft tools configuration (14.2)
Checking for memset requirement... (cached) yes
Checking for memcpy requirement... (cached) yes
Checking for C library gdi32... (cached) yes
Checking for C library user32... (cached) yes
Checking for C library pthread... (cached) no
Checking for C library iconv... (cached) no
Checking for C library shlwapi... (cached) yes
Checking for C library oleaut32... (cached) yes
Checking for C library version... (cached) yes
Checking for C library zdll... no
Checking for C library z... no
zlib (win32) is missing!
请注意,我已确保 x64 构建中的目录结构匹配,以便存在以下文件:
C:\Source\zlib-1.2.7\zlib1.dll
C:\Source\zlib-1.2.7\lib\zlib1.lib
C:\Source\zlib-1.2.7\include\zconf.h
C:\Source\zlib-1.2.7\include\zlib.h
我确实想到我告诉 scons 寻找 x86 zlib(因此 ZLIB_W32 中的 W32)但我没有看到告诉 scons 在 -h 输出中寻找 x64 zlib 的选项。
我错过了什么?
-更新 1- 我正在取得进展,但还没有走出困境。我发现我的构建存在几个问题。 #1,我实际上并没有像我想的那样使用 VS2012(我安装了几个版本)。请参阅上面的 scons 输出显示 14.0 (VS2019)。哎呀。不幸的是,简单地将 MSVC_VERSION=11.0 添加到我的命令行并不能解决它。似乎 nsis 项目并没有将其传递给 scons。我能弄清楚如何做到这一点的唯一方法是从以下位置修改 nsis SConstruct 文件:
######################################################################
####### Build Environment ###
######################################################################
path = ARGUMENTS.get('PATH', '')
toolset = ARGUMENTS.get('TOOLSET', '')
arch = ARGUMENTS.get('TARGET_ARCH', 'x86')
if toolset and path:
defenv = Environment(TARGET_ARCH = arch, ENV = {'PATH' : path}, TOOLS = toolset.split(',') + ['zip'])
else:
if path:
defenv = Environment(TARGET_ARCH = arch, ENV = {'PATH' : path})
if toolset:
defenv = Environment(TARGET_ARCH = arch, TOOLS = toolset.split(',') + ['zip'])
if not toolset and not path:
defenv = Environment(TARGET_ARCH = arch)
Export('defenv')
到:
######################################################################
####### Build Environment ###
######################################################################
path = ARGUMENTS.get('PATH', '')
toolset = ARGUMENTS.get('TOOLSET', '')
arch = ARGUMENTS.get('TARGET_ARCH', 'x86')
vs_version = ARGUMENTS.get('MSVC_VERSION', '')
if toolset and path:
defenv = Environment(TARGET_ARCH = arch, ENV = {'PATH' : path}, TOOLS = toolset.split(',') + ['zip'], MSVC_VERSION = vs_version)
else:
if path:
defenv = Environment(TARGET_ARCH = arch, ENV = {'PATH' : path}, MSVC_VERSION = vs_version)
if toolset:
defenv = Environment(TARGET_ARCH = arch, TOOLS = toolset.split(',') + ['zip'], MSVC_VERSION = vs_version)
if not toolset and not path:
defenv = Environment(TARGET_ARCH = arch, MSVC_VERSION = vs_version)
Export('defenv')
现在我的构建输出正确识别为 VS2012:
C:\Source\nsis\nsis-code-r7069-NSIS-tags-v304>scons ZLIB_W32=C:\Source\zlib MSVC_VERSION=11.0
scons: Reading SConscript files ...
WARNING: VER_PACKED not set, defaulting to 0x03003666!
Delete("nsis-19-Nov-2019.cvs")
Delete(".instdist")
Delete(".test")
Using Microsoft tools configuration (11.0)
Checking for memset requirement... (cached) yes
<snip>
似乎应该有更好的方法来解决这个问题,但我(还)对 scons 或 nsis 使用它来提交 PR 来解决这个问题还不够熟悉。或者它可能已经存在,只是我不够聪明(还)找不到它。
现在,开始构建 x64 nsis。非常感谢@Anders 缩小了需要的文件范围,@bdbaddog 建议查看 scons config.log,我发现在为 x64 构建 zlib.dll 库文件时,我错误地命名了它。将输出库更改为
C:\Source\zlib-1.2.7\lib\zdll.lib
它至少尝试构建但链接失败......
-编辑更新 1- 以前这里的所有链接错误都是我昨天遇到的一个坏兔子洞。不确定这是否是由于 scons 将一些临时文件留在某处或 VS 这样做或我只是愚蠢但今天当我开始尝试追踪链接错误时我无法重现它们(昨天机器重新启动,谁知道在此之前可能已被锁定/缓存的内容)。
-更新 2- 此更新删除了更新 1 中的所有误导性废话。当前情况是 x64 NSIS 构建(使用我的 zlib-1.2.7-amd64 构建和 NSIS 上的官方 NSIS zlib-1.2.8-amd64 预构建二进制文件wiki) 链接失败并出现同样的错误:
System.obj : error LNK2019: unresolved external symbol CallProc2 referenced in function Call
build\urelease\System\amd64-unicode\System.dll : fatal error LNK1120: 1 unresolved externals
scons: *** [build\urelease\System\amd64-unicode\System.dll] Error 1120
scons: building terminated because of errors.
到目前为止,我还没有弄清楚 CallProc2 是什么,但我认为这意味着 zlib 在这里不再有错。
-更新 3- 感谢@Anders 的指导,因为我真的被 Callproc 问题难住了,CallProc2 方法与系统插件隔离,是由于它没有正确构建造成的。在下面的 cmets 中进行了一些讨论,试图找出原因,但现在,我只是排除了那个插件,以便在回到这个问题之前找到一个可以工作的系统。
现在,scons 构建完成并生成 x64 二进制文件。
C:\Source\nsis\build\urelease\makensisw\>dumpbin /HEADERS ./makensisw.exe
Microsoft (R) COFF/PE Dumper Version 11.00.61030.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file ./makensisw.exe
PE signature found
File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
8664 machine (x64)
但是,安装程序构建现在会导致以下错误:
scons dist-installer ZLIB_W32=C:\Source\zlib-1.2.8-x64 MSVC_VERSION=11.0
link /nologo /map /subsystem:console,5.01 /OUT:build\urelease\VPatch\Source\GenPat\GenPat.exe /LIBPATH:C:\Source\zlib-1.2.8-x64\lib zdll.lib build\urelease\VPatch\Source\GenPat\adler32.obj build\urelease\VPatch\Source\GenPat\Checksums.obj build\urelease\VPatch\Source\GenPat\ChunkedFile.obj build\urelease\VPatch\Source\GenPat\FileFormat1.obj build\urelease\VPatch\Source\GenPat\GlobalTypes.obj build\urelease\VPatch\Source\GenPat\main.obj build\urelease\VPatch\Source\GenPat\md5.obj build\urelease\VPatch\Source\GenPat\PatchGenerator.obj build\urelease\VPatch\Source\GenPat\POSIXUtil.obj
adler32.obj : error LNK2019: unresolved external symbol _adler32 referenced in function "unsigned long __cdecl Checksum::adler32(unsigned long,unsigned char const *,unsigned int)" (?adler32@Checksum@@YAKKPBEI@Z)
build\urelease\VPatch\Source\GenPat\GenPat.exe : fatal error LNK1120: 1 unresolved externals
scons: *** [build\urelease\VPatch\Source\GenPat\GenPat.exe] Error 1120
不幸的是,没有安装程序,我又迷路了。 x64 二进制文件运行,但在尝试编译任何脚本时(我相信),我收到以下错误(请注意,我为此将 makensis 和 zlib1.dll 复制到同一目录中):
C:\Source>makensis.exe ./myapp.nsi
Error: reading stub "C:\Stubs\zlib-amd64-unicode"
Error initalizing CEXEBuild: error setting default stub
-更新 4- 忽略系统插件后,我终于成功构建了一个工作。这既适用于从 x64 的源代码编译 zlib,也适用于 NSIS wiki 的预构建版本(在下面的@Anders 答案中链接):
scons ZLIB_W32=C:\Source\zlib-1.2.8-x64 TARGET_ARCH=amd64 MSVC_VERSION=11.0 SKIPPLUGINS=System
并且我能够使用(从我安装到 Program Files 后启用管理员提示)部署到我的开发系统:
scons PREFIX="C:\Program Files (x86)\NSIS" install ZLIB_W32=C:\Source\zlib-1.2.8-x64 TARGET_ARCH=amd64 SKIPPLUGINS=System
不幸的是,您无法从此处(dist-install)构建 NSIS 安装程序,因为 NSIS 安装程序本身显然取决于系统插件的使用。因此,除非您要在该机器上从头开始构建所有内容,否则这种情况不足以准备构建机器。
另外,我还没有走出困境,因为我还为我的安装程序使用了系统插件,所以我需要弄清楚为什么它不起作用。
但是,我能够使用上述设置编译和运行纯 x64 最低安装程序包:
# name the installer
OutFile "Installer.exe"
# default section start; every NSIS script has at least one section.
Section
# default section end
SectionEnd
以上内容直接来自 NSIS 文档。
【问题讨论】:
-
ZLIB_W32 是正确的名称。
-
NSIS Sconscript 仍然使用旧的 SCons 名称“MSVS_VERSION”。 SCons 在某些时候改变了他们的命名,MSVS 和 MSVC 在 SCons 3 IIRC 中是两个不同的东西。
-
是的,我也尝试过使用 MSVS,但我相信它支持的最后一个版本是 8。在 VS2012 命令提示符下(根据 scons 文档)还尝试了 MSVC_USE_SCRIPT=None,但它也不起作用)。所有其他命令都说必须在 Environment 调用中设置它们,在我看来,nsis 没有将它们传递给调用(因此我进行了修改)。
-
MSVC_USE_SCRIPT=None 是 NSIS 并不真正支持的 SCons 东西,除非你这样做
mstoolkit=yes MSVC_USE_SCRIPT=None(它不关心你是否有“工具包”,它只需要 cl.exe %path% 等) -
函数名称中初始
_的区别可能是一些编译器设置或与函数导出方式相关的内容(extern "C" 等)。 NSIS 倾向于使用旧编译器构建,越旧越好。但是我觉得很奇怪,如果你自己构建 .dll 和 .lib,它们仍然不兼容!
标签: visual-studio-2012 nsis zlib scons