Source

nsis64 / SCons / Config / ms

print "Using Microsoft tools configuration"

Import('defenv')

### flags

import SCons
if SCons.__version__ == '1.3.0':
  # workaround for http://scons.tigris.org/issues/show_bug.cgi?id=2614
  # force inclusion of Platform SDK, sometimes ignored by SCons 1.3.0 due to environment contamination
  defenv.Tool('mssdk')

defenv['ENTRY_FLAG'] = lambda x: '/entry:' + x
defenv['MAP_FLAG'] = '/map'
defenv['NODEFLIBS_FLAG'] = '/NODEFAULTLIB'
defenv['C_FLAG'] = '/TC'
defenv['CPP_FLAG'] = '/TP'
defenv['CPP_REQUIRES_STDLIB'] = 0
defenv['SUBSYS_CON'] = '/subsystem:console'
defenv['MSVCRT_FLAG'] = '/MD'
defenv['STDCALL'] = '__stdcall'

msvs_version = float(defenv['MSVS_VERSION'].replace('Exp',''))
if msvs_version >= 8.0:
	defenv['EXCEPTION_FLAG'] = '/EHsc'
	defenv.Append(CCFLAGS = ['/GS-'])
	defenv.Append(CPPDEFINES = ['_CRT_SECURE_NO_WARNINGS', '_CRT_NONSTDC_NO_WARNINGS', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NON_CONFORMING_SWPRINTFS'])
else:
	defenv['EXCEPTION_FLAG'] = '/GX'
if msvs_version < 10.0:
	# not even /ALIGN:512 works for vc10... fails to load process
	defenv.Append(LINKFLAGS = ['/opt:nowin98'])

### defines

defenv.Append(CPPDEFINES = [('NSISCALL', '$STDCALL')])

### asm

defenv.Append(ASFLAGS = ['/coff'])

### debug

if defenv['DEBUG']:
	defenv.Append(CCFLAGS = ['/Zi'])
	defenv.Append(CCFLAGS = ['/Fd${TARGET.dir}\\${TARGET.dir.file}.pdb'])
	defenv.Append(LINKFLAGS = ['/debug'])

### unicode
tdefenv = defenv.Clone()
if tdefenv['UNICODE']:
	tdefenv.Append(CPPDEFINES = ['_UNICODE', 'UNICODE'])

### workarounds

# Some Platform SDK version includes a bad version of libcp.lib.
# if stl usage causes link failure, copy the good libcp.lib
# from one of the other lib folders and use it instead.

confenv = defenv.Clone()
conf = confenv.Configure()

# For VS 2005 and up, the single threaded version of C runtime
# need not be explicitly linked.
if float(defenv['MSVS_VERSION'].replace('Exp','')) < 8.0:
  libcptest = """
  #include <fstream>
  int main() {
    // %s
    std::ofstream header("test", std::ofstream::out);
    return 0;
  }
  """

  conf.env.PrependENVPath('LIB', Dir('#/.sconf_temp').abspath)
  conf.env.Append(CCFLAGS = ['$EXCEPTION_FLAG'])

  if not conf.TryLink(libcptest % 'no change', '.cpp'):
    import os, shutil

    libdirs = defenv['ENV']['LIB'].split(os.pathsep)

    for libdir in libdirs:
      try:
        libcp = r'%s\libcp.lib' % libdir
        shutil.copy(libcp, Dir('#/.sconf_temp').abspath)
        if conf.TryLink(libcptest % (r'using %s' % libcp), '.cpp'):
          defenv.PrependENVPath('LIB', Dir('#/.sconf_temp').abspath)
          break
      except IOError:
        continue
    else:
      print "*** Couldn't find a good version of libcp.lib"
      Exit(2)

conf.Finish()


### stub environment

stub_env = defenv.Clone()

stub_env.Append(CPPPATH = ['#$BUILD_CONFIG'])

if not defenv['DEBUG']:
	stub_env.Append(CCFLAGS = ['/O1'])               # optimize for size
stub_env.Append(CCFLAGS = ['/W3'])                 # level 3 warnings
stub_env.Append(CCFLAGS = ['/FAcs'])               # full listing files
stub_env.Append(CCFLAGS = ['/Fa${TARGET}.lst'])    # listing file name

stub_env.Append(LINKFLAGS = ['$NODEFLIBS_FLAG'])   # no default libraries
stub_env.Append(LINKFLAGS = ['$MAP_FLAG'])         # generate map file

stub_uenv = stub_env.Clone()
stub_uenv.Append(LINKFLAGS = ['/entry:wWinMain'])  # Unicode entry point
stub_uenv.Append(CPPDEFINES = ['_UNICODE', 'UNICODE'])
stub_env.Append(LINKFLAGS = ['/entry:WinMain'])    # ANSI entry point

### makensis environment

makensis_env = tdefenv.Clone()

makensis_env.Append(CPPPATH = ['#$BUILD_CONFIG'])

if not defenv['DEBUG']:
	makensis_env.Append(CCFLAGS = ['/O2'])           # optimize for speed
makensis_env.Append(CCFLAGS = ['$EXCEPTION_FLAG']) # enable exceptions
makensis_env.Append(CCFLAGS = ['/W3'])             # level 3 warnings
makensis_env.Append(CCFLAGS = ['/FAcs'])               # full listing files
makensis_env.Append(CCFLAGS = ['/Fa${TARGET}.lst'])    # listing file name

makensis_env.Append(LINKFLAGS = ['$MAP_FLAG'])     # generate map file
if defenv['UNICODE']:
	makensis_env.Append(LINKFLAGS = ['/STACK:2097152'])  # need 2 MB of stack in Unicode (default is 1 MB)

### plugin environment

plugin_env = defenv.Clone(no_import_lib = 1)

if not defenv['DEBUG']:
	plugin_env.Append(CCFLAGS = ['/O1'])             # optimize for size
plugin_env.Append(CCFLAGS = ['/W3'])               # level 3 warnings

plugin_env.Append(LINKFLAGS = ['$MAP_FLAG'])       # generate map file

plugin_uenv = plugin_env.Clone()
plugin_uenv.Append(CPPDEFINES = ['_UNICODE', 'UNICODE'])

### util environment

util_env = tdefenv.Clone()

if not defenv['DEBUG']:
	util_env.Append(CCFLAGS = ['/O1'])            # optimize for speed
util_env.Append(CCFLAGS = ['/W3'])              # level 3 warnings

util_env.Append(LINKFLAGS = ['$MAP_FLAG'])      # generate map file

### cross-platform util environment

cp_util_env = util_env.Clone()

cp_util_env.Append(CPPPATH = ['#$BUILD_CONFIG'])

### test environment

test_env = defenv.Clone()

test_env.Append(CPPPATH = ['#$BUILD_CONFIG'])

### weird compiler requirements

def check_requirement(ctx, func, trigger):
	ctx.Message('Checking for %s requirement... ' % func)

	flags = ctx.env['LINKFLAGS']

	ctx.env.Append(LINKFLAGS = ['$NODEFLIBS_FLAG'])
	ctx.env.Append(LINKFLAGS = ['/entry:main'])

	test = """
		int main() {
			%s
			return 0;
		}
	""" % trigger

	result = not ctx.TryLink(test, '.c')
	ctx.Result(result)

	ctx.env['LINKFLAGS'] = flags

	return result

def add_file_to_emitter(env, emitter_name, file, obj_name=None):
	if obj_name is None:
		obj_name = emitter_name
	try:
		original_emitter = env[emitter_name]
		if type(original_emitter) == list:
			original_emitter = original_emitter[0]
	except KeyError:
		original_emitter = None

	def emitter(target, source, env):
		if original_emitter:
			target, source = original_emitter(target, source, env)

		if '$NODEFLIBS_FLAG' not in env['LINKFLAGS']:
			return target, source

		return target, source + env.Object(obj_name, file)

	env[emitter_name] = emitter

def add_file(file, obj_name=None):
	file = File(file)
	add_file_to_emitter(stub_env, 'PROGEMITTER', file, obj_name)
	add_file_to_emitter(stub_uenv, 'PROGEMITTER', file, obj_name)
	add_file_to_emitter(util_env, 'PROGEMITTER', file, obj_name)
	add_file_to_emitter(plugin_env, 'SHLIBEMITTER', file, obj_name)
	add_file_to_emitter(plugin_uenv, 'SHLIBEMITTER', file, obj_name)

#
# MSVC 6 SP6 doesn't like direct shifting of 64-bit integers.
# It generates a call to ___aullshr which requires libc, which
# we don't like. However, it does agree to work properly with
# a call to Int64ShrlMod32.
#

conf = stub_env.Configure()

if defenv['UNICODE']:
	int64test = """
	#include <windows.h>
	int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPTSTR lpszCmdParam, int nCmdShow) {
		ULARGE_INTEGER *i = 0;
		return (int)(i->QuadPart >> 10);
	}
	"""
else:
	int64test = """
	#include <windows.h>
	int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpszCmdParam, int nCmdShow) {
		ULARGE_INTEGER *i = 0;
		return (int)(i->QuadPart >> 10);
	}
	"""

if not conf.TryLink(int64test, '.c'):
	stub_env.Append(CPPDEFINES = ['_NSIS_NO_INT64_SHR'])
	stub_uenv.Append(CPPDEFINES = ['_NSIS_NO_INT64_SHR'])

conf.Finish()	

#
# MSVC 2005 requires the memset CRT function to be present
#

conf = defenv.Configure(custom_tests = { 'CheckRequirement' : check_requirement })

if conf.CheckRequirement('memset', 'char c[128] = "test"; printf("%s", c);'):
	add_file('memset.c', 'memset')
memcpy_test = """
struct foo {
	int a;
	int b;
	int c;
	int d;
};
struct foo foo1 = {0,0,0,0};
struct foo foo2 = foo1;
printf("%d", foo2.a);
"""
if conf.CheckRequirement('memcpy', memcpy_test):
	add_file('memcpy.c', 'memcpy')

conf.Finish()	

### return

Return('stub_env makensis_env plugin_env util_env cp_util_env test_env stub_uenv plugin_uenv')
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.