diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml index bfd4f6ca..d140ba8b 100644 --- a/.github/workflows/build-linux.yml +++ b/.github/workflows/build-linux.yml @@ -7,7 +7,6 @@ jobs: runs-on: ubuntu-latest env: - PYTHONPATH: /opt/ikos/lib/python3.10/site-packages/ MAKEFLAGS: -j4 steps: @@ -20,7 +19,7 @@ jobs: gcc g++ cmake libgmp-dev libboost-dev libboost-filesystem-dev \ libboost-thread-dev libboost-test-dev \ libsqlite3-dev libtbb-dev libz-dev libedit-dev \ - python3 python3-pygments python3-distutils python3-pip \ + python3 python3-pip \ llvm-14 llvm-14-dev llvm-14-tools clang-14 - name: Compile IKOS run: | diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml index edae755e..c23ed110 100644 --- a/.github/workflows/build-macos.yml +++ b/.github/workflows/build-macos.yml @@ -12,9 +12,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - name: Install dependencies - run: | - pip3 install setuptools - name: Install dependencies run: | brew tap nasa-sw-vnv/core diff --git a/README.md b/README.md index d0c02442..503ef23c 100644 --- a/README.md +++ b/README.md @@ -171,12 +171,11 @@ To build and run the analyzer, you will need the following dependencies: * CMake >= 3.4.3 * GMP >= 4.3.1 * Boost >= 1.55 -* Python 2 >= 2.7.3 or Python 3 >= 3.3 +* Python >= 3.3 * SQLite >= 3.6.20 * TBB >= 2 * LLVM and Clang 14.0.x * (Optional) APRON >= 0.9.10 -* (Optional) Pygments Most of them can be installed using your package manager. diff --git a/analyzer/CMakeLists.txt b/analyzer/CMakeLists.txt index f3729747..c083cb92 100644 --- a/analyzer/CMakeLists.txt +++ b/analyzer/CMakeLists.txt @@ -333,48 +333,37 @@ else() "${CMAKE_CURRENT_SOURCE_DIR}/python/ikos/settings.py.in" VERBATIM) endif() +add_custom_target(ikos-python-settings ALL + DEPENDS "python/ikos/settings/__init__.py" +) # setup.py configure_file(python/setup.py.in python/setup.py @ONLY) -file(GLOB PYTHON_FILES python/ikos/*.py) - -# python module -add_custom_command( - OUTPUT - "python/build/lib/ikos/__init__.py" - COMMAND - ${PYTHON_EXECUTABLE} setup.py -q build - --build-base=build - --build-purelib=build/lib - COMMAND - ${CMAKE_COMMAND} -E touch "build/lib/ikos/__init__.py" # udpate timestamp - WORKING_DIRECTORY - "${CMAKE_CURRENT_BINARY_DIR}/python" - DEPENDS - "${CMAKE_CURRENT_BINARY_DIR}/python/setup.py" - "${CMAKE_CURRENT_BINARY_DIR}/python/ikos/settings/__init__.py" - ${PYTHON_FILES} -) -add_custom_target(ikos-python ALL - DEPENDS "python/build/lib/ikos/__init__.py" -) +option(INSTALL_PYTHON_VIRTUALENV "Install a python virtual environment for ikos" ON) +option(PYTHON_VENV_EXECUTABLE "Path to the python executable of an existing virtual environment") +if (INSTALL_PYTHON_VIRTUALENV) + install(CODE " + message(STATUS \"Running python -m venv ${CMAKE_INSTALL_PREFIX}/libexec\") + execute_process(COMMAND \"${PYTHON_EXECUTABLE}\" -m venv \"${CMAKE_INSTALL_PREFIX}/libexec\") -install(CODE " - set(PIP_INSTALL - \"${PYTHON_EXECUTABLE}\" - \"-m\" - \"pip\" - \"install\" - ) - if (DEFINED ENV{DESTDIR}) - list(APPEND PIP_INSTALL \"--target=\$ENV{DESTDIR}\") - endif() - list(APPEND PIP_INSTALL \".\") + message(STATUS \"Running ${CMAKE_INSTALL_PREFIX}/libexec/bin/python -m pip install -U pip\") + execute_process(COMMAND \"${CMAKE_INSTALL_PREFIX}/libexec/bin/python\" -m pip install -U pip) - execute_process(COMMAND \${PIP_INSTALL} - WORKING_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}/python\") -") + message(STATUS \"Running ${CMAKE_INSTALL_PREFIX}/libexec/bin/python -m pip install -U pygments setuptools\") + execute_process(COMMAND \"${CMAKE_INSTALL_PREFIX}/libexec/bin/python\" -m pip install pygments setuptools) + + message(STATUS \"Running ${CMAKE_INSTALL_PREFIX}/libexec/bin/python -m pip install .\") + execute_process(COMMAND \"${CMAKE_INSTALL_PREFIX}/libexec/bin/python\" -m pip install . + WORKING_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}/python\") + ") + set(PYTHON_VENV_EXECUTABLE "${CMAKE_INSTALL_PREFIX}/libexec/bin/python") +else() + # This can be used by the Homebrew formula or by package maintainers. + if (NOT PYTHON_VENV_EXECUTABLE) + message(FATAL_ERROR "Please specify -DPYTHON_VENV_EXECUTABLE= when using -DINSTALL_PYTHON_VIRTUALENV=OFF") + endif() +endif() # python web resources install(DIRECTORY python/ikos/view DESTINATION share/ikos) diff --git a/analyzer/README.md b/analyzer/README.md index ebf15013..03eb628b 100644 --- a/analyzer/README.md +++ b/analyzer/README.md @@ -59,12 +59,11 @@ To build and run the analyzer, you will need the following dependencies: * CMake >= 3.4.3 * GMP >= 4.3.1 * Boost >= 1.55 -* Python 2 >= 2.7.3 or Python 3 >= 3.3 +* Python >= 3.3 * SQLite >= 3.6.20 * TBB >= 2 * LLVM and Clang 14.0.x * (Optional) APRON >= 0.9.10 -* (Optional) Pygments * IKOS Core * IKOS AR * IKOS LLVM Frontend diff --git a/analyzer/python/ikos/highlight.py b/analyzer/python/ikos/highlight.py index e9141859..67d766c1 100644 --- a/analyzer/python/ikos/highlight.py +++ b/analyzer/python/ikos/highlight.py @@ -39,7 +39,8 @@ # UNILATERAL TERMINATION OF THIS AGREEMENT. # ############################################################################### -from ikos import html +import html + from ikos import log diff --git a/analyzer/python/ikos/html.py b/analyzer/python/ikos/html.py deleted file mode 100644 index cd09c748..00000000 --- a/analyzer/python/ikos/html.py +++ /dev/null @@ -1,47 +0,0 @@ -############################################################################### -# -# Wrapper for python standard library HTML -# -# Author: Thomas Bailleux -# -# Contact: ikos@lists.nasa.gov -# -# Notices: -# -# Copyright (c) 2018-2019 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Disclaimers: -# -# No Warranty: THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF -# ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED -# TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO SPECIFICATIONS, -# ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, -# OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL BE -# ERROR FREE, OR ANY WARRANTY THAT DOCUMENTATION, IF PROVIDED, WILL CONFORM TO -# THE SUBJECT SOFTWARE. THIS AGREEMENT DOES NOT, IN ANY MANNER, CONSTITUTE AN -# ENDORSEMENT BY GOVERNMENT AGENCY OR ANY PRIOR RECIPIENT OF ANY RESULTS, -# RESULTING DESIGNS, HARDWARE, SOFTWARE PRODUCTS OR ANY OTHER APPLICATIONS -# RESULTING FROM USE OF THE SUBJECT SOFTWARE. FURTHER, GOVERNMENT AGENCY -# DISCLAIMS ALL WARRANTIES AND LIABILITIES REGARDING THIRD-PARTY SOFTWARE, -# IF PRESENT IN THE ORIGINAL SOFTWARE, AND DISTRIBUTES IT "AS IS." -# -# Waiver and Indemnity: RECIPIENT AGREES TO WAIVE ANY AND ALL CLAIMS AGAINST -# THE UNITED STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL -# AS ANY PRIOR RECIPIENT. IF RECIPIENT'S USE OF THE SUBJECT SOFTWARE RESULTS -# IN ANY LIABILITIES, DEMANDS, DAMAGES, EXPENSES OR LOSSES ARISING FROM SUCH -# USE, INCLUDING ANY DAMAGES FROM PRODUCTS BASED ON, OR RESULTING FROM, -# RECIPIENT'S USE OF THE SUBJECT SOFTWARE, RECIPIENT SHALL INDEMNIFY AND HOLD -# HARMLESS THE UNITED STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, -# AS WELL AS ANY PRIOR RECIPIENT, TO THE EXTENT PERMITTED BY LAW. -# RECIPIENT'S SOLE REMEDY FOR ANY SUCH MATTER SHALL BE THE IMMEDIATE, -# UNILATERAL TERMINATION OF THIS AGREEMENT. -# -############################################################################### -try: - # Python 3 - from html import escape -except ImportError: - # Python 2 - from cgi import escape diff --git a/analyzer/python/ikos/http.py b/analyzer/python/ikos/http.py index 59b334c3..7e682d4c 100644 --- a/analyzer/python/ikos/http.py +++ b/analyzer/python/ikos/http.py @@ -39,21 +39,13 @@ # UNILATERAL TERMINATION OF THIS AGREEMENT. # ############################################################################### -try: - # Python 3 - from http.server import HTTPServer, BaseHTTPRequestHandler - from urllib.parse import parse_qs, urlencode - from urllib.request import urlopen -except ImportError: - # Python 2 - from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler - from urlparse import parse_qs - from urllib import urlencode - from urllib2 import urlopen +import os from errno import EAFNOSUPPORT +from http.server import HTTPServer, BaseHTTPRequestHandler from socket import AF_INET, AF_INET6 -import os +from urllib.parse import parse_qs, urlencode +from urllib.request import urlopen class HTTPServerIPv6(HTTPServer): ''' diff --git a/analyzer/python/ikos/output_db.py b/analyzer/python/ikos/output_db.py index 1f67ed2d..e121d257 100644 --- a/analyzer/python/ikos/output_db.py +++ b/analyzer/python/ikos/output_db.py @@ -68,7 +68,7 @@ def __init__(self, path): self.con = sqlite3.connect(path) # Use 'str' as text factory since it's the type of string literals - # This is bytes in python 2 and unicode in python 3 + # This is unicode self.con.text_factory = str def close(self): diff --git a/analyzer/python/ikos/view.py b/analyzer/python/ikos/view.py index 9710bf47..21e4f5a4 100644 --- a/analyzer/python/ikos/view.py +++ b/analyzer/python/ikos/view.py @@ -43,6 +43,7 @@ ############################################################################### import argparse import collections +import html import io import json import operator @@ -56,7 +57,6 @@ from ikos import args from ikos import colors -from ikos import html from ikos import log from ikos import report from ikos import settings diff --git a/analyzer/script/ikos-config.py.in b/analyzer/script/ikos-config.py.in index cb59fca2..31f31d81 100755 --- a/analyzer/script/ikos-config.py.in +++ b/analyzer/script/ikos-config.py.in @@ -1,4 +1,4 @@ -#!@PYTHON_EXECUTABLE@ +#!@PYTHON_VENV_EXECUTABLE@ ############################################################################### # # ikos-config: get configuration information @@ -44,16 +44,6 @@ import os.path import sys if __name__ == '__main__': - # Add ../lib/pythonX.Y/site-packages at the beginning of the python path - root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - site_pkg_dir = os.path.join( - root_dir, - 'lib', - 'python%d.%d' % (sys.version_info.major, sys.version_info.minor), - 'site-packages', - ) - sys.path.insert(1, site_pkg_dir) - try: import ikos.settings except ImportError: diff --git a/analyzer/script/ikos-report.py.in b/analyzer/script/ikos-report.py.in index b1d385af..4b5c8648 100755 --- a/analyzer/script/ikos-report.py.in +++ b/analyzer/script/ikos-report.py.in @@ -1,4 +1,4 @@ -#!@PYTHON_EXECUTABLE@ +#!@PYTHON_VENV_EXECUTABLE@ ############################################################################### # # ikos-report: generate an analysis report from a result database @@ -44,16 +44,6 @@ import os.path import sys if __name__ == '__main__': - # Add ../lib/pythonX.Y/site-packages at the beginning of the python path - root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - site_pkg_dir = os.path.join( - root_dir, - 'lib', - 'python%d.%d' % (sys.version_info.major, sys.version_info.minor), - 'site-packages', - ) - sys.path.insert(1, site_pkg_dir) - try: import ikos.report except ImportError: diff --git a/analyzer/script/ikos-scan-c++.py.in b/analyzer/script/ikos-scan-c++.py.in index 87fdce89..f9761629 100755 --- a/analyzer/script/ikos-scan-c++.py.in +++ b/analyzer/script/ikos-scan-c++.py.in @@ -1,4 +1,4 @@ -#!@PYTHON_EXECUTABLE@ +#!@PYTHON_VENV_EXECUTABLE@ ############################################################################### # # ikos-scan-c++: wrapper around clang++ for ikos-scan @@ -44,16 +44,6 @@ import os.path import sys if __name__ == '__main__': - # Add ../lib/pythonX.Y/site-packages at the beginning of the python path - root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - site_pkg_dir = os.path.join( - root_dir, - 'lib', - 'python%d.%d' % (sys.version_info.major, sys.version_info.minor), - 'site-packages', - ) - sys.path.insert(1, site_pkg_dir) - try: import ikos.scan except ImportError: diff --git a/analyzer/script/ikos-scan-cc.py.in b/analyzer/script/ikos-scan-cc.py.in index 66136460..d1ce7574 100755 --- a/analyzer/script/ikos-scan-cc.py.in +++ b/analyzer/script/ikos-scan-cc.py.in @@ -1,4 +1,4 @@ -#!@PYTHON_EXECUTABLE@ +#!@PYTHON_VENV_EXECUTABLE@ ############################################################################### # # ikos-scan-cc: wrapper around clang for ikos-scan @@ -44,16 +44,6 @@ import os.path import sys if __name__ == '__main__': - # Add ../lib/pythonX.Y/site-packages at the beginning of the python path - root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - site_pkg_dir = os.path.join( - root_dir, - 'lib', - 'python%d.%d' % (sys.version_info.major, sys.version_info.minor), - 'site-packages', - ) - sys.path.insert(1, site_pkg_dir) - try: import ikos.scan except ImportError: diff --git a/analyzer/script/ikos-scan-extract.py.in b/analyzer/script/ikos-scan-extract.py.in index 25016e91..f7bef818 100755 --- a/analyzer/script/ikos-scan-extract.py.in +++ b/analyzer/script/ikos-scan-extract.py.in @@ -1,4 +1,4 @@ -#!@PYTHON_EXECUTABLE@ +#!@PYTHON_VENV_EXECUTABLE@ ############################################################################### # # ikos-scan-extract: extract the llvm bitcode generated for a given file @@ -44,16 +44,6 @@ import os.path import sys if __name__ == '__main__': - # Add ../lib/pythonX.Y/site-packages at the beginning of the python path - root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - site_pkg_dir = os.path.join( - root_dir, - 'lib', - 'python%d.%d' % (sys.version_info.major, sys.version_info.minor), - 'site-packages', - ) - sys.path.insert(1, site_pkg_dir) - try: import ikos.scan except ImportError: diff --git a/analyzer/script/ikos-scan.py.in b/analyzer/script/ikos-scan.py.in index 0ded72a2..6af4641b 100755 --- a/analyzer/script/ikos-scan.py.in +++ b/analyzer/script/ikos-scan.py.in @@ -1,4 +1,4 @@ -#!@PYTHON_EXECUTABLE@ +#!@PYTHON_VENV_EXECUTABLE@ ############################################################################### # # ikos-scan: tool to analyze a whole project @@ -44,16 +44,6 @@ import os.path import sys if __name__ == '__main__': - # Add ../lib/pythonX.Y/site-packages at the beginning of the python path - root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - site_pkg_dir = os.path.join( - root_dir, - 'lib', - 'python%d.%d' % (sys.version_info.major, sys.version_info.minor), - 'site-packages', - ) - sys.path.insert(1, site_pkg_dir) - try: import ikos.scan except ImportError: diff --git a/analyzer/script/ikos-view.py.in b/analyzer/script/ikos-view.py.in index 278a9327..14faedd1 100755 --- a/analyzer/script/ikos-view.py.in +++ b/analyzer/script/ikos-view.py.in @@ -1,4 +1,4 @@ -#!@PYTHON_EXECUTABLE@ +#!@PYTHON_VENV_EXECUTABLE@ ############################################################################### # # ikos-view: web server to display an analysis report @@ -44,16 +44,6 @@ import os.path import sys if __name__ == '__main__': - # Add ../lib/pythonX.Y/site-packages at the beginning of the python path - root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - site_pkg_dir = os.path.join( - root_dir, - 'lib', - 'python%d.%d' % (sys.version_info.major, sys.version_info.minor), - 'site-packages', - ) - sys.path.insert(1, site_pkg_dir) - try: import ikos.view except ImportError: diff --git a/analyzer/script/ikos.py.in b/analyzer/script/ikos.py.in index 92f62d19..9f8c122e 100755 --- a/analyzer/script/ikos.py.in +++ b/analyzer/script/ikos.py.in @@ -1,4 +1,4 @@ -#!@PYTHON_EXECUTABLE@ +#!@PYTHON_VENV_EXECUTABLE@ ############################################################################### # # ikos: static analyzer for C/C++ programs @@ -44,16 +44,6 @@ import os.path import sys if __name__ == '__main__': - # Add ../lib/pythonX.Y/site-packages at the beginning of the python path - root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - site_pkg_dir = os.path.join( - root_dir, - 'lib', - 'python%d.%d' % (sys.version_info.major, sys.version_info.minor), - 'site-packages', - ) - sys.path.insert(1, site_pkg_dir) - try: import ikos.analyzer except ImportError: diff --git a/script/bootstrap b/script/bootstrap index dd46af85..1ee4ed22 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -95,9 +95,8 @@ boost_required_version="1.55.0" boost_install_version="1.70.0" tbb_required_version="2" tbb_install_version="11009" -python2_required_version="2.7.3" python3_required_version="3.3" -python_install_version="2.7.16" +python_install_version="3.3" llvm_required_version="9" llvm_install_version="9.0.0" @@ -775,8 +774,7 @@ function python_parse_version() { function python_satisfies_requirements() { local version=$1 - ([[ ${version:0:1} = 2 ]] && version_ge "$version" "$python2_required_version") || - ([[ ${version:0:1} = 3 ]] && version_ge "$version" "$python3_required_version") + ([[ ${version:0:1} = 3 ]] && version_ge "$version" "$python3_required_version") } # Parse and detect the version of llvm-config, given the command name @@ -2167,7 +2165,7 @@ fi ############################### if (( ! found_python )); then - progress "Could NOT find Python >= $python2_required_version or >= $python3_required_version" + progress "Could NOT find Python >= $python3_required_version" if [[ -x "$install_dir/python-$python_install_version/bin/python" ]]; then progress "Using already built ${cgreen}python $python_install_version"