【问题标题】:Building x64 NSIS (using VS2012)构建 x64 NSIS(使用 VS2012)
【发布时间】: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


【解决方案1】:

我的环境:

  • cl.exe: Microsoft (R) C/C++ Optimizing Compiler Version 19.24.28316 for x64
  • nsis 版本:3.06.1
  • zlib:Zlib-1.2.8-win64-AMD64

我修改了SCons/Tool/masm.py

C:\miniconda3\Lib\site-packages\SCons-4.0.1-py3.7.egg\SCons\Tool>diff -c masm.old.py masm.py
*** masm.old.py Fri Oct 09 22:02:45 2020
--- masm.py     Fri Oct 09 21:58:06 2020
***************
*** 61,66 ****
--- 61,68 ----
          shared_obj.add_emitter(suffix, SCons.Defaults.SharedObjectEmitter)

      env['AS']        = 'ml'
+     if env.get('TARGET_ARCH')=='amd64':
+         env['AS']   = 'ml64'
      env['ASFLAGS']   = SCons.Util.CLVar('/nologo')
      env['ASPPFLAGS'] = '$ASFLAGS'
      env['ASCOM']     = '$AS $ASFLAGS /c /Fo$TARGET $SOURCES'

同样修改nsis-3.06.1-src\Contrib\System\SConscript如下:

C:\dev\nsis-3.06.1-src\Contrib\System>diff -c SConscript.old SConscript
*** SConscript.old      Fri Oct 09 22:06:31 2020
--- SConscript          Fri Oct 09 19:17:40 2020
***************
*** 4,9 ****
--- 4,10 ----
        Source/Buffers.c
        Source/Plugin.c
        Source/System.c
+       Source/Call-amd64.S
  """)

  libs = Split("""

然后C:\dev\nsis-3.06.1-src&gt;scons TARGET_ARCH=amd64成功结束。

【讨论】:

  • 很高兴在这里给您一个赞成票,甚至将其标记为答案,因为这听起来比我最终得到的要远。不幸的是,由于这个问题,我失去了耐心并放弃了 NSIS(在使用了 15 年以上之后),所以我无法验证它是否有效 :)
【解决方案2】:

我有

\zlib1.dll
\include\zconf.h
\include\zlib.h
\lib\libzdll.a
\lib\zdll.lib
\lib\zlib.lib

您可以获得为 NSIS here 预先构建的 zlib。

在过去,我实际上使用 Process Monitor 来确定 SCons 正在寻找哪个文件,遗憾的是,这似乎是找出的最快方法。

关于 CallProc2。将“系统”添加到 SKIPPLUGINS 以解决此问题,以确保其他所有内容都能编译。 CallProc2 在 amd64 .S 文件中实现并由 system.c 使用。您需要正确检测到的 64 位 Microsoft 汇编程序来构建 .S 文件。

如果你只需要编译一次NSIS,那么你可以作弊;打开 Visual Studio 命令提示符并执行 ml64.exe /c Call-amd64.S,然后将 .obj 文件复制到与 system.obj 相同的构建目录并再次运行 Scons。

要正确执行此操作,您需要调查 Scons 未编译 .S 文件的原因。可能是相关 Sconscript 文件中的配置问题或错误。

【讨论】:

  • 你检查过scons运行配置逻辑时生成的config.log吗?
  • @bdbaddog 我现在没有编译任何东西,我只是查看了我拥有的文件,我知道它们可以工作。我确信 config.log 会有所帮助,但我经常忘记它的存在。
  • @Anders scons 似乎(使用 procmon)未能在我的设置中找到以下文件:libzdll.a、zdll.lib、lib.dll.a。我怀疑 zdll.lib 只是 scons 检查 zlib1.lib 的另一个可能名称(但它也确实找到了 zlib1.lib)。但是,如果是这样(意味着我的设置已满足该要求),这意味着唯一失败的是 .a 文件,它们是 GCC 特定的中间文件(无法使用 VS 生成这些文件)。我会玩弄你链接中的下载,看看我是否可以解决这个问题,但我想找到一个纯 VS 解决方案(所以它更干净)。
  • 我假设您不需要 .a 文件,但 NSIS Wiki 中的 zip 可能同时支持 MSVC 和 GCC。
  • @Anders 我能够使用 bdbaddog 推荐的 config.log 弄清楚 scons 在看什么。 scons 希望 zlib1.dll 的 lib 是 zdll.lib 而不是 zlib1.lib。不幸的是,这也会导致链接器错误。不幸的是,来自 NSIS wiki 的 zip 会导致相同的链接错误(请参阅编辑)。
猜你喜欢
  • 1970-01-01
  • 2014-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多