diff --git a/.vscode/launch.json b/.vscode/launch.json index e1e1c4a..3b49945 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -28,17 +28,17 @@ "internalConsoleOptions": "neverOpen" }, { - "name": "Attach to .NET 5 Debugger", + "name": "Attach to .NET 6 Debugger", "type": "coreclr", "request": "launch", - "preLaunchTask": "Build: .NET 5 Debug", - "program": "${workspaceFolder}/ProjectName/bin/Debug/net5.0/ProjectName.dll", + "preLaunchTask": "Build: .NET 6 Debug", + "program": "${workspaceFolder}/ProjectName/bin/Debug/net6.0/ProjectName.dll", "args": [], "env": { - "LD_LIBRARY_PATH": "${workspaceFolder}/ProjectName/bin/Debug/net5.0/lib64", - "DYLD_LIBRARY_PATH": "${workspaceFolder}/ProjectName/bin/Debug/net5.0/osx" + "LD_LIBRARY_PATH": "${workspaceFolder}/ProjectName/bin/Debug/net6.0/lib64", + "DYLD_LIBRARY_PATH": "${workspaceFolder}/ProjectName/bin/Debug/net6.0/osx" }, - "cwd": "${workspaceFolder}/ProjectName/bin/Debug/net5.0", + "cwd": "${workspaceFolder}/ProjectName/bin/Debug/net6.0", "console": "integratedTerminal", "internalConsoleOptions": "neverOpen" } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index fe5220a..d6913a7 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -121,12 +121,12 @@ "problemMatcher": [] }, { - "label": "Build & Run: .NET 5 Debug", + "label": "Build & Run: .NET 6 Debug", "type": "shell", "dependsOrder": "sequence", "dependsOn": [ - "Build: .NET 5 Debug", - "Run: .NET 5 Debug" + "Build: .NET 6 Debug", + "Run: .NET 6 Debug" ], "group": { "kind": "build", @@ -135,7 +135,7 @@ "problemMatcher": [] }, { - "label": "Build: .NET 5 Debug", + "label": "Build: .NET 6 Debug", "command": "dotnet", "args": [ "build", @@ -151,7 +151,7 @@ "problemMatcher": [] }, { - "label": "Run: .NET 5 Debug", + "label": "Run: .NET 6 Debug", "command": "dotnet", "args": [ "./ProjectName.dll" @@ -161,7 +161,7 @@ "LD_LIBRARY_PATH": "./lib64", "DYLD_LIBRARY_PATH": "./osx" }, - "cwd": "${workspaceFolder}/ProjectName/bin/x64/Debug/net5.0" + "cwd": "${workspaceFolder}/ProjectName/bin/x64/Debug/net6.0" }, "type": "process", "group": { @@ -171,7 +171,7 @@ "problemMatcher": [] }, { - "label": "Build: .NET 5 Release", + "label": "Build: .NET 6 Release", "command": "dotnet", "args": [ "build", @@ -189,7 +189,7 @@ "problemMatcher": [] }, { - "label": "Run: .NET 5 Release", + "label": "Run: .NET 6 Release", "command": "dotnet", "args": [ "./ProjectName.dll" @@ -199,7 +199,7 @@ "LD_LIBRARY_PATH": "./lib64", "DYLD_LIBRARY_PATH": "./osx" }, - "cwd": "${workspaceFolder}/ProjectName/bin/x64/Release/net5.0" + "cwd": "${workspaceFolder}/ProjectName/bin/x64/Release/net6.0" }, "type": "process", "group": { @@ -209,11 +209,11 @@ "problemMatcher": [] }, { - "label": "Build & Run: .NET 5 Release", + "label": "Build & Run: .NET 6 Release", "dependsOrder": "sequence", "dependsOn": [ - "Build: .NET 5 Release", - "Run: .NET 5 Release" + "Build: .NET 6 Release", + "Run: .NET 6 Release" ], "type": "shell", "group": { diff --git a/FNA.Settings.props b/FNA.Settings.props index 4c1d2c2..209e5df 100644 --- a/FNA.Settings.props +++ b/FNA.Settings.props @@ -1,6 +1,6 @@ - - $(DefineConstants) - + + $(DefineConstants) + diff --git a/ProjectName/DllMap.cs b/ProjectName/DllMap.cs deleted file mode 100644 index 3536d1f..0000000 --- a/ProjectName/DllMap.cs +++ /dev/null @@ -1,259 +0,0 @@ -// only works in .NET Core. disable in .NET framework - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Xml.Linq; - -public static class DllMap -{ - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - static extern bool SetDefaultDllDirectories(int directoryFlags); - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - static extern void AddDllDirectory(string lpPathName); - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - static extern bool SetDllDirectory(string lpPathName); - - const int LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000; - - public static Dictionary MapDictionary; - public static string OS; - public static string CPU; - public static bool Optimise; - - public static void Initialise(bool optimise = true) - { - Optimise = optimise; - - // Our executabe needs to know how to find the native libraries - // For Windows, we can set this to be x86 or x64 directory at runtime (below) - // For Linux we need to move our native libraries to 'netcoredeps' which is set by .net core - // For OSX we need to set an environment variable (DYLD_LIBRARY_PATH) outside of the process by a script - if (Environment.OSVersion.Platform == PlatformID.Win32NT) - { - try - { - SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); - AddDllDirectory(Path.Combine( - AppDomain.CurrentDomain.BaseDirectory, - Environment.Is64BitProcess ? "x64" : "x86" - )); - } - catch - { - // Pre-Windows 7, KB2533623 - SetDllDirectory(Path.Combine( - AppDomain.CurrentDomain.BaseDirectory, - Environment.Is64BitProcess ? "x64" : "x86" - )); - } - } - - // .NET Core also doesn't use DllImport but we can replicate this using NativeLibrary as per below - // Uses FNA.dll.config to dictate what the name of the native library is per platform and architecture - var fnaAssembly = Assembly.GetAssembly(typeof(Microsoft.Xna.Framework.Graphics.ColorWriteChannels)); - DllMap.Register(fnaAssembly); - } - - // Register a call-back for native library resolution. - public static void Register(Assembly assembly) - { - NativeLibrary.SetDllImportResolver(assembly, MapAndLoad); - - // Do setup so that MapLibraryName is faster than reading the XML each time - - // 1) Get platform & cpu - OS = GetCurrentPlatform().ToString().ToLowerInvariant(); - CPU = GetCurrentRuntimeArchitecture().ToString().ToLowerInvariant(); - - // 2) Setup MapDictionary - // For Windows use hardcoded values - // Why? This is our development platform and we wanted the fastest start time possible (eliminates XML Load) - if (OS == "windows" && Optimise) - { - MapDictionary = new Dictionary(); - MapDictionary.Add("SDL2", "SDL2.dll"); - MapDictionary.Add("SDL_image", "SDL_image.dll"); - MapDictionary.Add("FAudio", "FAudio.dll"); - } - else - { - // For every other platform use XML file - // Read in config XML and only store details we're interested in within MapDictionary - string xmlPath = Path.Combine(Path.GetDirectoryName(assembly.Location), - Path.GetFileNameWithoutExtension(assembly.Location) + ".dll.config"); - - if (!File.Exists(xmlPath)) - { - Console.WriteLine($"=== Cannot find XML: " + xmlPath); - return; - } - - XElement root = XElement.Load(xmlPath); - - MapDictionary = new Dictionary(); - ParseXml(root, true); // Direct match on OS & CPU first - ParseXml(root, false); // Loose match on CPU second (won't allow duplicates) - } - } - - private static void ParseXml(XElement root, bool matchCPU) - { - foreach (var el in root.Elements("dllmap")) - { - // Ignore entries for other OSs - if (el.Attribute("os").ToString().IndexOf(OS) < 0) - continue; - - // Ignore entries for other CPUs - if (matchCPU) - { - if (el.Attribute("cpu") == null) - continue; - if (el.Attribute("cpu").ToString().IndexOf(CPU) < 0) - continue; - } - else - { - if (el.Attribute("cpu") != null && el.Attribute("cpu").ToString().IndexOf(CPU) < 0) - continue; - } - - string oldLib = el.Attribute("dll").Value; - string newLib = el.Attribute("target").Value; - if (string.IsNullOrWhiteSpace(oldLib) || string.IsNullOrWhiteSpace(newLib)) - continue; - - // Don't allow duplicates - if (MapDictionary.ContainsKey(oldLib)) - continue; - - MapDictionary.Add(oldLib, newLib); - } - } - - // The callback: which loads the mapped libray in place of the original - private static IntPtr MapAndLoad(string libraryName, Assembly assembly, DllImportSearchPath? dllImportSearchPath) - { - string mappedName = null; - mappedName = MapLibraryName(assembly.Location, libraryName, out mappedName) ? mappedName : libraryName; - return NativeLibrary.Load(mappedName, assembly, dllImportSearchPath); - } - - // Parse the assembly.xml file, and map the old name to the new name of a library. - private static bool MapLibraryName(string assemblyLocation, string originalLibName, out string mappedLibName) - { - if (MapDictionary.TryGetValue(originalLibName, out mappedLibName)) - return true; - else - return false; - } - - // Below pinched from Mono.DllMap project: https://github.com/Firwood-Software/AdvancedDLSupport/tree/1b7394211a655b2f77649ce3b610a3161215cbdc/Mono.DllMap - public static DllMapOS GetCurrentPlatform() - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - return DllMapOS.Linux; - } - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return DllMapOS.Windows; - } - - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - return DllMapOS.OSX; - } - - var operatingDesc = RuntimeInformation.OSDescription.ToUpperInvariant(); - foreach (var system in Enum.GetValues(typeof(DllMapOS)).Cast() - .Except(new[] { DllMapOS.Linux, DllMapOS.Windows, DllMapOS.OSX })) - { - if (operatingDesc.Contains(system.ToString().ToUpperInvariant())) - { - return system; - } - } - - throw new PlatformNotSupportedException($"Couldn't detect platform: {RuntimeInformation.OSDescription}"); - } - - public static DllMapArchitecture GetCurrentRuntimeArchitecture() - { - switch (RuntimeInformation.ProcessArchitecture) - { - case Architecture.Arm: - { - return DllMapArchitecture.ARM; - } - case Architecture.X64: - { - return DllMapArchitecture.x86_64; - } - case Architecture.X86: - { - return DllMapArchitecture.x86; - } - } - - typeof(object).Module.GetPEKind(out _, out var machine); - switch (machine) - { - case ImageFileMachine.I386: - { - return DllMapArchitecture.x86; - } - case ImageFileMachine.AMD64: - { - return DllMapArchitecture.x86_64; - } - case ImageFileMachine.ARM: - { - return DllMapArchitecture.ARM; - } - case ImageFileMachine.IA64: - { - return DllMapArchitecture.IA64; - } - } - throw new PlatformNotSupportedException("Couldn't detect the current architecture."); - } - - public enum DllMapOS - { - Linux = 1 << 0, - OSX = 1 << 1, - Solaris = 1 << 2, - FreeBSD = 1 << 3, - OpenBSD = 1 << 4, - NetBSD = 1 << 5, - Windows = 1 << 6, - AIX = 1 << 7, - HPUX = 1 << 8 - } - - public enum DllMapArchitecture - { - x86 = 1 << 0, - x86_64 = 1 << 1, - SPARC = 1 << 2, - PPC = 1 << 3, - S390 = 1 << 4, - S390X = 1 << 5, - ARM = 1 << 6, - ARMV8 = 1 << 7, - MIPS = 1 << 8, - Alpha = 1 << 9, - HPPA = 1 << 10, - IA64 = 1 << 11 - } -} diff --git a/ProjectName/Program.cs b/ProjectName/Program.cs index 4e6bfda..cbde09e 100644 --- a/ProjectName/Program.cs +++ b/ProjectName/Program.cs @@ -5,43 +5,39 @@ using System.Runtime.InteropServices; namespace ProjectName { - class Program - { - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - static extern bool SetDllDirectory(string lpPathName); + class Program + { + [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + static extern bool SetDllDirectory(string lpPathName); - static void Main(string[] args) - { -#if NETCOREAPP - DllMap.Initialise(false); -#endif + static void Main(string[] args) + { + // https://github.com/FNA-XNA/FNA/wiki/4:-FNA-and-Windows-API#64-bit-support + if (Environment.OSVersion.Platform == PlatformID.Win32NT) + { + SetDllDirectory(Path.Combine( + AppDomain.CurrentDomain.BaseDirectory, + Environment.Is64BitProcess ? "x64" : "x86" + )); + } - // https://github.com/FNA-XNA/FNA/wiki/4:-FNA-and-Windows-API#64-bit-support - if (Environment.OSVersion.Platform == PlatformID.Win32NT) - { - SetDllDirectory(Path.Combine( - AppDomain.CurrentDomain.BaseDirectory, - Environment.Is64BitProcess ? "x64" : "x86" - )); - } + // https://github.com/FNA-XNA/FNA/wiki/7:-FNA-Environment-Variables#fna_graphics_enable_highdpi + // NOTE: from documentation: + // Lastly, when packaging for macOS, be sure this is in your app bundle's Info.plist: + // NSHighResolutionCapable + // True + Environment.SetEnvironmentVariable("FNA_GRAPHICS_ENABLE_HIGHDPI", "1"); - // https://github.com/FNA-XNA/FNA/wiki/7:-FNA-Environment-Variables#fna_graphics_enable_highdpi - // NOTE: from documentation: - // Lastly, when packaging for macOS, be sure this is in your app bundle's Info.plist: - // NSHighResolutionCapable - // True - Environment.SetEnvironmentVariable("FNA_GRAPHICS_ENABLE_HIGHDPI", "1"); + using (ProjectNameGame game = new ProjectNameGame()) + { + bool isHighDPI = Environment.GetEnvironmentVariable("FNA_GRAPHICS_ENABLE_HIGHDPI") == "1"; + if (isHighDPI) + Debug.WriteLine("HiDPI Enabled"); - using (ProjectNameGame game = new ProjectNameGame()) - { - bool isHighDPI = Environment.GetEnvironmentVariable("FNA_GRAPHICS_ENABLE_HIGHDPI") == "1"; - if (isHighDPI) - Debug.WriteLine("HiDPI Enabled"); - - game.Run(); - } - } - } + game.Run(); + } + } + } } diff --git a/ProjectName/ProjectName.Core.csproj b/ProjectName/ProjectName.Core.csproj index 28338ba..9a30dd8 100644 --- a/ProjectName/ProjectName.Core.csproj +++ b/ProjectName/ProjectName.Core.csproj @@ -4,28 +4,28 @@ x64;x86 - - WinExe - net5.0 - ProjectName - false - false - 7.3 - ProjectName.Program - ProjectName - ProjectName - true - win-x64;osx-x64;linux-x64 - - - - - Always - - - - - - - + + WinExe + net6.0 + ProjectName + false + false + 7.3 + ProjectName.Program + ProjectName + ProjectName + true + win-x64;osx-x64;linux-x64 + + + + + Always + + + + + + + diff --git a/ProjectName/ProjectName.Framework.csproj b/ProjectName/ProjectName.Framework.csproj index 76b2b76..e6ea1a0 100644 --- a/ProjectName/ProjectName.Framework.csproj +++ b/ProjectName/ProjectName.Framework.csproj @@ -4,31 +4,31 @@ x64;x86 - - Exe - net461 - ProjectName - false - false - 7.3 - ProjectName.Program - ProjectName - ProjectName - true - win-x64;osx-x64;linux-x64 - - - - $(DefaultItemExcludes);DllMap.cs - - - - Always - - - - - - - + + Exe + net461 + ProjectName + false + false + 7.3 + ProjectName.Program + ProjectName + ProjectName + true + win-x64;osx-x64;linux-x64 + + + + $(DefaultItemExcludes);DllMap.cs + + + + Always + + + + + + + diff --git a/ProjectName/ProjectNameGame.cs b/ProjectName/ProjectNameGame.cs index 7949ffa..65924f0 100644 --- a/ProjectName/ProjectNameGame.cs +++ b/ProjectName/ProjectNameGame.cs @@ -3,50 +3,50 @@ using Microsoft.Xna.Framework.Graphics; namespace ProjectName { - class ProjectNameGame : Game - { - GraphicsDeviceManager graphics; + class ProjectNameGame : Game + { + GraphicsDeviceManager graphics; - public ProjectNameGame() - { - graphics = new GraphicsDeviceManager(this); - graphics.PreferredBackBufferWidth = 1280; - graphics.PreferredBackBufferHeight = 720; - graphics.PreferMultiSampling = true; - Content.RootDirectory = "Content"; + public ProjectNameGame() + { + graphics = new GraphicsDeviceManager(this); + graphics.PreferredBackBufferWidth = 1280; + graphics.PreferredBackBufferHeight = 720; + graphics.PreferMultiSampling = true; + Content.RootDirectory = "Content"; - Window.AllowUserResizing = true; - IsMouseVisible = true; - } + Window.AllowUserResizing = true; + IsMouseVisible = true; + } - protected override void LoadContent() - { - base.LoadContent(); - } + protected override void LoadContent() + { + base.LoadContent(); + } - protected override void UnloadContent() - { - base.UnloadContent(); - } + protected override void UnloadContent() + { + base.UnloadContent(); + } - protected override void Update(GameTime gameTime) - { - // - // Insert your game update logic here. - // + protected override void Update(GameTime gameTime) + { + // + // Insert your game update logic here. + // - base.Update(gameTime); - } + base.Update(gameTime); + } - protected override void Draw(GameTime gameTime) - { - // - // Replace this with your own drawing code. - // + protected override void Draw(GameTime gameTime) + { + // + // Replace this with your own drawing code. + // - GraphicsDevice.Clear(Color.CornflowerBlue); + GraphicsDevice.Clear(Color.CornflowerBlue); - base.Draw(gameTime); - } - } + base.Draw(gameTime); + } + } } diff --git a/README.md b/README.md index f64ec39..17c54b1 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,19 @@ # FNA-VSCode-Template -Template and build tasks for developing a cross-platform multi-target .NET Framework, Mono, and .NET 5 FNA project in VSCode. +Template and build tasks for developing a cross-platform multi-target .NET Framework, Mono, and .NET 6 FNA project in VSCode. The generated solution file will also work in regular Visual Studio. ## Features - Includes project boilerplate code -- Build tasks for both .NET Framework, Mono, and .NET 5 side by side +- Build tasks for both .NET Framework, Mono, and .NET 6 side by side - VSCode debugger integration ## Requirements - [Git](https://git-scm.com/) or [Git for Windows](https://gitforwindows.org/) on Windows -- [.NET 5 SDK](https://dotnet.microsoft.com/download/dotnet/5.0) +- [.NET 6 SDK](https://dotnet.microsoft.com/download/dotnet/6.0) - [.NET Framework 4.6.1 Developer Pack](https://dotnet.microsoft.com/download/dotnet-framework/net461) on Windows - [Build Tools for Visual Studio 2019](https://visualstudio.microsoft.com/downloads/) on Windows - [Mono](https://www.mono-project.com/) on OSX or Linux @@ -35,7 +35,7 @@ The generated solution file will also work in regular Visual Studio. - Press Ctrl-Shift-B to open the build tasks menu - `Framework` tasks use .NET Framework to build and run (Windows only) - `Mono` tasks use Mono to build and run -- `5` tasks use .NET 5 to build and run +- `.NET 6` tasks use .NET 6 to build and run - Press F5 to build and debug ## Acknowledgments diff --git a/install.sh b/install.sh index 64ef79e..4f654c1 100755 --- a/install.sh +++ b/install.sh @@ -14,19 +14,19 @@ readlinkf(){ perl -MCwd -e 'print Cwd::abs_path shift' "$1";} # Checks if git is installed function checkGit() { - git --version > /dev/null 2>&1 - if [ ! $? -eq 0 ]; then - echo >&2 "ERROR: Git is not installed. Please install git to download FNA." - exit 1 - fi + git --version > /dev/null 2>&1 + if [ ! $? -eq 0 ]; then + echo >&2 "ERROR: Git is not installed. Please install git to download FNA." + exit 1 + fi } # Pulls FNA from github function pullFNA() { - checkGit - git submodule add https://github.com/FNA-XNA/FNA.git - echo "Updating to the latest git version of FNA..." + checkGit + git submodule add https://github.com/FNA-XNA/FNA.git + echo "Updating to the latest git version of FNA..." git submodule update --init --recursive if [ $? -eq 0 ]; then echo "Finished updating!" @@ -39,33 +39,33 @@ function pullFNA() # Downloads and extracts prepackaged archive of native libraries ("fnalibs") function getLibs() { - # Downloading - echo "Downloading latest fnalibs..." - curl https://fna.flibitijibibo.com/archive/fnalibs.tar.bz2 > "$MY_DIR/fnalibs.tar.bz2" - if [ $? -eq 0 ]; then - echo "Finished downloading!" - else - >&2 echo "ERROR: Unable to download successfully." - exit 1 - fi + # Downloading + echo "Downloading latest fnalibs..." + curl https://fna.flibitijibibo.com/archive/fnalibs.tar.bz2 > "$MY_DIR/fnalibs.tar.bz2" + if [ $? -eq 0 ]; then + echo "Finished downloading!" + else + >&2 echo "ERROR: Unable to download successfully." + exit 1 + fi - # Decompressing - echo "Decompressing fnalibs..." - mkdir -p "$MY_DIR"/fnalibs - tar xjC "$MY_DIR"/fnalibs -f "$MY_DIR"/fnalibs.tar.bz2 - if [ $? -eq 0 ]; then - echo "Finished decompressing!" - echo "" - rm "$MY_DIR"/fnalibs.tar.bz2 - else - >&2 echo "ERROR: Unable to decompress successfully." - exit 1 - fi + # Decompressing + echo "Decompressing fnalibs..." + mkdir -p "$MY_DIR"/fnalibs + tar xjC "$MY_DIR"/fnalibs -f "$MY_DIR"/fnalibs.tar.bz2 + if [ $? -eq 0 ]; then + echo "Finished decompressing!" + echo "" + rm "$MY_DIR"/fnalibs.tar.bz2 + else + >&2 echo "ERROR: Unable to decompress successfully." + exit 1 + fi } read -p "Enter your project name or 'exit' to quit: " newProjectName if [[ $newProjectName = 'exit' || -z "$newProjectName" ]]; then - exit 1 + exit 1 fi NEW_PROJECT_DIR="$MY_DIR/../$newProjectName" @@ -83,10 +83,10 @@ cp -R "$MY_DIR" "$NEW_PROJECT_DIR" cd "$NEW_PROJECT_DIR" files=(ProjectName.Core.sln ProjectName.Framework.sln .gitignore ProjectName/ProjectName.Core.csproj ProjectName/ProjectName.Framework.csproj ProjectName/ProjectNameGame.cs ProjectName/Program.cs .vscode/tasks.json .vscode/launch.json) for file in "${files[@]}"; do - sed -i -e "s/ProjectName/$newProjectName/g" "./$file" - if [ "$(uname)" == "Darwin" ]; then - rm ./${file}-e - fi + sed -i -e "s/ProjectName/$newProjectName/g" "./$file" + if [ "$(uname)" == "Darwin" ]; then + rm ./${file}-e + fi done mv ./ProjectName.Core.sln "./$newProjectName.Core.sln" @@ -108,7 +108,7 @@ dotnet sln ${newProjectName}.Core.sln add FNA/FNA.Core.csproj echo "Project $newProjectName created at: " if [ "$(uname)" == "Darwin" ]; then - echo $(readlinkf $NEW_PROJECT_DIR) + echo $(readlinkf $NEW_PROJECT_DIR) else - echo $(readlink -f $NEW_PROJECT_DIR) + echo $(readlink -f $NEW_PROJECT_DIR) fi