[med-svn] [Git][med-team/libedlib][upstream] New upstream version 1.2.7

Andreas Tille (@tille) gitlab at salsa.debian.org
Wed Oct 13 14:47:35 BST 2021



Andreas Tille pushed to branch upstream at Debian Med / libedlib


Commits:
81add7e1 by Andreas Tille at 2021-10-13T11:51:04+02:00
New upstream version 1.2.7
- - - - -


19 changed files:

- .gitignore
- .travis.yml
- CMakeLists.txt
- + Makefile
- README.md
- appveyor.yml
- bindings/python/.gitignore
- bindings/python/Makefile
- bindings/python/README.rst → bindings/python/README-tmpl.rst
- + bindings/python/README.md
- bindings/python/cedlib.pxd
- bindings/python/edlib.pyx
- bindings/python/setup.py
- bindings/python/test.py
- + edlib-config.cmake.in
- edlib.pc.in
- edlib/include/edlib.h
- edlib/src/edlib.cpp
- + meson.build


Changes:

=====================================
.gitignore
=====================================
@@ -24,3 +24,6 @@ callgrind.out.*
 core
 
 TAGS
+
+/meson-build
+/installation


=====================================
.travis.yml
=====================================
@@ -1,92 +1,169 @@
+# This ensures only commits on master, PRs towards master, and all tags are built.
+# Otherwise, build does not start.
+if: branch = master OR tag IS present
+
 language: cpp
-dist: trusty
 
-# In order to catch as many weird edge cases in the code with -Werror as
-# possible, we want to test a large range of old and new compilers on both
-# Linux and macOS. This gives us the best possible coverage while maintaining
-# compatibility with a large number of compilers.
-matrix:
+os: linux
+
+dist: xenial
+
+stages:
+  - ccpp
+  - python
+
+env:
+  global:
+    - TWINE_USERNAME=Martinsos
+    # Encrypted TWINE_PASSWORD:
+    - secure: "VfgRi/hcUMLDYzATLS8JOuZo+wg0VNCmEojIJ3gpy89LAXgPN1Qx/2n3c52PPgFWgWFdDgns2SdxhQ1/810qb+65choy2fOgTULnyFcH3ZFTM5nINVHlGB5dLDUesKjrqqfIKHnwB6LAskHqHHPm/qv7WxUjQbcpR6mICsKB7h3NI7yUSc3tRPmd8tVBc/mTUXpMRVznTxGFCo/rC4f2y57GI9odjDxS4VqGS8T9Igvgyteg+ougXYbl84FIi3Bij6TQITa1rP9cFw/lfXMTM2m1czTonzAbgGPC6q7798MCGhLpEdxr+Zu9NPCS8aWFYdxMUYmsisjffDtTdIagZFh/14YrnQb2RxqnLTqSi20E+xXx16GcHhnMOxw/sSOh6HUEaXcbLNtx/mqMEa7mQEcIFBdXHWs/czTHz8xEoGnHIVHI5zqItoK3nUD0W/X6XUex8GP8obvjSKVw2k8X/0bZUaqSyNVbTfYcLmOk53Kx8vfXd82BbTOWiJVZmvuugqrshIEaLOyRhSaoC4Bj5KjfijM/gKPa+n8wVEQ/4hF4HpJKr/33cAm1URDGsDnfvHfxfeEwizTq8gCIxnbpOzSsd1M6+3MQLr48DE8uYM+wkG2F+KsCKe3OexLiaqHG7rVZh1R99nOykoqfjhxek3H1KGfx7qFbdK80AaVBiQo="
+
+.ccpp: &ccpp
+  stage: ccpp # Builds C/CPP code.
+    
+  before_install:
+    - sudo -H pip3 install -U pip # Needed for Meson.
+    - sudo -H pip3 install -U setuptools # Needed for Meson.
+    - eval "${MATRIX_EVAL}"
+    
+  install:
+    - sudo -H pip3 install meson ninja # We use Ninja both with Meson and CMake.
+    
+  script:
+    # Build library and binaries using Meson and test them.
+    # Static library.
+    - make CXXFLAGS="-Werror" LIBRARY_TYPE=static BUILD_DIR=meson-build-static
+    # Shared library.
+    - make CXXFLAGS="-Werror" LIBRARY_TYPE=shared BUILD_DIR=meson-build-shared
+
+    # Check for memory leaks.
+    # I run this only on linux because osx returns errors from
+    # system libraries, which I would have to supress.
+    - |
+      if [ $TRAVIS_OS_NAME == "linux" ]; then
+        make check-memory-leaks BUILD_DIR=meson-build-static
+      fi
+
+    # Build library and binaries with CMake and test them.
+    - mkdir -p build && cd build
+    - CXXFLAGS="-Werror" cmake -GNinja ..
+    - ninja -v
+    - bin/runTests
+    - cd ..
+
+.python: &python
+  stage: python # Builds python binding.
+
+  install:
+    - wget -qO- https://bootstrap.pypa.io/get-pip.py | python3
+    - python3 -m pip install cibuildwheel==1.6.1
+
+  before_script:
+    - cd bindings/python
+
+  script:
+    # Build the wheels, put them into './wheelhouse'.
+    # cibuildwheel needs to be run from python directory.
+    # The python directory is mounted in the docker build containers,
+    # so we need to copy the edlib source before running cibuild wheel.
+    - make edlib # Copies edlib source to python dir.
+    - |
+      CIBW_SKIP="cp27-* pp* *-manylinux_i686" \
+      CIBW_BEFORE_BUILD="make sdist" \
+      CIBW_TEST_COMMAND="python3 {project}/test.py" \
+      python3 -m cibuildwheel --output-dir wheelhouse
+    - if [ $DEPLOY_SDIST_TO_PYPI ]; then make sdist; fi
+
+    # Deploy wheel(s) and source (sdist) to PYPI (if commit is tagged).
+    # NOTE: We are doing this in script section, and not in after_success,
+    #   because we want build to fail if deploying fails, which does not
+    #   happen if deployment is done inside after_success (that is how
+    #   travis works).
+    # NOTE: We check TRAVIS_TEST_RESULT because we don't want to deploy
+    #   if building failed.
+    - |
+      if [ $TRAVIS_TEST_RESULT -eq 0 ]; then
+        if [ $TRAVIS_TAG ]; then
+          # upgrade and upgrade-strategy-eager are here because of https://travis-ci.community/t/cant-deploy-to-pypi-anymore-pkg-resources-contextualversionconflict-importlib-metadata-0-18/10494/14 .
+          python3 -m pip install --upgrade --upgrade-strategy eager twine
+          python3 -m twine upload wheelhouse/*.whl
+          if [ $DEPLOY_SDIST_TO_PYPI ]; then
+            python3 -m twine upload dist/edlib-*.tar.gz
+          fi
+        else
+          echo "Skipping twine upload because not a tag, files built:"
+          ls -l wheelhouse
+          ls -l dist
+        fi
+      fi
+
+jobs:
   include:
-    - name: "GCC 4.9 (Linux)"
+    # In order to catch as many weird edge cases in the code with -Werror as
+    # possible, we want to test a large range of old and new compilers on both
+    # Linux and macOS. This gives us the best possible coverage while maintaining
+    # compatibility with a large number of compilers.
+    - name: "C/CPP (Linux; GCC 4.9)"
       os: linux
       addons:
         apt:
-          sources:
-            - ubuntu-toolchain-r-test
           packages:
             - g++-4.9
-            - ninja-build
+            - valgrind
+            - python3
+            - python3-pip
       env:
          - MATRIX_EVAL="export CC=gcc-4.9 && export CXX=g++-4.9"
+      <<: *ccpp
 
-    - name: "GCC 9 (Linux)"
+    - name: "C/CPP (Linux; GCC 9)"
       os: linux
       addons:
         apt:
           sources:
-            - ubuntu-toolchain-r-test
+            - ubuntu-toolchain-r-test # For g++-9
           packages:
             - g++-9
-            - ninja-build
+            - valgrind
+            - python3
+            - python3-pip
       env:
         - MATRIX_EVAL="export CC=gcc-9 && export CXX=g++-9"
+      <<: *ccpp
 
-    - name: "Clang 5.0 (Linux)"
+    - name: "C/CPP (Linux; Clang 5.0)"
       os: linux
       addons:
         apt:
-          sources:
-            - llvm-toolchain-trusty-5.0
           packages:
             - clang-5.0
-            - ninja-build
+            - valgrind
+            - python3
+            - python3-pip
       env:
         - MATRIX_EVAL="export CC=clang-5.0 && export CXX=clang++-5.0"
+      <<: *ccpp
 
-    - name: "Clang Xcode 7.3 (Mac)"
+    - name: "C/CPP (OSX; XCode 11; Clang)"
       os: osx
-      osx_image: xcode7.3
-      addons:
-        homebrew:
-          packages:
-            - ninja
-          update: true
+      osx_image: xcode11
+      <<: *ccpp
+
+    - name: "Python wheel (Linux)"
+      os: linux
+      language: python
+      python:
+        - "3.6"
+      services: docker
+      env:
+        # We need to upload sdist only once, since it is same for all jobs,
+        # so with this flag we specify which job will take care of that (this one).
+        - DEPLOY_SDIST_TO_PYPI="true"
+      <<: *python
 
-    - name: "Clang Xcode 11 (Mac)"
+    - name: "Python wheel (OSX)"
       os: osx
-      osx_image: xcode11
-      addons:
-        homebrew:
-          packages:
-            - ninja
-
-# NOTE: Currently I commented out testing of python binding on OSX because they do not support
-# Python building and I have to provide the tools myself. I could probably install correct pip
-# (and maybe python) version myself (homebrew?), however I haven't gotten to that yet.
-
-before_install:
-  - eval "${MATRIX_EVAL}"
-
-install:
-  - if [ $TRAVIS_OS_NAME == "linux" ]; then sudo apt-get install valgrind; fi
-  - if [ $TRAVIS_OS_NAME == "linux" ]; then sudo -H pip install cython; fi  # Needed to build Python module.
-
-before_script:
-  # Build C/C++ library and apps.
-  - mkdir -p build && cd build && CXXFLAGS="-Werror" cmake -GNinja .. && ninja -v && cd ..
-
-  # Build Python source distribution and install Edlib from it.
-  - if [ $TRAVIS_OS_NAME == "linux" ]; then cd bindings/python && make sdist && cd ../..; fi
-  - if [ $TRAVIS_OS_NAME == "linux" ]; then sudo -H pip install bindings/python/dist/edlib*.tar.gz; fi
-
-script:
-  # Test C/C++ library using CTest.
-  - ninja -C build -v test && cat build/Testing/Temporary/LastTest.log
-  # Check for memory leaks. Returns 2 if there was a memory leak/error, otherwise returns runTests exit code,
-  # which is 0 if all went fine or 1 if some of the tests failed. I test for memory leaks only on linux because
-  # osx returns errors from system libraries, which I would have to supress.
-  # This is run only on smaller number of tests, since executing on valgrind is slow.
-  - if [ $TRAVIS_OS_NAME == "linux" ]; then valgrind --quiet --error-exitcode=2 --tool=memcheck --leak-check=full build/bin/runTests 2; fi
-
-  # Test Python module.
-  - if [ $TRAVIS_OS_NAME == "linux" ]; then sudo -H python bindings/python/test.py; fi
+      language: shell
+      <<: *python
+
+    # TODO: Add windows x64 and linux aarch64 python wheel builds? Edlib users said they need them.


=====================================
CMakeLists.txt
=====================================
@@ -1,5 +1,9 @@
 cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
-project(edlib VERSION 1.2.5)
+project(edlib VERSION 1.2.6)
+
+option(EDLIB_ENABLE_INSTALL "Generate the install target" ON)
+option(EDLIB_BUILD_EXAMPLES "Build examples" ON)
+option(EDLIB_BUILD_UTILITIES "Build utilities" ON)
 
 set(MACOSX (${CMAKE_SYSTEM_NAME} MATCHES "Darwin"))
 
@@ -10,7 +14,7 @@ endif()
 include(GNUInstallDirs)
 include(CheckCXXCompilerFlag)
 
-set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD 14)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)  # Falling back to different standard it not allowed.
 set(CMAKE_CXX_EXTENSIONS OFF)  # Make sure no compiler-specific features are used.
 
@@ -48,18 +52,29 @@ file(GLOB SOURCES "edlib/src/*.cpp")
 
 # Create libraries.
 add_library(edlib ${SOURCES})
+add_library(edlib::edlib ALIAS edlib)
 set_target_properties(edlib
-    PROPERTIES
+  PROPERTIES
+    CXX_VISIBILITY_PRESET hidden
+    VISIBILITY_INLINES_HIDDEN ON
     VERSION ${PROJECT_VERSION}
-    SOVERSION ${PROJECT_VERSION})
+    SOVERSION ${PROJECT_VERSION_MAJOR}
+)
+
+target_compile_definitions(edlib PRIVATE DLIB_BUILD)
+if(BUILD_SHARED_LIBS)
+  target_compile_definitions(edlib PUBLIC EDLIB_SHARED)
+endif()
 
 target_include_directories(edlib PUBLIC
     $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/edlib/include>
-    $<INSTALL_INTERFACE:include>)
+    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
 
 # Build binaries.
-add_executable(helloWorld apps/hello-world/helloWorld.c)
-target_link_libraries(helloWorld edlib)
+if(EDLIB_BUILD_EXAMPLES)
+  add_executable(helloWorld apps/hello-world/helloWorld.c)
+  target_link_libraries(helloWorld edlib)
+endif()
 
 include(CTest)
 if (BUILD_TESTING)
@@ -69,19 +84,63 @@ if (BUILD_TESTING)
   add_test(edlib_tests ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/runTests)
 endif()
 
-if (NOT WIN32) # If on windows, do not build binaries that do not support windows.
-  add_executable(edlib-aligner apps/aligner/aligner.cpp)
-  target_link_libraries(edlib-aligner edlib)
+if(EDLIB_BUILD_UTILITIES)
+  if(NOT WIN32) # If on windows, do not build binaries that do not support windows.
+    add_executable(edlib-aligner apps/aligner/aligner.cpp)
+    target_link_libraries(edlib-aligner edlib)
+  endif()
 endif()
 
-
-# Create target 'install' for installing libraries.
-install(TARGETS edlib DESTINATION ${CMAKE_INSTALL_LIBDIR})
-install(FILES edlib/include/edlib.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
-
 # configure and install pkg-config file
+set(PKG_EDLIB_DEFS "")
+get_target_property(EDLIB_INTERFACE_DEFS edlib INTERFACE_COMPILE_DEFINITIONS)
+if(NOT (EDLIB_INTERFACE_DEFS STREQUAL "NOTFOUND" OR EDLIB_INTERFACE_DEFS STREQUAL "EDLIB_INTERFACE_DEFS-NOTFOUND"))
+  foreach(EDLIB_INTERFACE_DEF ${EDLIB_INTERFACE_DEFS})
+    list(APPEND PKG_EDLIB_DEFS "-D${EDLIB_INTERFACE_DEF}")
+  endforeach()
+endif()
+string(REPLACE ";" " " PKG_EDLIB_DEFS "${PKG_EDLIB_DEFS}")
 configure_file(
     ${CMAKE_CURRENT_SOURCE_DIR}/edlib.pc.in
-    ${CMAKE_CURRENT_BINARY_DIR}/edlib-1.pc
+    ${CMAKE_CURRENT_BINARY_DIR}/edlib-${PROJECT_VERSION_MAJOR}.pc
     @ONLY)
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/edlib-1.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
+
+if(EDLIB_ENABLE_INSTALL)
+  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/edlib-${PROJECT_VERSION_MAJOR}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
+  include(CMakePackageConfigHelpers)
+  set(EDLIB_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/edlib" CACHE STRING
+    "Installation directory for cmake files, relative to ${CMAKE_INSTALL_PREFIX}.")
+  set(version_config "${PROJECT_BINARY_DIR}/edlib-config-version.cmake")
+  set(project_config "${PROJECT_BINARY_DIR}/edlib-config.cmake")
+  set(targets_export_name edlib-targets)
+
+  # Generate the version, config and target files into the build directory.
+  write_basic_package_version_file(
+    ${version_config}
+    VERSION ${VERSION}
+    COMPATIBILITY AnyNewerVersion)
+  configure_package_config_file(
+    ${PROJECT_SOURCE_DIR}/edlib-config.cmake.in
+    ${project_config}
+    INSTALL_DESTINATION ${EDLIB_CMAKE_DIR})
+  export(TARGETS edlib NAMESPACE edlib::
+    FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake)
+
+  # Install version, config and target files.
+  # These are cmake config files and they are useful for some consumers, for example vcpkg.
+  install(
+    FILES ${project_config} ${version_config}
+    DESTINATION ${EDLIB_CMAKE_DIR})
+  install(EXPORT ${targets_export_name} DESTINATION ${EDLIB_CMAKE_DIR}
+    NAMESPACE edlib::)
+  
+  # Create target 'install' for installing libraries.
+  install(
+    TARGETS edlib
+    EXPORT ${targets_export_name} 
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+  )
+  install(FILES edlib/include/edlib.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+endif()


=====================================
Makefile
=====================================
@@ -0,0 +1,45 @@
+BUILD_DIR ?= meson-build
+# Can be 'static' or 'shared'.
+LIBRARY_TYPE ?= static
+TEST_DATA_DIR ?= apps/aligner/test_data
+
+YELLOW = \033[33m
+GREEN  = \033[32m
+BOLD   = \033[1m
+RESET  = \033[0m
+
+all:
+	@printf "${YELLOW}${BOLD}Configuring build setup via Meson...${RESET}\n"
+	${MAKE} configure
+	@printf "\n${YELLOW}${BOLD}Building ${LIBRARY_TYPE} library and binaries...${RESET}\n"
+	${MAKE} build
+	@printf "\n${YELLOW}${BOLD}Running tests...${RESET}\n"
+	${MAKE} test
+	@printf "\n${GREEN}${BOLD}Edlib successfully built! You can find built binaries and libraries in ${BUILD_DIR}/ directory.${RESET}\n"
+
+configure:
+	rm -rf ${BUILD_DIR}
+	meson setup ${BUILD_DIR} . \
+		--backend=ninja \
+    -Ddefault_library=${LIBRARY_TYPE}
+
+build:
+	meson compile -v -C ${BUILD_DIR}
+
+test:
+	meson test -v -C ${BUILD_DIR}
+
+# Valgrind Returns 2 if there was a memory leak/error,
+# otherwise returns runTests exit code, which is 0 if
+# all went fine or 1 if some of the tests failed.
+check-memory-leaks:
+	valgrind ${BUILD_DIR}/runTests 2 \
+    --quiet --error-exitcode=2 --tool=memcheck --leak-check=full
+
+install:
+	meson install -C ${BUILD_DIR}
+
+clean:
+	rm -rf ${BUILD_DIR}
+
+.PHONY: all build configure test install clean check-memory-leaks


=====================================
README.md
=====================================
@@ -1,8 +1,8 @@
 Edlib
 ·
 [![Latest Github release](https://img.shields.io/github/release/Martinsos/edlib.svg)](https://github.com/Martinsos/edlib/releases/latest)
-[![Build status of the master branch on Linux/OSX](https://img.shields.io/travis/Martinsos/edlib/master.svg?label=Linux%20%2F%20OSX%20build)](https://travis-ci.org/Martinsos/edlib)
-[![Build status of the master branch on Windows](https://img.shields.io/appveyor/ci/Martinsos/edlib.svg?label=Windows%20build)](https://ci.appveyor.com/project/Martinsos/edlib/branch/master)
+[![Build status of the master branch on Linux/OSX](https://img.shields.io/travis/Martinsos/edlib/master?label=Linux%20%2F%20OSX%20build)](https://travis-ci.com/Martinsos/edlib)
+[![Build status of the master branch on Windows](https://img.shields.io/appveyor/build/Martinsos/edlib/master?label=Windows%20build)](https://ci.appveyor.com/project/Martinsos/edlib/branch/master)
 [![Chat on Gitter](https://img.shields.io/gitter/room/Martinsos/edlib.svg?colorB=753a88)](https://gitter.im/Martinsos/edlib)
 [![Published in Bioinformatics](https://img.shields.io/badge/Published%20in-Bioinformatics-167DA4.svg)](https://doi.org/10.1093/bioinformatics/btw753)
 =====
@@ -14,6 +14,10 @@ Calculating edit distance of two strings is as simple as:
 edlibAlign("hello", 5, "world!", 6, edlibDefaultAlignConfig()).editDistance;
 ```
 
+Edlib is also available for **Python** [![PyPI version](https://img.shields.io/pypi/v/edlib.svg) (Click here for Python README)](https://pypi.python.org/pypi/edlib), with code residing at [bindings/python](bindings/python).
+
+There is also non-official [binding for Julia](https://github.com/cjdoris/Edlib.jl) by @cjdoris.
+
 ## Features
 * Calculates **edit distance (Levenshtein distance)**.
 * It can find **optimal alignment path** (instructions how to transform first sequence into the second sequence).
@@ -23,8 +27,6 @@ edlibAlign("hello", 5, "world!", 6, edlibDefaultAlignConfig()).editDistance;
 * It can easily handle small or **very large sequences**, even when finding alignment path, while consuming very little memory.
 * **Super fast** thanks to Myers's bit-vector algorithm.
 
-Edlib is also available for **Python** [![PyPI version](https://img.shields.io/pypi/v/edlib.svg)](https://pypi.python.org/pypi/edlib) and **Node.js** [![npm version](https://img.shields.io/npm/v/node-edlib.svg)](https://www.npmjs.com/package/node-edlib).
-
 
 ## Contents
 - [Features](#features)
@@ -42,22 +44,6 @@ Edlib is also available for **Python** [![PyPI version](https://img.shields.io/p
 - [Acknowledgements](#acknowledgements)
 
 
-## Building
-Edlib uses CMAKE to build libraries (static and shared) and binaries (apps and tests).
-Execute following commands to build Edlib using CMAKE:
-
-1. `cd build`
-2. `cmake -D CMAKE_BUILD_TYPE=Release ..`
-3. `make`
-
-This will create binaries in `bin/` directory and libraries (static and shared) in `lib/` directory.
-You can run `./bin/runTests` to confirm that it works!
-
-Optionally, you can run `sudo make install` to install edlib library on your machine (on Linux, this will usually install it to `usr/local/lib` and `usr/local/include`).
-
-You may also install edlib using Conda [![Anaconda-Server Badge](https://anaconda.org/bioconda/edlib/badges/installer/conda.svg)](https://conda.anaconda.org/bioconda): `conda install edlib`.
-
-
 ## Using Edlib in your project
 You can use Edlib in you project by either directly copying header and source files from [edlib/](edlib/), or by linking Edlib library (see [Building](#building) for instructions how to build Edlib libraries).
 In any case, only thing that you have to do in your source files is to include `edlib.h`.
@@ -113,10 +99,11 @@ helloWorld.cpp -> your program
 Now you can compile it with `c++ helloWorld.cpp -o helloWorld -I edlib/include -L edlib -ledlib`.
 
 ### Approach #3: Install edlib library on machine.
-Alternatively, you could avoid copying any Edlib files and instead install libraries by running `sudo make install` (check [Building](#building)). Now, all you have to do to compile your project is `c++ helloWorld.cpp -o helloWorld -ledlib`.
+Alternatively, you could avoid copying any Edlib files and instead install libraries by running `sudo make install` (check [Building](#building) for exact instructions depending on approach you used for building). Now, all you have to do to compile your project is `c++ helloWorld.cpp -o helloWorld -ledlib`.
 If you get error message like `cannot open shared object file: No such file or directory`, make sure that your linker includes path where edlib was installed.
 
 ### Approach #4: Use edlib in your project via CMake.
+#### Using git submodule
 If you are using CMake for compilation, we suggest adding edlib as a git submodule with the command `git submodule add https://github.com/martinsos/edlib vendor/edlib`. Afterwards, modify your top level CMakeLists.txt file accordingly:
 ```
 add_subdirectory(vendor/edlib EXCLUDE_FROM_ALL)
@@ -127,6 +114,65 @@ The `add_subdirectory` command adds a folder to the build tree, meaning it will
 
 For more example projects take a look at applications in [apps/](apps/).
 
+#### Using VCPKG
+Edlib is available on [VCPKG](https://github.com/microsoft/vcpkg) package manager. With VCPKG on your system, Edlib can be downloaded using the VCPKG install command `vcpkg install edlib`. Once the library has been downloaded, add the following instructions to your CMakeLists.txt file:
+```
+find_package(edlib CONFIG REQUIRED)
+target_link_libraries(MyProject PRIVATE edlib::edlib)
+```
+
+then you should be able to include the library header in your project (`#include "edlib.h`)
+
+
+## Building
+### Meson
+Primary way of building Edlib is via [Meson](https://mesonbuild.com/) build tool.
+
+Requirements: make sure that you have `meson` installed on your system.
+
+Execute
+```
+make
+```
+to build **static** library and binaries (apps and tests) and also run tests.  
+To build **shared** library and binaries, do `make LIBRARY_TYPE=shared`.
+
+Library and binaries will be created in `meson-build` directory.  
+You can choose alternate build directory like this: `make BUILD_DIR=some-other-dir`.
+
+Optionally, you can run
+```
+sudo make install
+```
+to install edlib library on your machine (on Linux, this will usually install it to `usr/local/lib` and `usr/local/include`).
+
+Check Makefile if you want to run individual steps on your own (building, tests, ...).
+
+NOTE: If you need more control, use `meson` command directly, `Makefile` is here only to help with common commands.
+
+### CMake
+Edlib can alternatively be built with CMake.
+
+Execute following command to build Edlib using CMAKE:
+```
+cd build && cmake -D CMAKE_BUILD_TYPE=Release .. && make
+```
+This will create binaries in `bin/` directory and libraries (static and shared) in `lib/` directory.
+
+```
+./bin/runTests
+```
+to run tests.
+
+Optionally, you can run
+```
+sudo make install
+```
+to install edlib library on your machine.
+
+### Conda
+Edlib can also be installed via Conda: [![Anaconda-Server Badge](https://anaconda.org/bioconda/edlib/badges/installer/conda.svg)](https://conda.anaconda.org/bioconda): `conda install edlib`.
+
 
 ## Usage and examples
 Main function in edlib is `edlibAlign`. Given two sequences (and their lengths), it will find edit distance, alignment path or its end and start locations.
@@ -263,3 +309,8 @@ Martin Šošić, Mile Šikić; Edlib: a C/C ++ library for fast, exact sequenc
 Mile Šikić (@msikic) - Mentoring and guidance through whole project.
 
 Ivan Sović (@isovic) - Help with testing and prioritizing features, valuable comments on the manuscript.
+
+## FAQ
+
+### What do terms NW, HW and SHW stand for?
+NW stands for Needleman-Wunsch, HW for Hybrid Wunsch, and SHW for Semi Hybrid Wunsch. While NW is a common abbreviation, HW and SHW abbreviations were made up at the very start of this project to describe additional modes of alignment. Later we started using terms "global", "infix" and "prefix" more, as they describe the modes better, but terms NW, HW and SHW are still very present in the project.


=====================================
appveyor.yml
=====================================
@@ -1,31 +1,53 @@
 platform:
-- x64
-- x86
+  - x64
 
-environment:
-  matrix:
+branches:
+  only:
+    - master # This will still build PRs.
 
-# VS 2010
-  - BUILD_TYPE: cmake
-    VS_VERSION: Visual Studio 10
+image:
+  - Visual Studio 2017
+  - Visual Studio 2019
 
-# VS 2012
-  - BUILD_TYPE: cmake
-    VS_VERSION: Visual Studio 11
+environment:
+  matrix:
+    - arch: x86
+    - arch: x64
 
-# VS 2013
-  - BUILD_TYPE: cmake
-    VS_VERSION: Visual Studio 12
+install:
+  # Configuration for Meson
+  - cmd: if %arch%==x86 (set PYTHON_ROOT=C:\python37) else (set PYTHON_ROOT=C:\python37-x64)
+  - cmd: echo Using Python at %PYTHON_ROOT%
+  - cmd: set PATH=%cd%;%PYTHON_ROOT%;%PYTHON_ROOT%\Scripts;%PATH%
+  - cmd: pip install ninja meson
 
-shallow_clone: true
+  # Enable using MSVC through command line.
+  - cmd: if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" ( call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" %arch% )
+  - cmd: if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2019" ( call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" %arch% )
 
 build_script:
-  - if "%platform%" == "x64" SET VS_FULL=%VS_VERSION% Win64
-  - if "%platform%" == "x86" SET VS_FULL=%VS_VERSION%
-  - cmake -G "%VS_FULL%" .
-  - cmake --build . --config Release
+  - cmd: echo Building on image %APPVEYOR_BUILD_WORKER_IMAGE%, arch %arch%.
+
+  # Build with CMake (builds both static and shared library).
+  - cmd: if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" ( SET "GENERATOR_VS_VERSION=Visual Studio 15 2017" )
+  - cmd: if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2019" ( SET "GENERATOR_VS_VERSION=Visual Studio 16 2019" )
+  - cmd: if "%arch%"=="x86" ( SET "GENERATOR_VS_ARCH=Win32" )
+  - cmd: if "%arch%"=="x64" ( SET "GENERATOR_VS_ARCH=x64" )
+  - cmd: cmake -G "%GENERATOR_VS_VERSION%" -A %GENERATOR_VS_ARCH% .
+  - cmd: cmake --build . --config Release
+
+  # Build with Meson.
+  # Static library.
+  - cmd: meson setup --backend=ninja -Ddefault_library=static meson-build-static .
+  - cmd: meson compile -v -C meson-build-static
+  # Shared library.
+  - cmd: meson setup --backend=ninja -Ddefault_library=shared meson-build-shared .
+  - cmd: meson compile -v -C meson-build-shared
 
 test_script:
-  - bin\Release\runTests.exe
+  # Test what CMake built.
+  - cmd: bin\Release\runTests.exe
 
-deploy: off
+  # Test what Meson built.
+  - cmd: meson test -C meson-build-static
+  - cmd: meson test -C meson-build-shared


=====================================
bindings/python/.gitignore
=====================================
@@ -6,3 +6,5 @@ edlib.c
 edlib.*.so
 .eggs/
 *.bycython.*
+README.rst
+README.html
\ No newline at end of file


=====================================
bindings/python/Makefile
=====================================
@@ -1,20 +1,35 @@
 default: build
 
-############### FILES #################
-FILES=edlib pyedlib.bycython.cpp setup.py MANIFEST.in README.rst
-
-edlib: ../../edlib
-	cp -R ../../edlib .
+.PHONY:
+edlib: $(shell find ../../edlib)
+	# create a clean (maybe updated) copy of edlib src
+	rm -rf edlib && cp -r ../../edlib .
 
 pyedlib.bycython.cpp: edlib.pyx cedlib.pxd
+	python -m pip install cython
 	cython --cplus edlib.pyx -o edlib.bycython.cpp
-#######################################
 
-############## COMMANDS ###############
-build: ${FILES}
+# To build package, README.rst is needed, because it goes into long description of package,
+# which is what is visible on PyPI.
+# However, to generate README.rst from README-tmpl.rst, built package is needed (for `import edlib` in cog)!
+# Therefore, we first build package without README.rst, use it to generate README.rst,
+# and then finally build package again but with README.rst.
+
+BUILD_SOURCE_FILES=edlib pyedlib.bycython.cpp setup.py
+
+buildWithoutREADME.rst: ${BUILD_SOURCE_FILES}
+	EDLIB_OMIT_README_RST=1 python setup.py build_ext -i
+
+README.rst: buildWithoutREADME.rst README-tmpl.rst
+	python -m pip install cogapp
+	cog -d -o README.rst README-tmpl.rst	
+
+BUILD_FILES=${BUILD_SOURCE_FILES} README.rst
+
+build: ${BUILD_FILES}
 	python setup.py build_ext -i
 
-sdist: ${FILES}
+sdist: edlib pyedlib.bycython.cpp setup.py README.rst MANIFEST.in
 	python setup.py sdist
 
 publish: clean sdist
@@ -23,4 +38,4 @@ publish: clean sdist
 clean:
 	rm -rf edlib dist edlib.egg-info build
 	rm -f edlib.c *.bycython.* edlib.*.so
-#######################################
+	rm -f README.rst


=====================================
bindings/python/README.rst → bindings/python/README-tmpl.rst
=====================================
@@ -1,15 +1,68 @@
+..  [[[cog
+        
+    import cog
+    import edlib
+       
+    def indent(text, indentation = "    "):
+        return indentation + text.replace("\n", "\n" + indentation)
+
+    def comment(text):
+        return "# " + text.replace("\n", "\n# ")
+
+    def cogOutExpression(expr):
+        cog.outl(indent(expr))
+        cog.outl(indent(comment(str(eval(expr)))))
+
+    ]]]
+    [[[end]]]
+
 =====
 Edlib
 =====
 
 Lightweight, super fast library for sequence alignment using edit (Levenshtein) distance.
 
-.. code:: python
-
-    edlib.align("hello", "world")
+Popular use cases: aligning DNA sequences, calculating word/text similarity.
+
+..  [[[cog
+   
+    cog.outl()
+    cog.outl(".. code:: python")
+    cog.outl()
+       
+    cogOutExpression('edlib.align("elephant", "telephone")')
+    cog.outl()
+       
+    cog.outl(indent(comment('Works with unicode characters (or any other iterable of hashable objects)!')))
+    cogOutExpression('edlib.align("ты милая", "ты гений")')
+    cog.outl()
+
+    cogOutExpression('edlib.align("AACG", "TCAACCTG", mode = "HW", task = "path")')
+    cog.outl()
+
+    cog.outl(indent('query = "elephant"; target = "telephone"'))
+    cog.outl(indent(comment('NOTE: `task` has to be "path" in order to get nice alignment.')))
+    cog.outl(indent('result = edlib.align(query, target, task = "path")'))
+    cog.outl(indent('nice = edlib.getNiceAlignment(result, query, target)'))
+    cog.outl(indent('print("\\n".join(nice.values()))'))
+
+    query = "elephant"; target = "telephone"
+    result = edlib.align(query, target, task = "path")
+    nice = edlib.getNiceAlignment(result, query, target)
+    output = "\n".join(nice.values())
+    cog.outl(indent(comment(output)))
+    cog.outl()
+
+    ]]]
+
+.. code::
+   
+   {{ Basic code examples will be generated here. }}
+
+..  [[[end]]]
 
 Edlib is actually a C/C++ library, and this package is it's wrapper for Python.
-Python Edlib has mostly the same API as C/C++ Edlib, so make sure to check out `C/C++ Edlib docs <http://github.com/Martinsos/edlib>`_ for more code examples, details on API and how Edlib works.
+Python Edlib has mostly the same API as C/C++ Edlib, so feel free to check out `C/C++ Edlib docs <http://github.com/Martinsos/edlib>`_ for more code examples, details on API and how Edlib works.
 
 --------
 Features
@@ -23,7 +76,7 @@ Features
 * It can easily handle small or **very large** sequences, even when finding alignment path.
 * **Super fast** thanks to Myers's bit-vector algorithm.
 
-NOTE: Size of alphabet has to be <= 256 (meaning that query and target together must have <= 256 unique values).
+**NOTE**: **Alphabet length has to be <= 256** (meaning that query and target together must have <= 256 unique values).
 
 ------------
 Installation
@@ -36,47 +89,97 @@ Installation
 API
 ---
 
-Edlib has two functions, `align()` and `getNiceAlignment()`:
+Edlib has two functions, ``align()`` and ``getNiceAlignment()``:
+
+align()
+-------
 
 .. code:: python
 
-    align(query, target, [mode], [task], [k])
+    align(query, target, [mode], [task], [k], [additionalEqualities])
+
+Aligns ``query`` against ``target`` with edit distance.
+
+``query`` and ``target`` can be strings, bytes, or any iterables of hashable objects, as long as all together they don't have more than 256 unique values.
+
+..  [[[cog
+
+    import pydoc
+
+    help_str = pydoc.plain(pydoc.render_doc(edlib.align, "%s"))
+
+    cog.outl()
+    cog.outl('Output of ``help(edlib.align)``:')
+    cog.outl()
+    cog.outl('.. code::\n')
+    cog.outl(indent(help_str))
+
+    ]]]
+
+.. code::
+   
+   {{ Content of help(edlib.align) will be generated here. }}
+    
+..  [[[end]]]
+
+getNiceAlignment()
+------------------
 
 .. code:: python
 
-    getNiceAlignment(alignResutl, query, target)
+    getNiceAlignment(alignResult, query, target)
+
+Represents alignment from ``align()`` in a visually attractive format.
+
+..  [[[cog
+
+    import pydoc
+
+    help_str = pydoc.plain(pydoc.render_doc(edlib.getNiceAlignment, "%s"))
+
+    cog.outl()
+    cog.outl('Output of ``help(edlib.getNiceAlignment)``:')
+    cog.outl()
+    cog.outl('.. code::\n')
+    cog.outl(indent(help_str))
+
+    ]]]
 
+.. code::
 
+   {{ Content of help(edlib.getNiceAlignment) will be generated here. }}
+
+..  [[[end]]]
 
-To learn more about it, type :code:`help(edlib.align)` in your python interpreter.
 
 -----
 Usage
 -----
-.. code:: python
 
-    import edlib
+..  [[[cog
+
+    cog.outl()
+    cog.outl(".. code:: python")
+    cog.outl()
 
-    result = edlib.align("elephant", "telephone")
-    print(result["editDistance"])  # 3
-    print(result["alphabetLength"])  # 8
-    print(result["locations"])  # [(None, 8)]
-    print(result["cigar"])  # None
+    cog.outl(indent('import edlib'))
+    cog.outl()
 
-    result = edlib.align("ACTG", "CACTRT", mode="HW", task="path", additionalEqualities=[("R", "A"), ("R", "G")])
-    print(result["editDistance"])  # 0
-    print(result["alphabetLength"])  # 5
-    print(result["locations"])  # [(1, 4)]
-    print(result["cigar"])  # "4="
+    cogOutExpression('edlib.align("ACTG", "CACTRT", mode="HW", task="path")')
+    cog.outl()
 
-    result = edlib.align("elephant", "telephone", task="path")  ## users must use 'task="path"' 
-    niceAlign = edlib.getNiceAlignment(result, "elephant", "telephone")
-    print(niceAlign['query_aligned'])  # "-elephant"
-    print(niceAlign['matched_aligned'])  # "-|||||.|."
-    print(niceAlign['target_aligned'])  # "telephone"
+    cog.outl(indent(comment('You can provide additional equalities.')))
+    cogOutExpression('edlib.align("ACTG", "CACTRT", mode="HW", task="path", additionalEqualities=[("R", "A"), ("R", "G")])')
+    cog.outl()
 
+    ]]]
 
+.. code::
 
+   {{ Additional usage examples will be generated here. }}
+
+..  [[[end]]]
+   
 
 ---------
 Benchmark
@@ -123,12 +226,5 @@ Check out `C/C++ Edlib docs <http://github.com/Martinsos/edlib>`_ for more infor
 Development
 -----------
 
-Run :code:`make build` to generate an extension module as .so file. You can test it then by importing it from python interpreter :code:`import edlib` and running :code:`edlib.align(...)` (you have to be positioned in the directory where .so was built). This is useful for testing while developing.
-
-Run :code:`make sdist` to create a source distribution, but not publish it - it is a tarball in dist/ that will be uploaded to pip on `publish`. Use this to check that tarball is well structured and contains all needed files, before you publish.
-Good way to test it is to run :code:`sudo pip install dist/edlib-*.tar.gz`, which will try to install edlib from it, same way as pip will do it when it is published.
-
-Run :code:`make publish` to create a source distribution and publish it to the PyPI. Use this to publish new version of package.
-Make sure to bump the version in `setup.py` before publishing, if needed..
+Check out `Edlib python package on Github <https://github.com/Martinsos/edlib/tree/master/bindings/python>`_.
 
-:code:`make clean` removes all generated files.


=====================================
bindings/python/README.md
=====================================
@@ -0,0 +1,29 @@
+# Edlib python package
+
+This README contains only development information, you can check out full README (README.rst) for the latest version of Edlib python package on [Edlib's PyPI page](https://pypi.org/project/edlib/).
+
+README.rst is not commited to git because it is generated from [README-tmpl.rst](./README-tmpl.rst).
+
+
+## Building
+
+Run `make build` to generate an extension module as .so file.
+You can test it then by importing it from python interpreter `import edlib` and running `edlib.align(...)` (you have to be positioned in the directory where .so was built).
+This is useful for testing while developing.
+
+Run `make sdist` to create a source distribution, but not publish it - it is a tarball in dist/ that will be uploaded to pip on `publish`.
+Use this to check that tarball is well structured and contains all needed files, before you publish.
+Good way to test it is to run `sudo pip install dist/edlib-*.tar.gz`, which will try to install edlib from it, same way as pip will do it when it is published.
+
+`make clean` removes all generated files.
+
+README.rst is auto-generated from [README-tmpl.rst](./README-tmpl.rst), to run regeneration do `make README.rst`.
+README.rst is also automatically regenerated when building package (e.g. `make build`).
+This enables us to always have up to date results of code execution and help documentation of edlib methods in readme.
+
+## Publishing
+Remember to update version in setup.py before publishing.
+
+To trigger automatic publish to PyPI, create a tag and push it to Github -> Travis will create sdist, build wheels, and push them all to PyPI while publishing new version.
+
+You can also publish new version manually if needed: run `make publish` to create a source distribution and publish it to the PyPI.


=====================================
bindings/python/cedlib.pxd
=====================================
@@ -12,11 +12,11 @@ cdef extern from "edlib.h" nogil:
          int k
          EdlibAlignMode mode
          EdlibAlignTask task
-         EdlibEqualityPair* additionalEqualities
+         const EdlibEqualityPair* additionalEqualities
          int additionalEqualitiesLength
 
      EdlibAlignConfig edlibNewAlignConfig(int k, EdlibAlignMode mode, EdlibAlignTask task,
-                                          EdlibEqualityPair* additionalEqualities,
+                                          const EdlibEqualityPair* additionalEqualities,
                                           int additionalEqualitiesLength)
      EdlibAlignConfig edlibDefaultAlignConfig()
 


=====================================
bindings/python/edlib.pyx
=====================================
@@ -32,30 +32,27 @@ def _map_to_bytes(query, target, additional_equalities):
         query_bytes = _map_ascii_string(query)
         target_bytes = _map_ascii_string(target)
     except NeedsAlphabetMapping:
-        # Map non-ascii symbols into an ASCII alphabet so it can be used
-        # in the C++ code
-        query_vals = set(query)
-        target_vals = set(target)
-        input_mapping = {
-            c: chr(idx)
-            for idx, c in enumerate(query_vals.union(target_vals))
-        }
-        if len(input_mapping) > 256:
+        # Map elements of alphabet to chars from 0 up to 255, so that Edlib can work with them,
+        # since C++ Edlib needs chars.
+        alphabet = set(query).union(set(target))
+        if len(alphabet) > 256:
             raise ValueError(
                 "query and target combined have more than 256 unique values, "
                 "this is not supported.")
-        map_seq = lambda seq: ''.join(input_mapping[x] for x in seq).encode('ascii')
+        alphabet_to_byte_mapping = {
+            c: idx.to_bytes(1, byteorder='big') for idx, c in enumerate(alphabet)
+        }
+        map_seq = lambda seq: b''.join(alphabet_to_byte_mapping[c] for c in seq)
         query_bytes = map_seq(query)
         target_bytes = map_seq(target)
         if additional_equalities is not None:
             additional_equalities = [
-                (input_mapping[a], input_mapping[b])
+                (alphabet_to_byte_mapping[a].decode('utf-8'), alphabet_to_byte_mapping[b].decode('utf-8'))
                 for a, b in additional_equalities
-                if a in input_mapping and b in input_mapping]
+                if a in alphabet_to_byte_mapping and b in alphabet_to_byte_mapping]
     return query_bytes, target_bytes, additional_equalities
 
 
-
 def align(query, target, mode="NW", task="distance", k=-1, additionalEqualities=None):
     """ Align query with target using edit distance.
     @param {str or bytes or iterable of hashable objects} query, combined with target must have no more
@@ -66,8 +63,8 @@ def align(query, target, mode="NW", task="distance", k=-1, additionalEqualities=
             - 'NW' for global (default)
             - 'HW' for infix
             - 'SHW' for prefix.
-    @param {string} task  Optional. Tells edlib what to calculate. Less there is to calculate,
-            faster it is. Possible value are (from fastest to slowest):
+    @param {string} task  Optional. Tells edlib what to calculate. The less there is to calculate,
+            the faster it is. Possible value are (from fastest to slowest):
             - 'distance' - find edit distance and end locations in target. Default.
             - 'locations' - find edit distance, end locations and start locations.
             - 'path' - find edit distance, start and end locations and alignment path.
@@ -81,8 +78,8 @@ def align(query, target, mode="NW", task="distance", k=-1, additionalEqualities=
             characters to act as a wildcards.
             Set to None (default) if you do not want to extend edlib's default equality definition.
     @return Dictionary with following fields:
-            {int} editDistance  -1 if it is larger than k.
-            {int} alphabetLength
+            {int} editDistance  Integer, -1 if it is larger than k.
+            {int} alphabetLength Integer, length of unique characters in 'query' and 'target'
             {[(int, int)]} locations  List of locations, in format [(start, end)].
             {string} cigar  Cigar is a standard format for alignment path.
                 Here we are using extended cigar format, which uses following symbols:
@@ -112,15 +109,17 @@ def align(query, target, mode="NW", task="distance", k=-1, additionalEqualities=
 
     cdef bytes tmp_bytes;
     cdef char* tmp_cstring;
+    cdef cedlib.EdlibEqualityPair* c_additionalEqualities = NULL
     if additionalEqualities is None:
         cconfig.additionalEqualities = NULL
         cconfig.additionalEqualitiesLength = 0
     else:
-        cconfig.additionalEqualities = <cedlib.EdlibEqualityPair*> PyMem_Malloc(len(additionalEqualities)
+        c_additionalEqualities = <cedlib.EdlibEqualityPair*> PyMem_Malloc(len(additionalEqualities)
                                                                           * cython.sizeof(cedlib.EdlibEqualityPair))
         for i in range(len(additionalEqualities)):
-            cconfig.additionalEqualities[i].first = bytearray(additionalEqualities[i][0].encode('utf-8'))[0]
-            cconfig.additionalEqualities[i].second = bytearray(additionalEqualities[i][1].encode('utf-8'))[0]
+            c_additionalEqualities[i].first = bytearray(additionalEqualities[i][0].encode('utf-8'))[0]
+            c_additionalEqualities[i].second = bytearray(additionalEqualities[i][1].encode('utf-8'))[0]
+        cconfig.additionalEqualities = c_additionalEqualities
         cconfig.additionalEqualitiesLength = len(additionalEqualities)
 
     # Run alignment -- need to get len before disabling the GIL
@@ -128,7 +127,7 @@ def align(query, target, mode="NW", task="distance", k=-1, additionalEqualities=
     target_len = len(target)
     with nogil:
         cresult = cedlib.edlibAlign(cquery, query_len, ctarget, target_len, cconfig)
-    if cconfig.additionalEqualities != NULL: PyMem_Free(cconfig.additionalEqualities)
+    if c_additionalEqualities != NULL: PyMem_Free(c_additionalEqualities)
 
     if cresult.status == 1:
         raise Exception("There was an error.")


=====================================
bindings/python/setup.py
=====================================
@@ -17,17 +17,20 @@ if USE_CYTHON:
 else:
     edlib_module_src = "edlib.bycython.cpp"
 
-# Load README into long description.
-here = os.path.abspath(os.path.dirname(__file__))
-with open(os.path.join(here, 'README.rst'), encoding='utf-8') as f:
-    long_description = f.read()
+# Load README.rst into long description.
+# User can skip using README.rst as long description: EDLIB_OMIT_README_RST=1 python setup.py install
+OMIT_README_RST = os.getenv('EDLIB_OMIT_README_RST', False)
+if not OMIT_README_RST:
+    here = os.path.abspath(os.path.dirname(__file__))
+    with open(os.path.join(here, 'README.rst'), encoding='utf-8') as f:
+        long_description = f.read()
 
 setup(
     # Information
     name = "edlib",
     description = "Lightweight, super fast library for sequence alignment using edit (Levenshtein) distance.",
     long_description = long_description,
-    version = "1.3.6",
+    version = "1.3.8.post2",
     url = "https://github.com/Martinsos/edlib",
     author = "Martin Sosic",
     author_email = "sosic.martin at gmail.com",


=====================================
bindings/python/test.py
=====================================
@@ -68,6 +68,17 @@ testFailed = testFailed or (not (result and result["editDistance"] == 0))
 result = edlib.align("telephone", "", mode="SHW")
 testFailed = testFailed or (not (result and result["editDistance"] == 9))
 
+# Unicode characters
+result = edlib.align("ты милая", "ты гений")
+testFailed = testFailed or (not (result and result["editDistance"] == 5 and result["alphabetLength"] == 12))
+
+# Long alphabet.
+long_alphabet = ''.join([chr(idx) for idx in range(1, 257)])
+long_seq1 = long_alphabet * 3
+long_seq2 = long_alphabet + long_alphabet[::-1] + long_alphabet
+result = edlib.align(long_seq1, long_seq2)
+testFailed = testFailed or (not (result and result["editDistance"] == 256))
+
 if testFailed:
     print("Some of the tests failed!")
 else:


=====================================
edlib-config.cmake.in
=====================================
@@ -0,0 +1,4 @@
+ at PACKAGE_INIT@
+
+include(${CMAKE_CURRENT_LIST_DIR}/@targets_export_name at .cmake)
+check_required_components(edlib)


=====================================
edlib.pc.in
=====================================
@@ -1,9 +1,9 @@
 libdir=@CMAKE_INSTALL_FULL_LIBDIR@
 includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
 
-Name: Edlib
+Name: edlib
 Description: Lightweight and super fast C/C++ library for sequence alignment using edit distance
 Version: @edlib_VERSION@
 
 Libs: -L${libdir} -ledlib
-Cflags: -I${includedir}
+Cflags: -I${includedir} @PKG_EDLIB_DEFS@


=====================================
edlib/include/edlib.h
=====================================
@@ -7,6 +7,21 @@
  * @brief Main header file, containing all public functions and structures.
  */
 
+// Define EDLIB_API macro to properly export symbols
+#ifdef EDLIB_SHARED
+#    ifdef _WIN32
+#        ifdef EDLIB_BUILD
+#            define EDLIB_API __declspec(dllexport)
+#        else
+#            define EDLIB_API __declspec(dllimport)
+#        endif
+#    else
+#        define EDLIB_API __attribute__ ((visibility ("default")))
+#    endif
+#else
+#    define EDLIB_API
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -115,7 +130,7 @@ extern "C" {
          * or e.g. if you want edlib to be case insensitive.
          * Can be set to NULL if there are none.
          */
-        EdlibEqualityPair* additionalEqualities;
+        const EdlibEqualityPair* additionalEqualities;
 
         /**
          * Number of additional equalities, which is non-negative number..
@@ -128,15 +143,17 @@ extern "C" {
      * Helper method for easy construction of configuration object.
      * @return Configuration object filled with given parameters.
      */
-    EdlibAlignConfig edlibNewAlignConfig(int k, EdlibAlignMode mode, EdlibAlignTask task,
-                                         EdlibEqualityPair* additionalEqualities,
-                                         int additionalEqualitiesLength);
+    EDLIB_API EdlibAlignConfig edlibNewAlignConfig(
+        int k, EdlibAlignMode mode, EdlibAlignTask task,
+        const EdlibEqualityPair* additionalEqualities,
+        int additionalEqualitiesLength
+    );
 
     /**
      * @return Default configuration object, with following defaults:
      *         k = -1, mode = EDLIB_MODE_NW, task = EDLIB_TASK_DISTANCE, no additional equalities.
      */
-    EdlibAlignConfig edlibDefaultAlignConfig(void);
+    EDLIB_API EdlibAlignConfig edlibDefaultAlignConfig(void);
 
 
     /**
@@ -204,7 +221,7 @@ extern "C" {
      * Frees memory in EdlibAlignResult that was allocated by edlib.
      * If you do not use it, make sure to free needed members manually using free().
      */
-    void edlibFreeAlignResult(EdlibAlignResult result);
+    EDLIB_API void edlibFreeAlignResult(EdlibAlignResult result);
 
 
     /**
@@ -222,9 +239,11 @@ extern "C" {
      * @return  Result of alignment, which can contain edit distance, start and end locations and alignment path.
      *          Make sure to clean up the object using edlibFreeAlignResult() or by manually freeing needed members.
      */
-    EdlibAlignResult edlibAlign(const char* query, int queryLength,
-                                const char* target, int targetLength,
-                                const EdlibAlignConfig config);
+    EDLIB_API EdlibAlignResult edlibAlign(
+        const char* query, int queryLength,
+        const char* target, int targetLength,
+        const EdlibAlignConfig config
+    );
 
 
     /**
@@ -246,10 +265,10 @@ extern "C" {
      *     Needed memory is allocated and given pointer is set to it.
      *     Do not forget to free it later using free()!
      */
-    char* edlibAlignmentToCigar(const unsigned char* alignment, int alignmentLength,
-                                EdlibCigarFormat cigarFormat);
-
-
+    EDLIB_API char* edlibAlignmentToCigar(
+        const unsigned char* alignment, int alignmentLength,
+        EdlibCigarFormat cigarFormat
+    );
 
 #ifdef __cplusplus
 }


=====================================
edlib/src/edlib.cpp
=====================================
@@ -361,7 +361,7 @@ static inline Word* buildPeq(const int alphabetLength,
     Word* Peq = new Word[(alphabetLength + 1) * maxNumBlocks];
 
     // Build Peq (1 is match, 0 is mismatch). NOTE: last column is wildcard(symbol that matches anything) with just 1s
-    for (unsigned char symbol = 0; symbol <= alphabetLength; symbol++) {
+    for (int symbol = 0; symbol <= alphabetLength; symbol++) {
         for (int b = 0; b < maxNumBlocks; b++) {
             if (symbol < alphabetLength) {
                 Peq[symbol * maxNumBlocks + b] = 0;
@@ -1460,7 +1460,7 @@ static string transformSequences(const char* const queryOriginal, const int quer
 
 
 extern "C" EdlibAlignConfig edlibNewAlignConfig(int k, EdlibAlignMode mode, EdlibAlignTask task,
-                                                EdlibEqualityPair* additionalEqualities,
+                                                const EdlibEqualityPair* additionalEqualities,
                                                 int additionalEqualitiesLength) {
     EdlibAlignConfig config;
     config.k = k;


=====================================
meson.build
=====================================
@@ -0,0 +1,99 @@
+project(
+  'edlib',
+  'cpp', 'c',
+  version : '1.2.6',
+  default_options : [
+    'buildtype=release',
+    'warning_level=3',
+    'cpp_std=c++14',
+    'b_ndebug=if-release',
+    'default_library=static'
+  ],
+  license : 'MIT',
+  meson_version : '>= 0.52.0',
+)
+
+project_version_major = meson.project_version().split('.')[0]
+
+###### Libraries ######
+
+edlib_lib_compile_args = ['-DEDLIB_BUILD']
+if get_option('default_library') != 'static'
+  edlib_lib_compile_args += ['-DEDLIB_SHARED']
+endif
+
+# If default_library == 'static', library() builds and returns static library.
+# If default_library == 'shared', library() builds and returns shared library.
+# If default_library == 'both', library() builds both static and shared libraries,
+#   but only shared one is returned as value and therefore used in the rest of the build.
+if (get_option('default_library') == 'both')
+  error('\'both\' as a value for default_library option is not supported because it would'
+        + ' build static library with shared library flags, exporting symbols!'
+        + 'Instead, build twice, once with \'static\' and once with \'shared\'.')
+endif
+edlib_lib = library('edlib',
+  sources : files(['edlib/src/edlib.cpp']),
+  include_directories : include_directories('edlib/include'),
+  dependencies : [],
+  install : true,
+  cpp_args : edlib_lib_compile_args,
+  gnu_symbol_visibility : 'inlineshidden',
+  soversion : project_version_major # Used only for shared library.
+)
+edlib_dep = declare_dependency(
+  include_directories : include_directories('edlib/include'),
+  link_with : edlib_lib,
+  compile_args : edlib_lib_compile_args
+)
+
+###### Executables ######
+
+hello_main = executable(
+  'hello-world',
+  files(['apps/hello-world/helloWorld.c']),
+  dependencies : [edlib_dep],
+)
+
+if build_machine.system() != 'windows'
+  aligner_main = executable(
+    'edlib-aligner',
+    files(['apps/aligner/aligner.cpp']),
+    dependencies : [edlib_dep],
+    install : true,
+  )
+endif
+
+runTests_main = executable(
+  'runTests',
+  files(['test/runTests.cpp']),
+  dependencies : [edlib_dep],
+  include_directories : include_directories('test'),
+)
+
+###### Tests ######
+
+test('runTests', runTests_main)
+
+test('hello', hello_main)
+
+if build_machine.system() != 'windows'
+  test('aligner', aligner_main,
+    args : [
+      files('apps/aligner/test_data/query.fasta',
+            'apps/aligner/test_data/target.fasta'),
+    ],
+  )
+endif
+
+###### Install ######
+
+install_headers('edlib/include/edlib.h')
+
+pkg = import('pkgconfig')
+pkg.generate(edlib_lib,
+  name: 'edlib',
+  url: 'https://github.com/Martinsos/edlib',
+  filebase : 'edlib-' + project_version_major,
+  extra_cflags : edlib_lib_compile_args,
+  description : 'Lightweight and super fast C/C++ library for sequence alignment using edit distance',
+)



View it on GitLab: https://salsa.debian.org/med-team/libedlib/-/commit/81add7e135537c10c2655f6f60504da02069fce9

-- 
View it on GitLab: https://salsa.debian.org/med-team/libedlib/-/commit/81add7e135537c10c2655f6f60504da02069fce9
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20211013/2908a20a/attachment-0001.htm>


More information about the debian-med-commit mailing list