Skip to content

Latest commit

 

History

History
396 lines (280 loc) · 15.5 KB

CONTRIBUTING.md

File metadata and controls

396 lines (280 loc) · 15.5 KB

Contributing to Zeno

👍🎉 First off, thanks for taking the time to contribute! 🎉👍

Contributions to Zeno are always welcome. Contributions can take many forms, such as:

  • Raising, responding to, or reacting to Issues or Pull Requests
  • Testing new in-progress changes and providing feedback
  • Discussing in our GitHub discussion channel
  • etc.

Both Chinese and English are supported! Feel free to express your idea in your favorable language!

Issues

If you have

  • found a bug in Zeno and would like to report (bug report)
  • a cool feature you'd like to have in Zeno (feature request)
  • any question on how to use Zeno (question)

Please check out this page for raising GitHub issues!

Make sure you choose the right issue template accordingly to your issue type, like Bug Report. Please take some time to fill the template completely, this help us understand your problem easier. Therefore you get a better answer, faster, thanks for your support!

Usage Tips

The GitHub issue tracker is for bug reports and features requests for the Zeno project, and on-topic comments and follow-ups to them. It is not for general discussion, general support or for any other purpose.

Issue titles are important. It's not usually helpful to write a title like bug report or issue with Zeno or even pasting an error message. Spend a minute to come up with a consise summary of the problem. This helps with management of issues, with triage, and above all with searching.

Attach the console output

For bug reports, the console output is very helpful to us, make sure you attach it if possible.

Hint: you may use triple back quotes to insert pretty-shown code (for console output) like this:

```

This is the Zeno log...

[ERROR] file not found: foo.txt

```

After submit the issue, it would be displayed as:

This is the Zeno log...
[ERROR] file not found: foo.txt

Reproduce your issue with the minimal graph

Many problems can be caused by unexpected configuration or other node combinations. A too complicated graph in bug report can make us hard to figure out the real problem.

Therefore when raising an issue, you must attempt to reproduce your issue with the minimal graph provided, and to provide any additional changes required to that graph in order to reproduce it. The purpose of this is to ensure that the issue is not a mistake in another node, or a problem unique to your configuration.

If your issue does not reproduce with the minimal graph, then you must say so in the issue report.

Fill the issue template

But above all else, please please complete the issue template. I know it is a little tedious to get all the various diagnostics, but you must provide them, even if you think they are irrelevant. This is important, because the maintainer(s) can quickly cross-check theories by inspecting the provided diagnostics without having to spend time asking for them, and waiting for the response. This means you get a better answer, faster. So it's worth it, honestly.

Searching for similar issues

Please search the issue tracker for similar issues before creating a new one. There's no point in duplication; if an existing open issue addresses your problem, please comment there instead of creating a duplicate. However, if the issue you found is closed as resolved (e.g. with a PR or the original user's problem was resolved), raise a new issue, because you've found a new problem. Reference the original issue if you think that's useful information.

Closed issues which have been inactive for 60 days will be locked, this helps to keep discussions focussed. If you believe you are still experiencing an issue which has been closed, please raise a new issue, completing the issue template.

If you do find a similar open issue, don't just post 'me too' or similar responses. This almost never helps resolve the issue, and just causes noise for the maintainers. Only post if it will aid the maintainers in solving the issue; if there are existing diagnostics requested in the thread, perform them and post the results.

Conclusion

Please do not be offended if your Issue or comment is closed or hidden, for any of the following reasons:

  • The issue template was not completed
  • The issue or comment is off-topic
  • The issue does not represent a Zeno bug or feature request
  • The issue cannot be reasonably reproduced using the minimal graph
  • The issue is a duplicate of an existing issue
  • etc.

Discussions

If you feel issues being too formal, check out our GitHub discussion channel for discussing problems in Q&A style interactively.

Pull Requests

Zeno is open to all contributors with ideas great and small! However, there is a limit to the intended scope of the plugin and the amount of time the maintainer has to support and... well... maintain features. It's probably well understood that the contributor's input typically ends when a PR is megred, but the maintainers have to keep it working forever.

Small changes

For bug fixes, documentation changes, gadget versin updates, etc. please just send a PR, I'm super happy to merge these!

If you are unsure, or looking for some pointers, feel free to ask in Gitter, or mention is in the PR.

Larger changes

For larger features that might be in any way controvertial, or increase the complexity of the overall plugin, please and talk to the maintainer(s) via GitHub discussions first. This saves a lot of potential back-and-forth and makes sure that we're "on the same page" about the idea and the ongoing maintenance.

In addition, if you like hacking, feel free to raise a PR tagged with [RFC] in the title and we can discuss the idea. I still prefer to discuss these things on Gitter rather than back-and-forth on GitHub, though.

Please don't be offended if the maintainer(s) request significant rework for (or perhaps even dismiss) a PR that's not gone through this process.

Please also don't be offended if the maintainer(s) ask if you're willing to provide ongoing support for the feature. As an OSS project manned entirely in what little spare time the maintainer(s) have, we're always looking for contributions and contributors who will help with support and maintenance of larger new features.

PR Guidelines

When contributing pull requests for Zeno, I ask that:

  • You provide a clear and complete summary of the change, the use case and how the change was tested either manually or automatically.
  • You follow the style of the code as-is; ref: Google C Style Guide.
  • Your changes worked on both Linux and Windows (GitHub CI will automatically check this).
  • Referencing to the issue number this PR is related to (if any).

Coding

Many people is using Zeno, if you find your wanted feature is missing, and you know how to implement it technically. Please help us improve by submitting your code to us (so called contribute), so that other people could also enjoy this cool feature you made!

Contributions to codebase can be a one-line BUG fix, a new example graph, or even a README improvement, up to a brand new simulation algorithm. We're very happy to see people utilizing Zeno and having fun in both using it and coding it!

How to play with Git

Get Zeno Source Code

Before start, we need to clone the source code of Zeno locally to your disk, to do so, you need Git.

After installing it, type the following command to cmd or bash:

git clone https://github.com/zenustech/zeno.git --depth=1
cd zeno

If you find GitHub too slow to download, you may clone from Gitee first (we will switch back to GitHub for creating PRs later):

git clone https://gitee.com/zenustech/zeno.git
cd zeno

Create your own Fork

Wait, before you start to modifying the source code to implement your cool feature, please create your own 'fork' of Zeno on GitHub. To do so, just click the 'Fork' button on the right-top of Zeno project main page.

After a few seconds, you will have something like https://github.com/YOUR_NAME/zeno, where YOUR_NAME is your user name. Congrats! You've successfully created your own fork of Zeno! Now you can edit it's source code freely.

Now, let's get into the source code you just cloned, and set upstream of it to your own fork (so that you can push to it):

git remote set-url https://github.com/YOUR_NAME/zeno.git

Don't forget to replace the YOUR_NAME to your user name :)

Start Coding

Now you could start writting codes with your favorite editor and implement the feature, and possibly debug it. After everying thing is done, let's push the change to your own fork hosted on GitHub:

git add .
git commit -m "This is my cool feature description"
git push -u origin master

May also check out this post for Git tutorial.

Create Pull Request (PR)

After push succeed, please head to https://github.com/YOUR_NAME/zeno, and there should be a 'Compare and Pull Request' button show there. Click it, then click 'Create Pull Request', click again. The maintainers will see your work soon, they might have some talks with you, have fun! After the changes are approved, the PR will be merged into codebase, and your cool feature will be available in next release for all Zeno users!

How to build Zeno

Zeno is written in C , which means we need a C developing environment to start coding in Zeno.

We support MSVC 2019 or GCC 9 for compiler, and optionally install require packages via vcpkg.

Please check the BUILD.md for the complete build instructions of Zeno.

If you have trouble setting up developing environment, please let us help by opening an issue!

Folder structures

  • docs - documentations for Zeno developers and contributors.
  • misc - some random files and scripts used by CI.
  • projects - source code of Zeno extension modules.
  • ui - source code of Zeno editor UI (written in Qt5).
  • zeno - source code of Zeno node system core.
  • zenovis - source code of Zeno visualization system.
  • .github - GitHub workflow and template files.

Code Style

Zeno is based on C 17, you may assume all C 17 features to be available in coding.

We generally follows the Google C Style Guide, excepts a few differences:

  • We use T const &t instead of const T& t
  • We allow implicit conversions when used properly
  • We allow exceptions as we widely adopted smart pointers for exception-safety
  • We avoid using STL streams (std::cout and so on) -- use zeno::format and zeno::log_info instead
  • We don't add Copyright blah blah to codebase since we're programmers, not lawyers :)
  • We mainly use smallCamelCase for functions, underline_case for variables
  • We don't add trialling underscope like m_google_style_, we use m_zeno_style

Code style is not forced, we also won't format every code merged in to the repo.

But it would be great if you could follow them for others to understand your code better and review your PR faster.

For example, suppose this is the content of zeno/src/funcs/my_demo.cpp:

#include <zeno/funcs/my_demo.h>      // first of all, include the decleration header of this .cpp file
#include <vector>                    // secondly, system headers should use '<>' brackets
#include <memory>
#include <string>
#include <tbb/parallel_for_each.h>   // third-party library headers, link it in CMakeLists.txt before use
#include <zeno/utils/log.h>          // finally, project headers should also use '<>' for absolute pathing
#include <zeno/utils/format.h>

// never 'using namespace std', think about std::data, std::size, std::ref, std::ws, std::tm, std::next

namespace zeno {  // all our code should be wrapped with 'namespace zeno'

namespace myutils {   // '{' should always stay in same line, and namespaces does not indent

namespace {        // use an anonymous namespace for static functions

auto staticFunc(int arg) {   // this function is visible only to this file
    std::vector<int> arr;        // tab size is 4
    for (auto const &x: arr) {   // C  11 range-based for loop when possible
       zeno::log_info("{}", x);   // use zeno logger for printing
    }
    
    // ^^ may leave a blank line for logical separation
    tbb::parallel_for_each([&] (auto &x) {
        // tab size in lambda is also 4
        x = x * 2   arg;  // leave two spaces between operators like '=', '*', ' '
    });

    std::string expr = zeno::format("the answer is {}", 42);  // instead of fmt or std
    
    return x;
}

// 'class' instead of 'typename' for type argument
template <class Type>
void templateFunc(Type value) {
   using T = typename Type::value_type;   // perfer 'using' instead of 'typedef' for aliasing
}

#define ZENO_YOUR_USEFUL_MACRO 1   // macro names should have ZENO_ prefix to prevent name conflict

}   // end of anonymous namespace

std::shared_ptr<MyType> globalFunc(std::string const &arg) {   // this function is visible globally
   auto ret = staticFunc(arg);
   if (ret.size() > 42) {                      // have space between 'if' and '('
       return nullptr;
   }
   auto ptr = std::make_shared<MyType>();      // use smart pointers instead of naked new/delete
   // std::shared_ptr<MyType> ptr(new MyType); // DO NOT USE THIS, use make_shared/make_unique instead

   ptr->some_attr = std::move(ret);            // use std::move for optimal zero-copying
   return ptr;
}

}   // end of namespace myutils

Then this is the content of zeno/include/zeno/funcs/my_demo.h:

#pragma once     // always use '#pragma once' instead of '#ifndef' guards

#include <memory>
#include <string>

namespace zeno {

struct MyType {   // perfer 'struct' instead of 'class'
   int m_age{};   // zero-initialize the POD members for security
   std::string m_name;
};

namespace myutils {

// 'const' qualifer should be on the right-side of type 'std::string'
// '&' or '*' should be attached to the variable name 'arg'
std::shared_ptr<MyType> globalFunc(std::string const &arg);

}  // end of namespace myutils

}  // end of namespace zeno

Idendifier naming convensions example:

namespace awesomenamespace {

int g_awesomeGlobal = 233;

void awesomeFunction(float awesomeArgument);

struct AwesomeClass {
private:
    int m_awesomeMember = 0;
    static int g_awesomeStaticMember = 1;

public:
    template <class AwesomeTemplateArgument = void, int kAwesomeNumber = 42>
    void awesomeMethod(int awesomeArgument = 0) const {
        int awesomeLocal = m_awesomeMember;
        awesomeLocal *= g_awesomeStaticMember;
        awesomeLocal  = awesomeArgument;
        m_awesomeMember = awesomeLocal;
    }

    static int awesomeStaticMethod() {
        return g_awesomeStaticMember;
    }
};

#define AWESOME_MACRO 3.14f

static constexpr int kAwesomeConstant = 42;

enum {
    kAwesomeEnum,
};

}  // end of namespace awesomenamespace

}  // all our code should be wrapped with 'namespace zeno'

See also .clang-format for automated formatting rules.

Code of conduct

Please see code of conduct.