Opened 9 years ago

Closed 9 years ago

#5025 closed feature request (fixed)

GHC should support -x objective-c

Reported by: guest Owned by:
Priority: high Milestone: 7.2.1
Component: Compiler Version: 7.0.2
Keywords: objective-c Cc: dagitj@…, as@…
Operating System: MacOS X Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


On OSX, gcc accepts .m files as objective-c source. It can even trivially compile .c and .m files in the same program or library.

Unfortunately, ghc treats .m files as input to the linker step. GHC supports -x as a means of saying what language a file is, except that unlike gcc it lacks support for "objective-c". For example, if I told ghc, -x c, then ghc would invoke gcc as gcc -x c and gcc would then treat as C source code.

Cabal gives all C files to ghc and lets ghc invoke gcc. This means that specifying objective-c files as "c-sources" results in GHC complaining about linker input. Even setting -pgmc is not sufficient to trick cabal. I spent several hours trying everything I could think of here to trick cabal, like setting my PATH and write wrapper scripts for gcc, but it seems that cabal always hands these files to ghc first.

Therefore, I propose that GHC adds support for -x objective-c foo.m. Even better would be for GHC to accept .m files on OSX without the extra -x flag. The new -x flag would be sufficient to write .cabal files that use objective-c to get access to OSX specific APIs, much like C can be used on other platforms.

I think even if cabal adds an "objective-c-sources" line in the .cabal file that the above solution is a nice-to-have for ghc. I also hope that it is super easy to implement, but I haven't looked at the ghc sources to see if that's the case.

Here is the relevant section of the gcc manpage

You can specify the input language explicitly with the -x option:

       -x language
           Specify explicitly the language for the following input files (rather than letting the compiler
           choose a default based on the file name suffix).  This option applies to all following input
           files until the next -x option.  Possible values for language are:

                   c  c-header  c-cpp-output
                   c++  c++-header  c++-cpp-output
                   objective-c  objective-c-header  objective-c-cpp-output
                   objective-c++ objective-c++-header objective-c++-cpp-output
                   assembler  assembler-with-cpp
                   f95  f95-cpp-input

       -x none
           Turn off any specification of a language, so that subsequent files are handled according to their
           file name suffixes (as they are if -x has not been used at all).

Having ghc support all of gcc -x flags would make me super happy! Unfortunately, I found that the order you pass -x to gcc matters (it must be passed before the corresponding input files are specified), and when I added "-optc-x -optcobjective-c" to the ghc commandline I found that it passed the -x flag too late.


Change History (10)

comment:1 Changed 9 years ago by simonmar

difficulty: Easy (less than 1 hour)
Milestone: 7.2.1
Priority: normalhigh

comment:2 Changed 9 years ago by igloo

A few of us discussed this on IRC. Should GHC really be trying to act as a compiler for .m files (and .c and .cpp files for that matter)? Wouldn't it make more sense to have Cabal support building files in other languages instead?

comment:3 Changed 9 years ago by guest

I was under the impression this is an easy change for GHC.

This would be a much harder change for Cabal as Cabal would have to figure out all the right flags to pass to GCC to match GHC.

It certainly raises the question, why does Cabal pass .c files to GHC? I think if you're going to pass .m files directly to gcc then .c files should be passed directly to gcc also so that things are built/handled consistently.

To get a feeling of how hard it would be to get Cabal to support this, see this ticket that is over 3 years old:

This would also be a nice feature for people who aren't using Cabal at all.

comment:4 Changed 9 years ago by duncan

Yes, Cabal should call gcc directly to compile .c files (and the appropriate compilers for other languages). Cabal knows enough to know what flags to pass (e.g. things inherited from package dependencies), it does not need to delegate this to ghc.

BTW, just because the ticket is 3 years old does not mean it is hard ;-).

Independent of whether we make Cabal do the right thing, there is a separate argument:

  • One view is that people using ghc and other compilers from the command line or makefiles should be using different compilers for different source languages because that's "the right thing to do".
  • allbery_b makes the claim that due to the way make works, and the builtin make rules, that it is more convenient in makefiles to have one compiler for multiple source languages than to "do the right thing" and get your makefiles to use the right compiler for the right language.

comment:5 Changed 9 years ago by guest


The ticket is marked hard and unsolved after 3 years. So, as an outsider to Cabal development, I assume it is actually hard :)

Additionally, as a GHC user, I have this perspective: Even if in the year 2023 using GHC 12.2.1 and Cabal 4.2, we no longer pass C/C++/Ada/Obj-C files to GHC and do something fundamentally better, it would still be nice to have this feature now under the assumption it is low maintenance as it fills a need we have today. It would greatly simplify the effort required to use Objective-C (and hence many native OSX apis) with cabal built packages. Right now a LOT of extra work is required and it's hard to reuse that work between packages.

comment:6 Changed 9 years ago by simonmar

This is an easy change to make to GHC, it doesn't do any harm, and it simplifies usage for some people. While Cabal should probably call gcc directly, that's a separate issue.

The reason GHC accepts .c files on the command line is so that the user doesn't have to remember where to find HsFFI.h, for example (indeed, they probably shouldn't have to know where to find HsFFI.h). Cabal also knows this and can pass the right flags to gcc, but often it's convenient to use GHC directly. The same applies to Obj-C.

comment:7 Changed 9 years ago by thoughtpolice

Cc: as@… added

I have a patch that will let GHC understand .m files and correctly give them to GCC with -x objective-c and so GHC can also compile standalone objective-C code. It creates a new stage in DriverPhases for the objective-c case, perhaps it should also be extended to support objective-c++?

These were darcs patches, but since then the git switchover has happened. They're pretty simple (maybe 10 lines,) so I'll move them over to git and post diffs shortly. I also need to write a patch for the testsuite.

comment:8 Changed 9 years ago by guest

That's wonderful news and I'm delighted to hear it was as easy as 10 lines!


comment:9 Changed 9 years ago by thoughtpolice

I have patches for GHC and the testsuite located in these github repositories at these branches:

Specifically, commits 9e27ad (ghc itself) and c4dbe4 (the testsuite.) These patches also teach the testsuite to compile objective-c source files.

You should be able to merge these easily into the GHC tree by pulling my branches and merging them to GHC's master branch. Is this sufficient, or should I attach a git send-email style patch instead?

comment:10 Changed 9 years ago by simonmar

Resolution: fixed
Status: newclosed

Committed, thanks!

Note: See TracTickets for help on using tickets.