diff --git a/.github/workflows/build-fmusim-gui.yml b/.github/workflows/build-fmusim-gui.yml index 09511834..ba47952f 100644 --- a/.github/workflows/build-fmusim-gui.yml +++ b/.github/workflows/build-fmusim-gui.yml @@ -8,7 +8,7 @@ on: branches: [ main ] jobs: - build-fmusim-gui: + build-fmusim-gui-windows: runs-on: windows-2019 steps: - uses: actions/checkout@v4 @@ -39,4 +39,27 @@ jobs: name: fmusim-gui-x86_64-windows path: fmusim-gui/build/fmusim-gui/Release if-no-files-found: error - + build-fmusim-gui-macos: + runs-on: macos-12 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.10' + - name: Install Qt + uses: jurplel/install-qt-action@v4 + with: + version: '6.7.1' + modules: 'qtpositioning qtwebchannel qtwebengine' + - run: python -m pip install fmpy requests + - run: python fmusim-gui/build/build_cvode.py + - run: python fmusim-gui/build/build_libxml2.py + - run: python fmusim-gui/build/build_zlib.py + - run: cmake -D CMAKE_PREFIX_PATH=${{env.QT_ROOT_DIR}} -S fmusim-gui -B fmusim-gui/build/fmusim-gui + - run: cmake --build fmusim-gui/build/fmusim-gui --config Release + - run: ${{env.QT_ROOT_DIR}}/bin/macdeployqt fmusim-gui/build/fmusim-gui/fmusim-gui.app + - uses: actions/upload-artifact@v4 + with: + name: fmusim-gui-x86_64-macos + path: fmusim-gui/build/fmusim-gui/*.app + if-no-files-found: error \ No newline at end of file diff --git a/fmusim-gui/CMakeLists.txt b/fmusim-gui/CMakeLists.txt index 4bb1e0be..2148ce48 100644 --- a/fmusim-gui/CMakeLists.txt +++ b/fmusim-gui/CMakeLists.txt @@ -9,10 +9,26 @@ set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) +if (${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "AMD64|x86_64") + set(FMI_ARCHITECTURE "x86_64") +elseif (${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "aarch64") + set(FMI_ARCHITECTURE "aarch64") +else () + message(FATAL_ERROR "Unknown System Architecture: ${CMAKE_SYSTEM_PROCESSOR}") +endif () + +if (WIN32) + set(FMI_PLATFORM "${FMI_ARCHITECTURE}-windows") +elseif (APPLE) + set(FMI_PLATFORM "${FMI_ARCHITECTURE}-darwin") +else () + set(FMI_PLATFORM "${FMI_ARCHITECTURE}-linux") +endif () + find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets) -set(CVODE_DIR ${CMAKE_SOURCE_DIR}/build/cvode-x86_64-windows/install) -set(LIBXML2_DIR ${CMAKE_SOURCE_DIR}/build/libxml2-x86_64-windows/install) -set(ZLIB_DIR ${CMAKE_SOURCE_DIR}/build/zlib-x86_64-windows/install) +set(CVODE_DIR ${CMAKE_SOURCE_DIR}/build/cvode-${FMI_PLATFORM}/install) +set(LIBXML2_DIR ${CMAKE_SOURCE_DIR}/build/libxml2-${FMI_PLATFORM}/install) +set(ZLIB_DIR ${CMAKE_SOURCE_DIR}/build/zlib-${FMI_PLATFORM}/install) set(ZLIB_SRC_DIR ${CMAKE_SOURCE_DIR}/build/zlib-1.3) @@ -31,7 +47,6 @@ set(PROJECT_SOURCES ../fmusim/miniunzip.c ${ZLIB_SRC_DIR}/contrib/minizip/unzip.c ${ZLIB_SRC_DIR}/contrib/minizip/ioapi.c - ${ZLIB_SRC_DIR}/contrib/minizip/iowin32.c ../fmusim/FMIModelDescription.c ../fmusim/FMIModelDescription.h ../fmusim/FMIBuildDescription.c @@ -40,6 +55,15 @@ set(PROJECT_SOURCES ../src/structured_variable_name.yy.c ) +if (WIN32) + set(PROJECT_SOURCES ${PROJECT_SOURCES} ${ZLIB_SRC_DIR}/contrib/minizip/iowin32.c) +elseif (APPLE) + set(MACOSX_BUNDLE_ICON_FILE icon.icns) + set(app_icon_macos "${CMAKE_CURRENT_SOURCE_DIR}/resources/icon/icon.icns") + set_source_files_properties(${app_icon_macos} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") + set(PROJECT_SOURCES ${PROJECT_SOURCES} ${app_icon_macos}) +endif () + if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) qt_add_executable(fmusim-gui MANUAL_FINALIZATION @@ -118,16 +142,26 @@ target_include_directories(fmusim-gui PRIVATE ${CVODE_DIR}/include ) -target_compile_definitions(fmusim-gui PRIVATE - YY_NO_UNISTD_H -) +if (WIN32) + target_compile_definitions(fmusim-gui PRIVATE YY_NO_UNISTD_H) +endif () -target_link_libraries(fmusim-gui PRIVATE - Qt6::WebEngineWidgets - ${LIBXML2_DIR}/lib/libxml2.lib - ${ZLIB_DIR}/lib/zlib.lib - ${CVODE_DIR}/lib/sundials_cvode.lib -) + +if (WIN32) + target_link_libraries(fmusim-gui PRIVATE + Qt6::WebEngineWidgets + ${LIBXML2_DIR}/lib/libxml2.lib + ${ZLIB_DIR}/lib/zlib.lib + ${CVODE_DIR}/lib/sundials_cvode.lib + ) +elseif (APPLE) + target_link_libraries(fmusim-gui PRIVATE + Qt6::WebEngineWidgets + ${LIBXML2_DIR}/lib/libxml2.dylib + ${ZLIB_DIR}/lib/libz.a + ${CVODE_DIR}/lib/libsundials_cvode.a + ) +endif () # Define target properties for Android with Qt 6 as: # set_property(TARGET fmusim-gui APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR diff --git a/fmusim-gui/MainWindow.cpp b/fmusim-gui/MainWindow.cpp index 76590340..b5391b38 100644 --- a/fmusim-gui/MainWindow.cpp +++ b/fmusim-gui/MainWindow.cpp @@ -24,6 +24,7 @@ extern "C" { #include "FMISimulation.h" #include "FMIEuler.h" #include "FMICVode.h" +#include } #define FMI_PATH_MAX 4096 @@ -561,7 +562,7 @@ void MainWindow::simulate() { const QByteArray ba = unzipdir.toLocal8Bit(); - settings->unzipdir = _strdup(ba.data()); + settings->unzipdir = strdup(ba.data()); settings->modelDescription = modelDescription; if (interfaceTypeComboBox->currentText() == "Co-Simulation") { @@ -610,7 +611,7 @@ void MainWindow::simulate() { for (auto [variable, value] : startValues.asKeyValueRange()) { settings->startVariables[i] = (FMIModelVariable*)variable; QByteArray buffer = value.toLocal8Bit(); - settings->startValues[i] = _strdup(buffer.data()); + settings->startValues[i] = strdup(buffer.data()); i++; } diff --git a/fmusim-gui/PlotUtil.cpp b/fmusim-gui/PlotUtil.cpp index 213183e4..054493a6 100644 --- a/fmusim-gui/PlotUtil.cpp +++ b/fmusim-gui/PlotUtil.cpp @@ -216,7 +216,6 @@ QString PlotUtil::createPlot(const FMIRecorder* initialRecorder, const FMIRecord " var layout = {" " showlegend: false," " autosize: true," - " font: {family: 'Segoe UI', size: 12}," + plotColors + " grid: {rows: " + QString::number(plotVariables.size()) + ", columns: 1, pattern: 'independent'}," + axes + diff --git a/fmusim-gui/build/build_cvode.py b/fmusim-gui/build/build_cvode.py index 4b635019..e944b728 100644 --- a/fmusim-gui/build/build_cvode.py +++ b/fmusim-gui/build/build_cvode.py @@ -1,24 +1,29 @@ from pathlib import Path from subprocess import check_call -from fmpy.util import download_file import tarfile +from fmpy import platform_tuple +from fmpy.util import download_file -archive = download_file('https://github.com/LLNL/sundials/releases/download/v6.4.1/cvode-6.4.1.tar.gz', - checksum='0a614e7d7d525d9ec88d5a30c887786d7c3681bd123bb6679fb9a4ec5f4609fe') - root = Path(__file__).parent -build_dir = root / 'cvode-x86_64-windows' / 'build' -install_prefix = root / 'cvode-x86_64-windows' / 'install' +archive = download_file('https://github.com/LLNL/sundials/releases/download/v6.4.1/cvode-6.4.1.tar.gz', + checksum='0a614e7d7d525d9ec88d5a30c887786d7c3681bd123bb6679fb9a4ec5f4609fe') with tarfile.open(archive) as file: file.extractall(root) -cmake_args = [ - '-G', 'Visual Studio 16 2019', - '-A', 'x64' -] + +if platform_tuple == 'x86_64-windows': + cmake_args = [ + '-G', 'Visual Studio 16 2019', + '-A', 'x64' + ] +else: + cmake_args = [] + +build_dir = root / f'cvode-{platform_tuple}' / 'build' +install_prefix = root / f'cvode-{platform_tuple}' / 'install' check_call( ['cmake'] + diff --git a/fmusim-gui/build/build_libxml2.py b/fmusim-gui/build/build_libxml2.py index 10e147fa..1f2f8d20 100644 --- a/fmusim-gui/build/build_libxml2.py +++ b/fmusim-gui/build/build_libxml2.py @@ -1,24 +1,26 @@ from pathlib import Path from subprocess import check_call +from fmpy import extract, platform_tuple from fmpy.util import download_file -from fmpy import extract +root = Path(__file__).parent + archive = download_file('https://github.com/GNOME/libxml2/archive/refs/tags/v2.11.5.zip', checksum='711675470075cc85ba450f56aff7424f1ecdef00bc5d1d5dced3ffecd1a9b772') -root = Path(__file__).parent - extract(archive, root) -build_dir = root / 'libxml2-x86_64-windows' / 'build' - -install_prefix = root / 'libxml2-x86_64-windows' / 'install' +if platform_tuple == 'x86_64-windows': + cmake_args = [ + '-G', 'Visual Studio 16 2019', + '-A', 'x64' + ] +else: + cmake_args = [] -cmake_args = [ - '-G', 'Visual Studio 16 2019', - '-A', 'x64' -] +build_dir = root / f'libxml2-{platform_tuple}' / 'build' +install_prefix = root / f'libxml2-{platform_tuple}' / 'install' check_call( ['cmake'] + diff --git a/fmusim-gui/build/build_zlib.py b/fmusim-gui/build/build_zlib.py index 57673512..e1fb5019 100644 --- a/fmusim-gui/build/build_zlib.py +++ b/fmusim-gui/build/build_zlib.py @@ -1,25 +1,29 @@ import tarfile from pathlib import Path from subprocess import check_call +from fmpy import platform_tuple from fmpy.util import download_file +root = Path(__file__).parent + archive = download_file('https://www.zlib.net/fossils/zlib-1.3.tar.gz', checksum='ff0ba4c292013dbc27530b3a81e1f9a813cd39de01ca5e0f8bf355702efa593e') -root = Path(__file__).parent - with tarfile.open(archive) as tf: tf.extractall(root) -build_dir = root / f'zlib-x86_64-windows' / 'build' -install_prefix = root / f'zlib-x86_64-windows' / 'install' +if platform_tuple == 'x86_64-windows': + cmake_args = [ + '-G', 'Visual Studio 16 2019', + '-A', 'x64' + ] +else: + cmake_args = [] -cmake_args = [ - '-G', 'Visual Studio 16 2019', - '-A', 'x64' -] +build_dir = root / f'zlib-{platform_tuple}' / 'build' +install_prefix = root / f'zlib-{platform_tuple}' / 'install' check_call( ['cmake'] + diff --git a/fmusim-gui/main.cpp b/fmusim-gui/main.cpp index 2507ffc9..19302276 100644 --- a/fmusim-gui/main.cpp +++ b/fmusim-gui/main.cpp @@ -16,10 +16,11 @@ int main(int argc, char *argv[]) { app.setStyle("Fusion"); QFont font = app.font(); - font.setPointSize(10); + // font.setPointSize(10); app.setFont(font); MainWindow *window = new MainWindow(); + //window->setStyleSheet("QWidget { font-size: 11px; }"); window->show(); for (qsizetype i = 1; i < app.arguments().length(); i++) { diff --git a/fmusim-gui/resources/icon/icon.icns b/fmusim-gui/resources/icon/icon.icns new file mode 100644 index 00000000..2cc2f5e0 Binary files /dev/null and b/fmusim-gui/resources/icon/icon.icns differ