Archive: port NSIS to VC8 and to x64 ?


port NSIS to VC8 and to x64 ?
Hello all
We are using NSIS to build Win32 installers for SW developed under VC8. So far, we use the prebuilt NSIS binaries.
Since NSIS binaries that would run on x64 do not seem to exist, I would like to port them.
This would be a two-step process
- adapt the NSIS sources and SCons scripts to build Win32 binaries with VC8
- add the x64 configurations and build them
The SCons 0.96.1 official release does not support VC8,
but the 0.96.92 testing pre-release does.

I tried to build NSIS from 2.19 sources, using SCons 0.96.92, and I ran into a build problem diagnosed as
"scons: *** An executable should have exactly one target with the suffix: .exe
File "SConstruct", line 502, in BuildUtil".

So, is there anyone experienced in SCons and in building NSIS on Windows, who would like to team up with me and help with this port?
I am willing to experiment and learn, but teamwork would make it go faster and more fun.

Rudif


The sconscripts need a bit of updating for 0.96.92, mainly for the problem you've encountered. Instead of directly building the utilities with their names, it should build it with whatever name scons wants and only install it with the name we need.

If I remember correctly, mingw.py also needs a few updates for 0.96.92.

Attached is the SConstruct file I updated for 0.06.92, but never got to finish. It kind of works now, I think. It was built on an older version of SConstruct, but I merged the new changes from NSIS 2.19.

BTW, even if you get it to build, there's still some work to be done for 64-bit installers. The installer stubs need some work for word-size neutrality and the compiler itself needs to write some headers with 64-bit integers. The compiler side already has an infrastructure for that using the writers introduced in 2.16 for big-endian support. However, there are no readers yet which are required to get the resource and dialog editor to work with both 32-bit and 64-bit resources.

For a simpler beginning and maybe a proof of concept, you can create two makensis builds, one for 32-bit installers and one for 64-bit installers.

Needless to say, any patch in this topic, including scons 0.96.92 support, will be happily accepted.


Hi Kichik

Thank you for the updated SConstruct. I made some progress using it.
I am learning basic python, scons and nsis build tricks, as I go along.


If I remember correctly, mingw.py also needs a few updates for 0.96.92.
I am conversant with building C++ applications under Visual Studio 2005 a.k.a. VC8, for Win32 and x64.
Currently I have no *nix or like tools for Win32 machines.


there's still some work to be done for 64-bit installers.
Right, I exepect some code adaptations before NSIS can be built for x64, and more adaptations to make it work.
Also, I see in Contrib\System\Source\System.c using the _asm {...} construct being used.
VC8 compiler for x64 has no _asm instruction, so I guess someone will need to move this into a x64 asm file
and assemble (working with asm is not my speciality at present).



Now, on to my experiments, aiming at building NSIS 2.19 for Win32 on a 32-bit machine running XP SP1, with VC8 installed :


I replaced the original nsis-2.19-src\SConctruct by a copy of your sconstruct[1].0.96.92.txt,
and launched scons

    scons: Building targets ...
cl /nologo /O1 /W3 /c Contrib\AdvSplash\advsplash.c /Fobuild\release\AdvSplash\advsplash.obj
advsplash.c
link /nologo /opt:nowin98 /map /entry:DllMain /NODEFAULTLIB /dll /out:build\release\AdvSplash\AdvSplash.dll kernel32.lib
user32.lib gdi32.lib winmm.lib build\release\AdvSplash\advsplash.obj
Creating library build\release\AdvSplash\AdvSplash.lib and object build\release\AdvSplash\AdvSplash.exp
advsplash.obj : error LNK2019: unresolved external symbol ___security_cookie referenced in function _WndProc@16
advsplash.obj : error LNK2019: unresolved external symbol @__security_check_cookie@4 referenced in function _WndProc@16
build\release\AdvSplash\AdvSplash.dll : fatal error LNK1120: 2 unresolved externals
scons: *** [build\release\AdvSplash\AdvSplash.dll] Error 1120
scons: building terminated because of errors.


On MSDN I found this

Visual C++ Compiler Options
/GS (Buffer Security Check)

Detects some buffer overruns that overwrite the return address, a common technique for exploiting code
that does not enforce buffer size restrictions. This is achieved by injecting security checks into the compiled code.

/GS[-]

Remarks

/GS is on by default. Use /GS- if you expect your application to have no security exposure.
OK, for now I assumed that NSIS has "no security exposure", and after a cursory RTF{scons}M,
I added to SConscript

    defenv = Environment()
defenv.Append(CCFLAGS = ' /GS-')



Scons did quite a bit more this time, and it stopped just after building the chm files :

    ...
Created h:\mauisoft\main\Sandbox\3rdparty\nsis-2.19-src\build\release\Docs\chm\NSIS.chm, 297,390 bytes
Compression decreased file by 618,934 bytes.
link /nologo /opt:nowin98 /map /entry:DllMain /NODEFAULTLIB /dll /out:build\release\InstallOptions\InstallOptions.dll
kernel32.lib user32.lib gdi32.lib shell32.lib comdlg32.lib
build\release\InstallOptions\InstallerOptions.obj build\release \InstallOptions\ioptdll.res
Creating library build\release\InstallOptions\InstallOptions.lib and object build\release\InstallOptions\InstallOptio
ns.exp
InstallerOptions.obj : error LNK2019: unresolved external symbol _memset referenced in function "long __stdcall
WMCommandProc(struct HWND__ *,unsigned int,struct HWND__ *,unsigned int)" (?WMCommandProc@@YGJPAUHWND__@@I0I@Z)
build\release\InstallOptions\InstallOptions.dll : fatal error LNK1120: 1 unresolved externals
scons: *** [build\release\InstallOptions\InstallOptions.dll] Error 1120
scons: building terminated because of errors.
...


MSDN (http://msdn2.microsoft.com/en-us/library/1fdeehz6.aspx) says that memset is available in

All versions of the C run-time libraries.

and gives details of these at http://msdn2.microsoft.com/en-us/library/abx4dbyh.aspx.

I suppose that /NODEFAULTLIB causes the problem.

I stopped here for now, since I don't know how to modify linker options for this target.

Where can I look it up ?

Also, removing /NODEFAULTLIB for all builds would probably cause problems elsewhere.


Rudif


It does not matter how slowly you go so long as you do not stop. -- Confucius


Kichik,


>> System is quite problematic when it comes to portability. It won't build on anything but MSVC and as a 32-bit target.

Sure. For now, my objective is to build NSIS with VC8 (using scons), so I will leave the 64-bit problems for later.


>> Using defenv.Append is indeed the way to add flags, but it should be done in the msvc specific code under SCons\Config\ms.

OK, makes sense. I moved my line

defenv.Append(CCFLAGS = ' /GS-')

from SConstruct to SCons\Config\ms, at the end of ### flags section.

It works as expected (suppresses the link problem with 2 missing symbols).




>> For a quick fix, you can add SCons\Config\memset.c as a source code file for InstallOptions.


I added to sconscripts for InstallerOptions, LangDLL and RegTool at : files = Split("""...

#SCons\Config\memset.c

This solved the linker error with missing memset.


Now the build is stopping here


link /nologo /opt:nowin98 /map /entry:DllMain /dll /out:build\release\Math\Math.dll kernel32.lib build\release\Math\Sour
ce\Math.obj build\release\Math\Source\MyMath.obj build\release\Math\Source\plugin.obj Contrib\Math\Source\mathcrt.lib
LIBCMT.lib(ftol2.obj) : error LNK2005: __ftol2 already defined in mathcrt.lib(ftol2.obj)
LINK : fatal error LNK1104: cannot open file 'LIBC.lib'
scons: *** [build\release\Math\Math.dll] Error 1104
scons: building terminated because of errors.


MSDN says this

"
The single-threaded CRT libraries, libc.lib and libcd.lib, have been removed. Use the multi-threaded CRT libraries.
The /ML compiler flag is no longer supported. Non-locking versions of some functions have been added in cases where
the performance difference between the multithreaded code and the single-threaded code is potentially significant.
"


Can you clarify something for me : above link is using Contrib\Math\Source\mathcrt.lib as input.

dumpbin /all Contrib\Math\Source\mathcrt.lib shows

/DEFAULTLIB:"LIBC"

so it looks like this is trying to pull in libc.lib.


I could not see mathcrt.lib itself being rebuilt.
Where did it come from ?

How could I rebuild it ?


Rudif


Math is a bit problematic as well. mathcrt.lib was generated from some freely available code on the web I can't currently find. I was sure I wrote it down somewhere, but I can't find it right now...

To avoid the problem you can remove the inclusion of mathcrt.lib as well as mathcrt.h and have VC add its own implementation of the mathematical functions. It'll be significantly larger, but it should work.

Please use [ quote ] and [ code ] for a nicer message format in the future.


Any progess? I would really like to be able to use MSVC 2005 Express with NSIS.


No progress on my side, I had other priorities in the last few weeks. Unless someone beats me to it, I intend to continue work on porting to VC8 in early October.

Rudif


Joost, using MSVC 2005 Express the end result only runs if you have .NET 2.0 installed on target machine, at least that is what I read (Express if the *Free* MS VC8 version right?)

Have not tested myself yet...


That's not true. You can of course develop .NET applications using Visual C++ 2005, but you can also create native Windows applications.


That is not what I said. I understood from MS MSDN site that EVEN with NATIVE Win32 C/C++ apps you need to have .NET installed. The compiled exe embedds a check for this.

That is why it is free probably with MS there is mostly a catch. This time it is to get as much PC with .NET installed in this belong to their strategy I guess.


My offer to you:

I can easily test this for you, please send a simple application you made with VC8 Express and I let it run on various Win32 OS's without .NET installed and post the result in the forum.


A native Windows application doesn't depend on .NET, that's why it's called native. You can create native programs with VC8 Express and they really don't need .NET. I also verified this myself.


Kichik


I made some progress towards building the math.dll with scons / VC8, but I got stuck a the end.


1- Following your advice, in Contrib\Math\SConscript I removed mathcrt.lib and I added memset.c


files = Split("""
Source/Math.c
Source/MyMath.c
Source/plugin.c
< Source/mathcrt.lib
-> #SCons\Config\memset.c
""")


2- I modified Contrib\Math\Source\mathcrt.h as follows



@@ -4,4 +4,6 @@
#pragma once

-> #ifdef ORIGINAL
->
extern "C"
{

@@ -85,3 +87,42 @@
void _fpreset(void);

< }
-> }
->
-> #else
->
-> #include <math.h>
->
-> #define DBL_MAX_EXP 308
->
-> #define _fsin sin
-> #define _fsinh sinh
-> #define _fasin asin
-> #define _fcos cos
-> #define _fcosh cosh
-> #define _facos acos
-> #define _ftan tan
-> #define _ftanh tanh
-> #define _fatan atan
-> #define _fabs abs
-> #define _flog log
-> #define _flog10 log10
-> #define _fexp exp
-> #define _fsqrt sqrt
-> #define _fceil ceil
-> #define _floor floor
-> #define _fatan2 atan2
-> #define _fpow pow
-> #define _fmod fmod
-> #define _frexp frexp
-> #define _fmodf modf
->
-> extern "C"
-> {
->
-> void _fpreset(void);
->
-> }
->
-> #endif




3- I also had to modify the function table code in math.c because the VC8 now has math functions overloaded on argument types,
and it was failing the compilation with " error C2440: 'initializing' : cannot convert from 'overloaded-function' to ..."





@@ -103,4 +103,5 @@
}

->
#define MATHFUNCNUM 29
const MathFunction MathFunctions[MATHFUNCNUM] = {

@@ -122,7 +123,7 @@
{{'f','l','r'}, ITF_MATH1 >> 8, _floor},

< {{'a','t','2'}, ITF_MATH2 >> 8, (Math1FuncPtr)_fatan2},
< {{'p','o','w'}, ITF_MATH2 >> 8, (Math1FuncPtr)_fpow},
< {{'f','m','d'}, ITF_MATH2 >> 8, (Math1FuncPtr)_fmod},
-> {{'a','t','2'}, ITF_MATH2 >> 8, (Math1FuncPtr)(Math2FuncPtr)_fatan2},
-> {{'p','o','w'}, ITF_MATH2 >> 8, (Math1FuncPtr)(Math2FuncPtr)_fpow},
-> {{'f','m','d'}, ITF_MATH2 >> 8, (Math1FuncPtr)(Math2FuncPtr)_fmod},

// type conversions

@@ -137,6 +138,6 @@
{{'c',0,0}, ITF_TYPE >> 8, (Math1FuncPtr)FTT_CHAR},

< {{'f','e','x'}, ITF_MATH2 >> 8, (Math1FuncPtr)_frexp},
< {{'m','d','f'}, ITF_MATH2 >> 8, (Math1FuncPtr)_fmodf},
-> {{'f','e','x'}, ITF_MATH2 >> 8, (Math1FuncPtr)(Math2iFuncPtr)_frexp},
-> {{'m','d','f'}, ITF_MATH2 >> 8, (Math1FuncPtr)(Math2dFuncPtr)_fmodf},
};




4- Finally, I added a dummy implementation




@@ -200,4 +200,15 @@
extern "C"
int _floatp10(double *fnum, int *fsign, int prec);
->
-> #ifndef ORIGINAL
-> extern "C"
-> int _floatp10(double *fnum, int *fsign, int prec)
-> {
-> // dummy stub for now
-> return 0;
-> }
-> #endif
->
->
extern "C"
int _ftol(double num);




Now the build runs and ends with this




scons: warning: Two different environments were specified for target H:\Sandbox\3rdparty\nsis-2.19-src\SCo
ns\Config\memset.obj,
but they appear to have the same action: $SHCC $SHCCFLAGS $CCCOMFLAGS
File "SConstruct", line 460, in BuildPlugin

scons: *** Two environments with different actions were specified for the same target: H:\Sandbox\3rdparty
\nsis-2.19-src\SCons\Config\memset.obj
File "SConstruct", line 460, in BuildPlugin




What am I doing wrong here ?

Also, do you have the source code for _floatp10() ?

It complains about memset.c being built twice in the same location. Copy memset.c over to the Math directory and useit from there for building Math.

_floatp10 was part of mathcrt.lib, I don't have the source code for it.


kichik,

I tried to advance my port to VC8, before leaving for 3 weeks vacations.

Not much to report on the success side, I am still stuck on Math.dll.


I added a copy of memset.c to Math\Sources directory, and added it to sconscript, replacing the mathcrt.lib.



target = 'Math'

files = Split("""
Source/Math.c
Source/MyMath.c
Source/plugin.c
Source/memset.c
""")



This produced the following



link /nologo /opt:nowin98 /map /entry:DllMain /dll /out:build\release\Math\Math.dll kernel32.lib build\release\Math\Sour
ce\Math.obj build\release\Math\Source\MyMath.obj build\release\Math\Source\plugin.obj build\release\Math\Source\memset.o
bj
LIBCMT.lib(fpinit.obj) : error LNK2005: __fltused already defined in Math.obj
Creating library build\release\Math\Math.lib and object build\release\Math\Math.exp
LIBCMT.lib(crt0.obj) : error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup
build\release\Math\Math.dll : fatal error LNK1120: 1 unresolved externals
scons: *** [build\release\Math\Math.dll] Error 1120
scons: building terminated because of errors.




I commented out in math.c


//int _fltused;



Now I got this



link /nologo /opt:nowin98 /map /entry:DllMain /dll /out:build\release\Math\Math.dll kernel32.lib build\release\Math\Sour
ce\Math.obj build\release\Math\Source\MyMath.obj build\release\Math\Source\plugin.obj build\release\Math\Source\memset.o
bj
Creating library build\release\Math\Math.lib and object build\release\Math\Math.exp
LIBCMT.lib(crt0.obj) : error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup
build\release\Math\Math.dll : fatal error LNK1120: 1 unresolved externals
scons: *** [build\release\Math\Math.dll] Error 1120
scons: building terminated because of errors.




I don't understand the cause of this, but on a hunch I tried to rerun the same link command line, leaving out /entry:DllMain



H:\Sandbox\3rdparty\nsis-2.19-src-2>link /nologo /opt:nowin98 /map /dll /out:build\release\Math\Math.dll
build\release\Math\Source\Math.obj build\release\Math\Source\MyMath.obj build\release\Math\Source\plugin.obj build\relea
se\Math\Source\memset.obj | tee 20060909-1900-link.txt
Creating library build\release\Math\Math.lib and object build\release\Math\Math.exp
MyMath.obj : error LNK2019: unresolved external symbol __ftol2_sse referenced in function "void __cdecl FloatFormatF(cha
r *,double,int)" (?FloatFormatF@@YAXPADNH@Z)
build\release\Math\Math.dll : fatal error LNK1120: 1 unresolved externals



This seemed to solve the entry problem, but revealed another problem, __ftol2_sse.



Googling produced this advice, found at http://forums.microsoft.com/MSDN/Sho...25048&SiteID=1


Quote:
I added to Config\ms


defenv.Append(CCFLAGS = ' /QIfist')



Indeed this produced multiple warnings about this option being deprecated, and the same error LNK2019: seen above.


Again I reran the link command in a cmd window with /entry:DllMain removed, and this time the link apparently succeeded:


H:\Sandbox\3rdparty\nsis-2.19-src-2>link /nologo /opt:nowin98 /map /dll /out:build\release\Math\Math.dll
kernel32.lib build\release\Math\Source\Math.obj build\release\Math\Source\MyMath.obj build\release\Math\Source\plugin.ob
j build\release\Math\Source\memset.obj | tee 20060909-2039-scons.txt
Creating library build\release\Math\Math.lib and object build\release\Math\Math.exp



Now I tried to edit


def BuildPlugin(target, source, libs, examples = None, docs = None,
entry = None, ### entry = 'DllMain', ...



but this produced a link error on the first item rebuilt



link /nologo /opt:nowin98 /map /NODEFAULTLIB /dll /out:build\release\AdvSplash\AdvSplash.dll kernel32.lib user32.lib gdi
32.lib winmm.lib build\release\AdvSplash\advsplash.obj
Creating library build\release\AdvSplash\AdvSplash.lib and object build\release\AdvSplash\AdvSplash.exp
LINK : error LNK2001: unresolved external symbol __DllMainCRTStartup@12
build\release\AdvSplash\AdvSplash.dll : fatal error LNK1120: 1 unresolved externals
scons: *** [build\release\AdvSplash\AdvSplash.dll] Error 1120
scons: building terminated because of errors.



so I reverted it immediately.


Question :

Supposing that a linking Math.dll without /entry:DllMain is the right thing to do, which settings should I edit to accomplish this ?

This is a known bug with VS2005 beta -- and apparently still exists with the released version.
Add /QIfist to the C/C++ Command Line Additional Options pane. It generates a deprecation warning but it works.

Another option which usually works is to cast the float to an __int64 before converting it to a long:

float foo = 3.14; // or any float value

long bar = (long)(__int64) foo;


Having `entry` as None is the right thing, however, you also need to remove /NODEFAULTLIB by setting `nodeflib` (another BuildPlugin parameter) to False.

If Math.dll is giving you so much trouble, I suggest you ignore it for now. The real issues are in the stubs and in the compiler. Once those are ready, everything else shouldn't be too complicated.


NSIS 2.20 & MSVC 2005 Express
This thread helped me, but no one has followed up with a success report, so I thought I would.

I got NSIS 2.20 built with MSVC 2005 Express, the downloadeable kit, using effectively the method here.

Notes:

1. Using Windows Server 2003 Platform SDK SP1
2. Using /GS- in CCFLAGS
3. Added the memset.c supplied to various SConscript files
4. As shipped, this version acts more like 2.07 did when NODEFAULTLIB was selected--but I didn't myself set that flag
4. Link with mathcrt.lib failed the first time with a multiple definition of __ftol2 -- I removed this symbol from mathcrt.lib using GNU objcopy, and everything has linked

But seriously, on the topic of mathcrt.lib--has any progress been made recovering the source code to this? I think relying on this binary object of unknown provenance is not defensible...:)


hi,

i have sucessfuly compiled a NSIS amd64 with PSDK for Windows Server 2003 R2 without the "math" plugin and with a limited "system" plugin.
I can't compile the full code of "system" plugin because of the inline assembler. The cl.exe of the PSDK seems not understand it.

Except the system::call function, this NSIS amd64 build's seems work fine :)

Can somebody who have the full Visual studio solution try to compile "system" plugin targetting amd64?


The System plug-in will take a bit more than recompilation. It's written specifically for 32-bit Windows. You might get it to compile, but it'll probably fail at even its simplest task.


According to MSDN, you cannot compile inline assembly for x64, you must remove the assembly to asm files, compile those, and then link them in.


I also got MSVC 2005 to work. It will be official soon.


MSVC 2005 support has been uploaded to NSIS CVS.

You should add TEMP_MSVC2005=yes to the build command line.


Yay! Just what I needed. Thanks Joost. XD

EDIT: Oh shit. I'm receiving the "Couldn't find a good version of libcp.lib" error. :( Maybe I should update my Platform SDK. Still, why does it happen?


You should run SCons from a MSVC 2005 command prompt and add TEMP_MSVC2005=yes to the SCons command line.

I also disabled the libcp check for MSVC 2005. It is not relevant anyway because it doesn't use libcp anymore.

Please try the latest CVS.


Thanks. I tried the latest CVS and it solved the problem. My CVS client didn't update scons related files for some reason.


Note that the MSVC 2005 CRT does not support Windows 95 and NT4 anymore. This means that the compiler will not work on these operating systems.

For the generated installers there is generally no problem. Only the Math plug-in uses the CRT.


It now works out-of-the-box without any additional settings.