Advertisement

Apple M1 processor MacOS

Started by July 15, 2022 10:21 PM
20 comments, last by WitchLord 2 years, 3 months ago

The 2.35.1 change notes indicate that David Carlier provided some changes to get M1 Mac support working.

I am trying to build my program for M1 and am having no end of problems. Does anyone have any experience with this? Does anyone know how David Carlier achieved success? Do we know if he was able to run the unit tests on M1?

I've fixed a few issues (all my changes on GitHub https://github.com/ramcdona/angelscript-mirror/tree/M1_Mac).​​ But I'm not entirely convinced they are all correct.

Once I get it to compile, test_performance bombs out with many errors like:

 (0, 0) : Error   : Failed in call to function 'RegisterGlobalFunction' with 'float Average(float, float)' (Code: asNOT_SUPPORTED, -7)
 (0, 0) : Error   : Invalid configuration. Verify the registered application interface.
 (0, 0) : Error   : Failed in call to function 'Prepare' with 'null' (Code: asNO_FUNCTION, -6)
 (0, 0) : Error   : Failed in call to function 'Execute' (Code: asCONTEXT_NOT_PREPARED, -4)
Execution didn't terminate with asEXECUTION_FINISHED

My ‘real’ program has similar problems.

Any help will be greatly appreciated.

Rob

Hi Rob,

yes, David provided some changes to make the library compile on M1 and with that it should be possible to use the generic calling convention with AS_MAX_PORTABILITY, though I don't know exactly what tests he ran. Support for native calling conventions is not yet available on M1, as that requires further code and assembler routines to work.

Unfortunately I do not have an environment to work on M1 myself, otherwise I would certainly give it a try to add this support. Since the support is already there for Linux with arm64, I believe the support for Mac M1 will take relatively small effort given the similarity in the CPU architecture and ABI.

test_performance has not been prepared for AS_MAX_PORTABILITY as the objective at the time was to test the performance with native calling conventions. That's why you see the errors asNOT_SUPPORTED when registering functions and methods.

I'll take a look at the changes you've made and include them for the next release. Thanks for sharing.

Regards,
Andreas

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement

@WitchLord Thanks much for the great tool and for the help.

My program is showing the same symptoms as test_performance – I suppose this is a sign that my program uses native calling conventions (it has only ever been built on x86 and x86-64).

From what I can tell, AngelScript is being built with AS_MAX_PORTABILITY as set by as_config.h. Do I need to tell my application to use it manually?

Here is a sample of the error I'm getting…

 (0, 0) : ERR  : Failed in call to function 'RegisterObjectBehaviour' with 'vec3d' and 'void f()' (Code: asNOT_SUPPORTED, -7)
 (0, 0) : ERR  : Failed in call to function 'RegisterObjectBehaviour' with 'vec3d' and 'void f(double, double, double)' (Code: asNOT_SUPPORTED, -7)
 (0, 0) : ERR  : Failed in call to function 'RegisterObjectBehaviour' with 'vec3d' and 'void f(const vec3d &in)' (Code: asNOT_SUPPORTED, -7)
 (0, 0) : ERR  : Failed in call to function 'RegisterObjectMethod' with 'vec3d' and 'double& opIndex(int) const' (Code: asNOT_SUPPORTED, -7)

Here is a sample of the code that is doing the registration – if I skip this, it has similar problems with the next bit of code, etc. I.e. this is pervasive for my program.

    //==== Register vec3d Object =====//
    int r = se->RegisterObjectType( "vec3d", sizeof( vec3d ), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CA );
    assert( r >= 0 );

    //==== Register the vec3d Constructors  ====//
    r = se->RegisterObjectBehaviour( "vec3d", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION( Vec3dDefaultConstructor ), asCALL_CDECL_OBJLAST );
    assert( r >= 0 );

    r = se->RegisterObjectBehaviour( "vec3d", asBEHAVE_CONSTRUCT, "void f(double, double, double)", asFUNCTION( Vec3dInitConstructor ), asCALL_CDECL_OBJLAST );
    assert( r >= 0 );

    r = se->RegisterObjectBehaviour( "vec3d", asBEHAVE_CONSTRUCT, "void f(const vec3d &in)", asFUNCTION( Vec3dCopyConstructor ), asCALL_CDECL_OBJLAST );
    assert( r >= 0 );

    //==== Register the vec3d Methods  ====//
    r = se->RegisterObjectMethod( "vec3d", "double& opIndex(int) const", asMETHODPR( vec3d, operator[], ( int ), double& ), asCALL_THISCALL );
    assert( r >= 0 );

Best,

Rob

Also, is there a better test I should try to get working on this machine? I first tried test_function, but I had a bunch of problems with it and did not get as far as I did with test_performance.

Rob

To use the generic calling convention you need to provide wrapper functions in C++ with the signature ‘void fund(asIScriptGeneric *)’ and then register these with asCALL_GENERIC instead of asCALL_CDECL, asCALL_THISCALL, etc.

Fortunately with the autowrappers add-on this isn't going to be a lot of work. For the most part it is just necessary to replace the macro used to get the address of the function or class method you're registering, e.g. use WRAP_FN instead of asFUNCTION, WRAP_FN_PR instead of asFUNCTIONPR, WRAP_MFN instead of asMETHOD, etc.

See the docs for autowrappers here: http://www.angelcode.com/angelscript/sdk/docs/manual/doc_addon_autowrap.html

ramcdona said:
Also, is there a better test I should try to get working on this machine? I first tried test_function, but I had a bunch of problems with it and did not get as far as I did with test_performance.

If you have an interest in trying to implement support for native calling conventions on M1, then the tests you want to start with are the ones in test_feature project. In the main function in main.cpp you'll find a block of functions designed for testing native calling conventions. It starts with the following piece of code:

	// The following tests are designed specifically to test the native calling conventions.
	// These are grouped by calling convention and ordered in increasing complexity.
	{
		// cdecl
		if( TestExecute()                 ) goto failed; else PRINTF("-- TestExecute passed\n");
		if( TestCDeclReturn::Test()       ) goto failed; else PRINTF("-- TestCDeclReturn passed\n");
		if( TestExecute1Arg()             ) goto failed; else PRINTF("-- TestExecute1Arg passed\n");

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Thanks for the tips. I will look into the wrapper generation. Hopefully there will be a clear way to keep my program cleanly cross-platform.

I am certainly interested in there existing native calling conventions on M1 – but I also must admit that I have no idea what it would take. I normally deal with engineering software – lots of numerical methods, Bezier surface math, aerodynamics, and other fun – but nothing bare metal like this.

I implementing native calling conventions for M1 would involve creating or modifying a small number of files – probably just one or two. Is there an AngelScript porting guide? Can you point me at a nearby example or the expected level of work?

Right now, test_function does not even compile for me. The first error I run into is this:

/AngelScript/sdk/add_on/datetime/datetime.cpp:277:89: error: no matching function for call to 'asFunctionPtr'
                r = engine->RegisterObjectMethod("datetime", "int64 opSub(const datetime &in) const", WRAP_MFN_PR(CDateTime, operator-, (const CDateTime &other) const, asINT64), asCALL_GENERIC); assert(r >= 0);
                                                                                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/AngelScript/sdk/add_on/datetime/../autowrapper/aswrappedcall.h:568:62: note: expanded from macro 'WRAP_MFN_PR'
#define WRAP_MFN_PR(ClassType, name, Parameters, ReturnType) asFUNCTION((::gw::Wrapper<ReturnType (ClassType::*)Parameters>::TMPL f< AS_METHOD_AMBIGUITY_CAST(ReturnType (ClassType::*)Parameters)(&ClassType::name) >))
                                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/AngelScript/sdk/tests/test_feature/projects/cmake/../../../../angelscript/include/angelscript.h:428:23: note: expanded from macro 'asFUNCTION'
#define asFUNCTION(f) asFunctionPtr(f)
                      ^~~~~~~~~~~~~
/AngelScript/sdk/tests/test_feature/projects/cmake/../../../../angelscript/include/angelscript.h:1222:19: note: candidate template ignored: couldn't infer template argument 'T'
inline asSFuncPtr asFunctionPtr(T func)
                  ^

Rob

Advertisement

My first attempt at using the wrappers is making some progress (working for asFUNCTION), but I'm having trouble with asMETHODPR…

/ScriptMgr.cpp:2203:74: error: no matching function for call to 'asFunctionPtr'
    r = se->RegisterObjectMethod( "vec3d", "double& opIndex(int) const", WRAP_MFN_PR( vec3d, operator[], ( int ), double& ), asCALL_GENERIC );
                                                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/angelscript/sdk/add_on/autowrapper/aswrappedcall.h:1542:62: note: expanded from macro 'WRAP_MFN_PR'
#define WRAP_MFN_PR(ClassType, name, Parameters, ReturnType) asFUNCTION((::gw::Wrapper<ReturnType (ClassType::*)Parameters>::TMPL f< AS_METHOD_AMBIGUITY_CAST(ReturnType (ClassType::*)Parameters)(&ClassType::name) >))
                                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/angelscript/sdk/angelscript/include/angelscript.h:424:23: note: expanded from macro 'asFUNCTION'
#define asFUNCTION(f) asFunctionPtr(f)
                      ^~~~~~~~~~~~~
/angelscript/sdk/angelscript/include/angelscript.h:1224:19: note: candidate template ignored: couldn't infer template argument 'T'
inline asSFuncPtr asFunctionPtr(T func)
                  ^

For the record, I went through and commented out all the RegisterObjectMethod's I used with WRAP_MFN_PR and was able to get my program to compile. So, it seems like this is the only problem I'm facing.

Here is a somewhat more generic example (a normal method instead of an operator).

/ScriptMgr.cpp:12661:98: error: no matching function for call to 'asFunctionPtr'
    r = se->RegisterGlobalFunction( "void Print(const string & in data, bool new_line = true )", WRAP_MFN_PR( ScriptMgrSingleton, Print, (const string &, bool), void ), asCALL_GENERIC, &ScriptMgr );
                                                                                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/angelscript/sdk/add_on/autowrapper/aswrappedcall.h:1743:62: note: expanded from macro 'WRAP_MFN_PR'
#define WRAP_MFN_PR(ClassType, name, Parameters, ReturnType) asFUNCTION((::gw::Wrapper<ReturnType (ClassType::*)Parameters>::TMPL f< AS_METHOD_AMBIGUITY_CAST(ReturnType (ClassType::*)Parameters)(&ClassType::name) >))
                                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/angelscript/sdk/angelscript/include/angelscript.h:424:23: note: expanded from macro 'asFUNCTION'
#define asFUNCTION(f) asFunctionPtr(f)
                      ^~~~~~~~~~~~~
/angelscript/sdk/angelscript/include/angelscript.h:1224:19: note: candidate template ignored: couldn't infer template argument 'T'
inline asSFuncPtr asFunctionPtr(T func)
                  ^

So, it is the same thing, but a slightly more simple case.

This looks like a slight incompatibility issue with the compiler you're using. Looks like your compiler is expecting a different syntax for evaluating the asFunctionPtr template function when using it with the auto wrapper templates.

What compiler and version are you using?

Can you try expanding the macro manually and identify the correct syntax accepted by your compiler?

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

I'm running XCode 13.4.1 - using the command line tools.

% /usr/bin/c++ --version
Apple clang version 13.1.6 (clang-1316.0.21.2.5)
Target: arm64-apple-darwin21.5.0

I'v expanded the macros manually, but so far it does not give me any insight, instead just a slightly more concise version of the same.

My code (with macros applied):

    r = se->RegisterGlobalFunction( "void Print(const string & in data, bool new_line = true )",
                                    asFunctionPtr(::gw::Wrapper<void (ScriptMgrSingleton::*)(const string &, bool)>::f< static_cast<void (ScriptMgrSingleton::*)(const string &, bool)>(&ScriptMgrSingleton::Print) >),
                                    asCALL_GENERIC, &ScriptMgr );

Corresponding error message:

/ScriptMgr.cpp:12664:37: error: no matching function for call to 'asFunctionPtr'
                                    asFunctionPtr(::gw::Wrapper<void (ScriptMgrSingleton::*)(const string &, bool)>::f< static_cast<void (ScriptMgrSingleton::*)(const string &, bool)>(&ScriptMgrSingleton::Print) >),
                                    ^~~~~~~~~~~~~
/angelscript/sdk/angelscript/include/angelscript.h:1224:19: note: candidate template ignored: couldn't infer template argument 'T'
inline asSFuncPtr asFunctionPtr(T func)
                  ^
1 error generated.

I also tried the ‘template’ substitution for TMPL

I also tried all of the variations of AS_METHOD_AMBIGUITY_CAST

None of those variations had any influence.

This topic is closed to new replies.

Advertisement