diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..3ea7bf6 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,68 @@ +# use a recent CMake version +cmake_minimum_required(VERSION 3.23 FATAL_ERROR) +cmake_policy(VERSION 3.23) +cmake_policy(SET CMP0083 NEW) + +# first of all protect against in-source builds +file(REAL_PATH "${CMAKE_SOURCE_DIR}" _srcdir) +file(REAL_PATH "${CMAKE_BINARY_DIR}" _bindir) + +if(${_srcdir} STREQUAL ${_bindir}) + message(FATAL_ERROR " FATAL: In-source builds are not allowed! + You should create a separate directory for build files.") +endif() +unset(_srcdir) +unset(_bindir) + +# update CMAKE_MODULE_PATH +list(PREPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/source/cmake ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_SOURCE_DIR} ${HOME_PATH}/cmake) + +if(NOT SW_VERSION) + set(SW_VERSION "7.3.3" CACHE STRING "Software Version") +endif() + +message(STATUS "`qtools` - see \"https://www.state-machine.com/qtools/\" for further details.") + +# the `qtools` project, consisting of the tools listed below +# qtools - https://www.state-machine.com/qtools/ +project( + qtools + VERSION ${SW_VERSION} + DESCRIPTION "QTools - https://www.state-machine.com/qtools/" + HOMEPAGE_URL "https://www.state-machine.com/qtools/" + LANGUAGES C +) + +# select target platform specific source directory +if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL Windows) + set(PLATFORM_DIR win32) +else() + set(PLATFORM_DIR posix) +endif() + +# the qclean tool - https://www.state-machine.com/qtools/qclean.html +add_executable(qclean) +add_subdirectory(qclean) + +# the qfsgen tool - https://www.state-machine.com/qtools/qfsgen.html +add_executable(qfsgen) +add_subdirectory(qfsgen) + +# the qspy tool - https://www.state-machine.com/qtools/qspy.html +add_executable(qspy) +add_subdirectory(qspy) + +# the `install` targets +set(QDATAROOT share/qtools) +set(QTARGETS qclean qfsgen qspy) +set(QDIRS qcalc qutest qview qwin) +set(QBIN cmock generate_test_runner python3 qcalc qspy_exit sha256) +list(TRANSFORM QBIN APPEND .bat) +list(APPEND QBIN Termite.ini) +list(TRANSFORM QBIN PREPEND bin/) + +install(TARGETS ${QTARGETS}) +install(PROGRAMS ${BIN_FILES} TYPE BIN) +install(DIRECTORY doc LICENSES DESTINATION ${QDATAROOT}/doc) +install(FILES README.md DESTINATION ${QDATAROOT}/doc) +install(DIRECTORY ${QDIRS} DESTINATION ${QDATAROOT}/data) diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..c60f449 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,38 @@ +{ + "version": 6, + "cmakeMinimumRequired": { + "major": 3, + "minor": 23, + "patch": 0 + }, + + "configurePresets": [ + { + "name": "qtools", + "displayName": "qtools", + "description": "Build all qtools", + "binaryDir": "${sourceDir}/build", + "generator": "Ninja Multi-Config", + "cacheVariables": { + "CMAKE_CONFIGURATION_TYPES": { + "type": "STRING", + "value": "Debug;Release" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Debug" + } + } + } + ], + + "buildPresets": [ + { + "name": "qtools", + "displayName": "qtools", + "description": "Build all qtools", + "configurePreset": "qtools", + "configuration": "Release" + } + ] +} diff --git a/README.md b/README.md index 0690ea2..00815c2 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,50 @@ define the environment variable `QTOOLS` to point to the installation directory of QTools. +## Build using `cmake` +With the right set of C compilation tools on your Windows or Linux +computer, you can build the tools by yourself. + +On a MS-Windows machine a setup with [MSys/MinGW64](https://www.msys2.org/) is recommended to +perform the build. With this environment you will still be able to +generate MS-Windows executable applications. +Another alternative would be to install [MS Visual Studio](https://visualstudio.microsoft.com/). +`CMake` is also able to generate build systems for this development environment. +This however will not be a topic of this discussion. Please see the +[CMake Documentation](https://cmake.org/cmake/help/latest/) for further +details. Especially refer to the section on +[cmake generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html). + +An appropriate [CMakeLists.txt](./CMakeLists.txt) file together with a [cmake presets +file](./CMakePresets.json) is provided with this source code package. + +From within the `qtools` directory you may use `cmake` to build and +install the 3 tools. For this you need the following in addition to the tools +mentioned [above](#about-qtools) + +1. [CMake](https://cmake.org/) - build system generator ([cmake features](https://cmake.org/features/)) + +2. [Ninja](https://ninja-build.org/) - small build system with a focus on speed + +To build with `cmake` +1. From within the `qtools` directory do `cmake --preset qtools` +2. Then build with + - `cmake --build --preset qtools` to build all tools at once or + - `cmake --build --preset qtools --target ` with tool being `qclean`, `qfsgen` or `qspy` + - to build the `Debug` configuration use `cmake --build --preset qtools --config Debug` + - `Release` is the default configuration, if you don't specify a desired config +3. The binaries are created in the `.../qtools/build/` directory +4. To install + - Build the `qtools` preset then + - call `cmake --install build [--config ]` + - The default installation location would be `/usr/local/bin` on a Linux machine or within + a MinGW environment on a Windows machine. + - add `--prefix ` to the installation command line to select a different installation destination. + E.g. `cmake --install build --prefix /usr` will install the built applications from the `Release` + configuration into `/usr/bin`. On a Linux machine you might need to use `sudo` to raise your access rights + in order to install into system directories. + + # Licensing The various Licenses for distributed components are located in the LICENSES/ sub-directory of this QTools distribution. diff --git a/qclean/CMakeLists.txt b/qclean/CMakeLists.txt new file mode 100644 index 0000000..2e3e420 --- /dev/null +++ b/qclean/CMakeLists.txt @@ -0,0 +1,11 @@ +message(STATUS "`qtools/qclean` - see \"https://www.state-machine.com/qtools/qclean.html\" for further details.") + +# the main target +target_sources(qclean PRIVATE + source/main.c + source/getopt.c + ${PLATFORM_DIR}/filesearch.c +) + +# add include dirs to target (-I...) +target_include_directories(qclean PRIVATE include) diff --git a/qfsgen/CMakeLists.txt b/qfsgen/CMakeLists.txt new file mode 100644 index 0000000..5afc129 --- /dev/null +++ b/qfsgen/CMakeLists.txt @@ -0,0 +1,11 @@ +# QTools/qfsgen +message(STATUS "`qtools/qfsgen` - see \"https://www.state-machine.com/qtools/qfsgen.html\" for further details.") + +# the main target +target_sources(qfsgen PRIVATE + source/main.c + ${PLATFORM_DIR}/filesearch.c +) + +# add include dirs to target (-I...) +target_include_directories(qfsgen PRIVATE include) diff --git a/qspy/CMakeLists.txt b/qspy/CMakeLists.txt new file mode 100644 index 0000000..87bd68e --- /dev/null +++ b/qspy/CMakeLists.txt @@ -0,0 +1,28 @@ +# QTools/qspy +message(STATUS "`qtools/qspy` - see \"https://www.state-machine.com/qtools/qspy.html\" for further details.") + +# the main target +target_sources(qspy PRIVATE + source/qspy.c + source/qspy_main.c + source/qspy_be.c + source/qspy_dict.c + source/qspy_seq.c + source/qspy_tx.c + source/getopt.c + ${PLATFORM_DIR}/qspy_pal.c +) + +# add include dirs to target (-I...) +target_include_directories(qspy PRIVATE + ${PLATFORM_DIR} + include +) + +# set defines (-D...) +target_compile_definitions(qspy PRIVATE QSPY_APP) + +# add link libraries (-l...) +if(CMAKE_SYSTEM_NAME STREQUAL Windows) + target_link_libraries(qspy PRIVATE ws2_32) +endif() diff --git a/qutest/qutest.py b/qutest/qutest.py index 52cb6ec..e1c7fc9 100644 --- a/qutest/qutest.py +++ b/qutest/qutest.py @@ -57,7 +57,7 @@ class QUTest: # public class constants - VERSION = 733 + VERSION = 734 TIMEOUT = 1.000 # timeout value [seconds] # private class variables @@ -933,7 +933,7 @@ def _test_end(self): pass def _reset_target(self): - if QUTest._host_exe: + if QUTest._host_exe[0]: if not QUTest._have_assert: #print("quitting exe") QUTest._quithost_exe() @@ -1523,7 +1523,7 @@ def main(): if len(qspy_conf) > 1 and not qspy_conf[1] == '': QSpy.host_udp[1] = int(qspy_conf[1]) if len(qspy_conf) > 2 and not qspy_conf[2] == '': - if QUTest._host_exe: + if QUTest._host_exe[0]: QUTest._host_exe[1] = (QSpy.host_udp[0] + ":" + qspy_conf[2]) else: print("\nTCP port specified without host executable\n") diff --git a/qutest/setup.py b/qutest/setup.py index 9595014..8422804 100644 --- a/qutest/setup.py +++ b/qutest/setup.py @@ -9,7 +9,7 @@ setup( name="qutest", - version="7.3.3", + version="7.3.4", author="Quantum Leaps", author_email="info@state-machine.com", description="QUTest Python scripting support", diff --git a/qview/qview.py b/qview/qview.py index c06284e..ceed9aa 100644 --- a/qview/qview.py +++ b/qview/qview.py @@ -49,7 +49,7 @@ # class QView: ## current version of QView - VERSION = 733 + VERSION = 734 # public static variables... ## menu to be customized @@ -58,6 +58,9 @@ class QView: ## canvas to be customized canvas = None + ## frame to be customized + frame = None + # private class variables... _text_lines = "end - 500 lines" _attach_dialog = None @@ -99,8 +102,11 @@ def _init_gui(root): # View menu... m = Menu(main_menu, tearoff=0) QView._view_canvas = IntVar() + QView._view_frame = IntVar() m.add_checkbutton(label="Canvas", variable=QView._view_canvas, command=QView._onCanvasView) + m.add_checkbutton(label="Frame", variable=QView._view_frame, + command=QView._onFrameView) main_menu.add_cascade(label="View", menu=m) # Global-Filters menu... @@ -253,6 +259,15 @@ def _init_gui(root): QView.canvas = Canvas(QView._canvas_toplevel) QView.canvas.pack() + # frame.............................................................. + QView._frame_toplevel = Toplevel() + QView._frame_toplevel.withdraw() # start not showing + QView._frame_toplevel.protocol("WM_DELETE_WINDOW", + QView._onFrameClose) + QView._frame_toplevel.title("QView -- Frame") + QView.frame = Frame(QView._frame_toplevel) + QView.frame.pack() + # tkinter variables for dialog boxes ................................. QView._locAO_OBJ = StringVar() QView._currObj = (StringVar(), StringVar(), StringVar(), @@ -306,6 +321,12 @@ def print_text(string): def show_canvas(view=1): QView._view_canvas.set(view) + ## Make the frame visible + # (to be used in the constructor of the customization class) + @staticmethod + def show_frame(view=1): + QView._view_frame.set(view) + # private static functions... @staticmethod def _quit(err=0): @@ -454,6 +475,21 @@ def _onCanvasClose(): QView._view_canvas.set(0) QView._canvas_toplevel.withdraw() + @staticmethod + def _onFrameView(*args): + if QView._view_frame.get(): + QView._frame_toplevel.state("normal") + # make the frame jump to the front + QView._frame_toplevel.attributes("-topmost", 1) + QView._frame_toplevel.attributes("-topmost", 0) + else: + QView._frame_toplevel.withdraw() + + @staticmethod + def _onFrameClose(): + QView._view_frame.set(0) + QView._frame_toplevel.withdraw() + @staticmethod def _onGlbFilter_SM(*args): QView._GlbFilterDialog("SM Group", QSpy._GLB_FLT_MASK_SM) @@ -1399,6 +1435,10 @@ def _poll0(): # only show the canvas, if visible QView._onCanvasView() + + # only show the frame, if visible + QView._onFrameView() + return elif recID == QSpy._PKT_DETACH: