Giter Club home page Giter Club logo

zproject's Introduction

zproject - CLASS Project Generator

Contents

Overview

Tutorial

Installation

Getting started

API models

Language Binding Notes

Draft API Support

Removal

Additional files

Notes for Writing Targets

Notes for Writing Language Targets

Ownership and License

Overview

zproject is a community project, like most ZeroMQ projects, built using the C4.1 process, and licensed under MPL v2. It solves the Makefile problem really well. It is unashamedly for C, and more pointedly, for that modern C dialect we call CLASS. CLASS is the Minecraft of C: fun, easy, playful, mind-opening, and social. Read more about it hintjens#79.

zproject grew out of the work that has been done to automatically generate the build environment in CZMQ. It allows to share these automations with other projects like zyre, malamute or hydra and at the same time keep everything in sync.

Scope and Goals

zproject has these primary goals:

  • generate cross-platform build environments.
  • generate CLASS (ZeroMQ RFC/21) compliant header and source skeletons for new classes.
  • generate a public header file for your library so it can be easily included by others.
  • generate stubs for man page documentation which uses the comment based approach from CZMQ.

All you need is a project.xml file in the project's root directory which is your

One file to rule them all

At least the following build environments are currently supported:

  • Autotools
  • CMake
  • Mingw32
  • Android
  • iOS
  • Visual Studio

Thanks to the ZeroMQ community, you can do all the heavy lifting in C and then easily generate bindings in the following languages:

  • Delphi
  • Java (JNI)
  • Python
  • QML
  • Qt
  • Ruby

The language bindings are minimal, meant to be wrapped in a handwritten idiomatic layer later.

Tutorial

To understand step by step what zproject can do for you, read chapter 3 of @hintjens book Scalable C. Note that the book is still work in progress!

Installation

zproject uses the universal code generator called GSL to process its XML inputs and create its outputs. Before you start you'll need to install GSL (https://github.com/zeromq/gsl) on your system.

git clone https://github.com/zeromq/gsl.git
cd gsl/src
make
make install

GSL must be able to find the zproject resources on your system. Therefore you'll need to install them. The following will install the zproject files to /usr/local/bin.

git clone https://github.com/zeromq/zproject.git
cd zproject
./autogen.sh
./configure
make
make install

NB: You may need to use the sudo command when running make install to elevate your privileges, e.g.

sudo make install

NB: If you don't have superuser rights on a system you'll have to make sure zproject's gsl scripts can be found on your PATH.

Getting started

Setup your project environment

The easiest way to start is to create a minimal project.xml.

<project script = "zproject.gsl">
    <use project = "czmq" />
    <main name = "hello" private = "1" />
</project>

Once you're done you can create your project's build environment and start compiling:

gsl project.xml
autogen.sh
configure.sh
make

NB: To get a more comprehensive example copy zproject's project.xml. It contains all possible configurations and according documentation.

Licensing your project is important thus you'll need a license file. Here's an overview that might help you decide to choose a license. zproject allows you to add an appropriate disclaimer of your license as a xml file, e.g. license.xml:

<license>
    Your license disclaimer goes here!
</license>

This disclaimer can be included in your project.xml and is used whenever zproject is generating new files e.g. CLASS skeletons or bindings.

<include filename = "license.xml" />

Configuration

zproject's project.xml contains an extensive description of the available configuration: The following snippet is taken from the project.xml:

<!--
    The project.xml generates build environments for:

        autotools           GNU build system (default)
        cmake               CMake build system (default)

        android             Native shared library for Android
        cucumber            Integration with cucumber-c
        cygwin              Cygwin build system
        debian              packaging for Debian
        delphi              Delphi binding
        docker              packaging for Docker
        ios                 Native library for iOS
        java                Java JNI binding
        java-msvc           MSVC builds for Java JNI binding
        jenkins             Jenkins pipeline build
        mingw32             Mingw32 build system
        nuget               Packaging for NuGet
        python              Python binding
        qml                 QML binding
        qt                  Qt binding
        redhat              Packaging for RedHat
        ruby                Ruby binding
        gh_actions          Github Actions configuration (same options as travis)
        travis              Travis CI scripts
            <option name="dist" value="trusty" /> Select a Linux distribution to use by default on Travis CI, also impacts the OBS-served repository of ZMQ-family packages to use (if not building from source all the time per use_pkg_deps_prereqs_source below). By default it would be "xenial" as of now.
            <option name="distcheck" value="0" /> "0" will disable run of make distcheck in Travis CI, "2" will enable it as a special testcase allowed to fail (default: 1 to enable and require to pass)
            <option name="use_pkg_deps_prereqs_source" value="0" /> "0" will disable use of use_pkg_deps_prereqs_source list in Travis CI and so cause rebuild of everything from scratch (default: 1, recently packaged prereqs must exist then)
            <option name="use_cmake" value="0" /> "0" will disable use of CMake recipes in Travis CI (default: 1)
            <option name="require_gitignore" value="1" /> "1" will require that the workspace is clean with regard to .gitignore settings after build (default: 0)
            <option name="clangformat_allow_failures" value="0" /> "1" will generate the option allowing non-fatal failure of clang-format test in Travis CI (default: 1)
            <option name="clangformat_require_good" value="0" /> "1" will generate the option allowing to report and not ignore failure of clang-format test in Travis CI (otherwise "0" hides the failure, and devs must look in test logs) (default: same as allow_failures)
            <option name="clangformat_implem" value="cmake|autotools" /> will pick one of two implems of the clang-format test in Travis CI (cmake is default and faster if available, since autotools needs to configure first)
            <option name="check_abi_compliance" value="0" /> "1" will compare the currently tested commit's ABI to the one in a "latest_release" branch or tag, using packaged prerequisites. Due to these limitations, the option is off by default.
            <option name="check_zproject" value="0" /> "1" will regenerate the zproject of the tested commit, and will verify that nothing changed, "2" will enable it as a special testcase allowed to fail. Many projects do customize their originally generated codebase, so to avoid surprises this option is off by default.
            <option name="shadow_gcc" value="0" /> "1" will enable builds with warnings configured as fatal in additional recent versions of GCC, and "2" will make failures in these cases non-fatal so you can take time to modernize your code with modern best practices in mind. This is off "0" by default.
            <option name="shadow_clang" value="0" /> "1" will enable builds with warnings configured as fatal in additional recent versions of CLANG, and "2" will make failures in these cases non-fatal so you can take time to modernize your code with modern best practices in mind. This is off "0" by default.
        vs2008              Microsoft Visual Studio 2008
        vs2010              Microsoft Visual Studio 2010
        vs2012              Microsoft Visual Studio 2012
        vs2013              Microsoft Visual Studio 2013
        vs2015              Microsoft Visual Studio 2015

    Classes are automatically added to all build environments. Further as you
    add new classes to your project you can generate skeleton header and source
    files according to http://rfc.zeromq.org/spec:21.

    script := The gsl script to generate all the stuff !!! DO NOT CHANGE !!!
    name := The name of your project (optional)
    description := A short description for your project (optional)
    email := The email address where to reach you (optional)
    url := The website or similar resource about the project or its ecosystem (optional)
    repository := git repository holding project (optional)
    unique_class_name := "0"|"1" (optional, defaults to 0) As a failsafe, forbid naming agents or classes same as the project itself (can cause conflicts in generated header filenames). Disable explicitly (set to 0) only in legacy projects that can not regenerate otherwise, and try to fix those.
    license := optional common tag of the project's license ("MPLv2", "GPL-2.0+", "CompanyName Proprietary" etc.); see also license.xml for longer wording
    check_license_years := "0"|"1"|"2" (optional, defaults to 0) When a project is regenerated, and if any license text(s) are defined, we check that at least one Copyright line in at least one license text contains the current year, and warn if not. If this option is set to "1", we also pause so that interactive developers can see this warning better and intervene. With "2" require that the year is mentioned, abort GSL with year if it is not.
-->
<project script = "zproject.gsl" name = "zproject"
    email = "[email protected]"
    license = "MPL-2.0"
    check_license_years = "0"
    url = "https://github.com/zeromq/zproject"
    repository = "https://github.com/zeromq/zproject">

    <!--
        Includes are processed first, so XML in included files will be
        part of the XML tree. This file can provide content of such tags
        as <license> (detailed text to put in generated file headers)
        and <starting_year> (a number to put in packaging copyright
        summaries). Note that a verbatim "license.xml" file would be
        created if it is currently missing but the tag is present, and
        then it would be seeded with a current starting_year and some
        boilerplate reminder to specify a real license and copyright.
    -->
    <include filename = "license.xml" />

    <!--
        Current version of your project.
        This will be used to package your distribution
    -->
    <version major = "1" minor = "1" patch = "0" />

    <!--
        Current libtool ABI version of your project's shared library.
        Start at 0:0:0 and see:
        http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
        for details on how/when to increment it.
        If not defined 0:0:0 will be used.
    <abi current = "0" revision = "0" age = "0" />
    -->

    <!--
        Check that the <symbol> is available after including a given <header>
        and store the result in a macro HAVE_DECL_SYMBOL. When the symbol is
        declared, HAVE_DECL_SYMBOL is defined to '1' otherwise '0'. Use
        HAVE_DECL_SYMBOL in #if:

          #if HAVE_DECL_SYMBOL
            // Do something with the symbol
          #endif

          #if !HAVE_DECL_SYMBOL
            // Alternative action without the symbol
          #endif
    <check_symbol_exists symbol = AI_V4MAPPED"" header = "netdb.h" />
    -->

    <!--
        Specify which other projects this depends on.
        These projects must be known by zproject, and the list of
        known projects is maintained in the zproject_known_projects.xml model.
        You need not specify sub-dependencies if they are implied.
        Dependencies that support the autotools build system are automatically
        built by travis ci if you supply a git repository or a tarball URI.
        Set type to "runtime" to have the packages install-depend on it rather
        than build-depend (default type is "build").
        The travis ci will use the installed packages when building instead of
        rebuilding if available.
    <use project = "zyre" min_major= "1" min_minor = "1" min_patch = "0" />
    <use project = "czmq"
        min_major= "3" min_minor = "0" min_patch = "2"
        next_incompatible_major = "4"
        />
    <use project = "uuid" optional= "1" implied = "1" />
    <use project = "myfirstlib" repository = "http://myfirstlib.org/myfirstlib.git" />
    <use project = "mysecondlib" tarball = "http://mysecondlib.org/mysecondlib-1.2.3.tar.gz" />
    <use project = "lua-5.1" am_lib_macro = "LUA_5_1" tarball = "..." />
    -->

    <use project = "gsl" type = "runtime" />

    <!-- Header Files
         name := The name the header file to include without file ending
    <header name = "myproject_prelude" />
    -->

    <!--
        Classes, if the class header or source file doesn't exist, this will
        generate a skeletons for them.
        Use private = "1" for internal classes
        Use selftest = "0" to not generate selftest code
    <class name = "myclass">Public class description</class>
    <class name = "someother" private = "1">Private class description</class>
    -->

    <!--
        Actors, are built using the simple actor framework from czmq. If the
        actors class header or source file doesn't exist, this will generate a
        skeleton for them. The generated test method of the actor will teach
        you how to use them. Also have a look at the CZMQ docs to learn more
        about actors.
        Use selftest = "0" to not generate selftest code
    <actor name = "myactor">Public actor description</actor>
    <actor name = "someactor" private = "1">Private actor description</actor>
    -->

    <!--
        Main programs built by the project
                 use private = "1" for internal tools
    <main name = "progname">Exported public tool</main>
    <main name = "progname" private = "1">Internal tool</main>
    <main name = "progname" service = "1">Installed as system service, single-instance</main>
    <main name = "progname" service = "2">Installed as system service, multi-instance (@)</main>
    <main name = "progname" service = "3">Installed as system service, both single and multi-instance (@)</main>
    <main name = "progname" timer = "3">Installed as system timer unit, both single and multi-instance (@)</main>
    <main name = "progname" service = "1" timer = "1">Installed with both system timer and service units, single-instance - probably the former triggers the latter occasionally</main>
        Note that <bin> tags for secondary distributed programs (or scripts)
        now also support the service and timer attributes with same semantics.
    -->

    <!--
        Benchmark programs built by the project
    <bench name = "benchname">Benchmark for class/function...</main>
    -->

    <!--
        Models that we build using GSL.
        This will generate a 'make code' target to build the models.
    <model name = "sockopts" />
    <model name = "zgossip" />
    <model name = "zgossip_msg" />

        If a model should be generated using a specific gsl script,
        this can be set through the script attribute:
    <model name = "hydra_msg" script = "zproto_codec_java.gsl" />

        Additional parameters to the script can be set via nested
        param elements:
    <model name = "hydra_msg" script = "zproto_codec_java.gsl">
        <param name = "root_path" value = "../main" />
    </model>
    -->

    <!-- Other source files that we need to package
    <extra name = "some_resource" />
    -->
    <!-- Specify targets to build; autotools and cmake are
         built in all cases.
    <target name = "cmake" />
    <target name = "autotools" />
    -->
    <!-- Targets may be customizable with their own options -->
    <target name = "cmake">
        <option name = "single setting" value = "value" />
        <option name = "list setting">
            <item name = "item name" value = "item value" />
        </option>
    </target>

    <target name = "obs" />
    <target name = "debian" />
    <target name = "redhat" />

    <!-- Cucumber target
    <target name = "cucumber">
        For each step_defs a cucumber steps runner will be registered
        in the build scripts and the project's cucumber_selftest is
        generated appropriately. Points the the source file
        $(step_defs.name)_step_defs.c
        <step_defs name = "brilliant_ideas" />
    </target>
    -->

    <!-- Note: zproject itself uses a customized CI-testing routine
         on Travis CI, not a generated one, so DO NOT ENABLE this one:
        <target name = "travis" />
    -->

    <!-- Jenkins target creates jenkins pipeline
         Pipeline file is not overwritten if it exists.

         Your projects can build under a docker container OR agents
         matched by a label OR under an "any" agent by default.
         If you specify a complex label expression, be sure to use
         XML escaping of the ampersand character (&amp;) if some of
         your tooling expects project.xml to be valid XML (the GSL
         parser accepts a verbatim ampersand character as well).

         The agent_single option is a flag that enables parallel
         builds of this component on several agents (specified by
         label or docker) vs. a sequential build on a single agent.

         Similarly, a check_sequential option can be defined so that
         self-testing stages would run sequentially. This can be needed
         at early stages of a project's evolution, where hard-coding is
         prevalent so parallel runs in same operating environment cause
         conflicts to each other. Ultimately a project should remove
         this flag ;)

         The build_* and test_* options influence the default setting
         of corresponding build arguments for the project. You can
         still run a custom Jenkins Build with Arguments with other
         checkboxes clicked, e.g. while developing a missing feature.
         If not explicitly set to 0, most of these options are assumed
         "true", as normally a project should be capable of all these
         aspects. Note however that a project with no classes marked
         "stable" would by default not test non-DRAFT builds as the
         configure.ac script would have no support for those anyway.

         The require_gitignore option (enabled by default) also causes
         the test to fail, rather than warn, if untracked or changed
         files are found as a result of some build or test stage.

         Also note, that after successful build and test steps, the
         job generated by this Jenkinsfile can optionally trigger
         some other job specific to your installation of a Jenkins
         server, to handle the deployment of tested code (whichever
         way you'd define that). For this optional feature, your
         Jenkins master should define (and propagate to its agents)
         the environment values DEFAULT_DEPLOY_BRANCH_PATTERN (regex)
         and DEFAULT_DEPLOY_JOB_NAME (note to start with a slash for
         absolute naming; jobs in a folder may use relative paths too).
         That job should accept parameters DEPLOY_GIT_URL (URL of repo),
         DEPLOY_GIT_BRANCH (name for decision-making), DEPLOY_GIT_COMMIT
         (actual commit to check out and shrink-wrap into packaging.

         The test_install check tries to "make DESTDIR=... install" where
         the DESTDIR is test_install_DESTDIR value (must be an absolute
         path), or BUILD_DIR/tmp/_inst if the option is unspecified/empty.

         The test_cppcheck is different, as it calls the "cppcheck" tool
         which may be not installed on a particular Jenkins deployment.
         The `make cppcheck` recipe is safe to call in either case, so by
         default this option is enabled if not set explicitly. Same idea
         goes for build_docs as it requires asciidoc and xmlto toolkits,
         except it is off by default to avoid churning CPUs with no tools.
         A further dist_docs enables preparation of a "dist" tarball from
         the workspace configured with docs, so you can forward it to the
         publishing helper job and avoid rebuilding man pages for packaging.

         Similarly, a test_check_clang_format requires an external tool,
         the clang-format-5.0 (or newer) to process the codebase and decide
         if it is stylish. By default the test is enabled but not required
         to pass (is just informative) and will run if the tool is available
         in the build system. Eventually, a project should define and uphold
         its coding style -- then this test can become one of requirements
         for new pull requests.

         The triggers_pollSCM option sets up the pipeline-generated job
         for regular polling of the original SCM repository, using the
         Jenkins cron syntax. The default is approximately every 5 minutes
         with a spread to minimize burst-loads vs quiet times. An explicit
         empty string disables polling, so you'd only run the job manually.
         Note that the most frequent working setting is "H/2", NOT a "H/1".

         On the Jenkins setup used by generated projects, sometimes it was
         re-scheduling the same commits over and over and even overlapping.
         Usually this was linked to some lagginess of the build system or
         its internet connection, but the result was a growing queue of
         same (and redundant) builds. To remedy this, projects can set a
         few experimental options now (and regenerate their Jenkinsfile):
         * use_earlymilestone -- uses a milestone to cancel builds that
            got to it later than the running one
         * use_deploymilestone -- uses a milestone to cancel builds that
            got to the 'deploy if appropriate' phase later than the
            running one
         * use_build_nonconcurrent -- sets a disableConcurrentBuilds option
         * use_checkout_explicit -- sets a skipDefaultCheckout option and
            defines a step to check out code explicitly; it is believed
            this may better succeed in recording which commits are already
            being processed by the server

         The use_test_timeout option sets up the default timeout for test
         steps (further configurable at run-time as a build argument).
         Generally unit tests should not take pathologically long, so the
         default of 30 minutes should commonly suffice even for distchecks.
         If your selftests are known to take a lot of time, perhaps due to
         using an occasionally overloaded Jenkins CI farm, set this option.

         A use_test_retry option allows to retry each failing test step
         for the specified amount of attempts; it is deemed good if the
         test passes at least once. This option should not normally need
         to be used -- only if selftests somehow depend on environmental
         circumstances and fail occasionally but not always. Ultimately,
         project developers should find and fix the issue in tests (or in
         the production codebase) so it always works on the first try,
         bulletproof.

         As a workaround for some versions of Jenkins, if your project uses
         "weird" (generally non-ASCII) filenames in the build directory,
         their removal with Pipeline deleteDir() can fail even though it
         should not. If this bites you, set use_deleteDir_rm_first=1 in
         the project, so the OS native "rm" is tried first.

         The two options do_cleanup_after_build (for parallelized tests)
         and do_cleanup_after_job control whether the pipeline would by
         default remove the build/test subdirectory after successful end
         of stage, and/or cleans the build workspace after the whole job
         succeeded, respectively. If not set, cleanup is enabled for both
         and in either case the active options are among build parameters.
         In opposite fashion, a do_cleanup_after_failed_build is disabled
         by default to allow post-mortem inspection of errors on CI server.
         You might want to keep the built sources to analyze the behavior
         of your build recipes in a particular environment, thought at a
         risk of using excessive disk space there. In case of failure the
         workspace remains on disk to make an in-place analysis possible,
         and would eat space until you clean it up manually or it would
         expire according to your Jenkins old-build retention policies.

    <target name = "jenkins">
        <option name = "file" value = "Jenkinsfile" />
        <option name = "agent_docker" value = "zeromqorg/czmq" />
        <option name = "agent_label" value = "linux || macosx || bsd || solaris || posix || windows" />
        <option name = "agent_single" value = "1" />
        <option name = "check_sequential" value = "1" />
        <option name = "triggers_pollSCM" value = "H/5 * * * *" />
        <option name = "build_without_draft_api" value = "0" />
        <option name = "build_with_draft_api" value = "0" />
        <option name = "build_docs" value = "1" />
        <option name = "dist_docs" value = "1" />
        <option name = "require_gitignore" value = "0" />
        <option name = "use_deleteDir_rm_first" value = "1" />
        <option name = "use_test_timeout" value = "60" />
        <option name = "use_test_retry" value = "3" />
        <option name = "test_check" value = "0" />
        <option name = "test_memcheck" value = "0" />
        <option name = "test_distcheck" value = "0" />
        <option name = "test_install" value = "0" />
        <option name = "test_install_DESTDIR" value = "/tmp/proto-area" />
        <option name = "test_cppcheck" value = "1" />
        <option name = "test_check_clang_format" value = "1" />
        <option name = "use_clang_format_prog" value = "clang-format-5.0" />
        <option name = "require_good_clang_format" value = "0" />
    </target>
    -->
    <target name = "jenkins" >
        <option name = "agent_label" value = "linux || macosx || bsd || solaris || posix || windows" />
        <option name = "agent_single" value = "1" />
        <!-- Note: for zproject itself, all the *check jobs are
             essentially a loopback to distcheck itself -->
        <option name = "test_check" value = "1" />
        <option name = "test_memcheck" value = "0" />
        <option name = "test_distcheck" value = "0" />
        <option name = "test_cppcheck" value = "0" />
    </target>

    <!-- In order loaded by zproject.gsl -->
    <bin name = "zproject.gsl" />
    <bin name = "zproject_projects.gsl" />
    <bin name = "zproject_class_api.gsl" />

    <!-- Mainline generation code -->
    <bin name = "zproject_skeletons.gsl" />
    <bin name = "zproject_bench.gsl" />
    <bin name = "zproject_class.gsl" />
    <bin name = "zproject_git.gsl" />
    <bin name = "zproject_valgrind.gsl" />

    <!-- Targets -->
    <bin name = "zproject_android.gsl" />
    <bin name = "zproject_autotools.gsl" />
    <bin name = "zproject_cmake.gsl" />
    <bin name = "zproject_cucumber.gsl" />
    <bin name = "zproject_cygwin.gsl" />
    <bin name = "zproject_debian.gsl" />
    <bin name = "zproject_delphi.gsl" />
    <bin name = "zproject_docker.gsl" />
    <bin name = "zproject_gh_actions.gsl" />
    <bin name = "zproject_gyp.gsl" />
    <bin name = "zproject_ios.gsl" />
    <bin name = "zproject_java.gsl" />
    <bin name = "zproject_java_lib.gsl" />
    <bin name = "zproject_java_msvc.gsl" />
    <bin name = "zproject_jenkins.gsl" />
    <bin name = "zproject_lua_ffi.gsl" />
    <bin name = "zproject_mingw32.gsl" />
    <bin name = "zproject_nodejs.gsl" />
    <bin name = "zproject_nuget.gsl" />
    <bin name = "zproject_obs.gsl" />
    <bin name = "zproject_python.gsl" />
    <bin name = "zproject_python_cffi.gsl" />
    <bin name = "zproject_qml.gsl" />
    <bin name = "zproject_qt.gsl" />
    <bin name = "zproject_redhat.gsl" />
    <bin name = "zproject_rpi.gsl" />
    <bin name = "zproject_ruby.gsl" />
    <bin name = "zproject_systemd.gsl" />
    <bin name = "zproject_travis.gsl" />
    <bin name = "zproject_vagrant.gsl" />
    <bin name = "zproject_vs2008.gsl" />
    <bin name = "zproject_vs20xx.gsl" />
    <bin name = "zproject_vs20xx_props.gsl" />

    <bin name = "zproject_known_projects.xml" />
</project>

Project dependencies

zproject's use element defines project dependencies. Model is described in zproject_known_projects.xml file:

<known_projects>

    <!-- ZeroMQ Projects -->
    <!--
        Problem: naming style is inconsistent
        we sometimes use libxxx and sometimes xxx; the git repo name
        is unpredictable; sometimes we override with the prefix and
        sometimes with libname.

        Proposed solution: project name should always be git repo
        name; prefix and libname should always be specified. For
        compatibility, we can define aliases. E.g.:

        Also, 'cmake name' is target specific and must go.

        Suggested model:
        <use
            project = "libzmq"          required
            master = "https://github.com/zeromq"
                                        required
            libname = "libzmq"          default = lib<prefix>
            prefix = "zmq"              default = project
            test = "zmq_init"           required same as AC_CHECK_LIB in autoconf
            release = "<tagname>"       default = "master"
            abi = "version"             default = "0:0:0"
            header = "<filename>"       default = <prefix>.h
            language = "C|C++"          default = "C"
            optional = "1"              default = "0"
            debian_name = "libzmq5-dev" default = lib<name>-dev
            redhat_name = "zeromq-devel" default = <name>-devel
                <add_config_opts>--with-dep1=nuance</add_config_opts>
                <add_config_opts>--enable-feature2</add_config_opts>
        </use>
    -->

    <use project = "libzmq" prefix = "zmq" debian_name = "libzmq3-dev" redhat_name = "zeromq-devel" brew_name = "zeromq"
        repository = "https://github.com/zeromq/libzmq.git"
        test = "zmq_init" />

    <!-- Note: if your project requires an older CZMQ (e.g. if you need
        `release = "v3.0.2"`), you may need to `test = "zctx_test"`.
        Also note that you can instead require particular package
        version (as reported by pkg-config records). -->
    <use project = "czmq" libname = "libczmq"
        repository = "https://github.com/zeromq/czmq.git"
        test = "zhashx_test">
        <use project = "libzmq" />
    </use>

    <use project = "zyre" libname = "libzyre"
        repository = "https://github.com/zeromq/zyre.git"
        test = "zyre_test">
        <use project = "czmq" />
    </use>

    <use project = "malamute" libname = "libmlm"
        repository = "https://github.com/zeromq/malamute.git"
        header = "malamute.h"
        prefix = "mlm"
        test = "mlm_server_test">
        <use project = "libzmq" />
        <use project = "czmq" />
    </use>

    <use project = "gsl" libname = ""
        repository = "https://github.com/zeromq/gsl.git"
        debian_name = "generator-scripting-language"
        redhat_name = "generator-scripting-language">
    </use>

    <!-- Edgenet Projects -->

    <use project = "drops" libname = "libdrops"
        repository = "https://github.com/edgenet/drops.git"
        test = "drops_test">
        <use project = "czmq" />
        <use project = "zyre" />
    </use>

    <use project = "hydra" libname = "libhydra"
        repository = "https://github.com/edgenet/hydra.git"
        test = "hydra_server_test">
        <use project = "czmq" />
    </use>

    <!-- Various known third-party projects
        (If you're unsure of where a project belongs, add it here) -->

    <use project = "cucumber"
         header = "cucumber_c.h"
         test = "cucumber_new"
         repository = "https://github.com/sappo/cucumber-c">
        <use project = "gherkin" private = "1" />
        <use project = "cJSON" private = "1" />
    </use>

    <use project = "gherkin"
         header = "compiler.h"
         repository = "https://github.com/cucumber/gherkin-c"
         test = "Compiler_new" />

    <use project = "cJSON"
         debian_name = "libcjson-dev"
         header = "cjson/cJSON.h"
         repository = "https://github.com/DaveGamble/cJSON"
         test = "cJSON_Parse" />

    <use project = "libsodium" prefix = "sodium"
        repository = "https://github.com/jedisct1/libsodium.git"
        release = "stable"
        test = "sodium_init" />

    <use project = "libcurl"
        prefix = "curl"
        repository = "https://github.com/curl/curl.git"
        debian_name = "libcurl4-nss-dev"
        brew_name = "curl"
        test = "curl_easy_init"
        header = "curl/curl.h" />

    <use project = "libmicrohttpd"
         brew_name = "libmicrohttpd"
         prefix = "microhttpd"
         repository = "https://git.gnunet.org/libmicrohttpd.git"
         tarball = "http://ftp.gnu.org/gnu/libmicrohttpd/libmicrohttpd-0.9.44.tar.gz"
         test = "MHD_start_daemon" />

    <use project = "editline"
        repository = "https://github.com/troglobit/editline.git"
        test = "readline" />

    <use project = "fuse"
        repository = "http://git.code.sf.net/p/fuse/fuse.git"
        test = "fuse_main" />

    <use project = "jansson"
        repository = "https://github.com/akheron/jansson.git"
        test = "json_object" />

    <use project = "jemalloc"
        repository = "https://github.com/jemalloc/jemalloc.git"
        test = "malloc"
        header = "jemalloc/jemalloc.h" />

    <use project = "msgpack"
        repository = "https://github.com/msgpack/msgpack-c.git"
        test = "msgpack_version" />

    <use project = "uuid"
        test = "uuid_generate"
        header = "uuid/uuid.h"
        brew_name = "ossp-uuid"
        redhat_name = "libuuid-devel"
        debian_name = "uuid-dev" />

    <use project = "asound"
        test = "snd_asoundlib_version"
        header = "alsa/asoundlib.h" />

    <use project = "zdb"
        repository = "https://bitbucket.org/tildeslash/libzdb.git"
        test = "ConnectionPool_start" />

    <use project = "json-c"
        header = "json-c/json.h"
        test = "json_object_to_json_string" />

    <use project = "libfastjson"
        repository = "https://github.com/rsyslog/libfastjson/"
        header = "libfastjson/json.h"
        test = "json_object_to_json_string" />

    <use project = "lognorm"
        repository = "https://github.com/rsyslog/liblognorm/"
        test = "ln_initCtx">
        <use project = "libfastjson" />
    </use>

    <use project = "zdiscgo"
        repository = "https://github.com/zeromq/zdiscgo.git"
        test = "zdiscgoplugin_new" />

    <use project = "systemd"
        libname = "libsystemd"
        prefix = "libsystemd"
        linkname = "systemd"
        header = "systemd/sd-daemon.h"
        test = "sd_listen_fds" />

    <use project = "protobuf-c"
         repository = "https://github.com/protobuf-c/protobuf-c/"
         test = "protobuf_c_version"
         header = "protobuf-c/protobuf-c.h"/>

    <!-- 42ITY project https://github.com/42ity https://42ity.org -->
    <use project = "fty-proto" libname = "libfty_proto" header="ftyproto.h"
        repository = "https://github.com/42ity/fty-proto"
        test = "fty_proto_test">
        <use project = "libzmq"/>
        <use project = "czmq"/>
        <use project = "malamute"/>
    </use>

    <!-- OS packagers make life hard by renaming the package, binaries and
         even library SONAMEs - so we have to guess a bit; note that for
         practical purposes, lua-5.2 suffices as lua-5.1 (if fixes happen
         to be needed, they are trivial and googlable) -->
    <use project = "lua-5.1" libname = "lua" prefix="lua"
        optional = "0" am_lib_macro = "LUA_5_1"
        min_major = "5" min_minor = "1" min_patch = "0"
        debian_name="liblua5.1-0-dev" redhat_name="lua-devel"
        test = "lua_close">
            <linkname>lua5.2</linkname>
            <linkname>lua52</linkname>
            <linkname>lua5.1</linkname>
            <linkname>lua51</linkname>
            <linkname>lua</linkname>
            <pkgconfig>lua5.2</pkgconfig>
            <pkgconfig>lua52</pkgconfig>
            <pkgconfig>lua5.1</pkgconfig>
            <pkgconfig>lua51</pkgconfig>
            <pkgconfig>lua</pkgconfig>
    </use>

    <use project = "lz4"
        libname = "liblz4"
        redhat_name = "liblz4-devel"
        header = "lz4.h"
        test = "LZ4_decompress_safe" />

    <use project = "nss"
        debian_name = "libnss3-dev"
        redhat_name = "nss-devel"
        header = "sechash.h"
        test = "HASH_Create" />

</known_projects>

Optional : Class filename configuration

Example:

<classfilename use-cxx = "true" use-cxx-gcc-4-9 = "true" pkgincludedir = "false" keep-tree = "true" pretty-print = "no" source-extension = "cpp" header-extension = "hpp" />
  • use-cxx will force usage (or not) of c++.
  • use-cxx-gcc-4-9 will enable "use-cxx" AND enforce the use of gcc-4.9 on Travis CI for nearly complete C++11 language support that is lacking in default gcc-4.8 there.
  • keep-tree will keep the include tree structure on the install (as opposed to flat delivery of include files basenames into the single-level target directory), must be used with a conservative name format (ex: pretty-print = "no"). Currently only supported with autotool.
  • pkgincludedir option chooses whether headers of this project should be dumped into the common system includedir (legacy default), or into an includedir/projname subdirectory?. Currently only supported with autotool.
  • pretty-print define the type of class name format change in order to generate the filename. It uses the pretty-print option of gsl (see Substituting Symbols and Expressions on https://github.com/zeromq/gsl#expressions for more information).
  • source-extension define the filename extension for source files in this project.
  • header-extension define the filename extension for header files in this project.

Default value :

  • pretty-print : substitute_non_alpha_to_make_c_identifier (c option)
  • header-extension : h
  • source-extension : c (unless a cc file is present, then cc)
  • use-cxx : true if a cc file is present, false otherwise
  • use-cxx-gcc-4-9 : false by default, older GCC versions still suffice for many C++11 features

Targets

Each target produces scripts and code for a specific build system, platform, or language binding.

To see a list of available targets:

gsl -target:? project.xml

To build a specific target:

gsl -target:android project.xml

To run zproject without building any targets:

gsl -target:- project.xml

To request specific targets in your project.xml file (autotools and cmake are automatic):

<target name = "android" />
<target name = "java" />

To request all targets in your project.xml file:

<target name = "*" />

Target Options

A target can accept options via project.xml like this:

<project
    name = "..."
    >
    ...
    <target name = "*" />
    <target name = "nuget">
        <option name = "id" value = "czmq_vc120" />
        <option name = "dependency">
            <item name = "libzmq_vc120" value = "4.2.0.0" />
        </option>
    </target>
</project>

This generates all targets (name = "*") and then configures the nuget target with options. Zproject aare provided to the target handler as:

project.nuget_id = "czmq_vc120"
project.nuget_dependency.name = "libzmq_vc120"
project.nuget_dependency.value = "4.2.0.0"
Android target options

The target android accepts the following options:

<target name = "android" >
    <option name = "ndk_version" value = "nnn" />
    <option name = "min_sdk_version" value = "sss" />
</target>

Generated files will have their default values like:

project.android_ndk_version = "nnn"
project.android_min_sdk_version = "sss"

Note: these 2 default values can be overridden via the export mechanism as explained in generated builds/android/README.md and bindings/jni/README.md.

If these options are not provided, default hard-coded values are applied from zproject_android.gsl code.

Target Scopes

Each target works in its own copy of 'project'. It can therefore modify and extend 'project' as wanted, without affecting other targets.

Modifying generated files in an already existent project

You may encounter a warning in a file you want to modify like this:

 ################################################################################
 #  THIS FILE IS 100% GENERATED BY ZPROJECT; DO NOT EDIT EXCEPT EXPERIMENTALLY  #
 #  Read the zproject/README.md for information about making permanent changes. #
 ################################################################################

If that happens, you need to follow these steps to make the modifications and then regenerate the code for czmq, malamute and zyre (all zeromq projects).

  1. Prior making any changes, run the script tstgenbld.sh and save its output to a log file. This will save the state of the world by regenerating several projects, building and running tests.
~/git/zproject$ ./tstgenbld.sh > ../before.log
  1. Search for a specific string from the file in the zproject files (use .)
  2. When you find it, make the modification in that file (most likely extensions will be .XML or .GSL)
  3. Then execute these steps in a Linux machine to regenerate all files for your project. This will build, install and run tests on them again, after your changes have been made.
~/git/zproject$ ./tstgenbld.sh > ../after.log
~/git/zproject$ meld ../after.log ../before.log
  1. Be aware that many files in the regenerated projects will change.
  2. This also means you will need to commit changes on zproject (your mods) and in czmq, malamute, zyre (the regenerated files with your mods). From git documentation, it seems like the command "git add -uv" could help to find out what files were actually modified from all the files that were regenerated. Supposedly this will only add the ones that were actually modified, but you should double check them. Make sure to double check even line termination (or use a comparisson tool that flags those differences). Windows specific files should have (CR+LF) termination, while Linux specific should have (LF) only termination. Best is to look for ".terminator=" examples in existing .GSL files.

API models

Using an API model zproject can generate the @interface section your class headers. Further it allows zproject to generate various language bindings on top of your CLASS project.

Sample API model

All API models are placed into the api directory which resides in the root directory of your project. For example, if your project.xml contains <class name = "myclass"/>, you could create the following api/myclass.api file:

<class name = "myclass">
    <!--
        This model defines a public API for binding.

        It shows a language binding developer what to expect from the API XML
        files.
    -->
    My Feature-Rich Class

    <include filename = "license.xml" />

    <constant name = "default port" value = "8080">registered with IANA</constant>

    <constant name = "normal" value = "1" />
    <constant name = "fast"   value = "2" />
    <constant name = "safe"   value = "3" />

    <!-- Constructor is optional; default one has no arguments -->
    <constructor>
        Create a new myclass with the given name.
        <argument name = "name" type = "string" />
    </constructor>

    <!-- Destructor is optional; default one follows standard style -->
    <destructor>
        Destructors implicitly get a new argument prepended, which:

        * is called `self_p`
        * is of this class' type
        * is passed by reference
        * is marked as the self pointer for the destructor (`destructor_self = "1"`)
    </destructor>

    <!-- This models an CZMQ actor. By default the actor method equals the
         class name.
    -->
    <actor>
        To work with my_actor, use the CZMQ zactor API:

        Create new my_actor instance.

            zactor_t *actor = zactor_new (my_actor, NULL);

        Destroy my_actor instance

            zactor_destroy (&amp;actor);

        Enable verbose logging of commands and activity:

            zstr_send (actor, "VERBOSE");
    </actor>

    <!-- This models a method with no return value -->
    <method name = "sleep">
        Put the myclass to sleep for the given number of milliseconds.
        No messages will be processed by it during this time.
        <argument name = "duration" type = "integer" />
    </method>

    <!-- This models an accessor method -->
    <method name = "has feature">
        Return true if the myclass has the given feature.
        <argument name = "feature" type = "string" />
        <return type = "boolean" />
    </method>

    <method name = "send strings">
        This does something with a series of strings (until NULL). The strings
        won't be touched.

        Because the next method has the same name with a prepended "v", it's
        recognized as this method's `va_list` sibling (in GSL:
        `method.has_va_list_sibling = "1"`). This information might be used by
        the various language bindings.
        <argument name = "string" type = "string" variadic = "1" />
        <return type = "boolean" />
    </method>

    <method name = "vsend strings">
        This does something with a series of strings (until NULL). The strings
        won't be touched (they're declared immutable by default).
        <argument name = "string" type = "string" variadic = "1" />
        <return type = "boolean" />
    </method>

    <!-- Callback typedefs can be declared like methods -->
    <callback_type name = "handler_fn">
        <argument name = "self" type = "myclass" />
        <argument name = "action" type = "string" />
        <return type = "boolean" />
    </callback_type>

    <!-- Callback types can be used as method arguments -->
    <method name = "add handler">
        Store the given callback function for later
        <argument name = "handler" type = "my_class_handler_fn" callback = "1" />
    </method>

    <!-- If singleton = "1", no class struct pointer is required. -->
    <method name = "test" singleton = "1">
        Self test of this class
        <argument name = "verbose" type = "boolean" />
    </method>

    <method name = "new thing" singleton = "1" >
	Creates a new myclass. The caller is responsible for destroying it when
	finished with it.
        <return type = "myclass" fresh = "1" />
    </method>

    <method name = "free" singleton = "1">
        Frees a provided string, and nullify the parent pointer. Setting
        `mutable = "1"` is not needed here, because transfering ownership from
        the caller to the function using `by_reference = "1"` implies that it's
        mutable.
        <argument name = "string pointer" type = "string" by_reference = "1" />
    </method>

    <method name = "rotate" singleton = "1">
        Rotates the characters in `data` in-place. This means that all
        characters are shifted to the left by one, removing the left-most
        character and appending it to the end.
        <argument name = "data" type = "string" mutable = "1" />
    </method>

    <!-- These are the types we support
         Not all of these are supported in all language bindings;
         see each language binding's file for supported types in that
         language, and add more types as needed where appropriate.

         Also, see zproject_class_api.gsl to see how they're handled exactly.
         -->
    <method name = "tutorial">
        <argument name = "void pointer" type = "anything" />
        <argument name = "standard int" type = "integer" />
        <argument name = "default float" type = "real" />
        <argument name = "standard float" type = "real" size = "4" />
        <argument name = "standard double" type = "real" size = "8" />
        <argument name = "standard bool" type = "boolean" />
        <argument name = "fixed size unsigned integer" type = "number" size = "4">
            Supported sizes are 1, 2, 4, and 8.
        </argument>
        <argument name = "a byte" type = "byte" />
        <argument name = "conversion mode" type = "integer" />
        <argument name = "char pointer to C string" type = "string" />
        <argument name = "byte pointer to buffer" type = "buffer" />
        <argument name = "buffer size" type = "size" />
        <argument name = "file handle" type = "FILE" />
        <argument name = "file size" type = "file_size" />
        <argument name = "time" type = "time" />
        <argument name = "format" type = "format">
            This makes the function is variadic (will cause a new argument to be
            added to represent the variadic arguments).
        </argument>
        <argument name = "variadic list argument" type = "va_list" />
        <argument name = "custom pointer" type = "my custom class">
            Any other type is valid, as long as there is a corresponding C
            type, in this case `my_custom_class_t`.
        </argument>
        <return type = "nothing">void method</return>
    </method>

    <method name = "set foo" polymorphic = "1">
      Set attribute foo to a new value. Note that this method takes a
      polymorphic reference (`void *`) as its first argument, which could point
      to structs of different types.

      This also means that high-level bindings might give you the choice to
      call this method directly on an instance, or with an explicit receiver.
      <argument name = "new value" type="integer" />
    </method>

    <method name = "set bar">
        This method takes an argument type of the (descriptive) type `foo`, but
        resolving it to a corresponding C type will be skipped because it's
        overridden to `foobarbaz_t` by the `c_type` attribute.
        <argument name = "new foo" type="foo" c_type="foobarbaz_t" />
    </method>
</class>

This model will cause the following @interface to be generated inside of include/myclass.h. Note that if include/myclass.h has other handwritten content outside the @interface section this content will be retained. If the header file does not exist zproject will create it.

//  @warning THE FOLLOWING @INTERFACE BLOCK IS AUTO-GENERATED BY ZPROJECT!
//  @warning Please edit the model at "api/myclass.api" to make changes.
//  @interface
//  Create a new myclass with the given name.
MYPROJECT_EXPORT myclass_t *
    myclass_new (const char *name);

//  Destroy the myclass.
MYPROJECT_EXPORT void
    myclass_destroy (myclass_t **self_p);

//  Return true if the myclass has the given feature.
MYPROJECT_EXPORT bool
    myclass_has_feature (myclass_t *self, const char *feature);

//  Put the myclass to sleep for the given number of milliseconds.
//  No messages will be processed by the actor during this time.
MYPROJECT_EXPORT void
    myclass_sleep (myclass_t *self, int duration);

//  Self test of this class
MYPROJECT_EXPORT void
    myclass_test (bool verbose);
//  @end

Supported API Model Attributes

The following attributes are supported for methods:

  • name - the name of the method (mandatory).
  • singleton = "1" - the method is not invoked within the context of a specific instance of an object. Use this if your method does not need to be passed a self pointer as the first argument as normal. Implicit for all constructors and destructors and for the implicit test method.

The following attributes are supported for arguments and return values:

  • type - the conceptual type or class name of the argument or return value (default: "nothing", which translates to void in C).
  • mutable = "1" - the argument or the return value can be modified. All string, format, and buffer arguments are immutable by default.
  • by_reference = "1" - ownership of the argument (and responsibility for freeing it) is transferred from the caller to the function - in practice, the implementation code should also nullify the caller's reference, though this is not enforced by the API model. If a string or buffer is passed by reference, it is also mutable by default.
  • fresh = "1" - the return value is freshly allocated, and the caller receives ownership of the object and the responsibility for destroying it. Implies mutable = "1".
  • variadic = "1" - used for representing variadic arguments.

For integer arguments you can specify one or more 'map' values, which a binding target can use to generate alternative methods. For example:

<argument name = "socket type" type = "integer">
    <map name = "PAIR" value = "ZMQ_PAIR" />
    <map name = "PUB"  value = "ZMQ_PUB" />
    <map name = "SUB"  value = "ZMQ_SUB" />
</argument>

The value should be a constant that the binding code has access to.

The following attributes are supported for arguments:

  • polymorphic - indicates that the passed class instance is a sockish type. For an example see CZMQ's zsock class.

API Types

This is an incomplete list of API types:

  • "nothing" -- for return only, means "void" in C.

  • "anything" -- means "void *" in C.

  • "size" -- long size (64 bits), "size_t" in C.

  • "time" -- long time (64 bits), "time_t" in C.

  • "msecs" -- long number of msecs, "int64_t" in C.

  • "file_size" -- long file size (64 bits).

  • "boolean" -- Boolean.

  • "byte" -- single octet.

  • "char" -- single character (possibly multibyte, do we care?)

  • "integer" -- 32-bit signed integer.

  • "number" -- unsigned number, with 'size = "1|2|4|8"'.

  • "real" -- single-precision floating point with 'size = "4"' (default) or double-precision with 'size = "8"'.

  • "buffer" -- byte array. When passing a buffer argument, if the next argument has type 'size', the binding may fill the size automatically. To return a buffer, you should specify 'size' attribute that defines how to set the buffer size. This can be a constant, 'size = "ZUUID_LEN"', or a dot followed by method name in the same class, e.g. 'size = ".size"'.

  • "string" -- character array.

  • "sockish" -- a variant socket type, may be a zsock_t, libzmq void *, or an actor handle.

  • "format" -- printf format, followed by zero or more arguments.

  • "FILE", "va_list", "zmq_pollitem", "socket" -- literally that, in C. (Not sure if it is wise to use raw C types.)

  • callbacks - tbd.

  • Names of classes, e.g. zmsg.

Tips

At any time, you can examine a resolved model as an XML string with all of its children and attributes using the appropriate GSL functions:

 # if the `method` variable is a <method/> entity:
echo method.string()  # will print the model as an XML string.
method.save(filename) # will save the model as an XML string to the given file.

You can save a snapshot of the entire resolved project model using this syntax:

gsl -save:1 project.xml

Generate API model from C header files

Writing API model for bigger project with a lot of classes can be tedious job. There mkapi.py, which automates most of the task.

In order to use it, you must install zproject itself and then pycparser. For most of real world code, you must have fake_libc_includes available too.

virtualenv/venv mkapi
source mkapi/bin/activate
pip install pycparser
git clone https://github.com/eliben/pycparser.git

Then from root directory of your project (for example czmq), type following

mkapi.py -I /path/to/your/pycparser/utils/fake_libc_include include/czmq.h

Note you must use top-level include as pycparser fails if it does not know any definition.

The tool might expect -DWITH_DRAFTS parameter if the class is not marked as a stable.

Known caveats

The tool can't distinguish methods which allocates new object. It does print a comment about adding fresh = "1" attribute to each method, which return non const pointer. However the final assigment must be done manually.

Language Binding Notes

Java Language Binding

  • Skips methods that it cannot handle properly.

  • To build, you need gradle (or equivalent). Run 'gradle build jar' in the bindings/jni directory.

  • To install, run 'gradle install'. This puts the files into $HOME/.m2/repository.

Draft API Support

zproject lets you mark classes and methods as 'draft' so that they are not installed by default in stable builds. This lets you deliver draft APIs to your users, and change them later.

By default, all classes and methods are draft, unless you specify otherwise. To mark the state of a class or method, specify in the project.xml:

<class name = "classname" state = "stable" />

Or in the class API XML file:

<class name = "classname" state = "stable">
    ...
    <method name = "methodname" state = "stable">
        ...
    </method>
</class>

The method will inherit the class state unless it has its own 'state' attribute.

The allowed states are:

  • draft - the class or method is not built/installed in stable releases.
  • stable - the class or method is always built and installed. A method may not be changed once marked as stable.
  • legacy - the class or method is always built and installed. It may carry a warning that support can be withdrawn at any time.

Using autotools or CMake, you can specify --with-drafts to enable draft APIs, and --without-drafts to disable them. By default, drafts are built and installed when you work in a git repository (if the directory ".git" is present), and otherwise they are not. That means, if you build from a tarball, drafts are disabled by default.

Removal

autotools

make uninstall

Additional files

Installation of third party files is a hard problem. It is not platform independent, became hard to maintain and impossible to use correctly. One of zproject's goals is a simplicity. There is a simple installation model

Design goals

  • KISS, less configuration options the better
  • no conditionals in the model, those SHALL be handled in background
  • each option solves a REAL problem, avoid extending it because you can

Example

    <main name = "MAIN">
        <install type = "systemd-tmpfiles" />
        <install type = "config" name = "MAIN-ldap-integration.cfg.example" />
    </main>

systemd-tmpfiles This will add install information about systemd tmpfiles.d configuration files to autotools, packaging, and so. The resulting file /usr/lib/tmpfiles.d/MAIN.conf will be installed only if configure was called with --with-systemd-units.

config This will install additional configuration files to $(sysconfdir)/$(project.name)/$(name).

Notes for Writing Targets

Snippets

If you write a new target or extend one you might be in the situation where you need to put code fragments into files which are not specific to your target. For example the systemd target has to extend files from the autotools, debian and redhat targets. In order to keep those files as maintainable as possible you'll include a snippet which is pull from your targets file. To include a snippet call:

    insert_snippet (target)

Where target is the identifier for the insertion point i.e. the filename. To register a snippet to be inserted simply call.

    register_snippet (target, name)

Target is must match the one in insert_snippet and the name identifies your snippet. Then you can create a function or macro with the following form (without the brackets):

    function snippet_<target>_<name>

    .macro snippet_<target>_<name>

This function will be called by the insert_snippet function. You can have an arbitrary amount of registered snippets per insertion point which will be inserted in arbitrary order so don't make any assumption on the order of the snippets per insertion point.

Notes for Writing Language Targets

This is the general form of a target:

register_target ("somename", "Decription of target")

function target_somename

\.macro generate_something
    ...
\.endmacro

    project.topdir = "someplace/somename"
    directory.create (project.topdir)
    generate_something ()
endfunction

Schema/Architecture Overview

  • All classes SHALL be in the project model (project.xml).
  • Each class MAY have a corresponding API model (api/{class name}.api).
  • A binding generator SHOULD consider only classes with an API model (where defined (class.api)).
  • Each API model SHALL consist of both explicit information (written in the XML file) and implicit information (inferred by the zproject_class_api script). Both kinds of information will already be resolved (and indistinguishable) when each language binding generator is invoked.
  • Each API model SHALL have exactly one class entity at the top level.
  • Each class SHALL have a name attribute.
  • Each class MAY have one or more method entities.
  • Each class MAY have one or more constructor entities.
  • Each class MAY have one or more destructor entities.
  • Each method, constructor, and destructor MAY have one or more argument entities.
  • Each method, constructor, and destructor SHALL at least one return entity, and if more than one return entity exist, only the first SHOULD be considered. The return entity MAY be ignored if it has type = "nothing" (the default when no type is given).
  • Each entity SHALL have its semantic attributes fully resolved before reaching the language binding generators.
  • Each language binding generator SHALL NOT modify values of semantic attributes of entities.
  • Each language binding generator MAY assign values to language-specific implementation attributes of entities.
  • Each language binding generator SHOULD use a unique prefix for names of language-specific implementation attributes of entities.

Informal Summary

A class is always the top-level entity in an API model, and it will be merged with the corresponding class entity defined in the project model. A class contains methods, constructors, and destructors (collectively, "method"s), and methods contain arguments and returns (collectively, "container"s). Each entity will contain both semantic attributes and language-specific implementation attributes.

Semantic Attributes

Semantic attributes describe something intrinsic about the container.

For example, arguments may be described as passed by_reference to indicate that ownership is transferred from the caller. Similarly, return values may be described as fresh to indicate that ownership is transferred to the caller, which must destroy the object when it is finished with it. It's important to remember that these attributes are primarily meant to be an abstraction that describes conceptual information, leaving the details of how code generators interpret (or ignore) each attribute up to the authors.

Semantic attributes may be implicit (not given a value in the written model). In this case, it is up to the zproject_class_api script to fully resolve default values for all attributes. Downstream code generators should never resolve or alter semantic attributes, as this could change the behavior of any code generator that is run after the errant code generator.

These are the semantic attributes for each kind of entity that will be resolved before language bindings generators are invoked:

class.name        # string (as given in the API model)
class.description # string (comment in the API model, or empty string)
method.name           # string (as given in the API model, or a default value)
method.description    # string (comment in the API model, or a default value)
method.singleton      # 0/1 (default: 0, but 1 for constructors/destructors)
method.is_constructor # 0/1 (default: 0, but 1 for constructors)
method.is_destructor  # 0/1 (default: 0, but 1 for destructors)
method.has_va_list_sibling # 0/1 (default: 0)
container.name         # string (as given in the API model, or "_")
container.type         # string (as given, or "nothing")
container.mutable      # 0/1 (default: 0)
container.by_reference # 0/1 (default: 0)
container.callback     # 0/1 (default: 0)
container.fresh        # 0/1 (default: 0)
container.variadic     # 0/1 (default: 0)
container.va_start     # string - that holds the argment name for va_start ()
container.optional     # 0/1 (default: 0), up to binding generator to use

Ownership and License

The contributors are listed in AUTHORS. This project uses the MPL v2 license, see LICENSE.

zproject uses the C4.1 (Collective Code Construction Contract) process for contributions.

To report an issue, use the zproject issue tracker at github.com.

Ownership and License of generated sources

The copyright of the output of zproject is by default property of the users. The license.xml file must be set up by the users to specify a license of their choosing.

Hints to Contributors

Make sure that the project model hides all details of backend scripts. For example don't make a user enter a header file because autoconf needs it.

Do read your code after you write it and ask, "Can I make this simpler?" We do use a nice minimalist and yet readable style. Learn it, adopt it, use it.

Before opening a pull request read our contribution guidelines. Thanks!

This Document

This documentation was generated from zproject/README.txt using Gitdown

zproject's People

Contributors

arnaudquette-eaton avatar barraudl avatar benjdero avatar bkmit avatar bluca avatar c-rack avatar dmeehan1968 avatar gotcha avatar gregoryyoung avatar hambre avatar hgourvest avatar hintjens avatar jemc avatar jimklimov avatar karolhrdina avatar lovmoen avatar madebr avatar michal42 avatar opedroso avatar paddor avatar perrettecl avatar pmienk avatar sappo avatar somdoron avatar sphaero avatar stephan57160 avatar taotetek avatar twhittock avatar vyskocilm avatar wesyoung avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

zproject's Issues

No rule to make target 'zproject.gsl'

i am getting following error. Do we need to have *.gsl in generated project? Isn't it enough to have *.gsl files in /usr/loca/bin?

make[1]: Entering directory '/home/mvala/MVALA/git/saske/mvala/zmon/doc'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/home/mvala/MVALA/git/saske/mvala/zmon/doc'
make[1]: Entering directory '/home/mvala/MVALA/git/saske/mvala/zmon'
  CC       src/src_libzmon_la-zmon_gtop.lo
  CCLD     src/libzmon.la
make[1]: *** No rule to make target 'zproject.gsl', needed by 'all-am'.  Stop.
make[1]: Leaving directory '/home/mvala/MVALA/git/saske/mvala/zmon'
Makefile:1000: recipe for target 'all-recursive' failed
make: *** [all-recursive] Error 1

Problem: Cannot identify zeromq sockets by type in bindings

czmq uses void pointers to pass sockets. This is not necessarily the case for bindings as they might wrap zsock or zactor and pass them. IMO it is easiest to add another type named socket or zsocket to identify socket parameters in the api.

Comments please ;-)

Problem: Ruby Finalizers are broken

In Short: because of the way the finalizers are created they cannot be run.

Solution:
something like this may work, cannot test it myself for the upcomming days.

def initialize(ptr, finalize = true)
  @ptr = ptr
  @finalize = finalize
  if @ptr.null?
    @ptr = nil
  elsif @finalize
    ObjectSpace.define_finalizer(@ptr, self.class.create_finalizer_for(@ptr.address))
  end
end

def self.create_finalizer_for(ptr_address)
  ->(obj_id) do
    ptr = FFI::MemoryPointer.new(:pointer)
    ptr.write_pointer(FFI::Pointer.new(ptr_address))
    ::$(project.RubyName:)::FFI.$(class.c_name)_$(destructor.c_name) ptr
  end
end

Problem: No convienient way to generate actor skeleton

While working on a new project I found myself creating multiple actors. I used zproject to generate the class skeleton which worked all nicely but then I needed to manually adjust the header and source files to add the actor method startup and shutdown functionality. As actors very useful, I like to add skeleton generation for them. I would like your input on how to do this in the project.xml:

Option 1:

<class name = "myactor" type = "actor" private = "0|1"></class>

Option 2:

<actor name = "myactor" private = "0|1"></actor>

Problem(s): sub-dependencies cannot be conditional on version, and a dependency is always linked against

Hello,

As discussed in zeromq/czmq#1048 I was trying to add a CI target for CMake in Zproject, so that it could be auto-generated, after hard-coding it into CZMQ.

Unfortunately, I do not think it can be done at the moment, and would require one of these two problems to be solved in order to be possible.

  1. There is currently no way of making a dependency of a dependency conditional on the dependency version.

The problem is CZMQ and libsodium: when compiling CZMQ against ZMQ < 4, libsodium is not needed. When compiling against ZMQ >= 4, libsodium is needed.

  1. There is currently no way of adding a dependency of a dependency that only gets installed (EG: for CI purposes), but not added to the pkg-config check and linked against. As the generator code currently works, the dependency of a dependency is automatically also a dependency. But that is generally not true.

By having the following in zproject_known_projects.xml:

    <use project = "zmq"
        repository = "https://github.com/zeromq/libzmq"
        test = "zmq_init"
        cmake_name = "ZeroMQ">
        <use project = "sodium" />
    </use>

Sodium becomes a mandatory dependency regardless of the ZMQ version, since CZMQ will always link to it. The problem affects the main build, with autotools (which is not auto-generated on CZMQ), but more importantly with general distribution outside of the CI: if libsodium is added as a dependency, every single build will need it, even if ZMQ < 4.

In my opinion this is conceptually wrong. If CZMQ used symbols from libsodium, then it would be a dependency and it would be linked against. But if it does not use any of the symbols from libsodium, then it should not be linked against it only because ZMQ depends on it. Only ZMQ should link against it.

Problem: ruby bindings aren't very ruby like

Currently trying to work with the czmq ruby bindings, the code you have to write to make it work is very c like

As far as i can see, no exceptions are thrown but null pointers and "error codes" instead.
Zmsg.recv for instance requires one to dig into the source code and find out there is no #to_ptr method for a Zsock instance, but only a #__ptr method.

FFI.errno = 0
zmsg = Zmsg.recv zsock.__ptr
if zmsg.null?
  raise SystemCallError.new("Zmsg.recv", FFI.errno)
end
first_frame = zmsg.first
puts first_frame.data.read_bytes(first_frame.size)
until (next_frame = zmsg.next).null?
  puts next_frame.data.read_bytes(next_frame.size)
end

This could be done like this

zmsg = Zmsg.recv zsock
zmsg.each do |zframe|
  puts "frame contents: #{zframe}"
end

ruby-ffi looks for a #to_ptr method on every object which is not a FFI Object and calls it automatically, so a renaming of #__ptr to #to_ptr would solve the issue in the first line.

Basic Error checking could be done too. Something like this for functions which return a int.

FFI.errno = 0
if some_method_call == -1
  raise SystemCallError.new(FFI.errno)
end

Something like a Zframe could get a #to_str method which would turn a Zframe into a ruby String.

I believe when it comes to direct interaction with FFI and C error checking it should be done in zproject.
Exposure of high level ruby functionality could be done in a high level wrapper.

libtool generated library version currently fixed

The current behavior fixes the LTVER used to specify the libtool library version (via -version-info) of the generated library to 2:0:1 which claims current version 2 with age 1 (back support). Given that it's fixed, there's no reason not to use the default of 0:0:0 when not specified. Alternately, a mapping must be provided between major.minor.revision which previously appeared in zproject to current.revision.age.

Problem: In autotools, *.so files are not properly linked to their dependency *.so files

This is broken since the merging of PR #66 and #70.

@pmienk: We need to fix this in a way that doesn't undo the work you did.

To summarize the problem, the resulting *.so files are not actually linked to their dependencies. This causes problem on the android platform, where libraries cannot see/call functions of their dependencies unless they are linked.

Here is the readelf output for a "normal" build for zyre on my desktop with zproject from before PR #66 and #70 were merged. (I truncated the rest of the output that is not relevant)

$ readelf -d /usr/local/lib/libzyre.so

Dynamic section at offset 0x1ddc0 contains 27 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libczmq.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libzmq.so.4]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000e (SONAME)             Library soname: [libzyre.so.1]

[...]

And here is the readelf output for a "normal" build for zyre on my desktop with the latest commit of zproject. Note that the zmq and czmq libraries are missing.

$ readelf -d /usr/local/lib/libzyre.so

Dynamic section at offset 0x1dde0 contains 25 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000e (SONAME)             Library soname: [libzyre.so.1]

[...]

I also note that in my config.log, I have LIBS='-lczmq -lzmq ' before the autoconf changes and LIBS='' now. It looks like maybe the intention is that LIBS is "replaced" by zmq_LIBS and czmq_LIBS in the new strategy, but something is not quite working here.

I also saw in src/Makemodule.am:

src_zyre_selftest_LDADD = \
    src/libzyre.la \
    ${zmq_LIBS} \
    ${czmq_LIBS}

It would seem to me that zmq_LIBS and czmq_LIBS should be linked to libzyre itself to solve our problem. If we can achieve that, having zmq_LIBS and czmq_LIBS explicitly linked to the selftest may become unecessary.

zproject_mkman is required on the build host

Problem: the generated Makefiles end up requiring zproject_mkman to build manpages. If the project files are stored into Git and the build host has no zproject nor even gsl installed, they are in trouble.
Solution: make it optional, or deliver the script/recipe among generated project files so it is guaranteed to exist.

Problem: <package_dependency /> makes gsl code too complicated

Having multiple expressions like:

for package_dependency where 
defined (package_dependency.for_lib) | 
defined (package_dependency.for_test) | 
defined (package_dependency.for_all)
...
endfor

in zproject_automake.gsl are making a mess out of the gsl code.

Solution:

Ruby bindings: format arguments

I've noticed that the format arguments aren't processed correctly. Given the following API declaration (example from zsock.xml):

      <method name = "connect">
          Connect a socket to a formatted endpoint
          Returns 0 if OK, -1 if the endpoint was invalid.
          <argument name = "format" type = "format" />      # this is the relevant line
          <return type = "integer" />
      </method>

which corresponds to the following C function declaration:

  //  Connect a socket to a formatted endpoint
  //  Returns 0 if OK, -1 if the endpoint was invalid.
  CZMQ_EXPORT int
      zsock_connect (zsock_t *self, const char *format, ...) CHECK_PRINTF (2);

It produces the following (correct) FFI binding:

        attach_function :zsock_connect, [:pointer, :string, :varargs], :int, **opts

But the following low-level Ruby binding method:

      # Connect a socket to a formatted endpoint        
      # Returns 0 if OK, -1 if the endpoint was invalid.
      def connect format, result
        raise DestroyedError unless @ptr
        format = String(format)
        result = ::CZMQ::FFI.zsock_connect @ptr, format, result
        result
      end

Apart from the very wrongly named second parameter, it's also makes calling this method impossible.

The method should actually use a variable length argument list as well, and pass them to the FFI-bound method, as follows:

      # Connect a socket to a formatted endpoint        
      # Returns 0 if OK, -1 if the endpoint was invalid.
      def connect format, *args
        raise DestroyedError unless @ptr
        format = String(format)
        result = ::CZMQ::FFI.zsock_connect @ptr, format, *args
        result
      end

Now, I tried to find code responsible for this bug inside https://github.com/zeromq/zproject/blob/master/zproject_bindings_ruby.gsl, but couldn't find it. I guess there has to be a new condition added: If an argument in the API-XML is of type format, then another argument has to be added, which will take up all the remaining arguments during a call.

If someone knows how to do this off the top of their head, I'd be very grateful.

Otherwise I guess I'll have to read up on GSL.

Problem: class api generators cannot specify arguments as optional/nullable

Currently looking into writing a mruby generator, some projects have method/constructor arguments which can either be a c string or NULL, mruby has a special argument type for that, where you can pass a string or nil value, or make that argument optional.

As far as i can see, the api generators don't have a way to tell if you can pass nil or omit that argument completely and default it to NULL.

python 3 compatibility

It seems the python binding generation is incompatible with python3

Around https://github.com/zeromq/zproject/blob/master/zproject_bindings_python.gsl#L297
(convenience) methods are used which are deprecated in python 3 because of the newer io system.

from: https://docs.python.org/3.3/c-api/file.html

These APIs are a minimal emulation of the Python 2 C API for built-in file objects, which 
used to rely on the buffered I/O (FILE*) support from the C standard library. In Python 3, 
files and streams use the new io module, which defines several layers over the low-level 
unbuffered I/O of the operating system.

If you look at https://docs.python.org/2.7/c-api/file.html you can see many methods are gone in python3. 2to3 is not taking this into account therefore the bindings fail in python3.

refering to: zeromq/czmq#998

Problem: api files cannot handle deprecated methods

An example from czmq (zsock_option.h):

#if (ZMQ_VERSION_MAJOR == 2)
//  Get socket options
CZMQ_EXPORT int zsock_hwm (void *self);
CZMQ_EXPORT int zsock_swap (void *self);
CZMQ_EXPORT int zsock_affinity (void *self);
#   if (ZMQ_VERSION_MINOR == 2)
CZMQ_EXPORT int zsock_rcvtimeo (void *self);
#   endif
#   if (ZMQ_VERSION_MINOR == 2)
CZMQ_EXPORT int zsock_sndtimeo (void *self);
#   endif
...
#endif

Ruby binding incomplete

Hi

I'm taking another approach at wrapping up a high-level Ruby binding based on the low-level Ruby bindings generated by this project. (https://github.com/paddor/cztop)

I get why the zchunk_* functions aren't attached. But is there a reason why the zauth_* and zcert_* functions aren't attached in the FFI binding?

Also, structs like the zmq_pollitem_t (although from libzmq) aren't defined. What's the way to go here? Just asking.

Also, there are no tests. Would it make sense to call all the z*_test functions?

Problem: there is no CI for OSX

Hello,

Travis supports OSX builds as a opt-in beta: http://docs.travis-ci.com/user/multi-os/

I requested my CZMQ fork to be enabled, and I did some work in libzmq, zeromq4-x, zeromq4-1, zproject and czmq to get it to work.

In case you are interested in enabling it, I am going to submit a set of PRs to fix the travis config and the ci_build environment so that it works on both Linux and OSX. The only code changes needed are backporting a test timeout fix that is in libzmq but not in zeromq4-1 and zeromq4-x, the rest is in the CI build scripts.

To enable OSX on a project, it is necessary to send an email to [email protected] with a link to the project, asking to be added.

Here is a CZMQ full run (with all the various ZMQ versions):

https://travis-ci.org/bluca/czmq/builds/73772078

(usability): ZProject returns project.xml errors one by one

Problem: if the project.xml lacks some required fields, etc., then zproject reports the first error and quits. This causes a need for several iterations to fix the basic issues.

Solution: add a mode like "make -k" to not abort on errors and report more of them at once.

Problem: Build on OS X fails

On OSX 10.10.2 and with autotools installed via Homebrew, the build fails.

$ ./autogen.sh                                                                                                                              [0:25:28]
autoreconf: Entering directory `.'
autoreconf: configure.ac: not using Gettext
autoreconf: running: aclocal -I config --force -I config
autoreconf: configure.ac: tracing
autoreconf: running: glibtoolize --copy --force
glibtoolize: putting auxiliary files in AC_CONFIG_AUX_DIR, `config'.
glibtoolize: copying file `config/ltmain.sh'
glibtoolize: putting macros in AC_CONFIG_MACRO_DIR, `config'.
glibtoolize: copying file `config/libtool.m4'
glibtoolize: copying file `config/ltoptions.m4'
glibtoolize: copying file `config/ltsugar.m4'
glibtoolize: copying file `config/ltversion.m4'
glibtoolize: copying file `config/lt~obsolete.m4'
autoreconf: running: /usr/local/Cellar/autoconf/2.69/bin/autoconf --include=config --force
autoreconf: running: /usr/local/Cellar/autoconf/2.69/bin/autoheader --include=config --force
autoheader: cannot rename /var/folders/qx/60b1pl155yv3r92hhtmg78l40000gn/T//arEjFCdm/ahNZl6F8/config.hin as src/platform.h.in: No such file or directory
autoreconf: /usr/local/Cellar/autoconf/2.69/bin/autoheader failed with exit status: 1
autogen.sh: error: autoreconf exited with status 0

The second autoreconf step fails, as the second last line reports. (Last error message is wrong, see #139)

It can't copy over the platform.h.in config header input file, because the src directory doesn't exist.

If I run

mkdir src

it fails one step later when trying to read src/Makemodule.am. Again this is easiy solved by

touch src/Makemodule.am

as an empty file is sufficient here.

These are likely only bootstrapping problems. But they can easily trip up new users.

Problem: Need an automated way to generate language bindings.

I'd like to set up a system that can automatically generate language bindings for projects using zproject. Particularly, I'm interested in automating the process for Ruby bindings and QML bindings from a single model, although the process could be generalized to other languages by other contributors. However, I'm not sure this is a good fit for zproject itself.

Suggested solution: Create new project zbinding as a partner for zproject with gsl scripts dedicated to generating various language bindings from <class> ... </class> models (as well as the C class headers they bind to, maybe?).

I wanted to bring this up here first in case anyone else had plans in this direction already so that we could coordinate. If no one else has plans or cares at the moment, I'll make the new repository under the zproject-maintainers group and forge on ahead.

@hintjens, @sappo, @lovmoen
Thoughts?

Problem: prelude headers collide

Currently when, for example, czmq is combined with zyre and you have CFLAGS: -Werror=pedantic, you get a long list of typedef collisions as errors.

Possible solution: remove prelude header from zproject and leave the proper preluding to czmq?

@sappo , @hintjens
Thoughts?

Problem:can't link with libczmq any longer

E.g. in malamute/malamute-core, linking main programs fails with:

/usr/bin/ld: src/mshell.o: undefined reference to symbol 'zsys_error'
/usr/bin/ld: note: 'zsys_error' is defined in DSO /usr/local/lib/libczmq.so.1 so try adding it to the linker command line
/usr/local/lib/libczmq.so.1: could not read symbols: Invalid operation
collect2: ld returned 1 exit status
make[1]: *** [src/mshell] Error 1
make[1]: *** Waiting for unfinished jobs....
/usr/bin/ld: src/malamute.o: undefined reference to symbol 'zsys_daemonize'
/usr/bin/ld: note: 'zsys_daemonize' is defined in DSO /usr/local/lib/libczmq.so.1 so try adding it to the linker command line
/usr/local/lib/libczmq.so.1: could not read symbols: Invalid operation
collect2: ld returned 1 exit status
make[1]: *** [src/malamute] Error 1
make[1]: Leaving directory `/home/ph/work/hintjens/malamute-core'
make: *** [all-recursive] Error 1

This is new, it's been working fine so far. So I suspect some recent changes in zproject.

Proposal for zproject_class.gsl reorganisation and simplification

I've been looking at zproject_class.gsl implementation, and would like to propose the following changes. Please comment if there is good reason to maintain any aspect of the current implementation.

  • Remove the initial generation and regeneration of the class header. The file only contains generated output, and not user edits that need preserving, so this seems to be a hangover from earlier.
  • Make constructor, destructor, print and test methods defaults in the 'method' collection if not specified in the api model. Use these for generation in the header and initial source module, as opposed to canned. This allows for more flexibility in arguments.
  • Rename zproject_class.gsl to zproject_binding_c.gsl for consistency with other bindings
  • Rename zproject_class_api.gsl to zproject_utils_c.gsl for clarity. Other bindings could follow if desired for consistency and improved modularity.
  • Allow for 'delete' option on constructor, destructor, print and test methods to suppress output. I have a use case where the constructor is not required.

Problem: when request zyre in my project, it wants to have czmq 3.1.0

In zproject_known_projects.xml there is

    <use project = "zyre"
        repository = "https://github.com/zeromq/zyre"
        test = "zyre_test">
        <use project = "czmq" min_major = "3" />
    </use>

when i add to my project.xml

<use project = "zyre" min_major= "1" min_minor = "1" min_patch = "0" />

i am getting following error

checking for czmq... no
configure: error: Cannot find required package for libczmq. Note, pkg-config is required due to specified version >= 3.1.0

Since czmq 3.1.0 doesn't exists.

I am going to do merge request to fix it soon

Problem: Fatal error in resolve_includes ()

When running ./generate.sh with latest zproject installed on a project.xml that includes another xml file (like license.xml), the following fatal error occurs:

2014/11/05 20:25:17: GSL/4.1a/github Copyright (c) 1996-2011 iMatix Corporation
2014/11/05 20:25:17: gsl/4 I: Processing project.xml...
2014/11/05 20:25:17: (project.gsl 11) Undefined expression: project.load_file (...)

I've tried a little bit of debugging here, but I'm not sure what part of the expression gsl is calling "undefined" in this context - load_file should be a function of the XML object, and I've tried using a string literal in the parentheses in case filename is missing in this context somehow.

Someone with more gsl knowledge want to take a look?

It may also be a good idea to add an include like a license to the project.xml of zproject as a kind of integration test every time someone generates the zproject project locally.

Problem: need 'make code' target

Solution: generate 'make code' for any models defined in project:

<model name = "mywhatever" />

Optionally passing script argument:

<model name = "mywhatever" script = "weirdalternative.gsl" />

Problem: CZMQ uses pthread symbols, but does not link to it

Commit zeromq/czmq@5ea2e81 changed to use zproject's auto-generated configure.ac and Makefile.am, but in the process this was lost:

AC_CHECK_LIB([pthread], [pthread_create])

And when building the library, -pthread is not used.

Among the other problems, this causes warnings when building a Debian package:

dpkg-shlibdeps: warning: symbol pthread_mutex_trylock used by
 debian/libczmq3/usr/lib/x86_64-linux-gnu/libczmq.so.3.0.0 found in none
 of the libraries
dpkg-shlibdeps: warning: symbol pthread_detach used by
 debian/libczmq3/usr/lib/x86_64-linux-gnu/libczmq.so.3.0.0 found in none
 of the libraries
dpkg-shlibdeps: warning: symbol pthread_create used by
 debian/libczmq3/usr/lib/x86_64-linux-gnu/libczmq.so.3.0.0 found in none
 of the libraries

The diff for the generated configure.ac and Makefile.am is really trivial:

+--- a/configure.ac
++++ b/configure.ac
+@@ -69,6 +69,13 @@
+     fi
+ fi
+ 
++# Checks for libraries
++AC_CHECK_LIB([pthread], [pthread_create], [
++       have_pthread=yes
++       pthread_LIBS="-pthread"],
++    [AC_MSG_ERROR([pthread is required for this program])])
++AC_SUBST(pthread_LIBS)
++
+ PREVIOUS_CFLAGS="${CFLAGS}"
+ PREVIOUS_LIBS="${LIBS}"
+ 
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -10,6 +10,7 @@
+     -I$(srcdir)/include
+ 
+ project_libs = \
++    ${pthread_LIBS} \
+     ${zmq_LIBS}
+ 
+ SUBDIRS =

But I cannot see where/how to do it in the template, in a way that's optional and it would apply only to CZMQ and not to other projects.

Does anyone have any pointer? I'm happy to do a PR once I figure it out :-)

README.txt incomplete for created new projects (missing license.xml)

The README.txt states:

Generate build environment in your project

Copy the project.xml and generate.sh to your project or an empty directory and adjust the values accordingly.

run ./generate.sh

the license.xml file should also be copied (and adapted) in order for the generate.sh to work.

Thoughts on zproject.

I'm sure you have already thought of a lot of these things, but I thought I'd just drop a line and share my two cents worth of ideas around zproject. The top-level use case that I would like to see implemented is having just one config-file, the model/project.xml define the whole project. Extending the project.gsl scripting to generating every input to the autotoolchain and build definitions would be highly beneficial for non-autotool savvies like me. (And I guess as much for those not familiar with msvc when it comes to setting up project files for that environment.) I foresee adding interpretation of such tags as "target", "extradist" etc to be able to build and package everything.
Additionally, zproject should offer a zproject_create script that generates the skeleton project, optionally performs git init etc. Skeleton versions of config files and scripts, project include etc should be generated automatically.
Again, I'm sure this is elementary stuff to you, I just needed to put down my thoughts somewhere, and couldn't think of a better place to do it than here. :-) And please drop me a line if I can do anything to help out!

Problem: Need consistent pattern for when class.name = project.name

Problem: Need consistent pattern for when class.name = project.name

In the current implementation, the project header clobbers the class header if the same name is used.

In zyre, for example, the switch to zproject moved the header for the zyre class from zyre.h to zyre_api.h. This breaks consistency, because the methods for $(class.name)_t are supposed to live in #(class.name).h. Also, the current arrangement seems a bit counterintuitive, because on the surface, if shown the two filenames zyre_api.h and zyre.h I would expect zyre_api.h to be the general api and zyre.h to be the specific class. However, even this runs counter to expectations, because one expects $(project.name).h to be the main include file for a given project. We're going to encounter the same problem in the edgenet/drops project.

For reference, here is the zyre commit:
zeromq/zyre@b39b96d

I'm not sure what the best solution here is, but I do know we need to establish a consistent pattern to employ for zyre, drops, and future projects that may have the main class name share the project name.

Ideas?

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.