diff --git a/README.md b/README.md index 3f7e36a6..8797f054 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ git clone --recursive https://github.com/FWGS/hlsdk-portable # Build Instructions -## Windows +## Windows x86. ### Prerequisites @@ -131,7 +131,7 @@ cmake -G "Visual Studio 16 2019" -A Win32 -B build After the configuration step, `HLSDK-PORTABLE.sln` should appear in the `build` directory. You can open this solution in Visual Studio and continue developing there. -## Windows. Using Microsoft Visual Studio 6 +## Windows x86. Using Microsoft Visual Studio 6 Microsoft Visual Studio 6 is very old, but if you still have it installed, you can use it to build this hlsdk. There are no project files, but two `.bat` files, for server and client libraries. They require variable **MSVCDir** to be set to the installation path of Visual Studio: @@ -142,7 +142,7 @@ cd dlls && compile.bat && cd ../cl_dll && compile.bat `hl.dll` and `client.dll` will appear in `dlls/` and `cl_dll/` diretories. The libraries built with msvc6 should be compatible with Windows XP. -## Linux. Using Steam Runtime in chroot +## Linux x86. Portable steam-compatible build using Steam Runtime in chroot ### Prerequisites @@ -168,7 +168,7 @@ schroot --chroot steamrt_scout_i386 -- cmake -B build-in-steamrt -S . schroot --chroot steamrt_scout_i386 -- cmake --build build-in-steamrt ``` -## Linux. Build without Steam Runtime +## Linux x86. Portable steam-compatible build without Steam Runtime ### Prerequisites @@ -190,7 +190,7 @@ cmake .. -DCMAKE_C_FLAGS="-static-libstdc++ -static-libgcc" ``` To ensure portability it's still better to build using Steam Runtime or another chroot of some older distro. -## Linux. Build in your own chroot +## Linux x86. Portable steam-compatible build in your own chroot ### Prerequisites @@ -237,13 +237,46 @@ schroot --chroot jessie -- cmake --build build-in-chroot TODO +## Nintendo Switch + +### Prerequisites + +1. Set up [`dkp-pacman`](https://devkitpro.org/wiki/devkitPro_pacman). +2. Install dependency packages: +``` +sudo dkp-pacman -S switch-dev dkp-toolchain-vars switch-mesa switch-libdrm_nouveau switch-sdl2 +``` +3. Make sure the `DEVKITPRO` environment variable is set to the devkitPro SDK root: +``` +export DEVKITPRO=/opt/devkitpro +``` +4. Install libsolder: +``` +source $DEVKITPRO/switchvars.sh +git clone https://github.com/fgsfdsfgs/libsolder.git +make -C libsolder install +``` + +### Building using CMake +``` +mkdir build && cd build +aarch64-none-elf-cmake -G"Unix Makefiles" -DCMAKE_PROJECT_HLSDK-PORTABLE_INCLUDE="$DEVKITPRO/portlibs/switch/share/SolderShim.cmake" .. +make -j +``` + +### Building using waf +``` +./waf configure -T release --nswitch +./waf build +``` + ## Other platforms -Building on other Unix-like platforms (e.g. FreeBSD) is supported. +Building on other architectures (e.g x86_64 or arm) and POSIX-compliant OSes (e.g. FreeBSD) is supported. ### Prerequisites -Install C and C++ compilers (like gcc or clang), cmake and make (or gmake) +Install C and C++ compilers (like gcc or clang), cmake and make. ### Building diff --git a/cl_dll/input_goldsource.cpp b/cl_dll/input_goldsource.cpp index bf029639..89408423 100644 --- a/cl_dll/input_goldsource.cpp +++ b/cl_dll/input_goldsource.cpp @@ -150,6 +150,7 @@ extern cvar_t *cl_pitchspeed; extern cvar_t *cl_movespeedkey; #if _WIN32 +static cvar_t* m_rawinput = NULL; static double s_flRawInputUpdateTime = 0.0f; static bool m_bRawInput = false; static bool m_bMouseThread = false; @@ -158,7 +159,6 @@ bool isMouseRelative = false; #if _WIN32 #include "progdefs.h" -extern globalvars_t *gpGlobals; #endif int CL_IsDead( void ); @@ -386,7 +386,7 @@ void IN_SetMouseMode(bool enable) if (mouseparmsvalid) restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0); - m_bRawInput = CVAR_GET_FLOAT( "m_rawinput" ) != 0; + m_bRawInput = m_rawinput && m_rawinput->value != 0; if(m_bRawInput) { #if USE_SDL2 @@ -781,13 +781,14 @@ void GoldSourceInput::IN_GetMouseDelta( int *pOutX, int *pOutY) #if _WIN32 // update m_bRawInput occasionally: - if ( gpGlobals && gpGlobals->time - s_flRawInputUpdateTime > 1.0f ) + const float currentTime = gEngfuncs.GetClientTime(); + if ( currentTime - s_flRawInputUpdateTime > 1.0f || s_flRawInputUpdateTime == 0.0f ) { - s_flRawInputUpdateTime = gpGlobals->time; + s_flRawInputUpdateTime = currentTime; bool lockEntered = MouseThread_ActiveLock_Enter(); - m_bRawInput = CVAR_GET_FLOAT( "m_rawinput" ) != 0; + m_bRawInput = m_rawinput && m_rawinput->value != 0; if(m_bRawInput && !isMouseRelative) { @@ -1571,7 +1572,8 @@ void GoldSourceInput::IN_Init (void) m_customaccel_exponent = gEngfuncs.pfnRegisterVariable ( "m_customaccel_exponent", "1", FCVAR_ARCHIVE ); #if _WIN32 - m_bRawInput = CVAR_GET_FLOAT( "m_rawinput" ) != 0; + m_rawinput = gEngfuncs.pfnGetCvarPointer("m_rawinput"); + m_bRawInput = m_rawinput && m_rawinput->value != 0; m_bMouseThread = gEngfuncs.CheckParm ("-mousethread", NULL ) != NULL; m_mousethread_sleep = gEngfuncs.pfnRegisterVariable ( "m_mousethread_sleep", "1", FCVAR_ARCHIVE ); // default to less than 1000 Hz diff --git a/cmake/LibraryNaming.cmake b/cmake/LibraryNaming.cmake index c97c92f7..156ab672 100644 --- a/cmake/LibraryNaming.cmake +++ b/cmake/LibraryNaming.cmake @@ -42,6 +42,7 @@ check_symbol_exists(XASH_SERENITY "build.h" XASH_SERENITY) check_symbol_exists(XASH_WIN32 "build.h" XASH_WIN32) check_symbol_exists(XASH_WIN64 "build.h" XASH_WIN64) check_symbol_exists(XASH_X86 "build.h" XASH_X86) +check_symbol_exists(XASH_NSWITCH "build.h" XASH_NSWITCH) unset(CMAKE_REQUIRED_INCLUDES) # engine/common/build.c @@ -63,6 +64,8 @@ elseif(XASH_HAIKU) set(BUILDOS "haiku") elseif(XASH_SERENITY) set(BUILDOS "serenityos") +elseif(XASH_NSWITCH) + set(BUILDOS "nswitch") else() message(SEND_ERROR "Place your operating system name here! If this is a mistake, try to fix conditions above and report a bug") endif() diff --git a/dlls/animation.cpp b/dlls/animation.cpp index c7d38e71..c66d49cd 100644 --- a/dlls/animation.cpp +++ b/dlls/animation.cpp @@ -238,7 +238,7 @@ void GetSequenceInfo( void *pmodel, entvars_t *pev, float *pflFrameRate, float * mstudioseqdesc_t *pseqdesc; - if( pev->sequence >= pstudiohdr->numseq ) + if( pev->sequence < 0 || pev->sequence >= pstudiohdr->numseq ) { *pflFrameRate = 0.0f; *pflGroundSpeed = 0.0f; @@ -265,7 +265,7 @@ int GetSequenceFlags( void *pmodel, entvars_t *pev ) studiohdr_t *pstudiohdr; pstudiohdr = (studiohdr_t *)pmodel; - if( !pstudiohdr || pev->sequence >= pstudiohdr->numseq ) + if( !pstudiohdr || pev->sequence < 0 || pev->sequence >= pstudiohdr->numseq ) return 0; mstudioseqdesc_t *pseqdesc; @@ -279,7 +279,7 @@ int GetAnimationEvent( void *pmodel, entvars_t *pev, MonsterEvent_t *pMonsterEve studiohdr_t *pstudiohdr; pstudiohdr = (studiohdr_t *)pmodel; - if( !pstudiohdr || pev->sequence >= pstudiohdr->numseq || !pMonsterEvent ) + if( !pstudiohdr || pev->sequence < 0 || pev->sequence >= pstudiohdr->numseq || !pMonsterEvent ) return 0; mstudioseqdesc_t *pseqdesc; @@ -379,7 +379,7 @@ float SetBlending( void *pmodel, entvars_t *pev, int iBlender, float flValue ) studiohdr_t *pstudiohdr; pstudiohdr = (studiohdr_t *)pmodel; - if( !pstudiohdr ) + if( !pstudiohdr || pev->sequence < 0 || pev->sequence >= pstudiohdr->numseq ) return flValue; mstudioseqdesc_t *pseqdesc; diff --git a/dlls/func_break.cpp b/dlls/func_break.cpp index 7c838551..2c35a8ce 100644 --- a/dlls/func_break.cpp +++ b/dlls/func_break.cpp @@ -26,6 +26,7 @@ #include "func_break.h" #include "decals.h" #include "explode.h" +#include "game.h" extern DLL_GLOBAL Vector g_vecAttackDir; @@ -925,12 +926,24 @@ void CPushable::Move( CBaseEntity *pOther, int push ) return; } - // g-cont. fix pushable acceleration bug (reverted as it used in mods) if( pOther->IsPlayer() ) { - // Don't push unless the player is pushing forward and NOT use (pull) - if( push && !( pevToucher->button & ( IN_FORWARD | IN_USE ) ) ) - return; + // g-cont. fix pushable acceleration bug (now implemented as cvar) + if (pushablemode.value == 1) + { + // Allow player push when moving right, left and back too + if ( push && !(pevToucher->button & (IN_FORWARD|IN_MOVERIGHT|IN_MOVELEFT|IN_BACK)) ) + return; + // Require player walking back when applying '+use' on pushable + if ( !push && !(pevToucher->button & (IN_BACK)) ) + return; + } + else + { + // Don't push unless the player is pushing forward and NOT use (pull) + if( push && !( pevToucher->button & ( IN_FORWARD | IN_USE ) ) ) + return; + } playerTouch = 1; } @@ -951,6 +964,13 @@ void CPushable::Move( CBaseEntity *pOther, int push ) else factor = 0.25f; + // Spirit fix for pushable acceleration + if (pushablemode.value == 2) + { + if (!push) + factor *= 0.5f; + } + pev->velocity.x += pevToucher->velocity.x * factor; pev->velocity.y += pevToucher->velocity.y * factor; diff --git a/dlls/game.cpp b/dlls/game.cpp index 95c028a7..d17df0c3 100644 --- a/dlls/game.cpp +++ b/dlls/game.cpp @@ -38,6 +38,7 @@ cvar_t satchelfix = { "satchelfix", "0", FCVAR_SERVER }; cvar_t explosionfix = { "explosionfix", "0", FCVAR_SERVER }; cvar_t monsteryawspeedfix = { "monsteryawspeedfix", "1", FCVAR_SERVER }; cvar_t corpsephysics = { "corpsephysics", "0", FCVAR_SERVER }; +cvar_t pushablemode = { "pushablemode", "0", FCVAR_SERVER }; cvar_t forcerespawn = { "mp_forcerespawn","1", FCVAR_SERVER }; cvar_t flashlight = { "mp_flashlight","0", FCVAR_SERVER }; cvar_t aimcrosshair = { "mp_autocrosshair","1", FCVAR_SERVER }; @@ -508,6 +509,7 @@ void GameDLLInit( void ) CVAR_REGISTER( &explosionfix ); CVAR_REGISTER( &monsteryawspeedfix ); CVAR_REGISTER( &corpsephysics ); + CVAR_REGISTER( &pushablemode ); CVAR_REGISTER( &forcerespawn ); CVAR_REGISTER( &flashlight ); CVAR_REGISTER( &aimcrosshair ); diff --git a/dlls/game.h b/dlls/game.h index 54e3281d..fee1a71b 100644 --- a/dlls/game.h +++ b/dlls/game.h @@ -33,6 +33,7 @@ extern cvar_t satchelfix; extern cvar_t explosionfix; extern cvar_t monsteryawspeedfix; extern cvar_t corpsephysics; +extern cvar_t pushablemode; extern cvar_t forcerespawn; extern cvar_t flashlight; extern cvar_t aimcrosshair; diff --git a/public/build.h b/public/build.h index 5b6bcc36..521e4675 100644 --- a/public/build.h +++ b/public/build.h @@ -79,6 +79,7 @@ For more information, please refer to #undef XASH_WIN32 #undef XASH_WIN64 #undef XASH_X86 +#undef XASH_NSWITCH //================================================================ // @@ -96,6 +97,10 @@ For more information, please refer to #if defined(_WIN64) #define XASH_WIN64 1 #endif +#elif defined __SWITCH__ + #define XASH_NSWITCH 1 + #define XASH_LITTLE_ENDIAN 1 + #define XASH_POSIX 1 #elif defined(__linux__) #define XASH_LINUX 1 #if defined(__ANDROID__) @@ -134,7 +139,7 @@ For more information, please refer to #error "Place your operating system name here! If this is a mistake, try to fix conditions above and report a bug" #endif -#if defined XASH_ANDROID || defined XASH_IOS +#if defined XASH_ANDROID || defined XASH_IOS || defined XASH_NSWITCH #define XASH_MOBILE_PLATFORM 1 #endif diff --git a/scripts/waifulib/library_naming.py b/scripts/waifulib/library_naming.py index f3b9762a..3709bc76 100644 --- a/scripts/waifulib/library_naming.py +++ b/scripts/waifulib/library_naming.py @@ -61,6 +61,7 @@ DEFINES = [ 'XASH_WIN32', 'XASH_WIN64', 'XASH_X86', +'XASH_NSWITCH', ] def configure(conf): @@ -92,6 +93,8 @@ def configure(conf): buildos = "haiku" elif conf.env.XASH_SERENITY: buildos = "serenityos" + elif conf.env.XASH_NSWITCH: + buildos = "nswitch" else: conf.fatal("Place your operating system name in build.h and library_naming.py!\n" "If this is a mistake, try to fix conditions above and report a bug") diff --git a/scripts/waifulib/xcompile.py b/scripts/waifulib/xcompile.py index b9ce398f..51d8ec87 100644 --- a/scripts/waifulib/xcompile.py +++ b/scripts/waifulib/xcompile.py @@ -30,6 +30,8 @@ ANDROID_NDK_API_MIN = { 10: 3, 19: 16, 20: 16, 23: 16, 25: 19 } # minimal API le ANDROID_STPCPY_API_MIN = 21 # stpcpy() introduced in SDK 21 ANDROID_64BIT_API_MIN = 21 # minimal API level that supports 64-bit targets +NSWITCH_ENVVARS = ['DEVKITPRO'] + # This class does support ONLY r10e and r19c/r20 NDK class Android: ctx = None # waf context @@ -348,14 +350,100 @@ class Android: ldflags += ['-march=armv5te'] return ldflags +class NintendoSwitch: + ctx = None # waf context + arch = "arm64" + dkp_dir = None + portlibs_dir = None + dka64_dir = None + libnx_dir = None + + def __init__(self, ctx): + self.ctx = ctx + + for i in NSWITCH_ENVVARS: + self.dkp_dir = os.getenv(i) + if self.dkp_dir != None: + break + else: + ctx.fatal('Set %s environment variable pointing to the DEVKITPRO home!' % + ' or '.join(NSWITCH_ENVVARS)) + + self.dkp_dir = os.path.abspath(self.dkp_dir) + + self.dka64_dir = os.path.join(self.dkp_dir, 'devkitA64') + if not os.path.exists(self.dka64_dir): + ctx.fatal('devkitA64 not found in `%s`. Install devkitA64!' % self.dka64_dir) + + self.libnx_dir = os.path.join(self.dkp_dir, 'libnx') + if not os.path.exists(self.libnx_dir): + ctx.fatal('libnx not found in `%s`. Install libnx!' % self.libnx_dir) + + self.portlibs_dir = os.path.join(self.dkp_dir, 'portlibs', 'switch') + if not os.path.exists(self.portlibs_dir): + ctx.fatal('No Switch libraries found in `%s`!' % self.portlibs_dir) + + def gen_toolchain_prefix(self): + return 'aarch64-none-elf-' + + def gen_gcc_toolchain_path(self): + return os.path.join(self.dka64_dir, 'bin', self.gen_toolchain_prefix()) + + def cc(self): + return self.gen_gcc_toolchain_path() + 'gcc' + + def cxx(self): + return self.gen_gcc_toolchain_path() + 'g++' + + def strip(self): + return self.gen_gcc_toolchain_path() + 'strip' + + def pkgconfig(self): + # counter-intuitively, this motherfucker is in portlibs/switch/bin + return os.path.join(self.portlibs_dir, 'bin', self.gen_toolchain_prefix() + 'pkg-config') + + def cflags(self, cxx = False): + cflags = [] + # arch flags + cflags += ['-D__SWITCH__', '-march=armv8-a+crc+crypto', '-mtune=cortex-a57', '-mtp=soft', '-ftls-model=local-exec', '-fPIE'] + # help the linker out + cflags += ['-ffunction-sections', '-fdata-sections'] + # base include dirs + cflags += ['-isystem %s/include' % self.libnx_dir, '-I%s/include' % self.portlibs_dir] + if cxx: + # while these are supported, they could fuck up the crappy dynamic linker + cflags += ['-fno-exceptions', '-fno-rtti'] + # the game wants GNU extensions + cflags += ['-std=gnu++17', '-D_GNU_SOURCE'] + else: + cflags += ['-std=gnu11', '-D_GNU_SOURCE'] + return cflags + + # they go before object list + def linkflags(self): + linkflags = ['-fPIE', '-specs=%s/switch.specs' % self.libnx_dir] + # libsolder only supports sysv hashes and we need to build everything with -rdynamic + linkflags += ['-Wl,--hash-style=sysv', '-rdynamic'] + # avoid pulling in and exposing mesa's internals, that crashes it for some god forsaken reason + linkflags += ['-Wl,--exclude-libs=libglapi.a', '-Wl,--exclude-libs=libdrm_nouveau.a'] + return linkflags + + def ldflags(self): + # NOTE: shared libraries should be built without standard libs, so that they could import their contents from the NRO, + # but executables, including the SDL2 sanity check, will generally require libstdc++ and libm, which we will add manually + ldflags = [] # ['-lm', '-lstdc++'] + return ldflags + def options(opt): - android = opt.add_option_group('Android options') - android.add_option('--android', action='store', dest='ANDROID_OPTS', default=None, + xc = opt.add_option_group('Cross compile options') + xc.add_option('--android', action='store', dest='ANDROID_OPTS', default=None, help='enable building for android, format: --android=,,, example: --android=armeabi-v7a-hard,4.9,9') - - magx = opt.add_option_group('MotoMAGX options') - magx.add_option('--enable-magx', action = 'store_true', dest = 'MAGX', default = False, - help = 'enable targetting for MotoMAGX phones [default: %default]') + xc.add_option('--enable-magx', action='store_true', dest='MAGX', default=False, + help='enable building for Motorola MAGX [default: %default]') + xc.add_option('--enable-msvc-wine', action='store_true', dest='MSVC_WINE', default=False, + help='enable building with MSVC using Wine [default: %default]') + xc.add_option('--nswitch', action='store_true', dest='NSWITCH', default = False, + help ='enable building for Nintendo Switch [default: %default]') def configure(conf): if conf.options.ANDROID_OPTS: @@ -389,18 +477,42 @@ def configure(conf): conf.msg('... C/C++ flags', ' '.join(android.cflags()).replace(android.ndk_home, '$NDK/')) conf.msg('... link flags', ' '.join(android.linkflags()).replace(android.ndk_home, '$NDK/')) conf.msg('... ld flags', ' '.join(android.ldflags()).replace(android.ndk_home, '$NDK/')) - - # conf.env.ANDROID_OPTS = android - conf.env.DEST_OS2 = 'android' elif conf.options.MAGX: # useless to change toolchain path, as toolchain meant to be placed in this path toolchain_path = '/opt/toolchains/motomagx/arm-eabi2/lib/' conf.env.INCLUDES_MAGX = [toolchain_path + i for i in ['ezx-z6/include', 'qt-2.3.8/include']] conf.env.LIBPATH_MAGX = [toolchain_path + i for i in ['ezx-z6/lib', 'qt-2.3.8/lib']] conf.env.LINKFLAGS_MAGX = ['-Wl,-rpath-link=' + i for i in conf.env.LIBPATH_MAGX] + elif conf.options.MSVC_WINE: + try: + toolchain_path = conf.environ['MSVC_WINE_PATH'] + except KeyError: + conf.fatal('Set MSVC_WINE_PATH environment variable to the MSVC toolchain root!') + + conf.environ['CC'] = conf.environ['CXX'] = os.path.join(toolchain_path, 'bin', conf.env.MSVC_TARGETS[0], 'cl') + conf.environ['LINK_CXX'] = os.path.join(toolchain_path, 'bin', conf.env.MSVC_TARGETS[0], 'link') + conf.environ['AR'] = os.path.join(toolchain_path, 'bin', conf.env.MSVC_TARGETS[0], 'lib') + conf.environ['WINRC'] = os.path.join(toolchain_path, 'bin', conf.env.MSVC_TARGETS[0], 'rc') + conf.env.DEST_OS = 'win32' + conf.env.DEST_CPU = conf.env.MSVC_TARGETS[0] + conf.env.COMPILER_CXX = conf.env.COMPILER_CC = 'msvc' + elif conf.options.NSWITCH: + conf.nswitch = nswitch = NintendoSwitch(conf) + conf.environ['CC'] = nswitch.cc() + conf.environ['CXX'] = nswitch.cxx() + conf.environ['STRIP'] = nswitch.strip() + conf.env.PKGCONFIG = nswitch.pkgconfig() + conf.env.CFLAGS += nswitch.cflags() + conf.env.CXXFLAGS += nswitch.cflags(True) + conf.env.LINKFLAGS += nswitch.linkflags() + conf.env.LDFLAGS += nswitch.ldflags() + conf.env.HAVE_M = True + conf.env.LIB_M = ['m'] + conf.env.DEST_OS = 'nswitch' conf.env.MAGX = conf.options.MAGX - MACRO_TO_DESTOS = OrderedDict({ '__ANDROID__' : 'android' }) + conf.env.MSVC_WINE = conf.options.MSVC_WINE + MACRO_TO_DESTOS = OrderedDict({ '__ANDROID__' : 'android', '__SWITCH__' : 'nswitch' }) for k in c_config.MACRO_TO_DESTOS: MACRO_TO_DESTOS[k] = c_config.MACRO_TO_DESTOS[k] # ordering is important c_config.MACRO_TO_DESTOS = MACRO_TO_DESTOS @@ -433,11 +545,17 @@ compiler_cxx_configure = getattr(compiler_cxx, 'configure') compiler_c_configure = getattr(compiler_c, 'configure') def patch_compiler_cxx_configure(conf): - compiler_cxx_configure(conf) + if not conf.env.MSVC_WINE: + compiler_cxx_configure(conf) + else: + conf.load('msvc', funs='no_autodetect') post_compiler_cxx_configure(conf) def patch_compiler_c_configure(conf): - compiler_c_configure(conf) + if not conf.env.MSVC_WINE: + compiler_c_configure(conf) + else: + conf.load('msvc', funs='no_autodetect') post_compiler_c_configure(conf) setattr(compiler_cxx, 'configure', patch_compiler_cxx_configure) diff --git a/wscript b/wscript index e7f6f14d..c4914b4e 100644 --- a/wscript +++ b/wscript @@ -74,8 +74,10 @@ def configure(conf): conf.load('msvs msdev strip_on_install') if conf.env.DEST_OS == 'android': - conf.options.GOLDSRC = False + conf.options.GOLDSRC = conf.env.GOLDSRC = False conf.env.SERVER_NAME = 'server' # can't be any other name, until specified + elif conf.env.DEST_OS == 'nswitch': + conf.options.GOLDSRC = conf.env.GOLDSRC = False if conf.env.MAGX: enforce_pic = False @@ -148,6 +150,13 @@ def configure(conf): cflags += conf.filter_cflags(compiler_optional_flags + c_compiler_optional_flags, cflags) cxxflags += conf.filter_cxxflags(compiler_optional_flags, cflags) + # on the Switch, allow undefined symbols by default, which is needed for libsolder to work + # additionally, shared libs are linked without libc + if conf.env.DEST_OS == 'nswitch': + linkflags.remove('-Wl,--no-undefined') + conf.env.append_unique('LINKFLAGS_cshlib', ['-nostdlib', '-nostartfiles']) + conf.env.append_unique('LINKFLAGS_cxxshlib', ['-nostdlib', '-nostartfiles']) + conf.env.append_unique('CFLAGS', cflags) conf.env.append_unique('CXXFLAGS', cxxflags) conf.env.append_unique('LINKFLAGS', linkflags)