Supporting .s assembly files

Hi there,

i have some libraries packaged as modules that contains .s files, but i can't add them to the juce modules info table cause they get ignored when generating the project/makefiles.

compiling masm is supported on all platforms, so it would be cool to support them (or .asm) too, making external libraries that needs assembler files to be packaged as modules, and avoid patching project files everytime we save project in the jucer.

probably this is more an issue of the juce modules rather than introjucer tho...

I could add .s and .asm to the sourceFileExtensions list in juce_CommonHeaders.h - does that do the job for you?

could work with gcc as they don’t require special switches, but i don’t know if msvc will handle them with particular compiler commands… will test it and see if it works on all platforms.

well, not the cleaner solution but that could work...

isn't possible to make also LibraryModule::findAndAddCompiledCode also favour .s and .asm ? i see there those files are filtered out from the build, and Project::Item item (projectSaver.addFileToGeneratedGroup (compiledFile)) always set item.shouldBeCompiled to false. this way packing modules with asm files that needs to be compiled is independent of remembering to add those file to the introjucer to make everything work...

can this be tweaked too please ?

void Project::Item::addFileUnchecked (const File& file, int insertIndex, const bool shouldCompile)
    Item item (project, ValueTree (Ids::FILE));
    item.getNameValue() = file.getFileName();
    item.getShouldCompileValue() = shouldCompile && file.hasFileExtension ("cpp;mm;c;m;cc;cxx;r;s;asm");
    item.getShouldAddToResourceValue() = project.shouldBeAddedToBinaryResourcesByDefault (file);
    if (canContain (item))
        item.setFile (file);
        addChild (item, insertIndex);

also, i've found those 
file.hasFileExtension ("whatever:extensions:needed") spread all over the code... isn't possible to organize them in global variables more organically ?

Thanks, I'll take a look.

still, for some obscure reasons, by adding s and asm to Project::Item::addFileUnchecked, i'm not able to make them appears in makefiles...

if you want i can send you my module so you can test it easily

the library i’m trying to package as module (namely libffi) has .S files and not .s, after a bit of research, s files are plain assembly files and S are assembly files with preprocessor macros in it, so they should both be supported. if you rename a S to s and pass it to the compiler it will complain.
anyway didn’t find any other project out there with .asm files extensions.

the problem was in the introjucer makefile exporter, when adding files that should be compiled, a check was made about “c” extensions but not “s” nor “S” so those files have been filtered out.
i still need to check in msvc and xcode exporter…

this actually did the trick and everything works...

hope it will be accepted for inclusion. i will report back if anything is wrong...

It's difficult to use diffs when you generate them on older versions of the tree, but I think I've made the relevant changes from that now - let me know if not.

sure i probably forgot to do a git pull on the tree before doing the diff… will check the commits and report back, thanks

one more change for visual studio:

diff --git a/extras/Introjucer/Source/Project Saving/jucer_ProjectExport_MSVC.h b/extras/Introjucer/Source/Project Saving/jucer_ProjectExport_MSVC.h
index 11b1bb8..46e416b 100644
--- a/extras/Introjucer/Source/Project Saving/jucer_ProjectExport_MSVC.h    
+++ b/extras/Introjucer/Source/Project Saving/jucer_ProjectExport_MSVC.h    
@@ -1389,7 +1389,8 @@ protected:
             jassert (path.getRoot() == RelativePath::buildTargetFolder);
-            if (path.hasFileExtension (cOrCppFileExtensions))
+            if (path.hasFileExtension (cOrCppFileExtensions)
+                || path.hasFileExtension (asmFileExtensions))
                 XmlElement* e = cpps.createNewChildElement ("ClCompile");
                 e->setAttribute ("Include", path.toWindowsStyle());

however this is still not enough, asm files are bypassed on visual studio... need to check a bit more

Here is what i did to allow compilation in MSVC:

diff --git a/extras/Introjucer/Source/Project Saving/jucer_ProjectExport_MSVC.h b/extras/Introjucer/Source/Project Saving/jucer_ProjectExport_MSVC.h
index 11b1bb8…24c7f1f 100644
— a/extras/Introjucer/Source/Project Saving/jucer_ProjectExport_MSVC.h    
+++ b/extras/Introjucer/Source/Project Saving/jucer_ProjectExport_MSVC.h    
@@ -1094,7 +1094,7 @@ protected:
             XmlElement* imports = projectXml.createNewChildElement (“Import”);
             imports->setAttribute (“Project”, “$(VCTargetsPath)\Microsoft.Cpp.Default.props”);

             for (ConstConfigIterator i (*this);
                 const VC2010BuildConfiguration& config = dynamic_cast<const VC2010BuildConfiguration&> (i);
    @@ -1125,6 +1125,8 @@ protected:
    e = projectXml.createNewChildElement (“ImportGroup”);
                 e->setAttribute (“Label”, “ExtensionSettings”);
  •            XmlElement* masm = e->createNewChildElement(“Import”);
  •            masm->setAttribute (“Project”, “$(VCTargetsPath)\BuildCustomizations\masm.props”);
    @@ -1302,6 +1304,11 @@ protected:
                     bsc->createNewChildElement (“OutputFile”)->addTextElement (getIntDirFile (config, config.getOutputFilename (".bsc", true)));
  •            {
  •                XmlElement* masm = group->createNewChildElement (“MASM”);
  •                masm->createNewChildElement (“GenerateDebugInformation”)->addTextElement ((isDebug || config.shouldGenerateDebugSymbols()) ? “true” : “false”);
  •            }

             if (config.getPrebuildCommandString().isNotEmpty())
                 group->createNewChildElement (“PreBuildEvent”)
                      ->createNewChildElement (“Command”)
@@ -1352,6 +1359,7 @@ protected:
             XmlElement* e = projectXml.createNewChildElement (“ImportGroup”);
             e->setAttribute (“Label”, “ExtensionTargets”);

  •            e->createNewChildElement(“Import”)->setAttribute (“Project”, “$(VCTargetsPath)\BuildCustomizations\masm.targets”);
    @@ -1393,7 +1401,7 @@ protected:
                     XmlElement* e = cpps.createNewChildElement (“ClCompile”);
                     e->setAttribute (“Include”, path.toWindowsStyle());
                     if (! projectItem.shouldBeCompiled())
                         e->createNewChildElement (“ExcludedFromBuild”)->addTextElement (“true”);
    @@ -1404,6 +1412,35 @@ protected:
                     headers.createNewChildElement (“ClInclude”)->setAttribute (“Include”, path.toWindowsStyle());
  •            else if (path.hasFileExtension (asmFileExtensions))
  •            {
  •                XmlElement* e = cpps.createNewChildElement (“MASM”);
  •                e->setAttribute (“Include”, path.toWindowsStyle());
  •                XmlElement* command = e->createNewChildElement (“Command”);
  •                XmlElement* outputs = e->createNewChildElement (“Outputs”);
  •                outputs->addTextElement ("(IntDir)%(Filename).obj;(IntDir)%(Filename).lst;%(Outputs)");
  •                XmlElement* excluded = e->createNewChildElement (“ExcludedFromBuild”);
  •                excluded->addTextElement(“true”);
  •                const bool isAssembler64bit = path.getFileNameWithoutExtension().endsWith(“64”);
  •                if (isAssembler64bit)
  •                {
  •                    command->addTextElement (""(VSInstallDir)VC\\bin\\x86_amd64\\ml64\" /c /Zi /Sa \"/Fl(IntDir)%(Filename).lst" “/Fo$(IntDir)%(Filename).obj” “%(FullPath)”");
  •                    command->setAttribute(“Condition”, “’$(Platform)’==‘x64’”);
  •                    outputs->setAttribute(“Condition”, “’$(Platform)’==‘x64’”);
  •                    excluded->setAttribute(“Condition”, “’$(Platform)’==‘Win32’”);
  •                }
  •                else
  •                {
  •                    command->addTextElement (""(VSInstallDir)VC\\bin\\ml\" /c /Zi /Sa \"/Fl(IntDir)%(Filename).lst" “/Fo$(IntDir)%(Filename).obj” “%(FullPath)”");
  •                    command->setAttribute(“Condition”, “’$(Platform)’==‘Win32’”);
  •                    outputs->setAttribute(“Condition”, “’$(Platform)’==‘Win32’”);
  •                    excluded->setAttribute(“Condition”, “’$(Platform)’==‘x64’”);
  •                }
  •            }
                 else if (! path.hasFileExtension (objCFileExtensions))
                     otherFiles.createNewChildElement (“None”)->setAttribute (“Include”, path.toWindowsStyle());

It's a bit tricky as it needs to enable and disable assembling for different arch, i'm now using filename suffix 32/64 (for example myfile32.asm will compile only on 32bit and myfile64.asm will compile on 64bit) as there is no way in ProjectExporter::addFilesToCompile to know if the file is allowed for one or both arch.

maybe in juce_module_info we could have also:

"compile": [
    { "file": "win32.asm", "target": "msvc", "platform": "x86" }, // compile for visual studio 32bit
    { "file": "linux64.asm",  "target": "linux", "platform": "x86_64" }, // compile for linux 64bit
    { "file": "generic.asm" }, // compile for any compiler any platform

what do you think ?

To have the file excluded from the build and then invoke masm as a tool seems a bit of a clunky way to do it.. Is that really what MSVC itself puts in the project file if you just add a .asm file to a project?

the file is not exluded from the build, is that it is not passed to cl.exe as that clunky cl does not know anything about asm.

the asm file needs to be passed to ml.exe (or ml64.exe depending on arch), and should be excluded from build when you are compiling the "other" arch.

it's the only way i found to make that clunky compiler actually assemble and link any piece of asm in the clunky visual studio...

try dragging an asm inside a plain visual studio project, automatically visual studio exlude it from the project, and if you enable building it, it's stupid enough to pass it to cl.exe and not ml.exe...

i'm on clunky VS2010, probably newer VS release handle this differently...

i have the other guys here all using 2010 so make them all upgrading is not viable solution actually, probably something todo at some point in future...


Well, what's all the importing of the masm.props stuff? I'd like to add something to make this work for you, but it all looks a bit creaky to me. Can you perhaps give me some changes that only add all this stuff in projects actually contain an asm file?

(BTW.. what on earth are you writing that needs asm files these days!? Can't you just use inline asm?)