From d231eac7b7e18f7c68852720c6d94dd9fab14575 Mon Sep 17 00:00:00 2001 From: Patrick Wieschollek Date: Wed, 1 Mar 2017 09:28:37 +0100 Subject: [PATCH] change build system to bazel (#78) * change build system to bazel Using bazel allows for using travis-docker infrastructure without sudo privileges. * adapt README file for the new changes * remove sudo --- .gitignore | 18 + .gitmodules | 3 - .travis.yml | 78 ++-- BUILD | 21 ++ CMakeLists.txt | 68 ---- README.md | 39 +- WORKSPACE | 15 + bazel.rc | 19 + cmake/Modules/FindEigen3.cmake | 83 ----- cmake/Modules/FindGlog.cmake | 48 --- cmake/Modules/FindMatlabMex.cmake | 47 --- cmake/lint.cmake | 31 -- compile.sh | 7 - eigen.BUILD | 11 + generator.bzl | 21 ++ get_dependencies.sh | 5 - gtest | 1 - gtest.BUILD | 14 + include/cppoptlib/BUILD | 9 + lint.py | 572 +++++++++++++++--------------- matlab/CMakeLists.txt | 28 -- src/examples/CMakeLists.txt | 7 - src/test/CMakeLists.txt | 12 - src/test/verify.cpp | 24 +- 24 files changed, 450 insertions(+), 731 deletions(-) delete mode 100644 .gitmodules create mode 100644 BUILD delete mode 100644 CMakeLists.txt create mode 100644 WORKSPACE create mode 100644 bazel.rc delete mode 100644 cmake/Modules/FindEigen3.cmake delete mode 100644 cmake/Modules/FindGlog.cmake delete mode 100644 cmake/Modules/FindMatlabMex.cmake delete mode 100644 cmake/lint.cmake delete mode 100755 compile.sh create mode 100644 eigen.BUILD create mode 100644 generator.bzl delete mode 100755 get_dependencies.sh delete mode 160000 gtest create mode 100644 gtest.BUILD create mode 100644 include/cppoptlib/BUILD delete mode 100644 matlab/CMakeLists.txt delete mode 100644 src/examples/CMakeLists.txt delete mode 100644 src/test/CMakeLists.txt diff --git a/.gitignore b/.gitignore index 2021b80..b6bd880 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,21 @@ CppNumericalSolvers.config *.mexw32 *.mexmaci64 *.mexglx + +# Ignore backup files. +*~ +# Ignore Vim swap files. +.*.swp +# Ignore files generated by IDEs. +/.classpath +/.factorypath +/.idea/ +/.project +/.settings +/WORKSPACE.user.bzl +/bazel.iml +# Ignore all bazel-* symlinks. There is no full list since this can change +# based on the name of the directory bazel is cloned into. +/bazel-* +# Ignore outputs generated during Bazel bootstrapping. +/output/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 48294b1..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "gtest"] - path = gtest - url = https://github.com/google/googletest.git diff --git a/.travis.yml b/.travis.yml index 9e07142..feb9a7b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,65 +1,35 @@ -sudo: required -dist: precise -language: cpp +dist: trusty + +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - wget + - pkg-config + - g++ + - g++-4.9 + - g++-5 + - pkg-config + - zip + - zlib1g-dev + - unzip -matrix: - include: - - compiler: gcc - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-4.9 - env: COMPILER=g++-4.9 - - compiler: gcc - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-5 - env: COMPILER=g++-5 before_install: - - sudo apt-get update -qq - - chmod u+x get_dependencies.sh - - ./get_dependencies.sh - - git submodule update --init --recursive + - wget https://github.com/bazelbuild/bazel/releases/download/0.4.4/bazel-0.4.4-installer-linux-x86_64.sh + - wget https://github.com/bazelbuild/bazel/releases/download/0.4.4/bazel-0.4.4-installer-linux-x86_64.sh.sha256 + - sha256sum -c bazel-0.4.4-installer-linux-x86_64.sh.sha256 + - chmod +x bazel-0.4.4-installer-linux-x86_64.sh + - ./bazel-0.4.4-installer-linux-x86_64.sh --user + - export PATH="$PATH:$HOME/bin" -install: - ############################################################################ - # Install a recent CMake - ############################################################################ - - | - if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then - CMAKE_DIR="install_cmake" - CMAKE_URL="http://www.cmake.org/files/v3.3/cmake-3.3.2-Linux-x86_64.tar.gz" - mkdir $CMAKE_DIR && travis_retry wget --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C $CMAKE_DIR - export PATH=${TRAVIS_BUILD_DIR}/${CMAKE_DIR}/bin:${PATH} - else - brew install cmake - fi script: - - mkdir build - - cd build - - cmake -DEIGEN3_INCLUDE_DIR=eigen -DCMAKE_CXX_COMPILER=$COMPILER -DCMAKE_BUILD_TYPE=Release .. - - make all -j - - make lint - - ./bin/verify + - bazel run verify + - python lint.py -addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-4.8 - - g++-4.8 notifications: email: false -branches: - except: - -gtest diff --git a/BUILD b/BUILD new file mode 100644 index 0000000..2c871b3 --- /dev/null +++ b/BUILD @@ -0,0 +1,21 @@ +package(default_visibility = ["//visibility:public"]) + +load("//:generator.bzl", "build_example", "build_test") + +build_example("linearregression") +build_example("logisticregression") +build_example("rosenbrock") +build_example("rosenbrock_float") +build_example("simple") +build_example("simple_withoptions") +build_example("neldermead") +build_example("neldermead-customized") + +build_test("verify") + + +py_binary( + name = "lint", + args = ["src/test/verify.cpp"], + srcs = ["lint.py"], +) \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index d762bfb..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -cmake_minimum_required(VERSION 3.1) -project(CppNumericalSolvers) - -option(BUILD_TESTING "Build tests" ON) -option(BUILD_EXAMPLES "Build examples" ON) - -set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) -set( CMAKE_TEST_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) - -# check existence of c++11 compiler -if(NOT CMAKE_CXX_STANDARD) # don't override - set(CMAKE_CXX_STANDARD 11) -endif() - -# set path to cmake modules -list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/Modules) -set(LINKER_LIBS "") - -if(BUILD_TESTING) - # Google Testing Framework - add_subdirectory(gtest) - include_directories(gtest) -endif() - -find_package(Eigen3 REQUIRED) -include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR}) - -add_library(cppoptlib INTERFACE) -target_include_directories(cppoptlib INTERFACE - $ - $) -if(TARGET ::Eigen3) - target_link_libraries(cppoptlib INTERFACE ::Eigen3) -endif() - -install(TARGETS cppoptlib EXPORT cppoptlib-targets) - -if(TARGET ::Eigen3) - install(EXPORT cppoptlib-targets DESTINATION lib/cmake/cppoptlib - NAMESPACE ::) # export name will be '::cppoptlib' - # write and install config module - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/hide/cppoptlib-config.cmake " - include(CMakeFindDependencyMacro) - find_dependency(Eigen3) - if(Eigen3_FOUND) - include(\"\${CMAKE_CURRENT_LIST_DIR}/cppoptlib-targets.cmake\") - endif() - ") - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/hide/cppoptlib-config.cmake - DESTINATION lib/cmake/cppoptlib) -else() - # config-module without referencing Eigen - install(EXPORT cppoptlib-targets DESTINATION lib/cmake/cppoptlib - NAMESPACE :: # export name will be '::cppoptlib' - FILE cppoptlib-config.cmake) -endif() - -install(DIRECTORY include/cppoptlib DESTINATION include) - -if(BUILD_EXAMPLES) - add_subdirectory(src/examples) -endif() - -if(BUILD_TESTING) - add_subdirectory(src/test) -endif() - -add_custom_target(lint COMMAND ${CMAKE_COMMAND} -P ${PROJECT_SOURCE_DIR}/cmake/lint.cmake) diff --git a/README.md b/README.md index f073911..5b04166 100644 --- a/README.md +++ b/README.md @@ -6,22 +6,15 @@ CppOptimizationLibrary Get this Library ----------- - git clone --recursive https://github.com/PatWie/CppNumericalSolvers.git - -or a complete copy and paste version ````bash - git clone --recursive https://github.com/PatWie/CppNumericalSolvers.git + git clone https://github.com/PatWie/CppNumericalSolvers.git cd CppNumericalSolvers/ - ./get_dependencies.sh - mkdir build - cd build - cmake .. - make all - ./bin/verify + bazel run verify ```` + About ----------- -Have you ever googled for a c++ version of *fminsearch*, which is easy to use without adding tons of dependencies and without editing many setting-structs? This project exactly addresses this issue by providing a *header-only* library without dependencies. All solvers are written from scratch, which means they do not represent the current state-of-the-art implementation with all tricky optimizations (at least for now). But they are very easy to use. Want a full example? +Have you ever looked for a c++ version of MATLAB's *fminsearch*, which is easy to use without adding tons of dependencies and without editing many setting-structs? This project exactly addresses this issue by providing a *header-only* library without dependencies. All solvers are written from scratch, which means they do not represent the current state-of-the-art implementation with all tricky optimizations (at least for now). But they are very easy to use. Want a full example? ````cpp class Rosenbrock : public Problem { @@ -62,24 +55,9 @@ For checking your gradient this library uses high-order central difference. Stud Install ----------- -Before compiling you need to adjust one path to the [Eigen3][eigen3]-Library (header only), which can by downloaded by a single bashscript, if you haven't Eigen already. -````bash - # download Eigen - ./get_dependencies.sh -```` -To compile the examples and the unit test just do -````bash - # create a new directory - mkdir build && cd build - cmake .. - # build tests and demo - make all - # run all tests - ./bin/verify - # run an example - ./bin/examples/linearregression -```` -For using the MATLAB-binding open Matlab and run `make.m` inside the MATLAB folder once. +Note, this library is header-only, so you just need to add `include/cppoptlib` to your project without compiling anything and without adding further dependencies. We ship some examples for demonstration purposes and use [bazel](https://bazel.build/) to compile these examples and unittests. The latest commit using CMake is da314c6581d076e0dbadacdd263aefe4d06a2397. + +When using the MATLAB-binding, you need to compile the mex-file. Hereby, open Matlab and run `make.m` inside the MATLAB folder once. Extensive Introduction ----------- @@ -192,7 +170,8 @@ Currently, not all solvers are equally good at all objective functions. The file # Contribute -Make sure that `make lint` does not display any errors and check if travis is happy. Do not forget to `chmod +x lint.py`. It would be great, if some of the Forks-Owner are willing to make pull-request. +Make sure that `python lint.py` does not display any errors and check if travis is happy. It would be great, if some of the Forks-Owner are willing to make pull-request. [eigen3]: http://eigen.tuxfamily.org/ +[bazel]: https://bazel.build/ [matlab]: http://www.mathworks.de/products/matlab/ diff --git a/WORKSPACE b/WORKSPACE new file mode 100644 index 0000000..b458b66 --- /dev/null +++ b/WORKSPACE @@ -0,0 +1,15 @@ +new_http_archive( + name = "eigen_archive", + url = "https://bitbucket.org/eigen/eigen/get/3.2.10.tar.gz", + build_file = "eigen.BUILD", + strip_prefix = "eigen-eigen-b9cd8366d4e8", +) + + +new_http_archive( + name = "gtest", + url = "https://github.com/google/googletest/archive/release-1.7.0.zip", + sha256 = "b58cb7547a28b2c718d1e38aee18a3659c9e3ff52440297e965f5edffe34b6d0", + build_file = "gtest.BUILD", + strip_prefix = "googletest-release-1.7.0", +) \ No newline at end of file diff --git a/bazel.rc b/bazel.rc new file mode 100644 index 0000000..71c6f48 --- /dev/null +++ b/bazel.rc @@ -0,0 +1,19 @@ +# This is from Bazel's former travis setup, to avoid blowing up the RAM usage. +startup --host_jvm_args=-Xmx2500m +startup --host_jvm_args=-Xms2500m +startup --batch +test --ram_utilization_factor=10 + +# This is so we understand failures better +build --verbose_failures + +# This is so we don't use sandboxed execution. Sandboxed execution +# runs stuff in a container, and since Travis already runs its script +# in a container (unless you require sudo in your .travis.yml) this +# fails to run tests. +build --spawn_strategy=standalone --genrule_strategy=standalone +test --test_strategy=standalone + +# Below this line, .travis.yml will cat the default bazelrc. +# This is needed so Bazel starts with the base workspace in its +# package path. \ No newline at end of file diff --git a/cmake/Modules/FindEigen3.cmake b/cmake/Modules/FindEigen3.cmake deleted file mode 100644 index 6c05ddd..0000000 --- a/cmake/Modules/FindEigen3.cmake +++ /dev/null @@ -1,83 +0,0 @@ -# - Try to find Eigen3 lib -# -# This module supports requiring a minimum version, e.g. you can do -# find_package(Eigen3 3.1.2) -# to require version 3.1.2 or newer of Eigen3. -# -# Once done this will define -# -# EIGEN3_FOUND - system has eigen lib with correct version -# EIGEN3_INCLUDE_DIR - the eigen include directory -# EIGEN3_VERSION - eigen version - -# Copyright (c) 2006, 2007 Montel Laurent, -# Copyright (c) 2008, 2009 Gael Guennebaud, -# Copyright (c) 2009 Benoit Jacob -# Redistribution and use is allowed according to the terms of the 2-clause BSD license. - -if(NOT Eigen3_FIND_VERSION) - if(NOT Eigen3_FIND_VERSION_MAJOR) - set(Eigen3_FIND_VERSION_MAJOR 2) - endif(NOT Eigen3_FIND_VERSION_MAJOR) - if(NOT Eigen3_FIND_VERSION_MINOR) - set(Eigen3_FIND_VERSION_MINOR 91) - endif(NOT Eigen3_FIND_VERSION_MINOR) - if(NOT Eigen3_FIND_VERSION_PATCH) - set(Eigen3_FIND_VERSION_PATCH 0) - endif(NOT Eigen3_FIND_VERSION_PATCH) - - set(Eigen3_FIND_VERSION "${Eigen3_FIND_VERSION_MAJOR}.${Eigen3_FIND_VERSION_MINOR}.${Eigen3_FIND_VERSION_PATCH}") -endif(NOT Eigen3_FIND_VERSION) - -macro(_eigen3_check_version) - file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header) - - string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}") - set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}") - string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen3_major_version_match "${_eigen3_version_header}") - set(EIGEN3_MAJOR_VERSION "${CMAKE_MATCH_1}") - string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen3_minor_version_match "${_eigen3_version_header}") - set(EIGEN3_MINOR_VERSION "${CMAKE_MATCH_1}") - - set(EIGEN3_VERSION ${EIGEN3_WORLD_VERSION}.${EIGEN3_MAJOR_VERSION}.${EIGEN3_MINOR_VERSION}) - if(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) - set(EIGEN3_VERSION_OK FALSE) - else(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) - set(EIGEN3_VERSION_OK TRUE) - endif(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) - - if(NOT EIGEN3_VERSION_OK) - - message(STATUS "Eigen3 version ${EIGEN3_VERSION} found in ${EIGEN3_INCLUDE_DIR}, " - "but at least version ${Eigen3_FIND_VERSION} is required") - endif(NOT EIGEN3_VERSION_OK) -endmacro(_eigen3_check_version) - -if (EIGEN3_INCLUDE_DIR) - - # in cache already - _eigen3_check_version() - set(EIGEN3_FOUND ${EIGEN3_VERSION_OK}) - -else (EIGEN3_INCLUDE_DIR) - - find_path(EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library - HINTS - eigen - PATHS - ${CMAKE_INSTALL_PREFIX}/include - ${KDE4_INCLUDE_DIR} - PATH_SUFFIXES eigen3 eigen - ) - - if(EIGEN3_INCLUDE_DIR) - _eigen3_check_version() - endif(EIGEN3_INCLUDE_DIR) - - include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK) - - mark_as_advanced(EIGEN3_INCLUDE_DIR) - -endif(EIGEN3_INCLUDE_DIR) - diff --git a/cmake/Modules/FindGlog.cmake b/cmake/Modules/FindGlog.cmake deleted file mode 100644 index 99abbe4..0000000 --- a/cmake/Modules/FindGlog.cmake +++ /dev/null @@ -1,48 +0,0 @@ -# - Try to find Glog -# -# The following variables are optionally searched for defaults -# GLOG_ROOT_DIR: Base directory where all GLOG components are found -# -# The following are set after configuration is done: -# GLOG_FOUND -# GLOG_INCLUDE_DIRS -# GLOG_LIBRARIES -# GLOG_LIBRARYRARY_DIRS - -include(FindPackageHandleStandardArgs) - -set(GLOG_ROOT_DIR "" CACHE PATH "Folder contains Google glog") - -if(WIN32) - find_path(GLOG_INCLUDE_DIR glog/logging.h - PATHS ${GLOG_ROOT_DIR}/src/windows) -else() - find_path(GLOG_INCLUDE_DIR glog/logging.h - PATHS ${GLOG_ROOT_DIR}) -endif() - -if(MSVC) - find_library(GLOG_LIBRARY_RELEASE libglog_static - PATHS ${GLOG_ROOT_DIR} - PATH_SUFFIXES Release) - - find_library(GLOG_LIBRARY_DEBUG libglog_static - PATHS ${GLOG_ROOT_DIR} - PATH_SUFFIXES Debug) - - set(GLOG_LIBRARY optimized ${GLOG_LIBRARY_RELEASE} debug ${GLOG_LIBRARY_DEBUG}) -else() - find_library(GLOG_LIBRARY glog - PATHS ${GLOG_ROOT_DIR} - PATH_SUFFIXES lib lib64) -endif() - -find_package_handle_standard_args(Glog DEFAULT_MSG GLOG_INCLUDE_DIR GLOG_LIBRARY) - -if(GLOG_FOUND) - set(GLOG_INCLUDE_DIRS ${GLOG_INCLUDE_DIR}) - set(GLOG_LIBRARIES ${GLOG_LIBRARY}) - message(STATUS "Found glog (include: ${GLOG_INCLUDE_DIR}, library: ${GLOG_LIBRARY})") - mark_as_advanced(GLOG_ROOT_DIR GLOG_LIBRARY_RELEASE GLOG_LIBRARY_DEBUG - GLOG_LIBRARY GLOG_INCLUDE_DIR) -endif() diff --git a/cmake/Modules/FindMatlabMex.cmake b/cmake/Modules/FindMatlabMex.cmake deleted file mode 100644 index 87b1291..0000000 --- a/cmake/Modules/FindMatlabMex.cmake +++ /dev/null @@ -1,47 +0,0 @@ -# This module looks for MatlabMex compiler -# Defines variables: -# Matlab_DIR - Matlab root dir -# Matlab_mex - path to mex compiler -# Matlab_mexext - path to mexext - -if(MSVC) - foreach(__ver "9.30" "7.14" "7.11" "7.10" "7.9" "7.8" "7.7") - get_filename_component(__matlab_root "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB\\${__ver};MATLABROOT]" ABSOLUTE) - if(__matlab_root) - break() - endif() - endforeach() -endif() - -if(APPLE) - foreach(__ver "R2014b" "R2014a" "R2013b" "R2013a" "R2012b" "R2012a" "R2011b" "R2011a" "R2010b" "R2010a") - if(EXISTS /Applications/MATLAB_${__ver}.app) - set(__matlab_root /Applications/MATLAB_${__ver}.app) - break() - endif() - endforeach() -endif() - -if(UNIX) - execute_process(COMMAND which matlab OUTPUT_STRIP_TRAILING_WHITESPACE - OUTPUT_VARIABLE __out RESULT_VARIABLE __res) - - if(__res MATCHES 0) # Suppress `readlink` warning if `which` returned nothing - execute_process(COMMAND which matlab COMMAND xargs readlink - COMMAND xargs dirname COMMAND xargs dirname COMMAND xargs echo -n - OUTPUT_VARIABLE __matlab_root OUTPUT_STRIP_TRAILING_WHITESPACE) - endif() -endif() - -find_path(Matlab_DIR NAMES bin/mex bin/mexext PATHS ${__matlab_root} - DOC "Matlab directory" NO_DEFAULT_PATH) - -find_program(Matlab_mex NAMES mex mex.bat HINTS ${Matlab_DIR} PATH_SUFFIXES bin NO_DEFAULT_PATH) -find_program(Matlab_mexext NAMES mexext mexext.bat HINTS ${Matlab_DIR} PATH_SUFFIXES bin NO_DEFAULT_PATH) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(MatlabMex DEFAULT_MSG Matlab_mex Matlab_mexext) - -if(MATLABMEX_FOUND) - mark_as_advanced(Matlab_mex Matlab_mexext) -endif() diff --git a/cmake/lint.cmake b/cmake/lint.cmake deleted file mode 100644 index baf5c38..0000000 --- a/cmake/lint.cmake +++ /dev/null @@ -1,31 +0,0 @@ -set(CMAKE_SOURCE_DIR ..) -set(LINT_COMMAND ${CMAKE_SOURCE_DIR}/lint.py) -set(SRC_FILE_EXTENSIONS h hpp hu c cpp cu cc) -set(LINT_DIRS include/cppoptlib src/examples) - -cmake_policy(SET CMP0009 NEW) # suppress cmake warning - -# find all files of interest -foreach(ext ${SRC_FILE_EXTENSIONS}) - foreach(dir ${LINT_DIRS}) - file(GLOB_RECURSE FOUND_FILES ${CMAKE_SOURCE_DIR}/${dir}/*.${ext}) - set(LINT_SOURCES ${LINT_SOURCES} ${FOUND_FILES}) - endforeach() -endforeach() - -execute_process( - COMMAND ${LINT_COMMAND} ${LINT_SOURCES} - RESULT_VARIABLE LINT_NUM_ERRORS - OUTPUT_VARIABLE LINT_RESULT -) - -if(LINT_NUM_ERRORS GREATER 0) - message(STATUS ${LINT_RESULT}) - if(LINT_NUM_ERRORS GREATER 1) - message(FATAL_ERROR "Linter found ${LINT_NUM_ERRORS} errors!") - else() - message(FATAL_ERROR "Linter found ${LINT_NUM_ERRORS} error!") - endif() -else() - message(STATUS "Linter did not find any errors!") -endif() diff --git a/compile.sh b/compile.sh deleted file mode 100755 index f2242f3..0000000 --- a/compile.sh +++ /dev/null @@ -1,7 +0,0 @@ -# Build project in release version -mkdir build -cd build -cmake -DEIGEN3_INCLUDE_DIR=eigen -DCMAKE_BUILD_TYPE=Release .. -make clean -make all -./bin/verify \ No newline at end of file diff --git a/eigen.BUILD b/eigen.BUILD new file mode 100644 index 0000000..4c8f832 --- /dev/null +++ b/eigen.BUILD @@ -0,0 +1,11 @@ +# Description: +# Eigen is a C++ template library for linear algebra: vectors, +# matrices, and related algorithms. + +cc_library( + name = "eigen3", + srcs = glob(['Eigen/src/**/*.h']), + includes = ['.'], + hdrs = glob(['Eigen/*']), + visibility = ["//visibility:public"], +) \ No newline at end of file diff --git a/generator.bzl b/generator.bzl new file mode 100644 index 0000000..b47ea1b --- /dev/null +++ b/generator.bzl @@ -0,0 +1,21 @@ +def build_example(name, visibility=None): + native.cc_binary( + name = name, + srcs = ["src/examples/"+name+".cpp"], + deps = [ + "//include/cppoptlib:cppoptlib", + "@eigen_archive//:eigen3" + ] + ) + +def build_test(name, visibility=None): + native.cc_test( + name = name, + srcs = ["src/test/"+name+".cpp"], + copts = ["-Iexternal/gtest/include"], + deps = [ + "//include/cppoptlib:cppoptlib", + "@eigen_archive//:eigen3", + "@gtest//:main" + ] + ) diff --git a/get_dependencies.sh b/get_dependencies.sh deleted file mode 100755 index 3e07a37..0000000 --- a/get_dependencies.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -# eigen library -EIGEN_VERSION="3.2.10" -curl https://bitbucket.org/eigen/eigen/get/$EIGEN_VERSION.tar.gz | tar xz -mv eigen-eigen-* eigen diff --git a/gtest b/gtest deleted file mode 160000 index d225acc..0000000 --- a/gtest +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d225acc90bc3a8c420a9bcd1f033033c1ccd7fe0 diff --git a/gtest.BUILD b/gtest.BUILD new file mode 100644 index 0000000..528c781 --- /dev/null +++ b/gtest.BUILD @@ -0,0 +1,14 @@ +cc_library( + name = "main", + srcs = glob( + ["src/*.cc"], + exclude = ["src/gtest-all.cc"] + ), + hdrs = glob([ + "include/**/*.h", + "src/*.h" + ]), + copts = ["-Iexternal/gtest/include"], + linkopts = ["-pthread"], + visibility = ["//visibility:public"], +) \ No newline at end of file diff --git a/include/cppoptlib/BUILD b/include/cppoptlib/BUILD new file mode 100644 index 0000000..f44960a --- /dev/null +++ b/include/cppoptlib/BUILD @@ -0,0 +1,9 @@ +cc_library( + name = "cppoptlib", + hdrs = glob([ + "*.h", + "solver/*.h", + "linesearch/*.h", + ]), + visibility = ["//visibility:public"], +) diff --git a/lint.py b/lint.py index 91ddd35..09a3c24 100755 --- a/lint.py +++ b/lint.py @@ -1,331 +1,313 @@ #!/usr/bin/env python import re import sys -import getopt +import glob import codecs import unicodedata -_settings_extensions = set(['cc', 'h', 'cpp', 'cu', 'cuh','hpp', 'cxx']) -_settings_lineWidth = 150 -_settings_extraInfo = True - -_settings_checks = {"studentname":False, - "space indentation":True, - "line width":True, - "space before {":True, - "symbol whitespace":True, - "trailing whitespace":True, - "function definition whitespace":True, - "camelCase":True, - "endif comment":True, - "global namespaces":True, - "multiple empty lines":True - } +_settings_extensions = set(['cc', 'h', 'cpp', 'cu', 'cuh', 'hpp', 'cxx']) +_settings_lineWidth = 150 +_settings_extraInfo = True +_settings_checks = {"studentname": False, + "space indentation": True, + "line width": True, + "space before {": True, + "symbol whitespace": True, + "trailing whitespace": True, + "function definition whitespace": True, + "camelCase": True, + "endif comment": True, + "global namespaces": True, + "multiple empty lines": True} regExCache = {} -ERROR_COUNTER = 0; - -# class bcolors: -# HEADER = '\033[95m' -# OKBLUE = '\033[94m' -# OKGREEN = '\033[92m' -# WARNING = '\033[93m' -# FAIL = '\033[91m' -# ENDC = '\033[0m' -# BOLD = '\033[1m' -# UNDERLINE = '\033[4m' +ERROR_COUNTER = 0 + class RegExMatcher(object): - def __init__(self, matchstring): - self.matchstring = matchstring - - def match(self,regExExpr): - if regExExpr not in regExCache: - regExCache[regExExpr] = re.compile(regExExpr) - self.ans = regExCache[regExExpr].match(self.matchstring) - return bool(self.ans) - - def search(self,regExExpr): - if regExExpr not in regExCache: - regExCache[regExExpr] = re.compile(regExExpr) - self.ans = regExCache[regExExpr].search(self.matchstring) - return bool(self.ans) - - def findall(self,regExExpr): - if regExExpr not in regExCache: - regExCache[regExExpr] = re.compile(regExExpr) - self.ans = regExCache[regExExpr].finditer(self.matchstring) - return bool(self.ans) - - def all(self): - return self.ans - - - def span(self): - return self.ans.span() - - -def lineWidth(line): - if isinstance(line, unicode): - width = 0 - for uc in unicodedata.normalize('NFC', line): - if unicodedata.east_asian_width(uc) in ('W', 'F'): - width += 2 - elif not unicodedata.combining(uc): - width += 1 - return width - else: - return len(line) + def __init__(self, matchstring): + self.matchstring = matchstring + + def match(self, regex_expr): + if regex_expr not in regExCache: + regExCache[regex_expr] = re.compile(regex_expr) + self.ans = regExCache[regex_expr].match(self.matchstring) + return bool(self.ans) + + def search(self, regex_expr): + if regex_expr not in regExCache: + regExCache[regex_expr] = re.compile(regex_expr) + self.ans = regExCache[regex_expr].search(self.matchstring) + return bool(self.ans) + + def findall(self, regex_expr): + if regex_expr not in regExCache: + regExCache[regex_expr] = re.compile(regex_expr) + self.ans = regExCache[regex_expr].finditer(self.matchstring) + return bool(self.ans) + + def all(self): + return self.ans + + def span(self): + return self.ans.span() + + +def line_width(line): + if isinstance(line, unicode): + width = 0 + for uc in unicodedata.normalize('NFC', line): + if unicodedata.east_asian_width(uc) in ('W', 'F'): + width += 2 + elif not unicodedata.combining(uc): + width += 1 + return width + else: + return len(line) + def print_error(filename, linenum, category, message, level=0, line="", char=-1): - global ERROR_COUNTER - ERROR_COUNTER = ERROR_COUNTER + 1; - # level 0: warning - # level 1: error - if level == 0: - sys.stderr.write('(line %s): \033[91m[%s]\033[0m %s\n' % ( linenum, category, message)) - elif level == 1: - sys.stderr.write('(line %s): \033[91m[%s]\033[0m %s\n' % ( linenum, category, message)) - else: - sys.stderr.write('(line %s): [%14s] %s\n' % ( linenum, category, message)) - - if _settings_extraInfo: - if char != -1: - sys.stderr.write('%s %s\n' % (' '*(10+3+3 + len(str(linenum))),line) ) - sys.stderr.write('%s \033[96m%s%s\033[0m\n' % (' '*(10+3+3 + len(str(linenum))),'-'*char,'^') ) - - -def processBraces(filename, lines, error): - ident = []; - for line in range(len(lines)): - for char in range(len(lines[line])): - if lines[line][char] == '{': - fullstr = lines[line] - startwhites = len(fullstr)-len(fullstr.lstrip()) - ident.append( (startwhites, line, char+2) ) - - if lines[line][char] == '}': - fullstr = lines[line] - startwhites = len(fullstr)-len(fullstr.lstrip()) - - if len(ident) == 0: - error(filename, line, 'ident', 'bracket in line %i at pos %i has no related opening' % (line,char ) ,1, lines[line], char) - break; - - if(ident[len(ident)-1][1] != line): - if(ident[len(ident)-1][0] != startwhites): - error(filename, line, 'ident', 'indentation of bracket in line %i does not match indentation of bracket in line %i' % (line,ident[len(ident)-1][1]) ) - del ident[-1] - - - -def processCleanFileLine(filename, file_extension, lines, error, linenum, raw): - - line = lines[linenum] - rline = raw[linenum] - # check if line is comment - m = RegExMatcher(line) - if m.match(r'\s*//'): - return - - if _settings_checks["space before {"]: - m = RegExMatcher(line) - if m.search(r'\S\{'): - if not line[m.span()[1]-2] == '"': - error(filename, linenum, 'braces', 'found no space before {',1 , rline, m.span()[1]-1) + global ERROR_COUNTER + ERROR_COUNTER = ERROR_COUNTER + 1 + # level 0: warning + # level 1: error + if level == 0: + sys.stderr.write('(line %s): \033[91m[%s]\033[0m %s\n' % (linenum, category, message)) + elif level == 1: + sys.stderr.write('(line %s): \033[91m[%s]\033[0m %s\n' % (linenum, category, message)) + else: + sys.stderr.write('(line %s): [%14s] %s\n' % (linenum, category, message)) - if _settings_checks["symbol whitespace"]: - m = RegExMatcher(line) - if m.search(r'^([^"]|"[^"]*")*?([,=])\S'): # do not look inside quoted strings - # exclude cases == - if not line[m.span()[1]-2:m.span()[1]] == "==": - error(filename, linenum, 'whitespace', 'no whitespace after symbol',1 , rline, m.span()[1]-2) + if _settings_extraInfo: + if char != -1: + sys.stderr.write('%s %s\n' % (' ' * (10 + 3 + 3 + len(str(linenum))), line)) + sys.stderr.write('%s \033[96m%s%s\033[0m\n' % (' ' * (10 + 3 + 3 + len(str(linenum))), '-' * char, '^')) - if _settings_checks["function definition whitespace"]: - m = RegExMatcher(line) - if m.search(r'[^(for)(while)(if)(else)\n&\*/\+\-\|=\,]+\s+\('): - # exclude special case with only whitespaces - mm = RegExMatcher(line[0:m.span()[1]]) - if not mm.search(r'^\s+\('): - if not mm.search(r'return\s\(') and not mm.search(r'<\s\('): - error(filename, linenum, 'whitespace', 'found whitespace before (',1 , rline, m.span()[1]-1) - - if _settings_checks["camelCase"]: - m = RegExMatcher(line) - if m.search(r'\w+\s*\s[A-Z]+\w*\(.*\{'): - error(filename, linenum, 'capitalization', 'found function without camelCase',1 , rline, m.span()[1]-1) - if _settings_checks["global namespaces"]: - m = RegExMatcher(line) - if m.search(r'using\s+namespace'): - error(filename, linenum, 'style', 'do not use global namespaces',1 , rline, m.span()[1]-1) +def process_braces(filename, lines, error): + ident = [] + for line in range(len(lines)): + for char in range(len(lines[line])): + if lines[line][char] == '{': + fullstr = lines[line] + startwhites = len(fullstr) - len(fullstr.lstrip()) + ident.append((startwhites, line, char + 2)) -def processFileLine(filename, file_extension, lines, error, linenum): + if lines[line][char] == '}': + fullstr = lines[line] + startwhites = len(fullstr) - len(fullstr.lstrip()) - line = lines[linenum] - # check if line is comment - m = RegExMatcher(line) - if m.match(r'\s*//'): - return - if _settings_checks["space indentation"]: - m = RegExMatcher(line) - if m.search('\t'): - error(filename, linenum, 'tab', 'use spaces instead of tabs',1 , line, m.span()[1]-1) + if len(ident) == 0: + msg = 'bracket in line %i at pos %i has no related opening' % (line, char) + error(filename, line, 'ident', msg, 1, lines[line], char) + break - if _settings_checks["line width"]: - if lineWidth(line) > _settings_lineWidth: - error(filename, linenum, 'line_length', 'lines should be <= %i characters long' % _settings_lineWidth) + if(ident[len(ident) - 1][1] != line): + if(ident[len(ident) - 1][0] != startwhites): + msg = 'indentation of bracket in line %i does not match indentation of bracket in line %i' + msg = msg % (line, ident[len(ident) - 1][1]) + error(filename, line, 'ident', msg) + del ident[-1] - if _settings_checks["trailing whitespace"]: - m = RegExMatcher(line) - if m.search(r'\s+$'): - error(filename, linenum, 'whitespace', 'found trailing whitespace',1 , line, m.span()[1]-1) - if _settings_checks["endif comment"]: +def process_clean_file_line(filename, file_extension, lines, error, linenum, raw): + + line = lines[linenum] + rline = raw[linenum] + # check if line is comment + m = RegExMatcher(line) + if m.match(r'\s*//'): + return + + if _settings_checks["space before {"]: + m = RegExMatcher(line) + if m.search(r'\S\{'): + if not line[m.span()[1] - 2] == '"': + error(filename, linenum, 'braces', 'found no space before {', 1, rline, m.span()[1] - 1) + + if _settings_checks["symbol whitespace"]: + m = RegExMatcher(line) + if m.search(r'^([^"]|"[^"]*")*?([,=])\S'): # do not look inside quoted strings + # exclude cases == + if not line[m.span()[1] - 2:m.span()[1]] == "==": + error(filename, linenum, 'whitespace', 'no whitespace after symbol', 1, rline, m.span()[1] - 2) + + if _settings_checks["function definition whitespace"]: + m = RegExMatcher(line) + if m.search(r'[^(for)(while)(if)(else)\n&\*/\+\-\|=\,]+\s+\('): + # exclude special case with only whitespaces + mm = RegExMatcher(line[0:m.span()[1]]) + if not mm.search(r'^\s+\('): + if not mm.search(r'return\s\(') and not mm.search(r'<\s\('): + error(filename, linenum, 'whitespace', 'found whitespace before (', 1, rline, m.span()[1] - 1) + + if _settings_checks["camelCase"]: + m = RegExMatcher(line) + if m.search(r'\w+\s*\s[A-Z]+\w*\(.*\{'): + error(filename, linenum, 'capitalization', 'found function without camelCase', 1, rline, m.span()[1] - 1) + + if _settings_checks["global namespaces"]: + m = RegExMatcher(line) + if m.search(r'using\s+namespace'): + error(filename, linenum, 'style', 'do not use global namespaces', 1, rline, m.span()[1] - 1) + + +def process_file_line(filename, file_extension, lines, error, linenum): + + line = lines[linenum] + # check if line is comment m = RegExMatcher(line) - if m.search(r'#endif\s*$'): - error(filename, linenum, 'comment', 'found endif without comment',1 , line, m.span()[1]-1) + if m.match(r'\s*//'): + return + if _settings_checks["space indentation"]: + m = RegExMatcher(line) + if m.search('\t'): + error(filename, linenum, 'tab', 'use spaces instead of tabs', 1, line, m.span()[1] - 1) + + if _settings_checks["line width"]: + if line_width(line) > _settings_lineWidth: + error(filename, linenum, 'line_length', 'lines should be <= %i characters long' % _settings_lineWidth) + + if _settings_checks["trailing whitespace"]: + m = RegExMatcher(line) + if m.search(r'\s+$'): + error(filename, linenum, 'whitespace', 'found trailing whitespace', 1, line, m.span()[1] - 1) + + if _settings_checks["endif comment"]: + m = RegExMatcher(line) + if m.search(r'#endif\s*$'): + error(filename, linenum, 'comment', 'found endif without comment', 1, line, m.span()[1] - 1) + + +def process_clean_file_content(filename, file_extension, lines, ignore_lines, error, raw): + lines = (['// marker so line numbers and indices both start at 1'] + lines + + ['// marker so line numbers end in a known way']) + raw = (['// marker so line numbers and indices both start at 1'] + raw + + ['// marker so line numbers end in a known way']) + for line in range(len(lines)): + if line not in ignore_lines: + process_clean_file_line(filename, file_extension, lines, error, line, raw) -def processCleanFileContent(filename, file_extension, lines, ignore_lines, error, raw): - lines = (['// marker so line numbers and indices both start at 1'] + lines + - ['// marker so line numbers end in a known way']) - raw = (['// marker so line numbers and indices both start at 1'] + raw + - ['// marker so line numbers end in a known way']) - for line in range(len(lines)): - if line not in ignore_lines: - processCleanFileLine(filename, file_extension, lines, error, line, raw) - -def processFileContent(filename, file_extension, lines, ignore_lines, error): - # test if file is ending with empty lines - empty_lines = 0; - for i in range(len(lines)): - if lines[len(lines)-i-1] == "": - empty_lines = empty_lines + 1; - else: - break +def process_file_content(filename, file_extension, lines, ignore_lines, error): + # test if file is ending with empty lines + empty_lines = 0 + for i in range(len(lines)): + if lines[len(lines) - i - 1] == "": + empty_lines = empty_lines + 1 + else: + break - if empty_lines == 0: - error(filename, len(lines)-empty_lines, 'empty', 'file ends without empty lines') + if empty_lines == 0: + error(filename, len(lines) - empty_lines, 'empty', 'file ends without empty lines') + lines = (['// marker so line numbers and indices both start at 1'] + lines + + ['// marker so line numbers end in a known way']) + for line in range(len(lines)): + if line not in ignore_lines: + process_file_line(filename, file_extension, lines, error, line) - lines = (['// marker so line numbers and indices both start at 1'] + lines + - ['// marker so line numbers end in a known way']) - for line in range(len(lines)): - if line not in ignore_lines: - processFileLine(filename, file_extension, lines, error, line) + process_braces(filename, lines, error) - processBraces(filename, lines, error) # http://stackoverflow.com/questions/241327/python-snippet-to-remove-c-and-c-comments def comment_remover(text): - def blotOutNonNewlines( strIn ) : # Return a string containing only the newline chars contained in strIn - return "" + ("\n" * strIn.count('\n')) - - def replacer( match ) : - s = match.group(0) - if s.startswith('/'): # Matched string is //...EOL or /*...*/ ==> Blot out all non-newline chars - return "@#@"+blotOutNonNewlines(s) - else: # Matched string is '...' or "..." ==> Keep unchanged - return s - - pattern = re.compile( - r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', - re.DOTALL | re.MULTILINE - ) - - raw = re.sub(pattern, replacer, text) - raw = re.sub(r'[ ]*@#@','',raw) - return raw; - - - -def processFile(filename): - error_collection = []; - - def error_handler(filename, linenum, category, message, level=0, line="", char=-1): - error_collection.append( (filename, linenum, category, message, level, line, char ) ) - - file_extension = filename[filename.rfind('.') + 1:] - - if not file_extension in _settings_extensions: - return; - - raw_source = codecs.open(filename, 'r', 'utf8', 'replace').read() - lines = raw_source.split('\n') - lf_lines = [] - crlf_lines = [] - for linenum in range(len(lines) - 1): - if lines[linenum].endswith('\r'): - lines[linenum] = lines[linenum].rstrip('\r') - crlf_lines.append(linenum + 1) - else: - lf_lines.append(linenum + 1) - - # check each line - if lf_lines and crlf_lines : - for linenum in crlf_lines: - error_handler(filename, linenum, 'newline', 'use \\n here') - - # check authorname - if _settings_checks["studentname"]: - m = RegExMatcher(lines[0]) - if not m.match(r'// @student:\s\w+[\s*\w*]*'): - error_handler(filename, 1, 'content', 'failed finding name of student in first line. Correct: "// @student: foo"',1) - - # check double newline - if _settings_checks["multiple empty lines"]: - m = RegExMatcher(raw_source) - if m.findall(r'(\n[ ]*){3,}'): - for mm in m.all(): - error_handler(filename, len(raw_source[:mm.span()[1]].split('\n'))-1, 'empty', 'too many empty new lines (count %i)' % (-2+len(raw_source[mm.span()[0]:mm.span()[1]].split('\n'))),1) - - - # get lines to ignore - ignore_lines = []; - pattern = re.compile(r'nolintnextline') - m.findall(pattern) - for mm in m.all(): - ignore_lines.append(len(raw_source[:mm.span()[1]].split('\n')) + 1) - pattern = re.compile(r'nolint') - m.findall(pattern) - for mm in m.all(): - ignore_lines.append(len(raw_source[:mm.span()[1]].split('\n'))) - - - processFileContent(filename, file_extension, lines, ignore_lines, error_handler) - # clean lines (remove multi line comment) - lines = raw_source.split('\n') - clines = comment_remover(raw_source).split('\n') - processCleanFileContent(filename, file_extension, clines, ignore_lines, error_handler, lines) - - if len(error_collection): - sys.stderr.write('\033[1m\033[93m%10s\033[0m:\n' % ( filename)) - for e in error_collection: - print_error(*e) - - - - -def main(): - filenames = sys.argv[1:]; - for filename in filenames: - processFile(filename) - - sys.stderr.write("\n\n"); - if ERROR_COUNTER == 0: - #sys.stderr.write("\033[92m NO LINT ERRORS! \033[0m\n"); - sys.exit(ERROR_COUNTER) - else: - # if ERROR_COUNTER == 1: - # sys.stderr.write("\033[91m FOUND %i LINT ERROR! \033[0m\n" % ERROR_COUNTER); - # else: - # sys.stderr.write("\033[91m FOUND %i LINT ERRORS! \033[0m\n" % ERROR_COUNTER); - sys.exit(ERROR_COUNTER) + def get_newline_chars(str_in): + return "" + ("\n" * str_in.count('\n')) + + def replacer(match): + s = match.group(0) + if s.startswith('/'): # Matched string is //...EOL or /*...*/ ==> Blot out all non-newline chars + return "@#@" + get_newline_chars(s) + else: # Matched string is '...' or "..." ==> Keep unchanged + return s + + pattern = re.compile(r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', + re.DOTALL | re.MULTILINE) + + raw = re.sub(pattern, replacer, text) + raw = re.sub(r'[ ]*@#@', '', raw) + return raw + + +def process_file(filename): + error_collection = [] + + def error_handler(filename, linenum, category, message, level=0, line="", char=-1): + error_collection.append((filename, linenum, category, message, level, line, char)) + + file_extension = filename[filename.rfind('.') + 1:] + + if file_extension not in _settings_extensions: + return + + raw_source = codecs.open(filename, 'r', 'utf8', 'replace').read() + lines = raw_source.split('\n') + lf_lines = [] + crlf_lines = [] + for linenum in range(len(lines) - 1): + if lines[linenum].endswith('\r'): + lines[linenum] = lines[linenum].rstrip('\r') + crlf_lines.append(linenum + 1) + else: + lf_lines.append(linenum + 1) + + # check each line + if lf_lines and crlf_lines: + for linenum in crlf_lines: + error_handler(filename, linenum, 'newline', 'use \\n here') + + # check authorname + if _settings_checks["studentname"]: + m = RegExMatcher(lines[0]) + if not m.match(r'// @student:\s\w+[\s*\w*]*'): + msg = 'failed finding name of student in first line. Correct: "// @student: foo"' + error_handler(filename, 1, 'content', msg, 1) + + # check double newline + if _settings_checks["multiple empty lines"]: + m = RegExMatcher(raw_source) + if m.findall(r'(\n[ ]*){3,}'): + for mm in m.all(): + msg = 'too many empty new lines (count %i)' + msg = msg % (-2 + len(raw_source[mm.span()[0]:mm.span()[1]].split('\n'))) + error_handler(filename, len(raw_source[:mm.span()[1]].split('\n')) - 1, 'empty', msg, 1) + + # get lines to ignore + ignore_lines = [] + pattern = re.compile(r'nolintnextline') + m.findall(pattern) + for mm in m.all(): + ignore_lines.append(len(raw_source[:mm.span()[1]].split('\n')) + 1) + pattern = re.compile(r'nolint') + m.findall(pattern) + for mm in m.all(): + ignore_lines.append(len(raw_source[:mm.span()[1]].split('\n'))) + + process_file_content(filename, file_extension, lines, ignore_lines, error_handler) + # clean lines (remove multi line comment) + lines = raw_source.split('\n') + clines = comment_remover(raw_source).split('\n') + process_clean_file_content(filename, file_extension, clines, ignore_lines, error_handler, lines) + + if len(error_collection): + sys.stderr.write('\033[1m\033[93m%10s\033[0m:\n' % (filename)) + for e in error_collection: + print_error(*e) if __name__ == '__main__': - main() + filenames = glob.glob("src/examples/*.cpp") + glob.glob("include/cppoptlib/*/*.h") + print("start linting") + print(filenames) + for filename in filenames: + process_file(filename) + + sys.stderr.write("\n\n") + if ERROR_COUNTER == 0: + sys.exit(ERROR_COUNTER) + else: + sys.exit(ERROR_COUNTER) diff --git a/matlab/CMakeLists.txt b/matlab/CMakeLists.txt deleted file mode 100644 index c2baf53..0000000 --- a/matlab/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -# borrow from http://stackoverflow.com/questions/23083024/building-matlab-mex-files-with-cmake-for-g2o-library -set(Matlab_mex /home/wieschol/apps/MATLAB/R2014a/bin/mex) - -# find_package(MatlabMex) -# if(MATLABMEX_FOUND) -# set(HAVE_MATLAB TRUE) -# endif() - -set (CMAKE_CXX_COMPILER ${Matlab_mex}) -set (CMAKE_C_COMPILER ${Matlab_mex}) - -SET( CMAKE_SHARED_LIBRARY_SUFFIX .mexa64 ) # set suffix to .mexa64 -SET( CMAKE_SHARED_LIBRARY_PREFIX ) # remove the "lib" prefix - -SET( CMAKE_CXX_FLAGS "-cxx -largeArrayDims CXXFLAGS='${CXXFLAGS} -std=c++11' COPTIMFLAGS='$COPTIMFLAGS -O2'" ) -SET( CMAKE_SHARED_LIBRARY_CXX_FLAGS ) # remove the -fPIC option. mex does not accept the "-fPIC" option -SET( CMAKE_CXX_COMPILE_OBJECT " -outdir -c ; mv /$$(basename .cxx ).o ") - -# #Variables controlling the linking-phase -SET( CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS ) # remove -shared options. mex does not accept the "-shared" option - -SET(CMAKE_CXX_CREATE_SHARED_LIBRARY " -cxx -output ") - - -SET( CMAKE_INSTALL_RPATH "\$ORIGIN" ) -MESSAGE( STATUS "mex.cmake is loaded.\n" ) - -ADD_LIBRARY( cns SHARED cns.cxx ) diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt deleted file mode 100644 index dc786fe..0000000 --- a/src/examples/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -SET( EXAMPLE_FILES linearregression logisticregression rosenbrock rosenbrock_float simple simple_withoptions nonnegls neldermead neldermead-customized) - -set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/examples ) -foreach( currentfile ${EXAMPLE_FILES} ) - add_executable( ${currentfile} "${currentfile}.cpp" ) - target_link_libraries (${currentfile} gtest gtest_main pthread) -endforeach( currentfile ${EXAMPLE_FILES} ) diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt deleted file mode 100644 index 3f81fa7..0000000 --- a/src/test/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# compile test -add_executable(verify verify.cpp ) -target_link_libraries(verify gtest gtest_main pthread) -install (TARGETS verify DESTINATION bin) -add_test(NAME verify COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/verify) - - -add_executable(benchmark benchmark.cpp ) -target_link_libraries(benchmark gtest gtest_main pthread) -install (TARGETS benchmark DESTINATION bin) -add_test(NAME benchmark COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/benchmark) - diff --git a/src/test/verify.cpp b/src/test/verify.cpp index 4edb89f..d8e6d95 100644 --- a/src/test/verify.cpp +++ b/src/test/verify.cpp @@ -3,18 +3,18 @@ #include #include #include -#include "../../gtest/googletest/include/gtest/gtest.h" -#include "../../include/cppoptlib/meta.h" -#include "../../include/cppoptlib/boundedproblem.h" -#include "../../include/cppoptlib/solver/gradientdescentsolver.h" -#include "../../include/cppoptlib/solver/conjugatedgradientdescentsolver.h" -#include "../../include/cppoptlib/solver/newtondescentsolver.h" -#include "../../include/cppoptlib/solver/bfgssolver.h" -#include "../../include/cppoptlib/solver/lbfgssolver.h" -#include "../../include/cppoptlib/solver/lbfgsbsolver.h" -#include "../../include/cppoptlib/solver/cmaessolver.h" -#include "../../include/cppoptlib/solver/cmaesbsolver.h" -#include "../../include/cppoptlib/solver/neldermeadsolver.h" +#include "gtest/gtest.h" +#include "include/cppoptlib/meta.h" +#include "include/cppoptlib/boundedproblem.h" +#include "include/cppoptlib/solver/gradientdescentsolver.h" +#include "include/cppoptlib/solver/conjugatedgradientdescentsolver.h" +#include "include/cppoptlib/solver/newtondescentsolver.h" +#include "include/cppoptlib/solver/bfgssolver.h" +#include "include/cppoptlib/solver/lbfgssolver.h" +#include "include/cppoptlib/solver/lbfgsbsolver.h" +#include "include/cppoptlib/solver/cmaessolver.h" +#include "include/cppoptlib/solver/cmaesbsolver.h" +#include "include/cppoptlib/solver/neldermeadsolver.h" #define PRECISION 1e-4 using namespace cppoptlib;