Giter VIP home page Giter VIP logo

oop's Introduction

OOP For C Language

oop is a static library, that allows the use of OOP in C language.

Download The Latest Release Of oop Here

  • For compiling with GNU's GCC, download oop-gcc.tar.gz.
  • For compiling with Microsoft's MSVC, download oop-msvc.zip.

Usage

Polymorphism

When creating a new class with the DEFINE_CLASS_H macro keyword, you actually polymorph the new class with the Object class.

Thus, every class you create, is polymorphed with Object.

NOTE 1 FOR DEVELOPERS ONLY

Every object is polymorphed with Legacy_Object (it is the most polymorhpic object in the library).

Dynamic Allocation

When you use Objects, you do not need to worry again about dynamic allocation (e.g. malloc, calloc...).

Objects allocate themselves (with calloc) in their constructor, and automatically destruct themselves (with free) after the main.

Although, in case you want to manually invoke the object's destructor (similarly to CPP's delete function) you may do so by invoking the DESTRUCT_OBJECT(objectToDestruct) macro.

NOTE 2 FOR DEVELOPERS ONLY

Every Object is composed of AutoDestructable, which handles the object to automatically be destructed after the main (see Legacy_AllocationTableList).

Contributing

See CONTRIBUTING.md

oop's People

Contributors

taljacob2 avatar

Watchers

 avatar

oop's Issues

Allow Old And Pedantic GCC Compiling

Let "c89" / "-Wpedantic" users be supported by oop.a:

  • change all line comments of (// ... ) to ( /* ... */ )
  • compile the oop.a library with the most restricted -Wpedantic ... and -std=c89

Reorder Release Directory / Zip For Linux And Windows

  • Linux should release the following oop folder:

    .
    ├── main.c
    └── oop
        ├── Atomic
        │   ├── Atomic.h
        │   ├── AtomicInteger.h
        ├── Object
        │   ├── AnonymousPointer.h
        │   ├── AutoDestructable.r
        │   ├── Bool.h
        │   ├── Concat.h
        │   ├── Destructable.r
        │   ├── InvocationStatus.r
        │   ├── Legacy_AllocationTable.r
        │   ├── Legacy_AllocationTableList.r
        │   ├── Legacy_AtomicFreer.r
        │   ├── Legacy_List.r
        │   ├── Legacy_MemberList.r
        │   ├── Legacy_Node.r
        │   ├── Legacy_Object.r
        │   ├── Legacy_ObjectComponent.r
        │   ├── Legacy_StringObjectContainerEntry.r
        │   ├── MemberList.r
        │   ├── Object.a
        │   ├── Object.h
        │   ├── Object.r
        │   ├── ObjectDefines.r
        │   ├── Quote.h
        ├── oop.a
        └── oop.h
    

    And an example main.c should look like so:

    #include "oop/oop.h"
    
    #include <stdio.h>
    
    int main() {
        printf("Hello World\n");
    
        Object* object = ObjectConstructor("Object");
        object->addIntegerRValueMember(object, PUBLIC, FIELD, "x", 121681);
        object->toString(object);
    
        return 0;
    }

    P.S. Maybe support oop32.a.

  • Windows should release the following oop folder:

    .
    ├── main.c
    └── oop
        ├── Atomic
        │   ├── Atomic.h
        │   ├── AtomicInteger.h
        ├── Object
        │   ├── AnonymousPointer.h
        │   ├── AutoDestructable.r
        │   ├── Bool.h
        │   ├── Concat.h
        │   ├── Destructable.r
        │   ├── InvocationStatus.r
        │   ├── Legacy_AllocationTable.r
        │   ├── Legacy_AllocationTableList.r
        │   ├── Legacy_AtomicFreer.r
        │   ├── Legacy_List.r
        │   ├── Legacy_MemberList.r
        │   ├── Legacy_Node.r
        │   ├── Legacy_Object.r
        │   ├── Legacy_ObjectComponent.r
        │   ├── Legacy_StringObjectContainerEntry.r
        │   ├── MemberList.r
        │   ├── Object.a
        │   ├── Object.h
        │   ├── Object.r
        │   ├── ObjectDefines.r
        │   ├── Quote.h
        ├── oop.lib
        ├── oop32.lib
        └── oop.h
    

    And an example main.c should look like so:

    #pragma comment(lib, "oop/oop.lib")
    #include "oop/oop.h"
    
    #include <stdio.h>
    
    int main() {
        printf("Hello World\n");
    
        Object* object = ObjectConstructor("Object");
        object->addIntegerRValueMember(object, PUBLIC, FIELD, "x", 121681);
        object->toString(object);
    
        return 0;
    }

    NOTE: The #pragma comment(lib, "oop/oop.lib") line is mandatory and allows the import of oop/oop.lib.

    Real solution example

    oop-windows-test
    ├── Debug
    │   └── .
    ├── Release
    ├── oop-windows-test
    │   ├── Debug
    │   │   .
    │   │   
    │   ├── Release
    │   │   .
    │   │   
    │   ├── main.c
    │   ├── oop
    │   │   ├── AnonymousObject
    │   │   │   ├── AnonymousObject.h
    │   │   │   ├── AnonymousObject.r
    │   │   │   └── BitDefines.r
    │   │   ├── Atomic
    │   │   │   ├── Atomic.h
    │   │   │   ├── AtomicDoubleRValue.h
    │   │   │   ├── AtomicInteger.h
    │   │   │   ├── AtomicIntegerRValue.h
    │   │   │   ├── AtomicLValue.h
    │   │   │   ├── Func.h
    │   │   │   ├── LValueDefines.h
    │   │   │   ├── RValueDefines.h
    │   │   │   └── Random.r
    │   │   ├── Object
    │   │   │   ├── AnonymousPointer.r
    │   │   │   ├── AutoDestructable.r
    │   │   │   ├── Bool.h
    │   │   │   ├── Concat.h
    │   │   │   ├── Destructable.r
    │   │   │   ├── InvocationStatus.r
    │   │   │   ├── Legacy_AllocationTable.r
    │   │   │   ├── Legacy_AllocationTableList.r
    │   │   │   ├── Legacy_AtomicFreer.r
    │   │   │   ├── Legacy_List.r
    │   │   │   ├── Legacy_MemberList.r
    │   │   │   ├── Legacy_Node.r
    │   │   │   ├── Legacy_Object.r
    │   │   │   ├── Legacy_ObjectComponent.r
    │   │   │   ├── Legacy_StringObjectContainerEntry.r
    │   │   │   ├── Object.h
    │   │   │   ├── Object.r
    │   │   │   ├── ObjectDefines.r
    │   │   │   └── Quote.h
    │   │   ├── oop.h
    │   │   ├── oop.lib
    │   │   └── oop32.lib
    │   ├── oop-windows-test.vcxproj
    │   ├── oop-windows-test.vcxproj.filters
    │   ├── oop-windows-test.vcxproj.user
    │   └── x64
    │       ├── Debug
    │       │   .
    │       │   
    │       └── Release
    │           .
    │           
    ├── oop-windows-test.sln
    └── x64
        ├ .
        .
    

Allow the user to implement the `CircleConstructor()` so he could add his own fields / methods he wishes

For CircleConstructor():

Allow the user to implement the CircleConstructor():
where in the README.md you specify he MUST use the following syntax to do so:

  • The constructor should have the following template name: <CLASS_NAME>Constructor.
  • In the body of CircleConstructor(): Run the line ObjectConstructor() first.

For example:

In Circle.c:

#include "Circle.h"

DEFINE_CLASS_C(Circle)

Circle *CircleConstructor() { /* `<CLASS_NAME>Constructor` is the MUST syntax for creating a constructor */
    Circle *instance = (Circle *) ObjectConstructor("Circle"); /* MUST LINE */
    instance->addPrivateField("radius", AtomicFloat(1.434));

    /* Add more "fields" / "methods" as you wish here ... */

    return instance;
}

Rename `construct` And `desturct` In `Object`

  • In Object.c And Object.r Rename construct to ObjectConstructor
  • In Object.c And Object.r Rename destruct to ObjectDestructor

Once you do it, remember to rename them too in ObjectDefines.r

Edit `README.md` Dynamic Allocation Section

in README.md:
in Dynamic Allocation section:

  • tell the user that he can also destruct the object implicitly by himself if he
    wants to destruct immediately.

  • (NOT SURE ABOUT THIS) (DEPENDS ON #3) Also, tell him that every object is "multiple free safe": so he could destruct
    multiple times the same object and it won't crash.

Fix `getImplmentation` Methods

In Object.c
Fix getImplementation Methods:

Do not EVER use concat and then free the returned conatted string.
This will cause the memberName to be freed from memory, and then you would not be able to search for the member within the Object.

Instead of using concat, you should use a const string as a memberName.
For example:

  • a "literal" const char * string
  • a #define macro that its value is a const string.

image

Fix `Object` Destructor

Tracked by branch feature-atomic-multiple-object-fields-fix-object-destructor


  • Add AutoDestructor To Object
  • Investigate and fix: why when invoking destruct the Object gets deleted twice.
  • Why when the AutoDestructor occurs, then the Object doesn't get deleted entirely.

Support `oop` Compilation For 32bit With GCC And MSVC

  • For MSVC:

    • Edit build-lib.bat to compile with 32bit.
    • Edit release-msvc.bat:
      • Add oop32.lib to the final archive.
  • For GCC:

    • Edit build-lib.sh to compile with 32bit.
    • Edit release-gcc.sh:
      • Add oop32.a to the final archive.

Remove `Constructable` Interface

Because we didn't use the constructor of Constructable in any way during building the objects in the project, we may consider to delete the Constructable interface entirely from the project, and delete all the assignments to it in the constructors.

For example:

Redundant Code:
image

Redundant Code:
image

typedef AUTO / VAR

Maybe (!), at the end of the milestone, add

typedef Object AUTO;

or

typedef Object VAR;

`Legacy_List` Delete In Reversed Order

ATTENTION (START WORKING ON THIS ISSUE ONLY IF THIS MAY SOLVE #22). ELSE, YOU MAY CLOSE THIS ISSUE.

UPDATE: This issue was found to be essential for solving #22. See #24 (comment)

In Legacy_List

  • Implement "delete from list in reversed order", with a prev pointer. (double linked list)
  • Modify ALL implementations of delete in the project, to be the "delete in reversed order" implementation, instead of the ordinary "delete in straight order".
    DONE, EXCEPT OF AllocationTableList Destructor implementation

That means, modify the Legacy_ListDestructorWithInvokingDeconstructorOfEachNodeData to be in reversed order.

Replace `AutoDestructableConstructor` That Has The 2 Parameters Of `(Legacy_Object *, const char *)` With Only The `(Legacy_Object*)` Parameter

When using AutoDestructable,

Replace:

instance->autoDestructable = AutoDestructableConstructorWithClassName(
        (Legacy_Object *) instance,
        instance->legacyObjectComponent->CLASS_NAME);

With

instance->autoDestructable = AutoDestructableConstructorWithClassName(
        (Legacy_Object *) instance);

And the CLASS_NAME will be defined automatically via instance->legacyObjectComponent->CLASS_NAME.

in case instance == NULL, then CLASS_NAME is AutoDestructable.


  • That means, that maybe we can entirely replace the AutoDestructableConstructor that has the parameters (Legacy_Object *, const char *) with only the (Legacy_Object*) parameter.
    • And that means, we need to modify the addImplementationThatIsConstructedWithLegacy_ObjectAsParameter method in Object.c / Object.r to receive a constructor that gets only one parameter of (Legacy_Object *).

Explicit Casting `calloc` Return Value

When doing a calloc in a constructor:

For example:

Object *instance = calloc(1, sizeof *instance);

Make the casting explicit (so it would be 100% supported by other compilers):

Object *instance = (Object *) calloc(1, sizeof *instance);

Do this for ALL the objects in the project.

Construct Inline `FunctionalInterface`

(DEPENDS ON #18)

Once you can create an AnonymousObject via ConstructAnonymousObject (the empty constructor of AnonymousObject):

Create new .h / .c files for a new class that would be called AnonymousFunctionalInterface:

so in AnonymousFunctionalInterface.c:

Make a constructor to it, that its name will be:
ConstructorAnonymousFunctionalInterface

And the content would be:

#define __FUNCITONAL_INTERFACE_METHOD_NAME__ "FunctionalInterfaceMethodName"

Object *ConstructorAnonymousFunctionalInterface(methodImplementationHere){
  Object *anonymousObject = ConstructorAnonymousObject();
  anonymousObject->addMethod(__FUNCITONAL_INTERFACE_METHOD_NAME__ , methodImplementationHere);
  return instance;
}

And then use it like so:

int plusTest(int num1) {
  return ++num1;
}
Object *anonymousFunctionalInterface = ConstructorAnonymousFunctionalInterface(&plusTest);

SUGGESTION

or insert the method's address as an inline-function: (NEED TO THINK ABOUT HOW TO DO THIS):

#ifndef FUNCTION_TYPE 
#define FUNCTION_TYPE int (*)(int)

int (*plusTestPointer)(int) plusTest = malloc(FUNCTION_TYPE);
plusTestPointer = &plusTest;
Object *anonymousFunctionalInterface = ConstructorAnonymousFunctionalInterface(plusTestPointer);
free(plusTestPointer);

return anonymousFunctionalInterface;

#undef FUNCTION_TYPE

Make Lambda Functions

Lambda Function In C

StackOverflow Answer

code example


// Creates a lambda.
// Usage:
//     LAMBDA(return_type)(params)(body)
// Example:
//     ptr = LAMBDA(int)(int x, int y)(return x + y;);
#define LAMBDA LAM_LAMBDA

// Defines a function.
// Usage:
//     FUNC(return_type)(name)(params)(body)
// Example:
//     FUNC(int)(foo)(int x, int y)(return x + y;)
//     some_func(foo);
#define FUNC LAM_FUNC

// Any time a `LAMBDA` or `FUNC` appears inside of parentheses,
//   those parentheses must be preceeded by this macro.
// For example, this is wrong:
//     foo(LAMBDA(int)()(return 42;));
// While this works:
//     foo L_(LAMBDA(int)()(return 42;));
#define L_ LAM_NEST

// `LAMBDA` and `FUNC` only work inside `ENABLE_LAMBDAS(...)`.
// `ENABLE_LAMBDAS(...)` expands to `...`, preceeded by function definitions for all the lambdas.
#define ENABLE_LAMBDAS LAM_ENABLE_LAMBDAS

// Lambda names are composed of this prefix and a numeric ID.
#ifndef LAM_PREFIX
#define LAM_PREFIX LambdaFunc_
#endif

// Implementation details:

// Returns nothing.
#define LAM_NULL(...)
// Identity macro.
#define LAM_IDENTITY(...) __VA_ARGS__
// Concats two arguments.
#define LAM_CAT(x, y) LAM_CAT_(x, y)
#define LAM_CAT_(x, y) x##y
// Given `(x)y`, returns `x`.
#define LAM_PAR(...) LAM_PAR_ __VA_ARGS__ )
#define LAM_PAR_(...) __VA_ARGS__ LAM_NULL(
// Given `(x)y`, returns `y`.
#define LAM_NO_PAR(...) LAM_NULL __VA_ARGS__
// Expands `...` and concats it with `_END`.
#define LAM_END(...) LAM_END_(__VA_ARGS__)
#define LAM_END_(...) __VA_ARGS__##_END

// A generic macro to define functions and lambdas.
// Usage: `LAM_DEFINE(wrap, ret)(name)(params)(body)`.
// In the encloding code, expands to `wrap(name)`.
#define LAM_DEFINE(wrap, ...) )(l,wrap,(__VA_ARGS__),LAM_DEFINE_0
#define LAM_DEFINE_0(name) name,LAM_DEFINE_1
#define LAM_DEFINE_1(...) (__VA_ARGS__),LAM_DEFINE_2
#define LAM_DEFINE_2(...) __VA_ARGS__)(c,

// Creates a lambda.
// Usage: `LAM_LAMBDA(ret)(params)(body)`.
#define LAM_LAMBDA(...) LAM_DEFINE(LAM_IDENTITY, __VA_ARGS__)(LAM_CAT(LAM_PREFIX, __COUNTER__))
// Defines a function.
// Usage: `LAM_FUNC(ret)(name)(params)(body)`.
#define LAM_FUNC(...) LAM_DEFINE(LAM_NULL, __VA_ARGS__)

// `LAM_LAMBDA` and `LAM_FUNC` only work inside of this macro.
#define LAM_ENABLE_LAMBDAS(...) \
    LAM_END( LAM_GEN_LAMBDAS_A (c,__VA_ARGS__) ) \
    LAM_END( LAM_GEN_CODE_A (c,__VA_ARGS__) )

// Processes lambdas and functions in the following parentheses.
#define LAM_NEST(...) )(open,)(c,__VA_ARGS__)(close,)(c,

// A loop. Returns the original code, with lambdas replaced with corresponding function names.
#define LAM_GEN_CODE_A(...) LAM_GEN_CODE_BODY(__VA_ARGS__) LAM_GEN_CODE_B
#define LAM_GEN_CODE_B(...) LAM_GEN_CODE_BODY(__VA_ARGS__) LAM_GEN_CODE_A
#define LAM_GEN_CODE_A_END
#define LAM_GEN_CODE_B_END
#define LAM_GEN_CODE_BODY(type, ...) LAM_CAT(LAM_GEN_CODE_BODY_, type)(__VA_ARGS__)
#define LAM_GEN_CODE_BODY_c(...) __VA_ARGS__
#define LAM_GEN_CODE_BODY_l(wrap, ret, name, ...) wrap(name)
#define LAM_GEN_CODE_BODY_open() (
#define LAM_GEN_CODE_BODY_close() )

// A loop. Generates lambda definitions, discarding all other code.
#define LAM_GEN_LAMBDAS_A(...) LAM_GEN_LAMBDAS_BODY(__VA_ARGS__) LAM_GEN_LAMBDAS_B
#define LAM_GEN_LAMBDAS_B(...) LAM_GEN_LAMBDAS_BODY(__VA_ARGS__) LAM_GEN_LAMBDAS_A
#define LAM_GEN_LAMBDAS_A_END
#define LAM_GEN_LAMBDAS_B_END
#define LAM_GEN_LAMBDAS_BODY(type, ...) LAM_CAT(LAM_GEN_LAMBDAS_BODY_, type)(__VA_ARGS__)
#define LAM_GEN_LAMBDAS_BODY_c(...)
#define LAM_GEN_LAMBDAS_BODY_l(wrap, ret, name, par, ...) static LAM_IDENTITY ret name par { __VA_ARGS__ }
#define LAM_GEN_LAMBDAS_BODY_open()
#define LAM_GEN_LAMBDAS_BODY_close()



#include <stdio.h>
#include <stdlib.h>

ENABLE_LAMBDAS(

void example1()
{
    int arr[] = {4,1,3,2,5};

    FUNC(int)(compare)(const void *a, const void *b)
    (
        return *(int*)a - *(int*)b;
    )
    qsort(arr, 5, sizeof(int), compare);

    for (int i = 0; i < 5; i++ )
        printf("%d ", arr[i]);
    putchar('\n');
}

void example2()
{
    int arr[] = {4,1,3,2,5};

    qsort L_(arr, 5, sizeof(int), LAMBDA(int)(const void *a, const void *b)
    (
        return *(int*)a - *(int*)b;
    ));

    for (int i = 0; i < 5; i++ )
        printf("%d ", arr[i]);
    putchar('\n');
}

int main()
{
    example1();
    example2();
}

) // ENABLE_LAMBDAS

Add `setMember` Methods to `Object`

  • Add setMemberValue
  • Add setIntegerRValueMember
  • Add setDoubleRValueMember

so by a given memberName (that is given in a parameter), the method will get the correct member, and set it with another member (that is given in a parameter).


BENEFITS

Especially for setIntegerRValueMember and setDoubleRValueMember

This way, for example, you could edit RValue members, instead of them being const literals.

Show `MemberList` From `Object`

show the MemberList field pointer in Object (so it won't be anonymous
anymore) -----> so you need to edit in ObjectDefines.r:

#define OBJECT_FIELDS \
    ANONYMOUS_POINTER_AS_FIELD; \
    MemberList *memberList;

Define `OBJECT_FIELDS`

In ObjectDefines.r:

#define _OBJECT_FIELDS_ (bitfield that contains *Legacy_Object and *Object)

and include in every future Object

Edit `AllocationTableList` To Have One `AllocationTable` That Deletes In Reversed Order

Continuing from tag v1.1.7.5-fix-autodestructable-invocation:

Continuing from tag v1.1.7.6-reorder-object-destruct:

  • We now must invoke destructors in the AllocationTableList in reversed order,
    so it will be recursive destructing. (That means we need to start working on #24 as suspected)
    Doing this task will Close #24.

  • That means we must NOT sort the destructors by CLASS_NAME, and we need to have only one generic AllocationTable in the AllocationTableList (!!!).

    • And that means, we may need AllocationTableList at all, and we could replace it with a single generic Singleton AllocationTable.
      Doing this task will Close #32.

Originally posted by @taljacob2 in #22 (comment)

Close #22

Add "public" `toString` Methods to `Object`

Add two "public" toString Methods to Object

  • toString(Object *self, enum MemberAccessModifier memberAccessModifier):
    that prints all members of Object with the given memberAccessModifier.

  • toString(Object *self, enum MemberType memberType):
    that prints all members of Object with the given memberType.

  • toStringAll(Object *self):
    that prints:

    • All METHODs of Object.
    • All CONSTRUCTORs of Object.
    • All DESTRUCTORs of Object.
    • All FIELDs of Object.

Rename Typo In `Legacy_List`

Rename:

in Legacy_List.r And Legacy_List.c:

Legacy_ListDestructorWithInvokingDeconstructorOfEachNodeData
To Legacy_ListDestructorWithInvokingDestructorOfEachNodeData

Reorder: Make `AutoDestructableDestructor` Private

  • Make AutoDestructableDestructor "private" in the AutoDestructable.c file only, (and remove it from AutoDestructable.h)
  • Change all the invocations of AutoDestructableDestructor to be with the Destrucatable->destructable->destructor interface.

Create AnonymousObject

Create AnonymousObject

that its "classname" is a generated number,

For example:

its .h file would be:
DEFINE_CLASS_H(ANONYMOUS_0)

and when creating another one it will generate the class:
DEFINE_CLASS_H(ANONYMOUS_1)

and when creating another one it will generate the class:
DEFINE_CLASS_H(ANONYMOUS_2)

and so on ...

so the user could create it inline:

Object *anonymousObject = ConstructorAnonymousObject();

Rename All Functions In The Whole Project To Have Their Related Object's `CLASS_NAME` Concatted To It

Rename All Functions In The Whole Project To Have Their Related Object's CLASS_NAME Concatted To It

In the whole project, make sure, that the functions in its .r .h .c files are have the actual CLASS_NAME of the object concatted to the function's name, so the function's name will surely be unique across compilation of all files.

Examples:

  • in the object AtomicIntegerRValue:

    In AtomicIntegerRValue.c:
    we have a function that its name is getData.
    So me MUST make sure to rename it to getData_AtomicIntegerRValue.

  • in the object Legacy_MemberList:

    In Legacy_MemberList.c:
    we have a function that its name is getMemberByName.
    So me MUST make sure to rename it to getMemberByName_Legacy_MemberList.

Create a generic constructor

if you make all methods in MemberList, then the sizeof every future Object
will be the same (and will be sizeof(Object)),

and then you could dynamically allocate Object with a constant size,

so you could make a generic constructor that is:

Object *Constructor("className"){

    // ...
    Object *instance = calloc(1, sizeof(Object));
    // ...

}

Update `README.md` With `push-release.bat` And `release.bat`

Doc how to use release.bat and push-release.bat, and how they work.

  • inform that you must have wsl on both of them,
  • and for push-release.bat to work, you should install jq on the wsl bash, via:
    sudo apt install jq
    
  • inform that you can push-release.bat help for more help about the script.

Free Safely

Do this for every legacyObjectComponent:

for safety if you have a pointer to the legacyObjectComponent and could possibly free more than once.

void *Legacy_AtomicFreerDestructor(Legacy_AtomicFreer *atomicFreer) {
    if (atomicFreer == NULL) { return NULL; }

    if (atomicFreer->legacyObjectComponent->destructorInvocationStatus == WAS_NOT_INVOKED) {
        atomicFreer->legacyObjectComponent->destructorInvocationStatus = WAS_INVOKED_ONCE;
        free(atomicFreer->data);

        free(atomicFreer->legacyObjectComponent);

        free(atomicFreer);
    }

    return NULL;
}

Need to check

maybe this is not possible because after the free there should be still atomicFreer->legacyObjectComponent->destructorInvocationStatus allocated. So that means there should be still at least 1 byte allocated, to preserve the "free safely"-lock.

Rename `ObjectContainer` To `Object`

  • rename MemberList to Legacy_MemberList

  • rename Object to MemberList

  • rename ObjectContainer to Object

  • and rename OBJECT_CONTAINER_FIELDS to OBJECT_FIELDS

  • rename Legacy_Object to Legacy_ObjectComponent

  • rename Legacy_ObjectContainer to Legacy_Object


  • Then reformat-code of all project.

Include header files in release

when you release the library, you must include ALL the .h (and .r) files.

So when you release: you MUST "zip" the whole "src/oop" folder, so it would the
.h / .r files and oop.a.


See this reference that was in an old commit of release.yml.

name: Upload Release Asset

on:
  push:
    # Sequence of patterns matched against refs/tags
    tags:
      - '*-release'

jobs:
  build:
    name: Upload Release Asset
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
      - name: Build project # This would actually build your project, using zip for an example artifact
        run: |
          zip --junk-paths my-artifact README.md
      - name: Create Release
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.ref }}
          release_name: Release ${{ github.ref }}
          draft: false
          prerelease: false
      - name: Upload Release Asset
        id: upload-release-asset
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
          asset_path: ./my-artifact.zip
          asset_name: my-artifact.zip
          asset_content_type: application/zip

Image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.