Import('defenv') print("Using Microsoft tools configuration (%s)" % defenv.get('MSVS_VERSION','')) ### 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') def entry(x,u): if x == 'WinMain' and u: x = 'w' + x return '/entry:' + x defenv['ENTRY_FLAG'] = entry 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['SUBSYS_WIN'] = '/subsystem:windows' defenv['MSVCRT_FLAG'] = '/MD' defenv['MSVCRT_NEEDSMANIFEST'] = False 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']) defenv['MSVCRT_FLAG'] = '/MT' # Avoid msvcr?0.dll dependency 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']) if defenv['MSTOOLKIT'] and msvs_version < 8.0: defenv['MSVCRT_FLAG'] = '/ML' # TK2003 does not have all libs if msvs_version >= 11.0: defenv['SUBSYS_CON'] = '/subsystem:console,5.01' # support windows xp defenv['SUBSYS_WIN'] = '/subsystem:windows,5.01' # support windows xp ### defines defenv.Append(CPPDEFINES = [('NSISCALL', '$STDCALL')]) ### asm if 'x86' in defenv.get('TARGET_ARCH','x86'): defenv.Append(ASFLAGS = ['/coff']) # ML64 does not support /coff ### debug if defenv['DEBUG']: defenv.Append(CCFLAGS = ['/Zi']) defenv.Append(CCFLAGS = ['/Fd${TARGET.dir}\\${TARGET.dir.file}.pdb']) defenv.Append(LINKFLAGS = ['/debug']) defenv['MSVCRT_FLAG'] = defenv['MSVCRT_FLAG'] + 'd' elif msvs_version >= 14.0 or defenv['TARGET_ARCH'] == 'arm64': defenv.Append(LINKFLAGS = ['/nocoffgrpinfo']) ### 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 int main() { // %s std::ofstream header("test", std::ofstream::out); return 0; } """ conf.env.Prepend(LIBPATH = 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) + defenv['LIBPATH'] for libdir in libdirs: libdir = confenv.subst(libdir) 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() # Linking to msvcr?0.dll (/MD) might require a manifest confenv = defenv.Clone() conf = confenv.Configure() if msvs_version >= 7.0: conf.env.Append(CCFLAGS = [defenv['MSVCRT_FLAG']]) code = """ #include int main() { return atoi("0"); } """ result = True # TryLink should not fail but default to True just in case so distribution will fail as well if conf.TryLink(code, '.cpp'): import os result = os.path.exists('%s.manifest' % conf.lastTarget) defenv['MSVCRT_NEEDSMANIFEST'] = result conf.Finish() ### unicode tdefenv = defenv.Clone() if tdefenv['UNICODE']: tdefenv.Append(CPPDEFINES = ['_UNICODE', 'UNICODE']) ### 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 if msvs_version >= 10.0: if stub_env['TARGET_ARCH'] != 'arm64': # LNK1246: '/FIXED' not compatible with 'ARM64' target machine stub_env.Append(LINKFLAGS = ['/FIXED']) # no relocations that our resource editor ignores stub_uenv = stub_env.Clone() stub_uenv.Append(CPPDEFINES = ['_UNICODE', 'UNICODE']) ### 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(CCFLAGS = [defenv['MSVCRT_FLAG']]) makensis_env.Append(LINKFLAGS = ['$MAP_FLAG']) # generate map file makensis_env.Append(LINKFLAGS = ['$SUBSYS_CON']) # console executable 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 defenv['TARGET_ARCH'] == 'amd64': plugin_env.Append(LINKFLAGS = ['/MACHINE:AMD64']) # Contrib\System\Resource will not link without this 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(CCFLAGS = [defenv['MSVCRT_FLAG']]) 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() conf.env.Append(LINKFLAGS = ['/entry:WinMain']) int64test = """ #include 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 # and the stubs might need memcpy (entry struct copy on x64) # BUGBUG: The tests are currently broken on x64 and designed to fail! # conf = defenv.Configure(custom_tests = { 'CheckRequirement' : check_requirement }) if conf.CheckRequirement('memset', 'char c[128] = "test";switch(sizeof(void*)){case 8:break;case sizeof(void*):return 1;}'): add_file('memset.c', 'memset') memcpy_test = """ switch(sizeof(void*)){case 8:break;case sizeof(void*):return 1;} """ if conf.CheckRequirement('memcpy', memcpy_test): add_file('memcpy.c', 'memcpy') stub_env.Append(CPPDEFINES = ['_NSIS_NODEFLIB_CRTMEMCPY']) stub_uenv.Append(CPPDEFINES = ['_NSIS_NODEFLIB_CRTMEMCPY']) conf.Finish() ### return Return('stub_env makensis_env plugin_env util_env cp_util_env test_env stub_uenv plugin_uenv')