1 Reply
      Latest reply: Jan 31, 2017 3:01 AM by eskimo RSS
      JoshKlint Level 1 Level 1 (0 points)

        I have a cross-platform C++ API I want to run on Linux, Windows, and Mac.  On Mac, it uses a main() function in Objective-C to initialize some stuff, and then calls the C++ main() function, which on Mac is renamed to main_() as follows:

        #ifdef __APPLE__
            int main_(int argc,const char *argv[])
        #else
            int main(int argc,const char *argv[])
        #endif
        {
        
        
        
        

        This is pretty ugly and I'd like to do away with it.  Is there any way to set the entry point to an Objective-C function that isn't named main(), or somehow make it so all our code examples don't have to have an ugly hack like this for Mac?


        I tried adding the link flag -emymain or -e_mymain and renaming my Objective-C main() function to mymain() but the linker says the function is not found for the architecture x86_64.

        • Re: Rename main() function?
          eskimo Apple Staff Apple Staff (6,075 points)

          The actual entry point to an executable is controlled by the LC_MAIN load command:

          $ otool -l build/Debug/MainTest | grep -A 3 LC_MAIN
                cmd LC_MAIN
            cmdsize 24
            entryoff 3872
          stacksize 0
          

          but that doesn’t point to main directly.  Rather, it points to start, which then calls mainstart comes from the ‘C runtime’ (aka crt), which is code that the build system links into your executable automatically.  You can find this within the platform SDK:

          $ nm /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/crt1.o
          …
                          U _main
          …
          0000000000000000 T start
          

          The reason why -e isn’t doing what you expect is pretty clear based on its description in ld:

          Specifies the entry point of a main executable.  By default the entry name is start which is found in crt1.o which contains the glue code need to set up and call main.

          You could certainly play linker games to resolve this issue but I don’t think that’s the best option.  You’re basically transferring the ugliness from the source code to the build system, and it seems likely that that will make things harder to understand.

          Does the Obj-C main need to ‘wrap’ the C++ ‘main’?  That is, both run before and after it?  Or does it just need to run first?  If it just needs to run first, the simplest solution would be something like this:

          int main(…) {
              PlatformMainStart();
              … do whatever your C++ `main` does …
          }
          

          and then define PlatformMainStart to do stuff on Apple platforms and be a no-op on other platforms.

          Share and Enjoy

          Quinn “The Eskimo!”
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"