diff --git a/SamplesDef.json b/SamplesDef.json index 12a73bb66..31e8e931f 100644 --- a/SamplesDef.json +++ b/SamplesDef.json @@ -486,6 +486,20 @@ "./RunSharpmake.ps1 -workingDirectory {testFolder} -sharpmakeFile \"HelloIOS.Main.sharpmake.cs\" -framework {framework}", "xcodebuild build-for-testing CODE_SIGNING_ALLOWED=NO -workspace {testFolder}/codebase/temp/solutions/HelloIOS_iOS.xcworkspace -configuration {configuration} -scheme exe_iOS -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14 Pro' test -derivedDataPath {testFolder}/test" ] - } + }, + { + "Name": "HelloAssemblyNasm", + "CIs": [ "github", "gitlab" ], + "OSs": [ "windows-2022" ], + "Frameworks": [ "net6.0" ], + "Configurations": [ "debug", "release" ], + "TestFolder": "samples/HelloAssemblyNasm", + "Commands": + [ + "./RunSharpmake.ps1 -workingDirectory {testFolder} -sharpmakeFile \"HelloAssemblyNasm.sharpmake.cs\" -framework {framework}", + "./Compile.ps1 -slnOrPrjFile \"helloassemblynasm_{VsVersionSuffix}_win64_msbuild.sln\" -configuration {configuration} -platform \"x64\" -WorkingDirectory \"{testFolder}/projects\" -VsVersion {os} -compiler MsBuild", + "&'./{testFolder}/projects/output/win64/{configuration}/HelloAssemblyNasmExecutable.exe'" + ] + }, ] } diff --git a/Sharpmake.Generators/CompilerSettings.cs b/Sharpmake.Generators/CompilerSettings.cs index 04c2aab81..2c0c8f810 100644 --- a/Sharpmake.Generators/CompilerSettings.cs +++ b/Sharpmake.Generators/CompilerSettings.cs @@ -59,6 +59,7 @@ public class Configuration public string Linker { get; set; } public string PlatformLibPaths { get; set; } public string Masm { get; set; } + public string Nasm { get; set; } public string Executable { get; set; } public string UsingOtherConfiguration { get; set; } public Platform Platform { get; private set; } diff --git a/Sharpmake.Generators/FastBuild/Bff.Template.cs b/Sharpmake.Generators/FastBuild/Bff.Template.cs index 11494a6ed..b8536eda7 100644 --- a/Sharpmake.Generators/FastBuild/Bff.Template.cs +++ b/Sharpmake.Generators/FastBuild/Bff.Template.cs @@ -91,6 +91,7 @@ public static class ConfigurationFile "; public static string MasmConfigNameSuffix = "Masm"; + public static string NasmConfigNameSuffix = "Nasm"; public static string Win64ConfigName = ".win64Config"; public static string CompilerSetting = @" @@ -120,6 +121,15 @@ public static class ConfigurationFile .Executable = '[fastBuildMasmCompiler]' .CompilerFamily = 'custom' } +"; + + // TODOANT + internal static string NasmCompilerSettings = @" +Compiler( '[fastBuildNasmCompilerName]' ) +{ + .Executable = '[fastBuildNasmCompiler]' + .CompilerFamily = 'custom' +} "; public static string CompilerConfiguration = @" @@ -296,6 +306,14 @@ public static class ConfigurationFile // ---------------- .CompilerOptions = ' $CompilerExtraOptions$' + ' /Fo""%2"" /c /Ta ""%1""' +"; + // TODOANT + public static string CompilerOptionsNasm = @" + // Compiler options + // ---------------- + .CompilerOptions = ' $CompilerExtraOptions$' + + ' -Xvc -Ox -o""%2"" ""%1""' + + ' [cmdLineOptions.NasmCompilerFormat] ' "; public static string CompilerOptionsClang = @" // Compiler options @@ -334,6 +352,14 @@ public static class ConfigurationFile + ' [cmdLineOptions.PreprocessorDefinitions]' "; + // TODOANT: NasmCompilerExtraOptions + public static string NasmCompilerExtraOptions = @" + .CompilerExtraOptions = '' + + ' [cmdLineOptions.AdditionalAssemblyNasmIncludeDirectories]' + + ' [cmdLineOptions.NasmPreprocessorDefinitions]' + + ' [cmdLineOptions.PreIncludedFiles]' +"; + public static string CPPCompilerExtraOptions = @" .CompilerExtraOptions = '' + ' [cmdLineOptions.AdditionalIncludeDirectories]' diff --git a/Sharpmake.Generators/FastBuild/Bff.cs b/Sharpmake.Generators/FastBuild/Bff.cs index daa8a90f2..b92b6863a 100644 --- a/Sharpmake.Generators/FastBuild/Bff.cs +++ b/Sharpmake.Generators/FastBuild/Bff.cs @@ -181,7 +181,8 @@ private enum Languages CPP = 4, ObjC = 8, ObjCPP = 16, - Swift = 32 + Swift = 32, + Nasm = 64 } [Flags] @@ -357,6 +358,7 @@ List skipFiles bool isCompileAsObjCPPFile = subConfig.Languages.HasFlag(Languages.ObjCPP); bool isCompileAsSwiftFile = subConfig.Languages.HasFlag(Languages.Swift); bool isASMFileSection = subConfig.Languages.HasFlag(Languages.Asm); + bool isNASMFileSection = subConfig.Languages.HasFlag(Languages.Nasm); bool isCompileAsCLRFile = subConfig.LanguageFeatures.HasFlag(LanguageFeatures.CLR); bool isCompileAsNonCLRFile = subConfig.LanguageFeatures.HasFlag(LanguageFeatures.NonCLR); bool isConsumeWinRTExtensions = subConfig.LanguageFeatures.HasFlag(LanguageFeatures.ConsumeWinRTExtensions) || (Options.GetObject(conf) == Options.Vc.Compiler.CompileAsWinRT.Enable); @@ -757,21 +759,47 @@ List skipFiles fastBuildUsingPlatformConfig = platformBff.CppConfigName(conf); } + // TODOANT: Add nasm/masm change if (isASMFileSection) { fastBuildUsingPlatformConfig += Template.ConfigurationFile.MasmConfigNameSuffix; } + if (isNASMFileSection) + { + fastBuildUsingPlatformConfig += Template.ConfigurationFile.NasmConfigNameSuffix; + } + + string fastBuildCompilerExtraOptions = Template.ConfigurationFile.CPPCompilerExtraOptions; + if (isASMFileSection) + { + fastBuildCompilerExtraOptions = Template.ConfigurationFile.MasmCompilerExtraOptions; + } + if (isNASMFileSection) + { + fastBuildCompilerExtraOptions = Template.ConfigurationFile.NasmCompilerExtraOptions; + } - string fastBuildCompilerExtraOptions = !isASMFileSection ? Template.ConfigurationFile.CPPCompilerExtraOptions : Template.ConfigurationFile.MasmCompilerExtraOptions; string fastBuildCompilerOptionsDeoptimize = FileGeneratorUtilities.RemoveLineTag; if (!isASMFileSection && conf.FastBuildDeoptimization != Project.Configuration.DeoptimizationWritableFiles.NoDeoptimization) fastBuildCompilerOptionsDeoptimize = Template.ConfigurationFile.CPPCompilerOptionsDeoptimize; - string compilerOptions = !isASMFileSection ? Template.ConfigurationFile.CompilerOptionsCPP : Template.ConfigurationFile.CompilerOptionsMasm; + string compilerOptions = Template.ConfigurationFile.CompilerOptionsCPP; + if (isASMFileSection) + { + compilerOptions = Template.ConfigurationFile.CompilerOptionsMasm; + } + if (isNASMFileSection) + { + compilerOptions = Template.ConfigurationFile.CompilerOptionsNasm; + } compilerOptions += Template.ConfigurationFile.CompilerOptionsCommon; - string compilerOptionsClang = Template.ConfigurationFile.CompilerOptionsClang + - Template.ConfigurationFile.CompilerOptionsCommon; + string compilerOptionsClang = Template.ConfigurationFile.CompilerOptionsClang; + if (isNASMFileSection) + { + compilerOptionsClang = Template.ConfigurationFile.CompilerOptionsNasm; + } + compilerOptionsClang += Template.ConfigurationFile.CompilerOptionsCommon; string fastBuildDeoptimizationWritableFiles = null; string fastBuildDeoptimizationWritableFilesWithToken = null; @@ -1197,8 +1225,10 @@ List skipFiles { if (isCompileAsSwiftFile) applePlatformBff?.SetupSwiftOptions(bffGenerator); - else + else if (!isNASMFileSection) clangPlatformBff?.SetupClangOptions(bffGenerator); // TODO: This checks twice if the platform supports Clang -- fix? + else + bffGenerator.Write(fastBuildCompilerExtraOptions); if (conf.Platform.IsUsingClang()) { @@ -1245,8 +1275,10 @@ List skipFiles { if (isCompileAsSwiftFile) applePlatformBff?.SetupSwiftOptions(bffGenerator); + else if (!isNASMFileSection) + clangPlatformBff?.SetupClangOptions(bffGenerator); // TODO: This checks twice if the platform supports Clang -- fix? else - clangPlatformBff?.SetupClangOptions(bffGenerator); // TODO: This checks twice if the platform supports Clang -- fix? + bffGenerator.Write(fastBuildCompilerExtraOptions); if (conf.Platform.IsUsingClang()) { @@ -1343,16 +1375,17 @@ List skipFiles { if (isCompileAsSwiftFile) applePlatformBff?.SetupSwiftOptions(bffGenerator); - else + else if (!isNASMFileSection) clangPlatformBff?.SetupClangOptions(bffGenerator); // TODO: This checks twice if the platform supports Clang -- fix? + else + bffGenerator.Write(fastBuildCompilerExtraOptions);; if (conf.Platform.IsUsingClang()) { if (isUsePrecomp) bffGenerator.Write(Template.ConfigurationFile.PCHOptionsClang); - bffGenerator.Write(Template.ConfigurationFile.CompilerOptionsCommon); - bffGenerator.Write(Template.ConfigurationFile.CompilerOptionsClang); + bffGenerator.Write(compilerOptionsClang); if (conf.FastBuildDeoptimization != Project.Configuration.DeoptimizationWritableFiles.NoDeoptimization) { if (isUsePrecomp) @@ -1558,6 +1591,8 @@ private static void GenerateBffOptions( var dependenciesInfo = FillLibrariesOptions(context); dependenciesInfoPerConf.Add(context.Configuration, dependenciesInfo); + + FillNasmOptions(context); } internal enum CompilerVersionForClangClType @@ -1805,7 +1840,6 @@ private static void FillIncludeDirectoriesOptions(BffGenerationContext context) // Fill Assembly include dirs var assemblyDirs = new List(); assemblyDirs.AddRange(assemblyIncludePaths.Select(p => CmdLineConvertIncludePathsFunc(context, context.EnvironmentVariableResolver, p, defaultCmdLineIncludePrefix))); - if (assemblyDirs.Any()) context.CommandLineOptions["AdditionalAssemblyIncludeDirectories"] = string.Join($"'{Environment.NewLine} + ' ", assemblyDirs); @@ -1930,6 +1964,54 @@ private static DependenciesInfo FillLibrariesOptions(BffGenerationContext contex return dependenciesInfo; } + private static void FillNasmOptions(BffGenerationContext context) + { + // Compiler path for nasm + context.CommandLineOptions["PathExe"] = context.Project.NasmExePath; + + // Pre included files for NASM syntax + var preIncludedFiles = new List(); + preIncludedFiles.AddRange(context.Project.NasmPreIncludedFiles.Select(p => "-P\"" + p + "\"")); + string preIncludedFilesJoined = string.Join(' ', preIncludedFiles); + context.CommandLineOptions["PreIncludedFiles"] = preIncludedFilesJoined; + + // Fill Assembly include dirs in nasm syntax + var nasmAssemblyDirs = new List(); + var platformVcxproj = PlatformRegistry.Query(context.Configuration.Platform); + var assemblyIncludePaths = new OrderableStrings(platformVcxproj.GetAssemblyIncludePaths(context)); + nasmAssemblyDirs.AddRange(assemblyIncludePaths.Select(p => CmdLineConvertIncludePathsFunc(context, context.EnvironmentVariableResolver, p, "-I "))); + + if (nasmAssemblyDirs.Any()) + { + context.CommandLineOptions["AdditionalAssemblyNasmIncludeDirectories"] = string.Join($"'{Environment.NewLine} + ' ", nasmAssemblyDirs); + } + else + { + context.CommandLineOptions["AdditionalAssemblyNasmIncludeDirectories"] = FileGeneratorUtilities.RemoveLineTag; + } + + // Defines in NASM syntax + var defines = new Strings(); + defines.AddRange(context.Options.ExplicitDefines); + defines.AddRange(context.Configuration.Defines); + + if (defines.Count > 0) + { + var fastBuildNasmDefines = new List(); + + foreach (string define in defines.SortedValues) + { + if (!string.IsNullOrWhiteSpace(define)) + fastBuildNasmDefines.Add(string.Format(@"{0}{1}{2}{1}", "-D", Util.DoubleQuotes, define.Replace(Util.DoubleQuotes, Util.EscapedDoubleQuotes))); + } + context.CommandLineOptions["NasmPreprocessorDefinitions"] = string.Join($"'{Environment.NewLine} + ' ", fastBuildNasmDefines); + } + else + { + context.CommandLineOptions["NasmPreprocessorDefinitions"] = FileGeneratorUtilities.RemoveLineTag; + } + } + private static void SelectAdditionalLibraryDirectoriesOption(BffGenerationContext context) { // TODO: really not ideal, refactor and move the properties we need from it someplace else @@ -2324,9 +2406,11 @@ out List filesInNonDefaultSections conf.ResolvedSourceFilesWithCompileAsWinRTOption.Contains(file.FileName)) && !(conf.ExcludeWinRTExtensions.Contains(file.FileName) || conf.ResolvedSourceFilesWithExcludeAsWinRTOption.Contains(file.FileName)); + // TODOANT: Also trigger on .nasm files bool isASMFile = string.Compare(file.FileExtension, ".asm", StringComparison.OrdinalIgnoreCase) == 0; bool isSwiftFile = string.Compare(file.FileExtension, ".swift", StringComparison.OrdinalIgnoreCase) == 0 && (PlatformRegistry.Query(conf.Platform)?.IsSwiftSupported() ?? false); + bool isNASMFile = string.Compare(file.FileExtension, ".nasm", StringComparison.OrdinalIgnoreCase) == 0; Options.Vc.Compiler.Exceptions exceptionSetting = conf.GetExceptionSettingForFile(file.FileName); @@ -2354,6 +2438,8 @@ out List filesInNonDefaultSections languageKind |= Languages.Swift; if (isASMFile) languageKind |= Languages.Asm; + if (isNASMFile) + languageKind |= Languages.Nasm; LanguageFeatures languageFeatures = LanguageFeatures.None; if (isCompileAsCLRFile) diff --git a/Sharpmake.Generators/FastBuild/MasterBff.cs b/Sharpmake.Generators/FastBuild/MasterBff.cs index 16b30040b..aa958e742 100644 --- a/Sharpmake.Generators/FastBuild/MasterBff.cs +++ b/Sharpmake.Generators/FastBuild/MasterBff.cs @@ -746,6 +746,11 @@ private static void WriteMasterCompilerSection(FileGenerator masterBffGenerator, using (masterBffGenerator.Declare("fastBuildResourceCompilerName", compConf.ResourceCompiler != FileGeneratorUtilities.RemoveLineTag ? "RC" + compilerConfiguration.Key : FileGeneratorUtilities.RemoveLineTag)) using (masterBffGenerator.Declare("fastBuildMasmCompiler", compConf.Masm)) using (masterBffGenerator.Declare("fastBuildMasmCompilerName", "ML" + compilerConfiguration.Key)) + + // TODOANT make sure we have nasm compiler found and used. + using (masterBffGenerator.Declare("fastBuildNasmCompiler", compConf.Nasm)) + using (masterBffGenerator.Declare("fastBuildNasmCompilerName", "Nasm" + compilerConfiguration.Key)) + using (masterBffGenerator.Declare("fastBuildCompilerName", compConf.Compiler != FileGeneratorUtilities.RemoveLineTag ? compConf.Compiler : compiler.Key)) using (masterBffGenerator.Declare("fastBuildLibrarian", compConf.Librarian)) using (masterBffGenerator.Declare("fastBuildLinker", compConf.Linker)) @@ -760,6 +765,10 @@ private static void WriteMasterCompilerSection(FileGenerator masterBffGenerator, if (!string.IsNullOrEmpty(compConf.Masm)) masterBffGenerator.Write(Bff.Template.ConfigurationFile.MasmCompilerSettings); + // TODOANT + if (!string.IsNullOrEmpty(compConf.Nasm)) + masterBffGenerator.Write(Bff.Template.ConfigurationFile.NasmCompilerSettings); + masterBffGenerator.Write(Bff.Template.ConfigurationFile.CompilerConfiguration); } } diff --git a/Sharpmake.Generators/VisualStudio/IPlatformVcxproj.cs b/Sharpmake.Generators/VisualStudio/IPlatformVcxproj.cs index 28b93aeb5..88ad869e1 100644 --- a/Sharpmake.Generators/VisualStudio/IPlatformVcxproj.cs +++ b/Sharpmake.Generators/VisualStudio/IPlatformVcxproj.cs @@ -82,6 +82,7 @@ public interface IPlatformVcxproj void GenerateProjectCompileVcxproj(IVcxprojGenerationContext context, IFileGenerator generator); void GenerateProjectLinkVcxproj(IVcxprojGenerationContext context, IFileGenerator generator); void GenerateProjectMasmVcxproj(IVcxprojGenerationContext context, IFileGenerator generator); + void GenerateProjectNasmVcxproj(IVcxprojGenerationContext context, IFileGenerator generator); void GenerateUserConfigurationFile(Project.Configuration conf, IFileGenerator generator); // Should take IVcxprojGenerationContext but this is called by BaseUserFile which should not know that interface. void GenerateRunFromPcDeployment(IVcxprojGenerationContext context, IFileGenerator generator); diff --git a/Sharpmake.Generators/VisualStudio/ProjectOptionsGenerator.cs b/Sharpmake.Generators/VisualStudio/ProjectOptionsGenerator.cs index a27b5f8ca..0a8dee959 100644 --- a/Sharpmake.Generators/VisualStudio/ProjectOptionsGenerator.cs +++ b/Sharpmake.Generators/VisualStudio/ProjectOptionsGenerator.cs @@ -260,8 +260,10 @@ private void GenerateCompilerOptions(IGenerationContext context, ProjectOptionsG context.Options["ForcedIncludeFilesVanilla"] = context.Configuration.ForcedIncludes.JoinStrings(";"); StringBuilder result = new StringBuilder(); + var platformDescriptor = PlatformRegistry.Get(context.Configuration.Platform); + string defaultCmdLineForceIncludePrefix = platformDescriptor.IsUsingClang ? @"-include""" : @"/FI"""; foreach (var forcedInclude in forcedIncludes) - result.Append(@"/FI""" + forcedInclude + @""" "); + result.Append(defaultCmdLineForceIncludePrefix + forcedInclude + @""" "); result.Remove(result.Length - 1, 1); context.CommandLineOptions["ForcedIncludeFiles"] = result.ToString(); } diff --git a/Sharpmake.Generators/VisualStudio/Vcxproj.Template.cs b/Sharpmake.Generators/VisualStudio/Vcxproj.Template.cs index cf5b0a85f..010fd33bd 100644 --- a/Sharpmake.Generators/VisualStudio/Vcxproj.Template.cs +++ b/Sharpmake.Generators/VisualStudio/Vcxproj.Template.cs @@ -106,6 +106,11 @@ public static class Project @" "; + public static string ProjectImportedNasmProps = +@" +"; + + public static string ProjectConfigurationImportedProps = @" "; @@ -144,6 +149,10 @@ public static class Project public static string ProjectMasmTargetsItem = @" +"; + + public static string ProjectNasmTargetsItem = +@" "; public static string ProjectConfigurationImportedTargets = diff --git a/Sharpmake.Generators/VisualStudio/Vcxproj.cs b/Sharpmake.Generators/VisualStudio/Vcxproj.cs index 5e168c555..c80f4d9f8 100644 --- a/Sharpmake.Generators/VisualStudio/Vcxproj.cs +++ b/Sharpmake.Generators/VisualStudio/Vcxproj.cs @@ -485,7 +485,21 @@ private void GenerateImpl(GenerationContext context, IList generatedFile // .props files fileGenerator.Write(Template.Project.ProjectAfterConfigurationsGeneral); if (context.Project.ContainsASM) + { fileGenerator.Write(Template.Project.ProjectImportedMasmProps); + } + + if (context.Project.ContainsNASM) + { + if (context.Project.NasmExePath.Length == 0) + { + throw new ArgumentNullException("NasmExePath not set and needed for NASM assembly files."); + } + using (fileGenerator.Declare("importedNasmPropsFile", context.Project.NasmPropsFile)) + { + fileGenerator.Write(Template.Project.ProjectImportedNasmProps); + } + } VsProjCommon.WriteProjectCustomPropsFiles(context.Project.CustomPropsFiles, context.ProjectDirectoryCapitalized, fileGenerator); VsProjCommon.WriteConfigurationsCustomPropsFiles(context.ProjectConfigurations, context.ProjectDirectoryCapitalized, fileGenerator); @@ -579,7 +593,13 @@ private void GenerateImpl(GenerationContext context, IList generatedFile platformVcxproj.GenerateProjectLinkVcxproj(context, fileGenerator); if (conf.Project.ContainsASM) + { platformVcxproj.GenerateProjectMasmVcxproj(context, fileGenerator); + } + if (conf.Project.ContainsNASM) + { + platformVcxproj.GenerateProjectNasmVcxproj(context, fileGenerator); + } if (conf.EventPreBuild.Count != 0) fileGenerator.Write(Template.Project.ProjectConfigurationsPreBuildEvent); @@ -651,6 +671,18 @@ private void GenerateImpl(GenerationContext context, IList generatedFile { fileGenerator.Write(Template.Project.ProjectMasmTargetsItem); } + if (context.Project.ContainsNASM) + { + if (context.Project.NasmExePath.Length == 0) + { + throw new ArgumentNullException("NasmExePath not set and needed for NASM assembly files."); + } + using (fileGenerator.Declare("importedNasmTargetsFile", context.Project.NasmTargetsFile)) + { + fileGenerator.Write(Template.Project.ProjectNasmTargetsItem); + } + } + foreach (string targetsFiles in context.Project.CustomTargetsFiles) { string capitalizedFile = Project.GetCapitalizedFile(targetsFiles) ?? targetsFiles; diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/BaseApplePlatform.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/BaseApplePlatform.cs index 608e8fc4e..1edd2423f 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/BaseApplePlatform.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/BaseApplePlatform.cs @@ -1433,6 +1433,11 @@ public void GenerateProjectMasmVcxproj(IVcxprojGenerationContext context, IFileG throw new NotImplementedException(SimplePlatformString + " should not be called by a Vcxproj generator"); } + public void GenerateProjectNasmVcxproj(IVcxprojGenerationContext context, IFileGenerator generator) + { + throw new NotImplementedException(SimplePlatformString + " should not be called by a Vcxproj generator"); + } + public void GenerateUserConfigurationFile(Project.Configuration conf, IFileGenerator generator) { throw new NotImplementedException(SimplePlatformString + " should not be called by a Vcxproj generator"); diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BasePlatform.Vcxproj.Template.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BasePlatform.Vcxproj.Template.cs index 9cca39e9d..60847101b 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BasePlatform.Vcxproj.Template.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BasePlatform.Vcxproj.Template.cs @@ -304,5 +304,14 @@ public abstract partial class BasePlatform "; + + private const string _projectConfigurationsNasmTemplate = + @" + [EscapeXML:options.PreprocessorDefinitions];%(PreprocessorDefinitions);$(PreprocessorDefinitions) + [options.AdditionalAssemblyIncludeDirectories] + [ExePath] + [PreIncludedFiles] + +"; } } diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BasePlatform.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BasePlatform.cs index 7f0f7de28..bfdae1308 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BasePlatform.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BasePlatform.cs @@ -339,6 +339,21 @@ public virtual void GenerateProjectMasmVcxproj(IVcxprojGenerationContext context { } + public virtual void GenerateProjectNasmVcxproj(IVcxprojGenerationContext context, IFileGenerator generator) + { + // Fill Assembly include dirs + var preIncludedFiles = new List(); + preIncludedFiles.AddRange(context.Project.NasmPreIncludedFiles.AsEnumerable()); + + string preIncludedFilesJoined = string.Join(';', preIncludedFiles); + + using (generator.Declare("ExePath", context.Project.NasmExePath)) + using (generator.Declare("PreIncludedFiles", preIncludedFilesJoined)) + { + generator.Write(_projectConfigurationsNasmTemplate); + } + } + public virtual void GenerateUserConfigurationFile(Project.Configuration conf, IFileGenerator generator) { generator.Write(_userFileConfigurationGeneralTemplate); diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Linux/LinuxPlatform.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Linux/LinuxPlatform.cs index d6c49e771..f4bd0ab56 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Linux/LinuxPlatform.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Linux/LinuxPlatform.cs @@ -126,6 +126,7 @@ public override void SetupPlatformTargetOptions(IGenerationContext context) context.Options["RandomizedBaseAddress"] = "true"; context.CommandLineOptions["TargetMachine"] = "/MACHINE:X64"; context.CommandLineOptions["RandomizedBaseAddress"] = "/DYNAMICBASE"; + context.CommandLineOptions["NasmCompilerFormat"] = "-felf64"; } public override void SetupSdkOptions(IGenerationContext context) diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/Win32Platform.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/Win32Platform.cs index 1a40133d3..4ef9a1438 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/Win32Platform.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/Win32Platform.cs @@ -36,6 +36,7 @@ public override void SetupPlatformTargetOptions(IGenerationContext context) { context.Options["TargetMachine"] = "MachineX86"; context.CommandLineOptions["TargetMachine"] = "/MACHINE:X86"; + context.CommandLineOptions["NasmCompilerFormat"] = "-fwin32"; } public override void SelectPlatformAdditionalDependenciesOptions(IGenerationContext context) diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/Win64Platform.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/Win64Platform.cs index ce1cf172f..0a9dac7e5 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/Win64Platform.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/Win64Platform.cs @@ -330,6 +330,19 @@ private void SetConfiguration( masmConfigurationName, masmConfiguration ); + + string nasmConfigurationName = configName + "Nasm"; + var nasmConfiguration = new CompilerSettings.Configuration( + Platform.win64, + compiler: "Nasm" + nasmConfigurationName, + usingOtherConfiguration: configName + ); + nasmConfiguration.Nasm = conf.Project.NasmExePath; + + configurations.Add( + nasmConfigurationName, + nasmConfiguration + ); } #endregion @@ -348,6 +361,7 @@ public override void SetupPlatformTargetOptions(IGenerationContext context) { context.Options["TargetMachine"] = "MachineX64"; context.CommandLineOptions["TargetMachine"] = "/MACHINE:X64"; + context.CommandLineOptions["NasmCompilerFormat"] = "-fwin64"; } public override void SelectPlatformAdditionalDependenciesOptions(IGenerationContext context) diff --git a/Sharpmake/Project.Configuration.cs b/Sharpmake/Project.Configuration.cs index 2998a1326..03f695eae 100644 --- a/Sharpmake/Project.Configuration.cs +++ b/Sharpmake/Project.Configuration.cs @@ -876,7 +876,7 @@ public string GetSolutionFolder(string solutionName) #endregion /// - /// Include paths for Microsoft Macro Assembler compilation. + /// Include paths for Assembly compilation. /// /// /// The maximum number of these paths is 10. diff --git a/Sharpmake/Project.cs b/Sharpmake/Project.cs index 49aafe9e2..60a8a813f 100644 --- a/Sharpmake/Project.cs +++ b/Sharpmake/Project.cs @@ -104,8 +104,8 @@ public string GuidReferencePath public Strings PreFilterSourceFiles { get { return _preFilterSourceFiles; } } - public Strings SourceFilesExtensions = new Strings(".cpp", ".c", ".cc", ".h", ".inl", ".hpp", ".hh", ".asm");// All files under SourceRootPath are evaluated, if match found, it will be added to SourceFiles - public Strings SourceFilesCompileExtensions = new Strings(".cpp", ".cc", ".c", ".asm"); // File that match this regex compile + public Strings SourceFilesExtensions = new Strings(".cpp", ".c", ".cc", ".h", ".inl", ".hpp", ".hh", ".asm", ".nasm");// All files under SourceRootPath are evaluated, if match found, it will be added to SourceFiles + public Strings SourceFilesCompileExtensions = new Strings(".cpp", ".cc", ".c", ".asm", ".nasm"); // File that match this regex compile public Strings SourceFilesCPPExtensions = new Strings(".cpp", ".cc"); public Strings SourceFilesFilters = null; // if != null, include only file in this filter @@ -229,6 +229,11 @@ internal void Resolve(string sourceRootPath, Resolver resolver) public Strings CustomPropsFiles = new Strings(); // vs2010+ .props files public Strings CustomTargetsFiles = new Strings(); // vs2010+ .targets files + public string NasmPropsFile = ""; + public string NasmTargetsFile = ""; + public string NasmExePath = ""; + public Strings NasmPreIncludedFiles = new Strings(); + public Strings LibraryPathsExcludeFromWarningRegex = new Strings(); // Library paths where we want to ignore the path doesn't exist warning public Strings IncludePathsExcludeFromWarningRegex = new Strings(); // Include paths where we want to ignore the path doesn't exist warning @@ -240,6 +245,7 @@ internal void Resolve(string sourceRootPath, Resolver resolver) public Dictionary CustomFilterMapping = new Dictionary(); /// maps relative source directory to a custom filter path for vcxproj.filter files public bool ContainsASM = false; + public bool ContainsNASM = false; // Some projects don't support changelist filter. and will generate build errors when trying to compile the resulting projects. public bool SkipProjectWhenFiltersActive = false; @@ -1213,7 +1219,10 @@ internal virtual void ResolveSourceFiles(Builder builder) if (sourceFile.EndsWith(".asm", StringComparison.OrdinalIgnoreCase)) { ContainsASM = true; - break; + } + if (sourceFile.EndsWith(".nasm", StringComparison.OrdinalIgnoreCase)) + { + ContainsNASM = true; } } @@ -1659,6 +1668,8 @@ internal void Initialize(Type targetType, Type configurationType, bool isInterna ConfigurationType = configurationType; ExtensionBuildTools[".asm"] = "MASM"; + ExtensionBuildTools[".nasm"] = "NASM"; + ClassName = GetType().Name; FullClassName = GetType().FullName; Targets.Initialize(targetType); diff --git a/samples/HelloAssemblyNasm/HelloAssemblyNasm.sharpmake.cs b/samples/HelloAssemblyNasm/HelloAssemblyNasm.sharpmake.cs new file mode 100644 index 000000000..c7ad98001 --- /dev/null +++ b/samples/HelloAssemblyNasm/HelloAssemblyNasm.sharpmake.cs @@ -0,0 +1,128 @@ +// Copyright (c) Ubisoft. All Rights Reserved. +// Licensed under the Apache 2.0 License. See LICENSE.md in the project root for license information. +using System.IO; +using Sharpmake; + +namespace HelloAssemblyNasm +{ + public static class Globals + { + // branch root path relative to current sharpmake file location + public const string RelativeRootPath = @".\codebase"; + public static string RootDirectory; + public static string NasmInstallPath = ""; + } + + + [Sharpmake.Generate] + public class HelloAssemblyNasmProject : Project + { + public HelloAssemblyNasmProject() + { + Name = "HelloAssemblyNasmExecutable"; + SourceRootPath = @"[project.SharpmakeCsPath]\codebase"; + + // The utils/precomp files are supposed to be only included, not built separately + SourceFilesBuildExclude.Add(@"[project.SharpmakeCsPath]\codebase\sub folder\utils.nasm"); + SourceFilesBuildExclude.Add(@"[project.SharpmakeCsPath]\codebase\sub folder\precomp.nasm"); + + // Remove asm from compilation, we are testing nasm only. + SourceFilesCompileExtensions.Remove(".asm"); + SourceFilesExtensions.Remove(".asm"); + + NasmExePath = Globals.NasmInstallPath; + + // FastBuild + StripFastBuildSourceFiles = false; + AddTargets(new Target( + Platform.win64, + DevEnv.vs2022, + Optimization.Debug | Optimization.Release, + OutputType.Lib, + Blob.NoBlob, + BuildSystem.FastBuild | BuildSystem.MSBuild + )); + } + + [Configure] + public void ConfigureAll(Configuration conf, Target target) + { + conf.ProjectFileName = "[project.Name]_[target.DevEnv]_[target.Platform]_[target.BuildSystem]"; + conf.ProjectPath = @"[project.SharpmakeCsPath]\projects"; + + conf.Defines.Add("_HAS_EXCEPTIONS=0"); + + conf.AssemblyIncludePaths.Add(@"[project.SharpmakeCsPath]\codebase\sub folder"); + conf.Project.NasmPreIncludedFiles.Add("precomp.nasm"); + } + + [Configure(BuildSystem.FastBuild)] + public void ConfigureFastBuild(Configuration conf, Target target) + { + conf.IsFastBuild = true; + conf.FastBuildBlobbed = target.Blob == Blob.FastBuildUnitys; + + // Force writing to pdb from different cl.exe process to go through the pdb server + conf.AdditionalCompilerOptions.Add("/FS"); + } + + [Configure(BuildSystem.MSBuild)] + public void ConfigureMSBuild(Configuration conf, Target target) + { + conf.Project.NasmTargetsFile = @"[project.SharpmakeCsPath]\custom\nasm.targets"; + conf.Project.NasmPropsFile = @"[project.SharpmakeCsPath]\custom\nasm.props"; + } + } + + [Sharpmake.Generate] + public class HelloAssemblyNasmSolution : Sharpmake.Solution + { + public HelloAssemblyNasmSolution() + { + Name = "HelloAssemblyNasm"; + AddTargets(new Target( + Platform.win64, + DevEnv.vs2022, + Optimization.Debug | Optimization.Release, + OutputType.Lib, + Blob.NoBlob, + BuildSystem.FastBuild | BuildSystem.MSBuild + )); + } + + [Configure()] + public void ConfigureAll(Configuration conf, Target target) + { + conf.SolutionFileName = "[solution.Name]_[target.DevEnv]_[target.Platform]_[target.BuildSystem]"; + conf.SolutionPath = @"[solution.SharpmakeCsPath]\projects"; + conf.AddProject(target); + } + } + + public static class Main + { + private static void ConfigureRootDirectory() + { + FileInfo fileInfo = Util.GetCurrentSharpmakeFileInfo(); + string rootDirectory = Path.Combine(fileInfo.DirectoryName, Globals.RelativeRootPath); + Globals.RootDirectory = Util.SimplifyPath(rootDirectory); + } + + [Sharpmake.Main] + public static void SharpmakeMain(Sharpmake.Arguments arguments) + { + ConfigureRootDirectory(); + + // Hardcoded executable for simplicity, no nuget dependency. + string nasmExePath = Util.PathGetAbsolute(Globals.RootDirectory, @"..\tools\"); + Globals.NasmInstallPath = Path.Combine(nasmExePath, "nasm.exe"); + + // for the purpose of this sample, we'll reuse the FastBuild executable that live in the sharpmake source repo + string sharpmakeFastBuildDir = Util.PathGetAbsolute(Globals.RootDirectory, @"..\..\..\tools\FastBuild"); + FastBuildSettings.FastBuildMakeCommand = Path.Combine(sharpmakeFastBuildDir, "Windows-x64", "FBuild.exe"); + + KitsRootPaths.SetUseKitsRootForDevEnv(DevEnv.vs2022, KitsRootEnum.KitsRoot10, Options.Vc.General.WindowsTargetPlatformVersion.v10_0_19041_0); + arguments.Generate(); + } + } +} diff --git a/samples/HelloAssemblyNasm/codebase/hello_world.nasm b/samples/HelloAssemblyNasm/codebase/hello_world.nasm new file mode 100644 index 000000000..099a96559 --- /dev/null +++ b/samples/HelloAssemblyNasm/codebase/hello_world.nasm @@ -0,0 +1,22 @@ +%include "utils.nasm" + +section .data + message db 'Hello world!', 0 + + +section .text + global hello_world + extern_function printf + +hello_world: + push rbp + mov rbp, rsp + sub rsp, 32 + + lea rcx, [rel message] + call printf + + add rsp, 32 + mov rsp, rbp + pop rbp + ret diff --git a/samples/HelloAssemblyNasm/codebase/main.cpp b/samples/HelloAssemblyNasm/codebase/main.cpp new file mode 100644 index 000000000..390bf44aa --- /dev/null +++ b/samples/HelloAssemblyNasm/codebase/main.cpp @@ -0,0 +1,7 @@ +extern "C" void hello_world(); + +int main(int, char**) +{ + hello_world(); + return 0; +} diff --git a/samples/HelloAssemblyNasm/codebase/sub folder/precomp.nasm b/samples/HelloAssemblyNasm/codebase/sub folder/precomp.nasm new file mode 100644 index 000000000..74317ef50 --- /dev/null +++ b/samples/HelloAssemblyNasm/codebase/sub folder/precomp.nasm @@ -0,0 +1 @@ +%define CONFIG_DEFINE 1 diff --git a/samples/HelloAssemblyNasm/codebase/sub folder/utils.nasm b/samples/HelloAssemblyNasm/codebase/sub folder/utils.nasm new file mode 100644 index 000000000..9f7372ed2 --- /dev/null +++ b/samples/HelloAssemblyNasm/codebase/sub folder/utils.nasm @@ -0,0 +1,5 @@ +%if CONFIG_DEFINE +%macro extern_function 1 + extern %1 +%endmacro +%endif diff --git a/samples/HelloAssemblyNasm/custom/nasm.props b/samples/HelloAssemblyNasm/custom/nasm.props new file mode 100644 index 000000000..009a28120 --- /dev/null +++ b/samples/HelloAssemblyNasm/custom/nasm.props @@ -0,0 +1,18 @@ + + + + Midl + CustomBuild + + + + $(IntDir)%(FileName).obj + [Path] -Xvc -f win32 [AllOptions] [AdditionalOptions] "%(FullPath)" + [Path] -Xvc -f win64 [AllOptions] [AdditionalOptions] "%(FullPath)" + echo NASM not supported on this platform +exit 1 + Assembling %(Filename)%(Extension) + + + \ No newline at end of file diff --git a/samples/HelloAssemblyNasm/custom/nasm.targets b/samples/HelloAssemblyNasm/custom/nasm.targets new file mode 100644 index 000000000..02da59975 --- /dev/null +++ b/samples/HelloAssemblyNasm/custom/nasm.targets @@ -0,0 +1,93 @@ + + + + + + _NASM + + + + + $(ComputeLinkInputsTargets); + ComputeNASMOutput; + + + $(ComputeLibInputsTargets); + ComputeNASMOutput; + + + + $(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml + + + + + + + <_NasmReadTlog Include="^%(NASM.FullPath);%(NASM.AdditionalDependencies)" /> + <_NasmWriteTlog Include="^%(NASM.FullPath);$([MSBuild]::NormalizePath('$(MSBuildProjectDirectory)', '%(NASM.ObjectFileName)'))" /> + + + + + <_NasmReadTlog Remove="@(_NasmReadTlog)" /> + <_NasmWriteTlog Remove="@(_NasmWriteTlog)" /> + + + + + + + + + + + + + + + + diff --git a/samples/HelloAssemblyNasm/custom/nasm.xml b/samples/HelloAssemblyNasm/custom/nasm.xml new file mode 100644 index 000000000..cbad94952 --- /dev/null +++ b/samples/HelloAssemblyNasm/custom/nasm.xml @@ -0,0 +1,204 @@ + + + + + + + + + + General + + + + + Preprocessing Options + + + + + Assembler Options + + + + + Command Line + + + + + + + + + + + + + + + + + + + + + Execute Before + + + Specifies the targets for the build customization to run before. + + + + + + + + + + + Execute After + + + Specifies the targets for the build customization to run after. + + + + + + + + + + + + + Additional Options + + + Additional Options + + + + + + + + diff --git a/samples/HelloAssemblyNasm/tools/nasm.exe b/samples/HelloAssemblyNasm/tools/nasm.exe new file mode 100644 index 000000000..a2e61291a Binary files /dev/null and b/samples/HelloAssemblyNasm/tools/nasm.exe differ