diff --git a/.editorconfig b/.editorconfig index 42e7c35f..6b22895f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -208,4 +208,4 @@ dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_ dotnet_naming_symbols.private_internal_fields.applicable_kinds = field dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal dotnet_naming_style.camel_case_underscore_style.required_prefix = _ -dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case \ No newline at end of file +dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml new file mode 100644 index 00000000..dba6d719 --- /dev/null +++ b/.github/workflows/checks.yml @@ -0,0 +1,28 @@ +name: Static checks + +on: + push: { branches: [ master ] } + pull_request: { branches: [ master ] } + release: { types: [published] } # runs on “Publish release” button + workflow_dispatch: # lets you run it by hand + +jobs: + build: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + name: Checkout Code + with: + fetch-depth: 0 + + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 8.0.x + + - name: Setup Just + uses: extractions/setup-just@v3 + + - name: Run static checks + shell: bash + run: just check-all diff --git a/.github/workflows/ci-pack.yml b/.github/workflows/ci-pack.yml new file mode 100644 index 00000000..6e1460f5 --- /dev/null +++ b/.github/workflows/ci-pack.yml @@ -0,0 +1,75 @@ +# .github/workflows/ci-pack.yml +name: CI-Pack + +on: + push: { branches: [ master ] } + pull_request: { branches: [ master ] } + release: { types: [published] } # runs on “Publish release” button + workflow_dispatch: # lets you run it by hand + +jobs: + win-build: + uses: ./.github/workflows/win-build.yml + + linux-build: + uses: ./.github/workflows/linux-build.yml + + pack: + needs: [win-build, linux-build] # ← the two workflow_call jobs + runs-on: windows-latest + + steps: + # 1) bring the two per-OS packages into this job -------------------- + - uses: actions/download-artifact@v4 + with: { name: win-bits, path: artifacts/win } + - uses: actions/download-artifact@v4 + with: { name: linux-bits, path: artifacts/linux } + + # 2) unzip → merge → zip ------------------------------------------ + - name: Merge NuGet packages + id: merge + shell: pwsh + run: | + # locate both nupkgs (Rubjerg.Graphviz..nupkg) + $winPkg = Get-ChildItem artifacts/win -Filter *.nupkg | Select -First 1 + $linuxPkg = Get-ChildItem artifacts/linux -Filter *.nupkg | Select -First 1 + if (-not $winPkg -or -not $linuxPkg) { throw "Packages missing" } + + # extract and from the file name + if ($winPkg.Name -notmatch '^(.+?)\.(\d+\.\d+\.\d+(?:-[A-Za-z0-9\.-]+)?)\.nupkg$') { + throw "Unexpected package file name $($winPkg.Name)" + } + $id = $Matches[1] # Rubjerg.Graphviz + $version = $Matches[2] # 2.0.2 (or 2.0.2-beta etc.) + + $stage = "stage" + Remove-Item $stage -Recurse -Force -ErrorAction SilentlyContinue + New-Item -ItemType Directory -Path $stage | Out-Null + + Expand-Archive $winPkg.FullName -DestinationPath $stage -Force + Expand-Archive $linuxPkg.FullName -DestinationPath $stage -Force + + $outFile = "$id.$version.nupkg" + Compress-Archive "$stage\*" $outFile -Force + + # expose the path for later steps + "outfile=$outFile" | Out-File -FilePath $env:GITHUB_OUTPUT -Append + + # 3) upload the merged package as a build artefact ------------------ + - name: Upload final package as artefact + uses: actions/upload-artifact@v4 + with: + name: merged-nupkg + path: ${{ steps.merge.outputs.outfile }} + retention-days: 30 + + # 4) push to NuGet only on a GitHub Release ------------------------- + # - name: Push to NuGet.org + # if: github.event_name == 'release' + # env: + # NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} + # run: | + # nuget push "${{ steps.merge.outputs.outfile }}" ` + # -Source https://api.nuget.org/v3/index.json ` + # -ApiKey $env:NUGET_API_KEY + diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml new file mode 100644 index 00000000..e8967505 --- /dev/null +++ b/.github/workflows/linux-build.yml @@ -0,0 +1,46 @@ +name: linux-build + +on: + workflow_call: + outputs: + artifact-name: + description: "Linux bits" + value: linux-bits + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + name: Checkout Code + with: + fetch-depth: 0 + + # Necessary for running neato + - name: Install libgts + run: sudo apt-get update && sudo apt-get install -y libgts-0.7-5 + + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 8.0.x + + - name: Setup Just + uses: extractions/setup-just@v3 + + - name: Build and test + run: just + + - name: Check diff + run: just check-diff + + - name: Locate nupkg + id: pkg + run: just locate-nupkg "$GITHUB_OUTPUT" + + - uses: actions/upload-artifact@v4 + with: + name: linux-bits + path: ${{ steps.pkg.outputs.package }} + retention-days: 3 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index e2bb3d2a..00000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,91 +0,0 @@ -# This is a basic workflow to help you get started with Actions - -name: CI - -# Controls when the action will run. Triggers the workflow on push or pull request -# events but only for the master branch -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -# https://timheuer.com/blog/building-net-framework-apps-using-github-actions/ -jobs: - # This workflow contains a single job called "build" - build: - - runs-on: windows-latest - - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - - uses: actions/checkout@v1 - name: Checkout Code - - - name: Check if line endings are CRLF - run: | - bash -c "git grep -rlIP . | xargs unix2dos" - echo test - git diff --exit-code - - - name: Add msbuild to PATH - uses: microsoft/setup-msbuild@v1.0.2 - - - name: Setup NuGet.exe for use with actions - uses: NuGet/setup-nuget@v1.0.5 - - - name: Restore Tools - run: dotnet tool restore - - - name: Restore NuGet Packages - run: nuget restore Rubjerg.Graphviz.sln - - - name: Build App - run: msbuild Rubjerg.Graphviz.sln /p:Configuration=Release - - - name: Check if README is up-to-date - run: git diff --exit-code -- README.md - - - name: Check if code is formatted - run: dotnet format whitespace --verify-no-changes -v diag Rubjerg.Graphviz.sln - - - name: Check if code is formatted - run: dotnet format whitespace --verify-no-changes -v diag Rubjerg.Graphviz.NugetTests.sln - - - name: Run Unittests Without Coverage (.NET 8) - run: bash run-tests-netcore.sh Rubjerg.Graphviz.Test\Rubjerg.Graphviz.Test.csproj - - - name: Run Unittests With Coverage Calculation (.NET 4.8) - run: packages\opencover\4.7.1221\tools\OpenCover.Console.exe -skipautoprops -returntargetcode -register '-target:bash.exe' -targetargs:'nunit-console.sh Rubjerg.Graphviz.Test\bin\x64\Release\net48\Rubjerg.Graphviz.Test.dll' '-filter:+[Rubjerg*]* -[Rubjerg.Graphviz.Test*]*' - - - name: Upload Coverage data - run: | - echo "C:\msys64\usr\bin" >> $GITHUB_PATH - Invoke-WebRequest -Uri 'https://codecov.io/bash' -OutFile codecov.sh - bash codecov.sh -f "results.xml" - - - name: Run Transitive Tests (.NET 8) - run: bash run-tests-netcore.sh Rubjerg.Graphviz.TransitiveTest\Rubjerg.Graphviz.TransitiveTest.csproj - - - name: Run Transitive Tests (.NET 4.8) - run: bash nunit-console.sh Rubjerg.Graphviz.TransitiveTest\bin\x64\Release\net48\Rubjerg.Graphviz.TransitiveTest.dll - - - name: Restore NuGet Packages for Nuget Tests (from local package source) - run: nuget restore Rubjerg.Graphviz.NugetTests.sln - - - name: Build Nuget Test Solution - run: msbuild Rubjerg.Graphviz.NugetTests.sln /p:Configuration=Release - - - name: Run Nuget Tests (.NET 8) - run: bash run-tests-netcore.sh Rubjerg.Graphviz.NugetTest\Rubjerg.Graphviz.NugetTest.csproj - - - name: Run Nuget Tests (.NET 4.8) - run: bash nunit-console.sh Rubjerg.Graphviz.NugetTest\bin\x64\Release\net48\Rubjerg.Graphviz.NugetTest.dll - - - name: Run Transitive Nuget Tests (.NET 4.8) - run: bash nunit-console.sh Rubjerg.Graphviz.TransitiveNugetTest\bin\x64\Release\net48\Rubjerg.Graphviz.TransitiveNugetTest.dll - - - name: Run Transitive Nuget Tests (.NET 8) - run: bash nunit-console.sh Rubjerg.Graphviz.TransitiveNugetTest\bin\x64\Release\net8.0\Rubjerg.Graphviz.TransitiveNugetTest.dll - diff --git a/.github/workflows/win-build.yml b/.github/workflows/win-build.yml new file mode 100644 index 00000000..5ef066be --- /dev/null +++ b/.github/workflows/win-build.yml @@ -0,0 +1,47 @@ +# This is a basic workflow to help you get started with Actions + +name: win-build + +# Controls when the action will run. Triggers the workflow on push or pull request +# events but only for the master branch + +on: + workflow_call: + outputs: + artifact-name: + description: "Windows bits" + value: win-bits + +jobs: + build: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + name: Checkout Code + with: + fetch-depth: 0 + + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@v1.0.2 + + - name: Setup NuGet.exe for use with actions + uses: NuGet/setup-nuget@v1.0.5 + + - name: Setup Just + uses: extractions/setup-just@v3 + + - name: Build and test + run: just + + - name: Check diff + run: just check-diff + + - name: Locate nupkg + id: pkg + run: just locate-nupkg $env:GITHUB_OUTPUT + + - uses: actions/upload-artifact@v4 + with: + name: win-bits + path: ${{ steps.pkg.outputs.package }} + retention-days: 3 diff --git a/ConsoleApplication/.gitignore b/ConsoleApplication/.gitignore index 046d185a..1cc3faa4 100644 --- a/ConsoleApplication/.gitignore +++ b/ConsoleApplication/.gitignore @@ -1,3 +1,4 @@ +bin x64 *.vcxproj.user *.svg diff --git a/ConsoleApplication/ConsoleApplication.cpp b/ConsoleApplication/ConsoleApplication.cpp index e855de63..101ca514 100644 --- a/ConsoleApplication/ConsoleApplication.cpp +++ b/ConsoleApplication/ConsoleApplication.cpp @@ -1,20 +1,30 @@ #include -#include -#include "GraphvizWrapper.h" +#include + +#ifdef _WIN32 + #include +#else + #include +#endif + +#include "../GraphvizWrapper/GraphvizWrapper.h" using namespace std; -int main() -{ +int main() { cout << "Make sure to set the current working directory to the repository root!" << endl; cout << "Running tests..." << endl; - + cout << test_agread() << endl; cout << test_agmemread() << endl; cout << test_rj_agmemread() << endl; cout << missing_label_repro() << endl; cout << stackoverflow_repro() << endl; - - cout << "Press key to exit.."; - auto c = _getch(); + cout << agclose_repro() << endl; + + cout << "Press Enter to exit..."; + cin.get(); // Portable replacement for _getch() + + return 0; } + diff --git a/ConsoleApplication/ConsoleApplication.vcxproj b/ConsoleApplication/ConsoleApplication.vcxproj index f4c52d5b..8dd4513a 100644 --- a/ConsoleApplication/ConsoleApplication.vcxproj +++ b/ConsoleApplication/ConsoleApplication.vcxproj @@ -1,15 +1,21 @@ + + Debug x64 + bin/Debug/ Release x64 + bin/Release/ + + 17.0 Win32Proj @@ -17,13 +23,72 @@ ConsoleApplication 10.0 - + + + + + {f9bc5523-352d-469f-8dbb-97eca9d70648} + + + + + + GraphvizWrapper + + + + + + + + + + Always + + + Always + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ../Rubjerg.Graphviz/Resources/ + + + ../Rubjerg.Graphviz/Resources/ + + + Application true v143 Unicode + Application false @@ -31,48 +96,38 @@ true Unicode - - - - - - - - - - - - - - ../Rubjerg.Graphviz/ - - - ../Rubjerg.Graphviz/ - - + + Level3 + Disabled true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true + ProgramDatabase ..\GraphvizWrapper\;..\GraphvizWrapper\include; + true Console true - ..\Rubjerg.Graphviz\GraphvizWrapper.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) + ..\Rubjerg.Graphviz\Resources\GraphvizWrapper.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) false - + + Level3 + MaxSpeed true true true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + AnySuitable + Speed true ..\GraphvizWrapper\;..\GraphvizWrapper\include; @@ -81,25 +136,52 @@ true true true + ..\Rubjerg.Graphviz\Resources\GraphvizWrapper.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) - - - - - - - {f9bc5523-352d-469f-8dbb-97eca9d70648} + + false - - - - Document - - - Document - - - - - - \ No newline at end of file + + + + + + + + + + + + + clang++ + -std=c++17 -O2 -Wl,-rpath,'$ORIGIN' + bin/linux/ + ConsoleApplication + ../GraphvizWrapper/include + ../Rubjerg.Graphviz/Resources + ConsoleApplication.cpp + + $(LibDirs)/libGraphvizWrapper.so $(LibDirs)/libcgraph.so.6 $(LibDirs)/libgvc.so.6 $(LibDirs)/libxdot.so.4 + + + + + $(OutputPath)$(OutputFile) + + + + + + + + + + + + + + + + + + diff --git a/GraphvizWrapper/.gitignore b/GraphvizWrapper/.gitignore index 0a254cfb..d9534a2a 100644 --- a/GraphvizWrapper/.gitignore +++ b/GraphvizWrapper/.gitignore @@ -1,2 +1,4 @@ bin *.vcxproj.user +*.rpm +*.deb diff --git a/GraphvizWrapper/GraphvizWrapper.h b/GraphvizWrapper/GraphvizWrapper.h index e54fd668..e3c481c3 100644 --- a/GraphvizWrapper/GraphvizWrapper.h +++ b/GraphvizWrapper/GraphvizWrapper.h @@ -1,12 +1,18 @@ #pragma once #define _CRT_SECURE_NO_DEPRECATE -#include #include #include #include -#define GVDLL 1 +#ifdef _WIN32 + #define STRDUP _strdup + #define GVDLL 1 + #define API __declspec(dllexport) +#else + #define STRDUP strdup + #define API +#endif #include "cgraph.h" #include "gvc.h" @@ -19,7 +25,7 @@ using namespace std; static int rj_afread(void* stream, char* buffer, int bufsize) { - istringstream* is = (istringstream*)stream; + istream* is = (istream*)stream; is->read(buffer, bufsize); int result = (int)is->gcount(); return result; @@ -27,14 +33,14 @@ static int rj_afread(void* stream, char* buffer, int bufsize) static int rj_putstr(void* stream, const char* s) { - ostringstream* os = (ostringstream*)stream; + ostream* os = (ostream*)stream; (*os) << s; return 0; } static int rj_flush(void* stream) { - ostringstream* os = (ostringstream*)stream; + ostream* os = (ostream*)stream; os->flush(); return 0; } @@ -44,129 +50,128 @@ static Agdisc_t disc = { 0, &ioDisc }; extern "C" { - __declspec(dllexport) void free_str(char* str); + API void free_str(char* str); #pragma region "CGraph" // Some wrappers around cgraph macros - __declspec(dllexport) Agedge_t* rj_agmkin(Agedge_t* e); - __declspec(dllexport) Agedge_t* rj_agmkout(Agedge_t* e); - __declspec(dllexport) Agnode_t* rj_aghead(Agedge_t* edge); - __declspec(dllexport) Agnode_t* rj_agtail(Agedge_t* edge); - __declspec(dllexport) int rj_ageqedge(Agedge_t* e, Agedge_t* f); + API Agedge_t* rj_agmkin(Agedge_t* e); + API Agedge_t* rj_agmkout(Agedge_t* e); + API Agnode_t* rj_aghead(Agedge_t* edge); + API Agnode_t* rj_agtail(Agedge_t* edge); + API int rj_ageqedge(Agedge_t* e, Agedge_t* f); // Some wrappers around existing cgraph functions to handle string marshaling - __declspec(dllexport) const char* rj_agmemwrite(Agraph_t* g); - __declspec(dllexport) Agraph_t* rj_agmemread(const char* s); - __declspec(dllexport) Agraph_t* rj_agopen(char* name, int graphtype); - __declspec(dllexport) const char* rj_sym_key(Agsym_t* sym); - - __declspec(dllexport) double node_x(Agnode_t* node); - __declspec(dllexport) double node_y(Agnode_t* node); - __declspec(dllexport) double node_width(Agnode_t* node); - __declspec(dllexport) double node_height(Agnode_t* node); - - __declspec(dllexport) textlabel_t* node_label(Agnode_t* node); - __declspec(dllexport) textlabel_t* edge_label(Agedge_t* edge); - __declspec(dllexport) textlabel_t* graph_label(Agraph_t* graph); - - __declspec(dllexport) double label_x(textlabel_t* label); - __declspec(dllexport) double label_y(textlabel_t* label); - __declspec(dllexport) double label_width(textlabel_t* label); - __declspec(dllexport) double label_height(textlabel_t* label); - __declspec(dllexport) const char* label_text(textlabel_t* label); - __declspec(dllexport) double label_fontsize(textlabel_t* label); - __declspec(dllexport) const char* label_fontname(textlabel_t* label); - - __declspec(dllexport) void clone_attribute_declarations(Agraph_t* from, Agraph_t* to); - __declspec(dllexport) void convert_to_undirected(Agraph_t* graph); + API const char* rj_agmemwrite(Agraph_t* g); + API Agraph_t* rj_agmemread(const char* s); + API Agraph_t* rj_agopen(char* name, int graphtype); + API const char* rj_sym_key(Agsym_t* sym); + + API double node_x(Agnode_t* node); + API double node_y(Agnode_t* node); + API double node_width(Agnode_t* node); + API double node_height(Agnode_t* node); + + API textlabel_t* node_label(Agnode_t* node); + API textlabel_t* edge_label(Agedge_t* edge); + API textlabel_t* graph_label(Agraph_t* graph); + + API double label_x(textlabel_t* label); + API double label_y(textlabel_t* label); + API double label_width(textlabel_t* label); + API double label_height(textlabel_t* label); + API const char* label_text(textlabel_t* label); + API double label_fontsize(textlabel_t* label); + API const char* label_fontname(textlabel_t* label); + + API void clone_attribute_declarations(Agraph_t* from, Agraph_t* to); + API void convert_to_undirected(Agraph_t* graph); #pragma endregion #pragma region "xdot" - __declspec(dllexport) size_t get_cnt(xdot* xdot); - __declspec(dllexport) xdot_op* get_ops(xdot* xdot); - __declspec(dllexport) xdot_kind get_kind(xdot_op* op); - __declspec(dllexport) xdot_rect* get_ellipse(xdot_op* op); - __declspec(dllexport) xdot_polyline* get_polygon(xdot_op* op); - __declspec(dllexport) xdot_polyline* get_polyline(xdot_op* op); - __declspec(dllexport) xdot_polyline* get_bezier(xdot_op* op); - __declspec(dllexport) xdot_text* get_text(xdot_op* op); - __declspec(dllexport) xdot_image* get_image(xdot_op* op); - __declspec(dllexport) char* get_color(xdot_op* op); - __declspec(dllexport) xdot_color* get_grad_color(xdot_op* op); - __declspec(dllexport) xdot_font* get_font(xdot_op* op); - __declspec(dllexport) char* get_style(xdot_op* op); - __declspec(dllexport) unsigned int get_fontchar(xdot_op* op); - __declspec(dllexport) xdot_rect* get_pos(xdot_image* img); - __declspec(dllexport) char* get_name_image(xdot_image* img); - __declspec(dllexport) double get_size(xdot_font* font); - __declspec(dllexport) char* get_name_font(xdot_font* font); - __declspec(dllexport) xdot_grad_type get_type(xdot_color* clr); - __declspec(dllexport) char* get_clr(xdot_color* clr); - __declspec(dllexport) xdot_linear_grad* get_ling(xdot_color* clr); - __declspec(dllexport) xdot_radial_grad* get_ring(xdot_color* clr); - __declspec(dllexport) double get_x_text(xdot_text* txt); - __declspec(dllexport) double get_y_text(xdot_text* txt); - __declspec(dllexport) xdot_align get_align(xdot_text* txt); - __declspec(dllexport) double get_width(xdot_text* txt); - __declspec(dllexport) char* get_text_str(xdot_text* txt); - __declspec(dllexport) double get_x0_ling(xdot_linear_grad* ling); - __declspec(dllexport) double get_y0_ling(xdot_linear_grad* ling); - __declspec(dllexport) double get_x1_ling(xdot_linear_grad* ling); - __declspec(dllexport) double get_y1_ling(xdot_linear_grad* ling); - __declspec(dllexport) int get_n_stops_ling(xdot_linear_grad* ling); - __declspec(dllexport) xdot_color_stop* get_stops_ling(xdot_linear_grad* ling); - __declspec(dllexport) double get_x0_ring(xdot_radial_grad* ring); - __declspec(dllexport) double get_y0_ring(xdot_radial_grad* ring); - __declspec(dllexport) double get_r0_ring(xdot_radial_grad* ring); - __declspec(dllexport) double get_x1_ring(xdot_radial_grad* ring); - __declspec(dllexport) double get_y1_ring(xdot_radial_grad* ring); - __declspec(dllexport) double get_r1_ring(xdot_radial_grad* ring); - __declspec(dllexport) int get_n_stops_ring(xdot_radial_grad* ring); - __declspec(dllexport) xdot_color_stop* get_stops_ring(xdot_radial_grad* ring); - __declspec(dllexport) float get_frac(xdot_color_stop* stop); - __declspec(dllexport) char* get_color_stop(xdot_color_stop* stop); - __declspec(dllexport) size_t get_cnt_polyline(xdot_polyline* polyline); - __declspec(dllexport) xdot_point* get_pts_polyline(xdot_polyline* polyline); - __declspec(dllexport) double get_x_point(xdot_point* point); - __declspec(dllexport) double get_y_point(xdot_point* point); - __declspec(dllexport) double get_z_point(xdot_point* point); - __declspec(dllexport) double get_x_rect(xdot_rect* rect); - __declspec(dllexport) double get_y_rect(xdot_rect* rect); - __declspec(dllexport) double get_w_rect(xdot_rect* rect); - __declspec(dllexport) double get_h_rect(xdot_rect* rect); - __declspec(dllexport) xdot_color_stop* get_color_stop_at_index(xdot_color_stop* stops, int index); - __declspec(dllexport) xdot_op* get_op_at_index(xdot_op* ops, int index); - __declspec(dllexport) xdot_point* get_pt_at_index(xdot_point* pts, int index); + API size_t get_cnt(xdot* xdot); + API xdot_op* get_ops(xdot* xdot); + API xdot_kind get_kind(xdot_op* op); + API xdot_rect* get_ellipse(xdot_op* op); + API xdot_polyline* get_polygon(xdot_op* op); + API xdot_polyline* get_polyline(xdot_op* op); + API xdot_polyline* get_bezier(xdot_op* op); + API xdot_text* get_text(xdot_op* op); + API xdot_image* get_image(xdot_op* op); + API char* get_color(xdot_op* op); + API xdot_color* get_grad_color(xdot_op* op); + API xdot_font* get_font(xdot_op* op); + API char* get_style(xdot_op* op); + API unsigned int get_fontchar(xdot_op* op); + API xdot_rect* get_pos(xdot_image* img); + API char* get_name_image(xdot_image* img); + API double get_size(xdot_font* font); + API char* get_name_font(xdot_font* font); + API xdot_grad_type get_type(xdot_color* clr); + API char* get_clr(xdot_color* clr); + API xdot_linear_grad* get_ling(xdot_color* clr); + API xdot_radial_grad* get_ring(xdot_color* clr); + API double get_x_text(xdot_text* txt); + API double get_y_text(xdot_text* txt); + API xdot_align get_align(xdot_text* txt); + API double get_width(xdot_text* txt); + API char* get_text_str(xdot_text* txt); + API double get_x0_ling(xdot_linear_grad* ling); + API double get_y0_ling(xdot_linear_grad* ling); + API double get_x1_ling(xdot_linear_grad* ling); + API double get_y1_ling(xdot_linear_grad* ling); + API int get_n_stops_ling(xdot_linear_grad* ling); + API xdot_color_stop* get_stops_ling(xdot_linear_grad* ling); + API double get_x0_ring(xdot_radial_grad* ring); + API double get_y0_ring(xdot_radial_grad* ring); + API double get_r0_ring(xdot_radial_grad* ring); + API double get_x1_ring(xdot_radial_grad* ring); + API double get_y1_ring(xdot_radial_grad* ring); + API double get_r1_ring(xdot_radial_grad* ring); + API int get_n_stops_ring(xdot_radial_grad* ring); + API xdot_color_stop* get_stops_ring(xdot_radial_grad* ring); + API float get_frac(xdot_color_stop* stop); + API char* get_color_stop(xdot_color_stop* stop); + API size_t get_cnt_polyline(xdot_polyline* polyline); + API xdot_point* get_pts_polyline(xdot_polyline* polyline); + API double get_x_point(xdot_point* point); + API double get_y_point(xdot_point* point); + API double get_z_point(xdot_point* point); + API double get_x_rect(xdot_rect* rect); + API double get_y_rect(xdot_rect* rect); + API double get_w_rect(xdot_rect* rect); + API double get_h_rect(xdot_rect* rect); + API xdot_color_stop* get_color_stop_at_index(xdot_color_stop* stops, int index); + API xdot_op* get_op_at_index(xdot_op* ops, int index); + API xdot_point* get_pt_at_index(xdot_point* pts, int index); #pragma endregion #pragma region "testing/debugging" - __declspec(dllexport) bool echobool(bool arg); - __declspec(dllexport) int echoint(int arg); - __declspec(dllexport) bool return_true(); - __declspec(dllexport) bool return_false(); - __declspec(dllexport) int return1(); - __declspec(dllexport) int return_1(); + API bool echobool(bool arg); + API int echoint(int arg); + API bool return_true(); + API bool return_false(); + API int return1(); + API int return_1(); typedef enum { Val1, Val2, Val3, Val4, Val5 } TestEnum; - __declspec(dllexport) TestEnum echo_enum(TestEnum e); - __declspec(dllexport) TestEnum return_enum1(); - __declspec(dllexport) TestEnum return_enum2(); - __declspec(dllexport) TestEnum return_enum5(); - __declspec(dllexport) char* echo_string(char* str); - __declspec(dllexport) char* return_empty_string(); - __declspec(dllexport) char* return_hello(); - __declspec(dllexport) char* return_copyright(); - __declspec(dllexport) int stackoverflow_repro(); - __declspec(dllexport) int missing_label_repro(); - __declspec(dllexport) int test_agread(); - __declspec(dllexport) int test_agmemread(); - __declspec(dllexport) int test_rj_agmemread(); + API TestEnum echo_enum(TestEnum e); + API TestEnum return_enum1(); + API TestEnum return_enum2(); + API TestEnum return_enum5(); + API char* echo_string(char* str); + API const char* return_empty_string(); + API const char* return_hello(); + API const char* return_copyright(); + API int agclose_repro(); + API int stackoverflow_repro(); + API int missing_label_repro(); + API int test_agread(); + API int test_agmemread(); + API int test_rj_agmemread(); #pragma endregion } - - diff --git a/GraphvizWrapper/GraphvizWrapper.vcxproj b/GraphvizWrapper/GraphvizWrapper.vcxproj index 3d067d28..7a566e96 100644 --- a/GraphvizWrapper/GraphvizWrapper.vcxproj +++ b/GraphvizWrapper/GraphvizWrapper.vcxproj @@ -1,5 +1,7 @@  + + Debug @@ -10,49 +12,77 @@ x64 + + {F9BC5523-352D-469F-8DBB-97ECA9D70648} GraphvizWrapper 10.0 GraphvizWrapper - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ..\Rubjerg.Graphviz\Resources\ + bin\Intermediate\$(Configuration)\ + false + + + ..\Rubjerg.Graphviz\Resources\ + bin\Intermediate\$(Configuration)\ + false + + + + DynamicLibrary true v143 MultiByte - + + DynamicLibrary false v143 true MultiByte - - - - - - - - - - - - - - ..\Rubjerg.Graphviz\ - bin\Intermediate\$(Configuration)\ - false - - - ..\Rubjerg.Graphviz\ - bin\Intermediate\$(Configuration)\ - false - - + + Level3 Disabled @@ -62,7 +92,7 @@ true - xcopy /y /d /s /e "graphvizfiles/$(Configuration)" "$(OutDir)" + xcopy /y /d /s /e "graphvizfiles/$(Configuration)" "$(OutDir)" Console @@ -72,7 +102,8 @@ lib - + + Level3 MaxSpeed @@ -85,7 +116,7 @@ Speed - xcopy /y /d /s /e "graphvizfiles/$(Configuration)" "$(OutDir)" + xcopy /y /d /s /e "graphvizfiles/$(Configuration)" "$(OutDir)" true @@ -95,15 +126,44 @@ lib - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + clang++ + + -std=c++17 -shared -fPIC -O2 graphvizfiles/linux/libcgraph.so.6 graphvizfiles/linux/libgvc.so.6 graphvizfiles/linux/libxdot.so.4 -Wl,-rpath,'$ORIGIN' + ../Rubjerg.Graphviz/Resources/ + libGraphvizWrapper.so + include/ + graphvizfiles/linux + Main.cpp Test.cpp XDot.cpp + + + + + $(OutputPath)$(OutputFile) + + + + + + + + + + + + + + + + + diff --git a/GraphvizWrapper/Main.cpp b/GraphvizWrapper/Main.cpp index a5adfaaa..9e8c62bf 100644 --- a/GraphvizWrapper/Main.cpp +++ b/GraphvizWrapper/Main.cpp @@ -1,5 +1,4 @@ #define _CRT_SECURE_NO_DEPRECATE -#include #include #include #include @@ -42,8 +41,8 @@ const char* rj_agmemwrite(Agraph_t* g) ostringstream os; agwrite(g, &os); // Note that os and os.str() will go out of scope when this function returns. - // Therefore we need to strdup the underlying c string - return _strdup(os.str().c_str()); + // Therefore we need to STRDUP the underlying c string + return STRDUP(os.str().c_str()); } diff --git a/GraphvizWrapper/Test.cpp b/GraphvizWrapper/Test.cpp index d0094294..80f263b3 100644 --- a/GraphvizWrapper/Test.cpp +++ b/GraphvizWrapper/Test.cpp @@ -1,5 +1,4 @@ #define _CRT_SECURE_NO_DEPRECATE -#include #include #include #include @@ -24,14 +23,15 @@ char* echo_string(char* str) { // may already be freed when the consumer uses the string. // Instead, we have to duplicate the string. // Note that the caller has to free the returned string though, because we transfer ownership. - return _strdup(str); + return STRDUP(str); } /// Ownership is not returned to the caller -char* return_empty_string() { return ""; } +const char* return_empty_string() { return ""; } /// Ownership is not returned to the caller -char* return_hello() { return "hello"; } +const char* return_hello() { return "hello"; } /// Ownership is not returned to the caller -char* return_copyright() { return u8""; } +const char* return_copyright() { return "\xC2\xA9"; } // UTF-8 encoding for + char* readFile(const std::string& filename) { std::ifstream file(filename, std::ios::binary | std::ios::ate); @@ -70,33 +70,8 @@ int renderToSvg(char* dotString) return 0; } -// This test fails only the first time. Rerunning it makes it work. -int missing_label_repro() { - const std::string filename = "missing-label-repro.dot"; - char* dotString = readFile(filename); - if (dotString == nullptr) - return 1; - if (renderToSvg(dotString) > 0) return 2; - - char* svgText = readFile("test.svg"); - char* expected = ">OpenNode"; - if (strstr(svgText, expected) == nullptr) - return 3; - return 0; -} - -int stackoverflow_repro() { - - const std::string filename = "stackoverflow-repro.dot"; - char* dotString = readFile(filename); - if (dotString == nullptr) - return 1; - return renderToSvg(dotString); -} - - int test_agread() { - char* filename = "missing-label-repro.dot"; + const char* filename = "missing-label-repro.dot"; // Open the file for reading FILE* fp = fopen(filename, "r"); if (fp == nullptr) @@ -105,6 +80,7 @@ int test_agread() { if (graph == nullptr) return 2; fclose(fp); + agclose(graph); return 0; } @@ -116,6 +92,7 @@ int test_agmemread() { auto graph = agmemread(dotString); if (graph == nullptr) return 1; + agclose(graph); return 0; } @@ -127,6 +104,49 @@ int test_rj_agmemread() { auto graph = rj_agmemread(dotString); if (graph == nullptr) return 2; + agclose(graph); + return 0; +} + +// This test fails only the first time. Rerunning it makes it work. +int missing_label_repro() { + const std::string filename = "missing-label-repro.dot"; + char* dotString = readFile(filename); + if (dotString == nullptr) + return 1; + if (renderToSvg(dotString) > 0) return 2; + + char* svgText = readFile("test.svg"); + const char* expected = ">OpenNode"; + if (strstr(svgText, expected) == nullptr) + return 3; return 0; } +int stackoverflow_repro() { + const std::string filename = "stackoverflow-repro.dot"; + char* dotString = readFile(filename); + if (dotString == nullptr) + return 1; + return renderToSvg(dotString); +} + +int agclose_repro() { + auto gvc = gvContext(); + + auto root = rj_agopen(const_cast("test"), 0); // Cast to avoid warnings + agattr(root, 1, const_cast("label"), const_cast("")); + auto nodeA = agnode(root, const_cast("A"), 1); + agset(nodeA, const_cast("label"), const_cast("1")); + auto dot = rj_agmemwrite(root); + agclose(root); + + root = rj_agmemread(dot); + gvLayout(gvc, root, "dot"); + gvRender(gvc, root, "xdot", 0); + agclose(root); + root = rj_agopen(const_cast("test 2"), 0); + agclose(root); + + return 0; +} diff --git a/GraphvizWrapper/graphvizfiles/linux/acyclic b/GraphvizWrapper/graphvizfiles/linux/acyclic new file mode 100755 index 00000000..2cbe1dab Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/acyclic differ diff --git a/GraphvizWrapper/graphvizfiles/linux/bcomps b/GraphvizWrapper/graphvizfiles/linux/bcomps new file mode 100755 index 00000000..3ee15628 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/bcomps differ diff --git a/GraphvizWrapper/graphvizfiles/linux/ccomps b/GraphvizWrapper/graphvizfiles/linux/ccomps new file mode 100755 index 00000000..b5a9eb13 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/ccomps differ diff --git a/GraphvizWrapper/graphvizfiles/linux/cluster b/GraphvizWrapper/graphvizfiles/linux/cluster new file mode 100755 index 00000000..45054b77 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/cluster differ diff --git a/GraphvizWrapper/graphvizfiles/linux/diffimg b/GraphvizWrapper/graphvizfiles/linux/diffimg new file mode 100755 index 00000000..63fb2121 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/diffimg differ diff --git a/GraphvizWrapper/graphvizfiles/linux/dijkstra b/GraphvizWrapper/graphvizfiles/linux/dijkstra new file mode 100755 index 00000000..1b3b289f Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/dijkstra differ diff --git a/GraphvizWrapper/graphvizfiles/linux/dot b/GraphvizWrapper/graphvizfiles/linux/dot new file mode 100755 index 00000000..f8ae8a1b Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/dot differ diff --git a/GraphvizWrapper/graphvizfiles/linux/dot_builtins b/GraphvizWrapper/graphvizfiles/linux/dot_builtins new file mode 100755 index 00000000..65b63e97 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/dot_builtins differ diff --git a/GraphvizWrapper/graphvizfiles/linux/edgepaint b/GraphvizWrapper/graphvizfiles/linux/edgepaint new file mode 100755 index 00000000..9716c346 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/edgepaint differ diff --git a/GraphvizWrapper/graphvizfiles/linux/gc b/GraphvizWrapper/graphvizfiles/linux/gc new file mode 100755 index 00000000..5606fb9f Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/gc differ diff --git a/GraphvizWrapper/graphvizfiles/linux/gml2gv b/GraphvizWrapper/graphvizfiles/linux/gml2gv new file mode 100755 index 00000000..9d8fdce8 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/gml2gv differ diff --git a/GraphvizWrapper/graphvizfiles/linux/graphml2gv b/GraphvizWrapper/graphvizfiles/linux/graphml2gv new file mode 100755 index 00000000..a55d9887 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/graphml2gv differ diff --git a/GraphvizWrapper/graphvizfiles/linux/graphviz/config6 b/GraphvizWrapper/graphvizfiles/linux/graphviz/config6 new file mode 100644 index 00000000..2b6301ce --- /dev/null +++ b/GraphvizWrapper/graphvizfiles/linux/graphviz/config6 @@ -0,0 +1,331 @@ +# This file was generated by "dot -c" at time of install. + +# You may temporarily disable a plugin by removing or commenting out +# a line in this file, or you can modify its "quality" value to affect +# default plugin selection. + +# Manual edits to this file **will be lost** on upgrade. + +libgvplugin_core.so.6 core { + device { + dot:dot 1 + gv:dot 1 + canon:dot 1 + plain:dot 1 + plain-ext:dot 1 + xdot:xdot 1 + xdot1.2:xdot 1 + xdot1.4:xdot 1 + } + device { + fig:fig 1 + } + device { + ismap:map 1 + cmap:map 1 + imap:map 1 + cmapx:map 1 + imap_np:map 1 + cmapx_np:map 1 + } + device { + mp:mp -1 + } + device { + ps:ps 1 + ps2:ps 1 + eps:ps 1 + } + device { + svg:svg 1 + svgz:svg 1 + svg_inline:svg 1 + } + device { + json:json 1 + json0:json 1 + dot_json:json 1 + xdot_json:json 1 + } + device { + tk:tk 1 + } + device { + pic:pic -1 + } + device { + pov:pov 1 + } + render { + dot 1 + xdot 1 + } + render { + fig 1 + } + render { + map 1 + } + render { + mp -1 + } + render { + ps 1 + } + render { + svg 1 + svg_inline 1 + } + render { + json 1 + json0 1 + dot_json 1 + xdot_json 1 + } + render { + tk 1 + } + render { + pic -1 + } + render { + pov 1 + } + loadimage { + png:svg 1 + gif:svg 1 + jpeg:svg 1 + jpe:svg 1 + jpg:svg 1 + png:fig 1 + gif:fig 1 + jpeg:fig 1 + jpe:fig 1 + jpg:fig 1 + png:vrml 1 + gif:vrml 1 + jpeg:vrml 1 + jpe:vrml 1 + jpg:vrml 1 + eps:ps 1 + ps:ps 1 + (lib):ps 1 + png:map 1 + gif:map 1 + jpeg:map 1 + jpe:map 1 + jpg:map 1 + ps:map 1 + eps:map 1 + svg:map 1 + png:dot 1 + gif:dot 1 + jpeg:dot 1 + jpe:dot 1 + jpg:dot 1 + ps:dot 1 + eps:dot 1 + svg:dot 1 + png:xdot 1 + gif:xdot 1 + jpeg:xdot 1 + jpe:xdot 1 + jpg:xdot 1 + ps:xdot 1 + eps:xdot 1 + svg:xdot 1 + svg:svg 1 + gif:tk 1 + } +} +libgvplugin_devil.so.6 devil { + device { + bmp:cairo -1 + jpg:cairo -1 + jpe:cairo -1 + jpeg:cairo -1 + png:cairo -1 + tif:cairo -1 + tiff:cairo -1 + tga:cairo -1 + } +} +libgvplugin_dot_layout.so.6 dot_layout { + layout { + dot 0 + } +} +libgvplugin_gd.so.6 gd { + render { + gd 1 + } + render { + vrml 1 + } + textlayout { + textlayout 2 + } + loadimage { + gd:gd 1 + gd2:gd 1 + gif:gd 1 + jpeg:gd 1 + jpe:gd 1 + jpg:gd 1 + png:gd 1 + gd:ps 1 + gd:lasi 1 + gd2:ps 1 + gd2:lasi 1 + gif:ps 1 + gif:lasi 1 + jpeg:ps 1 + jpg:ps 1 + jpe:ps 1 + jpeg:lasi 1 + jpg:lasi 1 + jpe:lasi 1 + png:ps 1 + png:lasi 1 + gd:cairo 1 + gd2:cairo 1 + gif:cairo 1 + jpeg:cairo 1 + jpg:cairo 1 + jpe:cairo 1 + png:cairo -1 + } + device { + gif:cairo 10 + wbmp:cairo 5 + jpe:cairo 5 + jpeg:cairo 5 + jpg:cairo 5 + png:cairo 5 + gd:cairo 5 + gd2:cairo 5 + } + device { + gif:gd 1 + wbmp:gd 1 + jpe:gd 1 + jpeg:gd 1 + jpg:gd 1 + png:gd 1 + gd:gd 1 + gd2:gd 1 + } + device { + vrml:vrml 1 + } +} +libgvplugin_gdk.so.6 gdk { + device { + bmp:cairo 6 + ico:cairo 6 + jpe:cairo 6 + jpeg:cairo 6 + jpg:cairo 6 + png:cairo 6 + tif:cairo 6 + tiff:cairo 6 + } + loadimage { + bmp:cairo 1 + jpe:cairo 2 + jpg:cairo 2 + jpeg:cairo 2 + png:cairo -1 + ico:cairo 1 + } +} +libgvplugin_gs.so.6 gs { + loadimage { + ps:cairo 1 + eps:cairo 1 + } +} +libgvplugin_kitty.so.6 kitty { + device { + kitty:cairo 0 + kittyz:cairo 1 + } +} +libgvplugin_lasi.so.6 lasi { + device { + ps:lasi -5 + ps2:lasi -5 + eps:lasi -5 + } + render { + lasi -5 + } + loadimage { + eps:lasi -5 + ps:lasi -5 + } +} +libgvplugin_neato_layout.so.6 neato_layout { + layout { + neato 0 + fdp 0 + sfdp 0 + twopi 0 + circo 0 + patchwork 0 + osage 0 + nop 0 + nop1 0 + nop2 0 + } +} +libgvplugin_pango.so.6 cairo { + render { + cairo 10 + } + textlayout { + textlayout 10 + } + loadimage { + png:cairo 1 + png:lasi 2 + png:ps 2 + } + device { + png:cairo 10 + ps:cairo -10 + eps:cairo -10 + pdf:cairo 10 + svg:cairo -10 + } +} +libgvplugin_poppler.so.6 poppler { + loadimage { + pdf:cairo 1 + } +} +libgvplugin_rsvg.so.6 rsvg { + loadimage { + svg:cairo 1 + } +} +libgvplugin_vt.so.6 vt { + device { + vt:cairo 0 + vt-24bit:cairo 0 + } +} +libgvplugin_webp.so.6 webp { + device { + webp:cairo 1 + } + loadimage { + webp:cairo 1 + } +} +libgvplugin_xlib.so.6 xlib { + device { + xlib:cairo 0 + x11:cairo 0 + } +} diff --git a/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_core.so.6 b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_core.so.6 new file mode 100755 index 00000000..924f9dfd Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_core.so.6 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_devil.so.6 b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_devil.so.6 new file mode 100755 index 00000000..db63b4cf Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_devil.so.6 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_dot_layout.so.6 b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_dot_layout.so.6 new file mode 100755 index 00000000..fdaa6eae Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_dot_layout.so.6 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_gd.so.6 b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_gd.so.6 new file mode 100755 index 00000000..46db0f61 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_gd.so.6 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_gdk.so.6 b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_gdk.so.6 new file mode 100755 index 00000000..e71af780 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_gdk.so.6 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_gs.so.6 b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_gs.so.6 new file mode 100755 index 00000000..3ab421ca Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_gs.so.6 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_kitty.so.6 b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_kitty.so.6 new file mode 100755 index 00000000..b370f6de Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_kitty.so.6 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_lasi.so.6 b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_lasi.so.6 new file mode 100755 index 00000000..a52dae44 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_lasi.so.6 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_neato_layout.so.6 b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_neato_layout.so.6 new file mode 100755 index 00000000..1656a2e0 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_neato_layout.so.6 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_pango.so.6 b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_pango.so.6 new file mode 100755 index 00000000..d7c53a80 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_pango.so.6 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_poppler.so.6 b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_poppler.so.6 new file mode 100755 index 00000000..bd1bcb78 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_poppler.so.6 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_rsvg.so.6 b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_rsvg.so.6 new file mode 100755 index 00000000..3ea47a8a Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_rsvg.so.6 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_vt.so.6 b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_vt.so.6 new file mode 100755 index 00000000..fc9e4a81 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_vt.so.6 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_webp.so.6 b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_webp.so.6 new file mode 100755 index 00000000..8a877cfd Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_webp.so.6 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_xlib.so.6 b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_xlib.so.6 new file mode 100755 index 00000000..83f23f50 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/graphviz/libgvplugin_xlib.so.6 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/gv2gml b/GraphvizWrapper/graphvizfiles/linux/gv2gml new file mode 100755 index 00000000..cfe9a513 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/gv2gml differ diff --git a/GraphvizWrapper/graphvizfiles/linux/gvcolor b/GraphvizWrapper/graphvizfiles/linux/gvcolor new file mode 100755 index 00000000..55170921 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/gvcolor differ diff --git a/GraphvizWrapper/graphvizfiles/linux/gvedit b/GraphvizWrapper/graphvizfiles/linux/gvedit new file mode 100755 index 00000000..18194f26 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/gvedit differ diff --git a/GraphvizWrapper/graphvizfiles/linux/gvgen b/GraphvizWrapper/graphvizfiles/linux/gvgen new file mode 100755 index 00000000..c525a47c Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/gvgen differ diff --git a/GraphvizWrapper/graphvizfiles/linux/gvmap b/GraphvizWrapper/graphvizfiles/linux/gvmap new file mode 100755 index 00000000..f851baa1 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/gvmap differ diff --git a/GraphvizWrapper/graphvizfiles/linux/gvmap.sh b/GraphvizWrapper/graphvizfiles/linux/gvmap.sh new file mode 100755 index 00000000..97a9a920 --- /dev/null +++ b/GraphvizWrapper/graphvizfiles/linux/gvmap.sh @@ -0,0 +1,106 @@ +#!/usr/bin/sh + +# Script for gvmap pipeline +# Use -A to add flags for gvmap; e.g., -Ae results in gvmap -e +# -K can be used to change the original layout; by default, sfdp is used +# -T is used to specify the final output format +# -G, -N and -E flags can be used to tailor the rendering +# -g, -n and -e flags can be used to tailor the initial layout +# Be careful of spaces in the flags. If these are not wrapped in quotes, the +# parts will be separated during option processing. + +LAYOUT=sfdp +OPTSTR="vVA:G:E:N:g:e:n:K:T:o:" +USAGE="Usage: gvmap [-vV] [-A gvmap flags] [-G attr=val] [-E attr=val] [-N attr=val] [-g attr=val] [-e attr=val] [-n attr=val] [-K layout] [-T output format] [-o outfile]" +FLAGS1= +FLAGS2= +FLAGS3= + +while getopts ":$OPTSTR" c +do + case $c in + v ) + VERBOSE=1 + FLAGS1="$FLAGS1 -v" + FLAGS2="$FLAGS2 -v" + FLAGS3="$FLAGS3 -v" + ;; + V ) + dot -V + exit 0 + ;; + K ) + LAYOUT=$OPTARG + ;; + A ) + FLAGS2="$FLAGS2 -$OPTARG" + ;; + T ) + FLAGS3="$FLAGS3 -T$OPTARG" + ;; + e ) + FLAGS1="$FLAGS1 -E$OPTARG" + ;; + n ) + FLAGS1="$FLAGS1 -N$OPTARG" + ;; + g ) + FLAGS1="$FLAGS1 -G$OPTARG" + ;; + E ) + FLAGS3="$FLAGS3 -E$OPTARG" + ;; + N ) + FLAGS3="$FLAGS3 -N$OPTARG" + ;; + G ) + FLAGS3="$FLAGS3 -G$OPTARG" + ;; + o ) + FLAGS3="$FLAGS3 -o$OPTARG" + ;; + :) + printf '%s requires a value\n' "$OPTARG" >&2 + exit 2 + ;; + \? ) + if [ "$OPTARG" = "?" ] + then + printf '%s\n' "$USAGE" + exit 0 + else + printf 'gvmap: unknown flag %s\n' "$OPTARG" >&2 + printf '%s\n' "$USAGE" + exit 2 + fi + ;; + esac +done +shift $((OPTIND-1)) + +if [ $# -eq 0 ] +then + if [ -n "$VERBOSE" ] + then + printf '%s -Goverlap=prism %s | gvmap %s | neato -n2 %s\n' "$LAYOUT" "$FLAGS1" "$FLAGS2" "$FLAGS3" >&2 + fi + $LAYOUT -Goverlap=prism $FLAGS1 | gvmap $FLAGS2 | neato -n2 $FLAGS3 +else + while [ $# -gt 0 ] + do + if [ -f "$1" ] + then + if [ -n "$VERBOSE" ] + then + printf '%s -Goverlap=prism %s %s | gvmap %s | neato -n2 %s\n' "$LAYOUT" "$FLAGS1" "$1" "$FLAGS2" "$FLAGS3" >&2 + fi + $LAYOUT -Goverlap=prism $FLAGS1 $1 | gvmap $FLAGS2 | neato -n2 $FLAGS3 + else + printf 'gvmap: unknown input file %s - ignored\n' "$1" >&2 + fi + shift + done +fi + + + diff --git a/GraphvizWrapper/graphvizfiles/linux/gvpack b/GraphvizWrapper/graphvizfiles/linux/gvpack new file mode 100755 index 00000000..f844ac64 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/gvpack differ diff --git a/GraphvizWrapper/graphvizfiles/linux/gvpr b/GraphvizWrapper/graphvizfiles/linux/gvpr new file mode 100755 index 00000000..2ad229d1 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/gvpr differ diff --git a/GraphvizWrapper/graphvizfiles/linux/gxl2gv b/GraphvizWrapper/graphvizfiles/linux/gxl2gv new file mode 100755 index 00000000..d3c59871 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/gxl2gv differ diff --git a/GraphvizWrapper/graphvizfiles/linux/libcdt.so.5 b/GraphvizWrapper/graphvizfiles/linux/libcdt.so.5 new file mode 100755 index 00000000..37afaaea Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/libcdt.so.5 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/libcgraph.so.6 b/GraphvizWrapper/graphvizfiles/linux/libcgraph.so.6 new file mode 100755 index 00000000..596dc6e3 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/libcgraph.so.6 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/libgvc.so.6 b/GraphvizWrapper/graphvizfiles/linux/libgvc.so.6 new file mode 100755 index 00000000..8b180b58 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/libgvc.so.6 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/libpathplan.so.4 b/GraphvizWrapper/graphvizfiles/linux/libpathplan.so.4 new file mode 100755 index 00000000..5591801c Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/libpathplan.so.4 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/libxdot.so.4 b/GraphvizWrapper/graphvizfiles/linux/libxdot.so.4 new file mode 100755 index 00000000..e8d96d3b Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/libxdot.so.4 differ diff --git a/GraphvizWrapper/graphvizfiles/linux/mingle b/GraphvizWrapper/graphvizfiles/linux/mingle new file mode 100755 index 00000000..3010b365 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/mingle differ diff --git a/GraphvizWrapper/graphvizfiles/linux/mm2gv b/GraphvizWrapper/graphvizfiles/linux/mm2gv new file mode 100755 index 00000000..84bdfa72 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/mm2gv differ diff --git a/GraphvizWrapper/graphvizfiles/linux/nop b/GraphvizWrapper/graphvizfiles/linux/nop new file mode 100755 index 00000000..b351c125 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/nop differ diff --git a/GraphvizWrapper/graphvizfiles/linux/pkgconfig/libcdt.pc b/GraphvizWrapper/graphvizfiles/linux/pkgconfig/libcdt.pc new file mode 100644 index 00000000..9fefefa6 --- /dev/null +++ b/GraphvizWrapper/graphvizfiles/linux/pkgconfig/libcdt.pc @@ -0,0 +1,10 @@ +prefix=/usr/local +exec_prefix=/usr/local +libdir=/usr/local/lib64 +includedir=/usr/local/include + +Name: libcdt +Description: Container DataType library +Version: 11.0.0 +Libs: -L${libdir} -lcdt +Cflags: -I${includedir} -I${includedir}/graphviz diff --git a/GraphvizWrapper/graphvizfiles/linux/pkgconfig/libcgraph.pc b/GraphvizWrapper/graphvizfiles/linux/pkgconfig/libcgraph.pc new file mode 100644 index 00000000..3fd48cac --- /dev/null +++ b/GraphvizWrapper/graphvizfiles/linux/pkgconfig/libcgraph.pc @@ -0,0 +1,10 @@ +prefix=/usr/local +exec_prefix=/usr/local +libdir=/usr/local/lib64 +includedir=/usr/local/include + +Name: libcgraph +Description: Graph library (file i/o, dot language parsing, graph, subgraph, node, edge, attribute, data structure manipulation) +Version: 11.0.0 +Libs: -L${libdir} -lcgraph -lcdt +Cflags: -I${includedir} -I${includedir}/graphviz diff --git a/GraphvizWrapper/graphvizfiles/linux/pkgconfig/libgvc.pc b/GraphvizWrapper/graphvizfiles/linux/pkgconfig/libgvc.pc new file mode 100644 index 00000000..3aa1f987 --- /dev/null +++ b/GraphvizWrapper/graphvizfiles/linux/pkgconfig/libgvc.pc @@ -0,0 +1,12 @@ +prefix=/usr/local +exec_prefix=/usr/local +libdir=/usr/local/lib64 +includedir=/usr/local/include +plugins=7 + +Name: libgvc +Description: The GraphVizContext library +Version: 11.0.0 +Libs: -L${libdir} -lgvc -lcgraph -lcdt +Cflags: -I${includedir} -I${includedir}/graphviz + diff --git a/GraphvizWrapper/graphvizfiles/linux/pkgconfig/libgvpr.pc b/GraphvizWrapper/graphvizfiles/linux/pkgconfig/libgvpr.pc new file mode 100644 index 00000000..6f6143b2 --- /dev/null +++ b/GraphvizWrapper/graphvizfiles/linux/pkgconfig/libgvpr.pc @@ -0,0 +1,11 @@ +prefix=/usr/local +exec_prefix=/usr/local +libdir=/usr/local/lib64 +includedir=/usr/local/include + +Name: libgvpr +Description: The GVPR library +Version: 11.0.0 +Libs: -L${libdir} -lgvpr -lcgraph -lcdt +Cflags: -I${includedir} -I${includedir}/graphviz + diff --git a/GraphvizWrapper/graphvizfiles/linux/pkgconfig/libpathplan.pc b/GraphvizWrapper/graphvizfiles/linux/pkgconfig/libpathplan.pc new file mode 100644 index 00000000..175ad4cd --- /dev/null +++ b/GraphvizWrapper/graphvizfiles/linux/pkgconfig/libpathplan.pc @@ -0,0 +1,10 @@ +prefix=/usr/local +exec_prefix=/usr/local +libdir=/usr/local/lib64 +includedir=/usr/local/include + +Name: libpathplan +Description: Library for planning polyline and bezier paths around polygon obstacles +Version: 11.0.0 +Libs: -L${libdir} -lpathplan +Cflags: -I${includedir} -I${includedir}/graphviz diff --git a/GraphvizWrapper/graphvizfiles/linux/pkgconfig/libxdot.pc b/GraphvizWrapper/graphvizfiles/linux/pkgconfig/libxdot.pc new file mode 100644 index 00000000..48954442 --- /dev/null +++ b/GraphvizWrapper/graphvizfiles/linux/pkgconfig/libxdot.pc @@ -0,0 +1,10 @@ +prefix=/usr/local +exec_prefix=/usr/local +libdir=/usr/local/lib64 +includedir=/usr/local/include + +Name: libxdot +Description: Library for parsing graphs in xdot format +Version: 11.0.0 +Libs: -L${libdir} -lxdot +Cflags: -I${includedir} -I${includedir}/graphviz diff --git a/GraphvizWrapper/graphvizfiles/linux/prune b/GraphvizWrapper/graphvizfiles/linux/prune new file mode 100755 index 00000000..93609716 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/prune differ diff --git a/GraphvizWrapper/graphvizfiles/linux/sccmap b/GraphvizWrapper/graphvizfiles/linux/sccmap new file mode 100755 index 00000000..4112dbf0 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/sccmap differ diff --git a/GraphvizWrapper/graphvizfiles/linux/smyrna b/GraphvizWrapper/graphvizfiles/linux/smyrna new file mode 100755 index 00000000..8203a8d7 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/smyrna differ diff --git a/GraphvizWrapper/graphvizfiles/linux/tred b/GraphvizWrapper/graphvizfiles/linux/tred new file mode 100755 index 00000000..ba7954e2 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/tred differ diff --git a/GraphvizWrapper/graphvizfiles/linux/unflatten b/GraphvizWrapper/graphvizfiles/linux/unflatten new file mode 100755 index 00000000..5a0a4f68 Binary files /dev/null and b/GraphvizWrapper/graphvizfiles/linux/unflatten differ diff --git a/GraphvizWrapper/graphvizfiles/linux/vimdot b/GraphvizWrapper/graphvizfiles/linux/vimdot new file mode 100755 index 00000000..af28d5b5 --- /dev/null +++ b/GraphvizWrapper/graphvizfiles/linux/vimdot @@ -0,0 +1,47 @@ +#!/usr/bin/sh +# Written by: John Ellson + +if [ "$1" = "-?" ]; then + echo "Usage: vimdot [file]" >&2 + exit 0 +fi + +error() { echo "$0: $*" >&2; exit 1; } + +# Try $EDITOR first, else try vim or vi +editor="$(which $EDITOR)" || editor="/usr/bin/vim" +[ -x "$editor" ] || editor="/usr/bin/vi" +[ -x "$editor" ] || error "EDITOR not found or not executable"; + +default="noname.gv" + +if test -z "$1"; then + f="$default" + if ! test -f "$f"; then + if ! test -w .; then error "directory `pwd` is not writable"; fi + cat >"$f" < vimdot +} +EOF + fi +else + f="$1" +fi + +if ! test -w "$f"; then error "$f is not writable"; fi + +# dot -Txlib watches the file $f for changes using inotify() +dot -Txlib "$f" 2>/dev/null & +# open an editor on the file $f (could be any editor; gvim &'s itself) +exec $editor "$f" diff --git a/GraphvizWrapper/graphvizfiles/normalize-names.sh b/GraphvizWrapper/graphvizfiles/normalize-names.sh new file mode 100644 index 00000000..ccf8cd3b --- /dev/null +++ b/GraphvizWrapper/graphvizfiles/normalize-names.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +if [ $# -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +TARGET_DIR=$1 + +echo "Normalizing .so filenames under '$TARGET_DIR'..." + +find "$TARGET_DIR" -type l -exec rm -v {} + + +# Step 2: Rename each real .so.* file to match its SONAME, in place +find "$TARGET_DIR" -type f -name "lib*.so.*" | while read -r file; do + soname=$(readelf -d "$file" 2>/dev/null | awk -F'[][]' '/SONAME/ { print $2 }') + if [[ -z "$soname" ]]; then + echo "No SONAME found in $file — skipping" + continue + fi + + dirname=$(dirname "$file") + target="$dirname/$soname" + + if [[ "$(basename "$file")" != "$soname" ]]; then + echo "Renaming $file -> $target" + mv "$file" "$target" + else + echo "Skipping $file (already matches SONAME)" + fi +done diff --git a/GraphvizWrapper/graphvizfiles/patch-rpath.sh b/GraphvizWrapper/graphvizfiles/patch-rpath.sh new file mode 100644 index 00000000..3b7aee7a --- /dev/null +++ b/GraphvizWrapper/graphvizfiles/patch-rpath.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# Modify the RPATH of all binaries to make sure all locally deployed dependencies can be found. + +# Ensure a directory is provided +if [ $# -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Check if patchelf is installed +if ! command -v patchelf &>/dev/null; then + echo "Error: patchelf is not installed. Install it using your package manager." + exit 1 +fi + +TARGET_DIR=$1 + +echo "Adding RPATH '\$ORIGIN' to all binaries in $TARGET_DIR..." + +find "$TARGET_DIR" -maxdepth 1 -type f -perm -111 | while read -r exe_file; do + echo "Processing: $exe_file" + patchelf --set-rpath '$ORIGIN' "$exe_file" && echo "RPATH '\$ORIGIN' added to $exe_file" || echo "Failed to patch $exe_file" +done + +echo "Adding RPATH '\$ORIGIN' and '\$ORIGIN/../' to all files in $TARGET_DIR/graphviz..." + +find "$TARGET_DIR/graphviz" -type f \( -perm -111 \) | while read -r graphviz_file; do + echo "Processing: $graphviz_file" + + # Set RPATH to include both $ORIGIN and $ORIGIN/../ + patchelf --set-rpath '$ORIGIN:$ORIGIN/../' "$graphviz_file" && \ + echo "RPATH '\$ORIGIN:\$ORIGIN/../' added to $graphviz_file" || \ + echo "Failed to patch $graphviz_file" +done + + +echo "RPATH update complete." + diff --git a/GraphvizWrapper/graphvizfiles/unpack-rpm.sh b/GraphvizWrapper/graphvizfiles/unpack-rpm.sh new file mode 100644 index 00000000..4b08c3f5 --- /dev/null +++ b/GraphvizWrapper/graphvizfiles/unpack-rpm.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# Ensure an .rpm file is provided +if [ $# -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +RPM_FILE=$1 +TARGET_DIR="linux" +EXTRACT_DIR="rpm_extracted" + +# Ensure rpm2cpio and cpio tools are installed +if ! command -v rpm2cpio &>/dev/null || ! command -v cpio &>/dev/null; then + echo "Error: rpm2cpio and cpio are required but not installed." + echo "Install them using: sudo apt-get install rpm2cpio cpio (on Debian or Ubuntu)" + exit 1 +fi + +# Create clean target and extraction directories +rm -r "$TARGET_DIR" "$EXTRACT_DIR" +mkdir -p "$TARGET_DIR" "$EXTRACT_DIR" + +# Extract the .rpm file into EXTRACT_DIR +echo "Extracting $RPM_FILE..." +rpm2cpio "$RPM_FILE" | cpio -idmv -D "$EXTRACT_DIR" || { echo "Failed to extract $RPM_FILE"; exit 1; } + +# Copy the desired folders to the target directory +echo "Copying usr/bin, usr/lib, and usr/lib/graphviz to $TARGET_DIR..." + +cp -a "./$EXTRACT_DIR/usr/bin/" "$TARGET_DIR" +cp -a "./$EXTRACT_DIR/usr/lib64/" "$TARGET_DIR" +mkdir -p "$TARGET_DIR/graphviz/" +cp -a "./$EXTRACT_DIR/usr/lib64/graphviz/"* "$TARGET_DIR/graphviz/" + +# Clean up extraction directory +rm -r "$EXTRACT_DIR" + +echo "The specified directories have been copied to: $TARGET_DIR" +echo "Result:" +ls -R "$TARGET_DIR" + + +echo +echo "Copying usr/include/graphviz to $TARGET_DIR/../../include/" +cp "./$EXTRACT_DIR/usr/include/graphviz/"* "$TARGET_DIR/../../include/" && unix2dos "$TARGET_DIR/../../include/"* + diff --git a/How-to-release.txt b/How-to-release.txt index 809d1231..41f1ebeb 100644 --- a/How-to-release.txt +++ b/How-to-release.txt @@ -1,13 +1,12 @@ - Bump the version number in Rubjerg.Graphviz.csproj to the version to be released. -- Do a Release build. You can use the `build-release.sh` script for this. -- Upload the generated .nupkg file to nuget.org. - - Located at Rubjerg.Graphviz\bin\x64\Release\Rubjerg.Graphviz.x.y.z.nupkg +- Make a PR and grab the nuget package from the CI artifacts. +- Upload the .nupkg file to nuget.org. - Upload to https://www.nuget.org/packages/manage/upload - Make a cup of coffee -- Update the version of the referenced Nuget package in the NugetTest project to the package that was just uploaded and run the test. - - dotnet add Rubjerg.Graphviz.NugetTest\Rubjerg.Graphviz.NugetTest.csproj package Rubjerg.Graphviz -- If the build and test succeeds we are ready to release. Commit the changes, add the tag, and push this to github. - - git commit -am 'Release vx.y.z' +- Update the version of the referenced Nuget package in the NugetOrgTest project to the package that was just uploaded and run the test. + - dotnet add Rubjerg.Graphviz.NugetOrgTest\Rubjerg.Graphviz.NugetOrgTest.csproj package Rubjerg.Graphviz +- If the build and test succeeds we are ready to release. Merge the PR, add the tag, and push this to github. + - Merge PR on github - git tag vx.y.z - git push github --tags - In GitHub, add a new release of the just pushed commit at https://github.com/Rubjerg/Graphviz.NetWrapper/releases. diff --git a/How-to-upgrade-graphviz.txt b/How-to-upgrade-graphviz.txt index a161ce29..2dfa41e1 100644 --- a/How-to-upgrade-graphviz.txt +++ b/How-to-upgrade-graphviz.txt @@ -1,5 +1,6 @@ - Navigate to https://gitlab.com/groups/graphviz/-/packages/ and click the version you want to upgrade to +First on Windows - Download and extract `windows_10_cmake_Debug_Graphviz--win64.zip`. - Navigate to `bin/` and copy all the files in that folder to `Graphviz.NetWrapper\GraphvizWrapper\graphvizfiles\Debug\`. Check that every existing file was overwritten. @@ -13,8 +14,19 @@ Check that every existing file was overwritten. - Make sure that the toolset selected for GraphvizWrapper.dll is compatible with the vcruntime version shipped with graphviz. -- Remove all DLLs starting with `concrt`, `msvcp` or `vcruntime`. These are part of the Visual C++ redistributable package, and we're not shipping those. -- Remove all files ending in `.sh`, these are not crossplatform and we don't need them. +- Remove all new DLLs starting with `concrt`, `msvcp` or `vcruntime`. These are part of the Visual C++ redistributable package, and we're not shipping those. +- Remove all new files ending in `.sh`, these are not windows compatible and we don't need them. - Check if any other files are new, and investigate if that is expected. - Compile and run the tests + +Now on linux (e.g. WSL) +- cd to GraphvizWrapper/graphvizfiles/ +- Download the Fedora package (e.g. fedora_41_graphviz--cmake.rpm) into the current working directory +- Run `bash unpack-rpm.sh fedora_41_graphviz--cmake.rpm` to deploy the files to the linux subfolder +- Run `bash patch-rpath.sh linux/` to patch the RPATH of all binaries so they can find the locally deployed version of graphviz. +- Make sure none of the include files have changed (as a sanity check that this is the same version as on windows) + +- Compile and run the tests +- Update version number in README-src.md and run `bash generatereadme.sh` + diff --git a/Rubjerg.Graphviz.NugetTest/.gitignore b/NugetOrgTests/Rubjerg.Graphviz.NugetOrgTest/.gitignore similarity index 100% rename from Rubjerg.Graphviz.NugetTest/.gitignore rename to NugetOrgTests/Rubjerg.Graphviz.NugetOrgTest/.gitignore diff --git a/Rubjerg.Graphviz.NugetTest/Rubjerg.Graphviz.NugetTest.csproj b/NugetOrgTests/Rubjerg.Graphviz.NugetOrgTest/Rubjerg.Graphviz.NugetOrgTest.csproj similarity index 91% rename from Rubjerg.Graphviz.NugetTest/Rubjerg.Graphviz.NugetTest.csproj rename to NugetOrgTests/Rubjerg.Graphviz.NugetOrgTest/Rubjerg.Graphviz.NugetOrgTest.csproj index b5ea741d..df767f28 100644 --- a/Rubjerg.Graphviz.NugetTest/Rubjerg.Graphviz.NugetTest.csproj +++ b/NugetOrgTests/Rubjerg.Graphviz.NugetOrgTest/Rubjerg.Graphviz.NugetOrgTest.csproj @@ -2,13 +2,14 @@ Library - net48;net8.0 + net8.0 x64 x64 Chiel ten Brinke Rubjerg ..\packages true + embedded diff --git a/Rubjerg.Graphviz.NugetTest/TestNugetPackage.cs b/NugetOrgTests/Rubjerg.Graphviz.NugetOrgTest/Test.cs similarity index 69% rename from Rubjerg.Graphviz.NugetTest/TestNugetPackage.cs rename to NugetOrgTests/Rubjerg.Graphviz.NugetOrgTest/Test.cs index 19c8ada7..dbda65d7 100644 --- a/Rubjerg.Graphviz.NugetTest/TestNugetPackage.cs +++ b/NugetOrgTests/Rubjerg.Graphviz.NugetOrgTest/Test.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; -namespace Rubjerg.Graphviz.NugetTest +namespace Rubjerg.Graphviz.NugetOrgTest { [TestFixture()] public class TestNugetPackage @@ -25,6 +25,10 @@ digraph test { var B = root.GetNode("B"); _ = root.GetOrAddEdge(A, B, ""); Assert.AreEqual(4, A.EdgesOut().Count()); + + root.ToSvgFile(TestContext.CurrentContext.TestDirectory + "/dot_out.svg"); + + root.ToSvgFile(TestContext.CurrentContext.TestDirectory + "/neato_out.svg", LayoutEngines.Neato); } } } diff --git a/Rubjerg.Graphviz.NugetTests.sln b/NugetOrgTests/Rubjerg.Graphviz.NugetOrgTests.sln similarity index 82% rename from Rubjerg.Graphviz.NugetTests.sln rename to NugetOrgTests/Rubjerg.Graphviz.NugetOrgTests.sln index d3f8b68a..177cd669 100644 --- a/Rubjerg.Graphviz.NugetTests.sln +++ b/NugetOrgTests/Rubjerg.Graphviz.NugetOrgTests.sln @@ -3,14 +3,14 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.29509.3 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rubjerg.Graphviz.NugetTest", "Rubjerg.Graphviz.NugetTest\Rubjerg.Graphviz.NugetTest.csproj", "{8AF7A4E8-17D2-43E8-91FA-8EF1E4D75F0E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rubjerg.Graphviz.NugetOrgTest", "Rubjerg.Graphviz.NugetOrgTest\Rubjerg.Graphviz.NugetOrgTest.csproj", "{8AF7A4E8-17D2-43E8-91FA-8EF1E4D75F0E}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AD0D286A-6205-449D-AF8A-E9CA8066F6E0}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rubjerg.Graphviz.TransitiveNugetTest", "Rubjerg.Graphviz.TransitiveNugetTest\Rubjerg.Graphviz.TransitiveNugetTest.csproj", "{700F7942-B740-4F9A-949E-238FA3944D59}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rubjerg.Graphviz.NugetOrgTransitiveTest", "Rubjerg.Graphviz.NugetOrgTransitiveTest\Rubjerg.Graphviz.NugetOrgTransitiveTest.csproj", "{700F7942-B740-4F9A-949E-238FA3944D59}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Rubjerg.Graphviz.TransitiveNugetTest/.gitignore b/NugetOrgTests/Rubjerg.Graphviz.NugetOrgTransitiveTest/.gitignore similarity index 100% rename from Rubjerg.Graphviz.TransitiveNugetTest/.gitignore rename to NugetOrgTests/Rubjerg.Graphviz.NugetOrgTransitiveTest/.gitignore diff --git a/Rubjerg.Graphviz.TransitiveNugetTest/Rubjerg.Graphviz.TransitiveNugetTest.csproj b/NugetOrgTests/Rubjerg.Graphviz.NugetOrgTransitiveTest/Rubjerg.Graphviz.NugetOrgTransitiveTest.csproj similarity index 83% rename from Rubjerg.Graphviz.TransitiveNugetTest/Rubjerg.Graphviz.TransitiveNugetTest.csproj rename to NugetOrgTests/Rubjerg.Graphviz.NugetOrgTransitiveTest/Rubjerg.Graphviz.NugetOrgTransitiveTest.csproj index 242afbea..eccd2c9a 100644 --- a/Rubjerg.Graphviz.TransitiveNugetTest/Rubjerg.Graphviz.TransitiveNugetTest.csproj +++ b/NugetOrgTests/Rubjerg.Graphviz.NugetOrgTransitiveTest/Rubjerg.Graphviz.NugetOrgTransitiveTest.csproj @@ -2,17 +2,18 @@ Library - net48;net8.0 + net8.0 x64 x64 Chiel ten Brinke Rubjerg ..\packages true + embedded - + diff --git a/NugetOrgTests/Rubjerg.Graphviz.NugetOrgTransitiveTest/Test.cs b/NugetOrgTests/Rubjerg.Graphviz.NugetOrgTransitiveTest/Test.cs new file mode 100644 index 00000000..eb1aec2e --- /dev/null +++ b/NugetOrgTests/Rubjerg.Graphviz.NugetOrgTransitiveTest/Test.cs @@ -0,0 +1,17 @@ +using NUnit.Framework; +using Rubjerg.Graphviz.Test; + +namespace Rubjerg.Graphviz.NugetOrgTest +{ + [TestFixture()] + public class TestNugetPackageTransitive + { + [Test()] + public void Test() + { + var test = new TestNugetPackage(); + test.TestReadDotFile(); + } + } +} + diff --git a/NugetOrgTests/nuget.config b/NugetOrgTests/nuget.config new file mode 100644 index 00000000..cd9ea174 --- /dev/null +++ b/NugetOrgTests/nuget.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/README-src.md b/README-src.md index c543bd8f..e207b9a6 100644 --- a/README-src.md +++ b/README-src.md @@ -1,46 +1,39 @@ Graphviz.NetWrapper =================== -[![codecov](https://codecov.io/gh/Rubjerg/Graphviz.NetWrapper/branch/master/graph/badge.svg)](https://codecov.io/gh/Rubjerg/Graphviz.NetWrapper) - ## Supported platforms -At the moment, `Rubjerg.Graphviz` ships with a bunch of precompiled Graphviz dlls built for 64 bit Windows. -This library is compatible with .NET Standard 2.0. -The unit tests run against .NET Framework 4.8 and .NET 8.0. -In the future support may be extended to other platforms. +`Rubjerg.Graphviz` ships with precompiled Graphviz binaries to ensure the exact graphviz version is used that we have tested and to make deployment more predictable. +The current version we ship is Graphviz 11.0.0. -## Contributing +### Windows +`Rubjerg.Graphviz` ships with a bunch of precompiled Graphviz dlls built for 64 bit Windows. +This library is compatible with .NET Standard 2.0, but the nuget package only supports .NET5.0 and higher. +The unit tests run on windows and linux against .NET Framework .NET 8.0. -This project aims to provide a thin .NET shell around the Graphviz C libraries, -together with some convenience functionality that helps abstracting away some -of the peculiarities of the Graphviz library and make it easier to integrate in -an application. -Pull request that fall within the scope of this project are welcome. +### Linux +In the same vein as our windows build, we ship precompiled binaries to make sure that this library is deployed with the same binaries as we've tested it. +However, we do not ship graphviz dependencies, you will have to installed those yourself, if you need them. +[Here is a list of all the graphviz dependencies.](https://packages.fedoraproject.org/pkgs/graphviz/graphviz/fedora-rawhide.html#dependencies) +In practice you may not need all of those. +In particular, if you only want to read graphs and e.g. run the DOT algorithm, libc and libz are enough. +To run our tests successfully you will also need libgts and libpcre2 (for the neato algorithm). +For more details, check the dependencies of any graphviz binaries with `ldd`. ## Installation -You can either add this library as a nuget package to project, or include the source and add a -project reference. +Add the [Rubjerg.Graphviz nuget package](https://www.nuget.org/packages/Rubjerg.Graphviz/) to your project. -To run the code from this library, you must have the Microsoft Visual C++ Redistributable (2015-2022) installed, which provides the required runtime libraries. +To run the code from this library on windows, you must have the Microsoft Visual C++ Redistributable (2015-2022) installed, which provides the required runtime libraries. You can download it from the [official Microsoft website](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist). -### Adding as a Nuget package - -Add the [Rubjerg.Graphviz nuget package](https://www.nuget.org/packages/Rubjerg.Graphviz/) to -your project. - -### Adding the Rubjerg.Graphviz code to your project or solution -1. Make this code available to your own code, e.g. by adding this repository as a git submodule to your own repository. -2. Add the projects Rubjerg.Graphviz and GraphvizWrapper to your solution. -3. To use Rubjerg.Graphviz within a project of yours, simply add a project reference to it. +## Contributing -When building your project, you should now see all the Graphviz binaries show up in your output -folder. If you don't, try setting the `CopyLocalLockFileAssemblies` property in your referencing -project file to `true`. If that still fails, try reordering the projects in your solution, such -that GraphvizWrapper and Rubjerg.Graphviz are at the top. -There is an [outstanding issue for this](https://github.com/Rubjerg/Graphviz.NetWrapper/issues/36). +This project aims to provide a thin .NET shell around the Graphviz C libraries, +together with some convenience functionality that helps abstracting away some +of the peculiarities of the Graphviz library and make it easier to integrate in +an application. +Pull request that fall within the scope of this project are welcome. ## Documentation diff --git a/README.md b/README.md index 1c094d1c..8e2e37b7 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,39 @@ Graphviz.NetWrapper =================== -[![codecov](https://codecov.io/gh/Rubjerg/Graphviz.NetWrapper/branch/master/graph/badge.svg)](https://codecov.io/gh/Rubjerg/Graphviz.NetWrapper) - ## Supported platforms -At the moment, `Rubjerg.Graphviz` ships with a bunch of precompiled Graphviz dlls built for 64 bit Windows. -This library is compatible with .NET Standard 2.0. -The unit tests run against .NET Framework 4.8 and .NET 8.0. -In the future support may be extended to other platforms. +`Rubjerg.Graphviz` ships with precompiled Graphviz binaries to ensure the exact graphviz version is used that we have tested and to make deployment more predictable. +The current version we ship is Graphviz 11.0.0. -## Contributing +### Windows +`Rubjerg.Graphviz` ships with a bunch of precompiled Graphviz dlls built for 64 bit Windows. +This library is compatible with .NET Standard 2.0, but the nuget package only supports .NET5.0 and higher. +The unit tests run on windows and linux against .NET Framework .NET 8.0. -This project aims to provide a thin .NET shell around the Graphviz C libraries, -together with some convenience functionality that helps abstracting away some -of the peculiarities of the Graphviz library and make it easier to integrate in -an application. -Pull request that fall within the scope of this project are welcome. +### Linux +In the same vein as our windows build, we ship precompiled binaries to make sure that this library is deployed with the same binaries as we've tested it. +However, we do not ship graphviz dependencies, you will have to installed those yourself, if you need them. +[Here is a list of all the graphviz dependencies.](https://packages.fedoraproject.org/pkgs/graphviz/graphviz/fedora-rawhide.html#dependencies) +In practice you may not need all of those. +In particular, if you only want to read graphs and e.g. run the DOT algorithm, libc and libz are enough. +To run our tests successfully you will also need libgts and libpcre2 (for the neato algorithm). +For more details, check the dependencies of any graphviz binaries with `ldd`. ## Installation -You can either add this library as a nuget package to project, or include the source and add a -project reference. +Add the [Rubjerg.Graphviz nuget package](https://www.nuget.org/packages/Rubjerg.Graphviz/) to your project. -To run the code from this library, you must have the Microsoft Visual C++ Redistributable (2015-2022) installed, which provides the required runtime libraries. +To run the code from this library on windows, you must have the Microsoft Visual C++ Redistributable (2015-2022) installed, which provides the required runtime libraries. You can download it from the [official Microsoft website](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist). -### Adding as a Nuget package - -Add the [Rubjerg.Graphviz nuget package](https://www.nuget.org/packages/Rubjerg.Graphviz/) to -your project. - -### Adding the Rubjerg.Graphviz code to your project or solution -1. Make this code available to your own code, e.g. by adding this repository as a git submodule to your own repository. -2. Add the projects Rubjerg.Graphviz and GraphvizWrapper to your solution. -3. To use Rubjerg.Graphviz within a project of yours, simply add a project reference to it. +## Contributing -When building your project, you should now see all the Graphviz binaries show up in your output -folder. If you don't, try setting the `CopyLocalLockFileAssemblies` property in your referencing -project file to `true`. If that still fails, try reordering the projects in your solution, such -that GraphvizWrapper and Rubjerg.Graphviz are at the top. -There is an [outstanding issue for this](https://github.com/Rubjerg/Graphviz.NetWrapper/issues/36). +This project aims to provide a thin .NET shell around the Graphviz C libraries, +together with some convenience functionality that helps abstracting away some +of the peculiarities of the Graphviz library and make it easier to integrate in +an application. +Pull request that fall within the scope of this project are welcome. ## Documentation diff --git a/Rubjerg.Graphviz.Test/Reproductions.cs b/Rubjerg.Graphviz.Test/Reproductions.cs index c97faac6..de87676a 100644 --- a/Rubjerg.Graphviz.Test/Reproductions.cs +++ b/Rubjerg.Graphviz.Test/Reproductions.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.IO; using System.Linq; +using static Rubjerg.Graphviz.ForeignFunctionInterface; namespace Rubjerg.Graphviz.Test; @@ -21,6 +22,30 @@ public void SetUp() _testDir = TestContext.CurrentContext.TestDirectory; } + [Test()] + public void TestCloseCrash() + { + RootGraph root = Utils.CreateUniqueTestGraph(); + + string dot = "digraph test { A [label=1]; }"; + root = RootGraph.FromDotString(dot); + root.ComputeLayout(); + root.Close(); + Utils.CreateUniqueTestGraph().Close(); + } + + [Test()] + public void TestAgcloseCrash() + { + string dot = "digraph test { A [label=1]; }"; + var root = Rjagmemread(dot); + _ = GvLayout(GVC, root, "dot"); + _ = GvRender(GVC, root, "xdot", IntPtr.Zero); + _ = Agclose(root); + root = Rjagopen("test 2", 0); + _ = Agclose(root); + } + [Test()] public void ExportPathWithSpaces() { diff --git a/Rubjerg.Graphviz.Test/Rubjerg.Graphviz.Test.csproj b/Rubjerg.Graphviz.Test/Rubjerg.Graphviz.Test.csproj index 5686dfdd..ae9652cb 100644 --- a/Rubjerg.Graphviz.Test/Rubjerg.Graphviz.Test.csproj +++ b/Rubjerg.Graphviz.Test/Rubjerg.Graphviz.Test.csproj @@ -2,7 +2,7 @@ Library - net48;net8.0 + net8.0 x64 x64 Chiel ten Brinke @@ -10,6 +10,7 @@ ..\packages true latest + embedded @@ -17,10 +18,9 @@ - - - - + + 2.0.*-* + 3.18.3 @@ -50,7 +50,7 @@ generatereadme.bat - + diff --git a/Rubjerg.Graphviz.Test/TestInterop.cs b/Rubjerg.Graphviz.Test/TestInterop.cs index 2c9173ab..a4960be4 100644 --- a/Rubjerg.Graphviz.Test/TestInterop.cs +++ b/Rubjerg.Graphviz.Test/TestInterop.cs @@ -1,5 +1,6 @@ using NUnit.Framework; using System.IO; +using System; using static Rubjerg.Graphviz.ForeignFunctionInterface; namespace Rubjerg.Graphviz.Test; @@ -7,6 +8,14 @@ namespace Rubjerg.Graphviz.Test; [TestFixture()] public class TestInterop { + [Test()] + public void TestAgclose() + { + IntPtr root = Rjagopen("test", 0); + _ = Agnode(root, "node1", 1); + Agclose(root); + } + [Test()] public void TestMarshaling() { diff --git a/Rubjerg.Graphviz.Test/generatereadme.bat b/Rubjerg.Graphviz.Test/generatereadme.bat index 90e24c89..14f05253 100644 --- a/Rubjerg.Graphviz.Test/generatereadme.bat +++ b/Rubjerg.Graphviz.Test/generatereadme.bat @@ -2,4 +2,4 @@ ECHO Generating README.md TYPE ..\README-src.md>..\README.md ECHO ```cs>>..\README.md TYPE Tutorial.cs>>..\README.md -ECHO ```>>..\README.md \ No newline at end of file +ECHO ```>>..\README.md diff --git a/Rubjerg.Graphviz.Tests.sln b/Rubjerg.Graphviz.Tests.sln new file mode 100644 index 00000000..0fa1ffee --- /dev/null +++ b/Rubjerg.Graphviz.Tests.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32428.209 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AD0D286A-6205-449D-AF8A-E9CA8066F6E0}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rubjerg.Graphviz.Test", "Rubjerg.Graphviz.Test\Rubjerg.Graphviz.Test.csproj", "{3E7CBBC1-A6AE-42A9-950C-54433B6F0E7C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rubjerg.Graphviz.TransitiveTest", "Rubjerg.Graphviz.TransitiveTest\Rubjerg.Graphviz.TransitiveTest.csproj", "{FAB37EA6-101F-4B84-816F-7A98D571BAE7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3E7CBBC1-A6AE-42A9-950C-54433B6F0E7C}.Debug|x64.ActiveCfg = Debug|x64 + {3E7CBBC1-A6AE-42A9-950C-54433B6F0E7C}.Debug|x64.Build.0 = Debug|x64 + {3E7CBBC1-A6AE-42A9-950C-54433B6F0E7C}.Release|x64.ActiveCfg = Release|x64 + {3E7CBBC1-A6AE-42A9-950C-54433B6F0E7C}.Release|x64.Build.0 = Release|x64 + {FAB37EA6-101F-4B84-816F-7A98D571BAE7}.Debug|x64.ActiveCfg = Debug|x64 + {FAB37EA6-101F-4B84-816F-7A98D571BAE7}.Debug|x64.Build.0 = Debug|x64 + {FAB37EA6-101F-4B84-816F-7A98D571BAE7}.Release|x64.ActiveCfg = Release|x64 + {FAB37EA6-101F-4B84-816F-7A98D571BAE7}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C3E34AE1-9B7D-4D90-9007-A063FEBB8BF1} + EndGlobalSection +EndGlobal diff --git a/Rubjerg.Graphviz.TransitiveNugetTest/TestNugetPackage.cs b/Rubjerg.Graphviz.TransitiveNugetTest/TestNugetPackage.cs deleted file mode 100644 index 19c8ada7..00000000 --- a/Rubjerg.Graphviz.TransitiveNugetTest/TestNugetPackage.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Linq; -using NUnit.Framework; - -namespace Rubjerg.Graphviz.NugetTest -{ - [TestFixture()] - public class TestNugetPackage - { - [Test()] - public void TestReadDotFile() - { - RootGraph root = RootGraph.FromDotString(@" -digraph test { - A; - B; - B -> B; - A -> B[name = edgename]; - A -> B[name = edgename]; - A -> B[name = edgename]; -} -"); - var A = root.GetNode("A"); - Assert.AreEqual(3, A.EdgesOut().Count()); - - var B = root.GetNode("B"); - _ = root.GetOrAddEdge(A, B, ""); - Assert.AreEqual(4, A.EdgesOut().Count()); - } - } -} diff --git a/Rubjerg.Graphviz.TransitiveTest/Rubjerg.Graphviz.TransitiveTest.csproj b/Rubjerg.Graphviz.TransitiveTest/Rubjerg.Graphviz.TransitiveTest.csproj index 3f64da69..4b172ff3 100644 --- a/Rubjerg.Graphviz.TransitiveTest/Rubjerg.Graphviz.TransitiveTest.csproj +++ b/Rubjerg.Graphviz.TransitiveTest/Rubjerg.Graphviz.TransitiveTest.csproj @@ -2,7 +2,7 @@ Library - net48;net8.0 + net8.0 x64 x64 Chiel ten Brinke @@ -10,12 +10,9 @@ ..\packages true latest + embedded - - - - 3.18.3 @@ -34,4 +31,8 @@ + + + + diff --git a/Rubjerg.Graphviz.TransitiveTest/Test.cs b/Rubjerg.Graphviz.TransitiveTest/Test.cs new file mode 100644 index 00000000..d61e2bfd --- /dev/null +++ b/Rubjerg.Graphviz.TransitiveTest/Test.cs @@ -0,0 +1,17 @@ +using NUnit.Framework; +using Rubjerg.Graphviz.Test; + +namespace Rubjerg.Graphviz.TransitiveTest +{ + [TestFixture()] + public class TransitiveTest + { + [Test()] + public void Test() + { + var tutorial = new Tutorial(); + tutorial.GraphConstruction(); + tutorial.Layouting(); + } + } +} diff --git a/Rubjerg.Graphviz.TransitiveTest/TestReference.cs b/Rubjerg.Graphviz.TransitiveTest/TestReference.cs deleted file mode 100644 index 110a70a3..00000000 --- a/Rubjerg.Graphviz.TransitiveTest/TestReference.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Linq; -using NUnit.Framework; - -namespace Rubjerg.Graphviz.NugetTest; - -[TestFixture()] -public class TestReference -{ - [Test()] - public void TestReadDotFile() - { - RootGraph root = RootGraph.FromDotString(@" -digraph test { - A; - B; - B -> B; - A -> B[name = edgename]; - A -> B[name = edgename]; - A -> B[name = edgename]; -} -"); - var A = root.GetNode("A"); - Assert.AreEqual(3, A.EdgesOut().Count()); - - var B = root.GetNode("B"); - _ = root.GetOrAddEdge(A, B, ""); - Assert.AreEqual(4, A.EdgesOut().Count()); - } -} diff --git a/Rubjerg.Graphviz.sln b/Rubjerg.Graphviz.sln index afb06d77..6caf2304 100644 --- a/Rubjerg.Graphviz.sln +++ b/Rubjerg.Graphviz.sln @@ -3,50 +3,41 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.32428.209 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rubjerg.Graphviz", "Rubjerg.Graphviz\Rubjerg.Graphviz.csproj", "{66D83B79-08D5-4590-90E3-8F6CDF108D5E}" - ProjectSection(ProjectDependencies) = postProject - {F9BC5523-352D-469F-8DBB-97ECA9D70648} = {F9BC5523-352D-469F-8DBB-97ECA9D70648} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GraphvizWrapper", "GraphvizWrapper\GraphvizWrapper.vcxproj", "{F9BC5523-352D-469F-8DBB-97ECA9D70648}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rubjerg.Graphviz.Test", "Rubjerg.Graphviz.Test\Rubjerg.Graphviz.Test.csproj", "{3E7CBBC1-A6AE-42A9-950C-54433B6F0E7C}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AD0D286A-6205-449D-AF8A-E9CA8066F6E0}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rubjerg.Graphviz.TransitiveTest", "Rubjerg.Graphviz.TransitiveTest\Rubjerg.Graphviz.TransitiveTest.csproj", "{FAB37EA6-101F-4B84-816F-7A98D571BAE7}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GraphvizWrapper", "GraphvizWrapper\GraphvizWrapper.vcxproj", "{F9BC5523-352D-469F-8DBB-97ECA9D70648}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ConsoleApplication", "ConsoleApplication\ConsoleApplication.vcxproj", "{27A1D045-B8C9-4785-A2DA-ECAC48158725}" + ProjectSection(ProjectDependencies) = postProject + {F9BC5523-352D-469F-8DBB-97ECA9D70648} = {F9BC5523-352D-469F-8DBB-97ECA9D70648} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rubjerg.Graphviz", "Rubjerg.Graphviz\Rubjerg.Graphviz.csproj", "{66D83B79-08D5-4590-90E3-8F6CDF108D5E}" + ProjectSection(ProjectDependencies) = postProject + {F9BC5523-352D-469F-8DBB-97ECA9D70648} = {F9BC5523-352D-469F-8DBB-97ECA9D70648} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 Release|x64 = Release|x64 + Debug|x64 = Debug|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {66D83B79-08D5-4590-90E3-8F6CDF108D5E}.Debug|x64.ActiveCfg = Debug|x64 - {66D83B79-08D5-4590-90E3-8F6CDF108D5E}.Debug|x64.Build.0 = Debug|x64 - {66D83B79-08D5-4590-90E3-8F6CDF108D5E}.Release|x64.ActiveCfg = Release|x64 - {66D83B79-08D5-4590-90E3-8F6CDF108D5E}.Release|x64.Build.0 = Release|x64 {F9BC5523-352D-469F-8DBB-97ECA9D70648}.Debug|x64.ActiveCfg = Debug|x64 {F9BC5523-352D-469F-8DBB-97ECA9D70648}.Debug|x64.Build.0 = Debug|x64 {F9BC5523-352D-469F-8DBB-97ECA9D70648}.Release|x64.ActiveCfg = Release|x64 {F9BC5523-352D-469F-8DBB-97ECA9D70648}.Release|x64.Build.0 = Release|x64 - {3E7CBBC1-A6AE-42A9-950C-54433B6F0E7C}.Debug|x64.ActiveCfg = Debug|x64 - {3E7CBBC1-A6AE-42A9-950C-54433B6F0E7C}.Debug|x64.Build.0 = Debug|x64 - {3E7CBBC1-A6AE-42A9-950C-54433B6F0E7C}.Release|x64.ActiveCfg = Release|x64 - {3E7CBBC1-A6AE-42A9-950C-54433B6F0E7C}.Release|x64.Build.0 = Release|x64 - {FAB37EA6-101F-4B84-816F-7A98D571BAE7}.Debug|x64.ActiveCfg = Debug|x64 - {FAB37EA6-101F-4B84-816F-7A98D571BAE7}.Debug|x64.Build.0 = Debug|x64 - {FAB37EA6-101F-4B84-816F-7A98D571BAE7}.Release|x64.ActiveCfg = Release|x64 - {FAB37EA6-101F-4B84-816F-7A98D571BAE7}.Release|x64.Build.0 = Release|x64 {27A1D045-B8C9-4785-A2DA-ECAC48158725}.Debug|x64.ActiveCfg = Debug|x64 {27A1D045-B8C9-4785-A2DA-ECAC48158725}.Debug|x64.Build.0 = Debug|x64 {27A1D045-B8C9-4785-A2DA-ECAC48158725}.Release|x64.ActiveCfg = Release|x64 {27A1D045-B8C9-4785-A2DA-ECAC48158725}.Release|x64.Build.0 = Release|x64 + {66D83B79-08D5-4590-90E3-8F6CDF108D5E}.Debug|x64.ActiveCfg = Debug|x64 + {66D83B79-08D5-4590-90E3-8F6CDF108D5E}.Debug|x64.Build.0 = Debug|x64 + {66D83B79-08D5-4590-90E3-8F6CDF108D5E}.Release|x64.ActiveCfg = Release|x64 + {66D83B79-08D5-4590-90E3-8F6CDF108D5E}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Rubjerg.Graphviz/.gitignore b/Rubjerg.Graphviz/.gitignore index ffb5f0a8..a6ff4a97 100644 --- a/Rubjerg.Graphviz/.gitignore +++ b/Rubjerg.Graphviz/.gitignore @@ -1,14 +1,6 @@ bin/ obj/ +Resources/ *.csproj.user -*.dll -*.exe -*.exp -*.lib -*.pdb -config6 -*.ipdb -*.iobj -*.exe *.svg *.dot diff --git a/Rubjerg.Graphviz/Constants.cs b/Rubjerg.Graphviz/Constants.cs new file mode 100644 index 00000000..c3a6930b --- /dev/null +++ b/Rubjerg.Graphviz/Constants.cs @@ -0,0 +1,19 @@ +using System; +using System.Runtime.InteropServices; + +namespace Rubjerg.Graphviz; + +internal static class Constants +{ +#if _WINDOWS + public const string GvcLib = "gvc.dll"; + public const string CGraphLib = "cgraph.dll"; + public const string XDotLib = "xdot.dll"; + public const string GraphvizWrapperLib = "GraphvizWrapper.dll"; +#else + public const string GvcLib = "libgvc.so.6"; + public const string CGraphLib = "libcgraph.so.6"; + public const string XDotLib = "libxdot.so.4"; + public const string GraphvizWrapperLib = "libGraphvizWrapper.so"; +#endif +} diff --git a/Rubjerg.Graphviz/ForeignFunctionInterface.cs b/Rubjerg.Graphviz/ForeignFunctionInterface.cs index db5e2c21..fd15473f 100644 --- a/Rubjerg.Graphviz/ForeignFunctionInterface.cs +++ b/Rubjerg.Graphviz/ForeignFunctionInterface.cs @@ -4,6 +4,7 @@ namespace Rubjerg.Graphviz; using static Marshaling; +using static Constants; /// /// Graphviz is thread unsafe, so we wrap all function calls inside a lock to make sure we don't run into @@ -499,144 +500,144 @@ public static IntPtr Rjagopen(string? name, int graphtype) } } - [DllImport("gvc.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GvcLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr gvContext(); - [DllImport("gvc.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GvcLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern int gvFreeContext(IntPtr gvc); - [DllImport("gvc.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GvcLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern int gvLayout(IntPtr gvc, IntPtr graph, IntPtr engine); - [DllImport("gvc.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GvcLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern int gvFreeLayout(IntPtr gvc, IntPtr graph); - [DllImport("gvc.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GvcLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern int gvRender(IntPtr gvc, IntPtr graph, IntPtr format, IntPtr @out); - [DllImport("gvc.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GvcLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern int gvRenderFilename(IntPtr gvc, IntPtr graph, IntPtr format, IntPtr filename); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr agnode(IntPtr graph, IntPtr name, int create); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern int agdegree(IntPtr graph, IntPtr node, int inset, int outset); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr agfstout(IntPtr graph, IntPtr node); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr agnxtout(IntPtr graph, IntPtr edge); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr agfstin(IntPtr graph, IntPtr node); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr agnxtin(IntPtr graph, IntPtr edge); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr agfstedge(IntPtr graph, IntPtr node); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr agnxtedge(IntPtr graph, IntPtr edge, IntPtr node); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern void agattr(IntPtr graph, int type, IntPtr name, IntPtr deflt); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern void agset(IntPtr obj, IntPtr name, IntPtr value); - [DllImport("cgraph.dll", SetLastError = false, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr agstrdup_html(IntPtr obj, IntPtr html); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern void agsafeset(IntPtr obj, IntPtr name, IntPtr val, IntPtr deflt); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr agroot(IntPtr obj); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr agnxtattr(IntPtr obj, int kind, IntPtr attribute); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern int agcopyattr(IntPtr from, IntPtr to); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.U1)] - private static extern bool rj_ageqedge(IntPtr edge1, IntPtr edge2); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr rj_agtail(IntPtr node); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr rj_aghead(IntPtr node); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr agedge(IntPtr graph, IntPtr tail, IntPtr head, IntPtr name, int create); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr rj_agmkin(IntPtr edge); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr rj_agmkout(IntPtr edge); - - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr agparent(IntPtr obj); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern int agclose(IntPtr graph); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern int agdelete(IntPtr graph, IntPtr item); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr agfstnode(IntPtr graph); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr agnxtnode(IntPtr graph, IntPtr node); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern int agcontains(IntPtr graph, IntPtr obj); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr agsubg(IntPtr graph, IntPtr name, int create); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr agfstsubg(IntPtr graph); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr agnxtsubg(IntPtr graph); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern int agisstrict(IntPtr ptr); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern int agisdirected(IntPtr ptr); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern int agisundirected(IntPtr ptr); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr agsubedge(IntPtr graph, IntPtr edge, int create); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr agsubnode(IntPtr graph, IntPtr node, int create); + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr agget(IntPtr obj, IntPtr name); + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr agnameof(IntPtr obj); + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr agedge(IntPtr graph, IntPtr tail, IntPtr head, IntPtr name, int create); + + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.U1)] + private static extern bool rj_ageqedge(IntPtr edge1, IntPtr edge2); + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr rj_agtail(IntPtr node); + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr rj_aghead(IntPtr node); + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr rj_agmkin(IntPtr edge); + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr rj_agmkout(IntPtr edge); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr edge_label(IntPtr node); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr rj_agmemwrite(IntPtr graph); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr graph_label(IntPtr node); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr agget(IntPtr obj, IntPtr name); - [DllImport("cgraph.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr agnameof(IntPtr obj); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern void clone_attribute_declarations(IntPtr graphfrom, IntPtr graphto); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr rj_sym_key(IntPtr sym); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern double label_x(IntPtr label); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern double label_y(IntPtr label); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern double label_width(IntPtr label); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern double label_height(IntPtr label); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr label_text(IntPtr label); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern double label_fontsize(IntPtr label); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr label_fontname(IntPtr label); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern double node_x(IntPtr node); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern double node_y(IntPtr node); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern double node_width(IntPtr node); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern double node_height(IntPtr node); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr node_label(IntPtr node); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern void convert_to_undirected(IntPtr graph); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr rj_agmemread(IntPtr input); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr rj_agopen(IntPtr name, int graphtype); @@ -670,42 +671,42 @@ static ForeignFunctionInterface() #region debugging and testing // .NET uses UnmanagedType.Bool by default for P/Invoke, but our C++ code uses UnmanagedType.U1 - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool echobool([MarshalAs(UnmanagedType.U1)] bool arg); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool return_true(); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool return_false(); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int echoint(int arg); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int return1(); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int return_1(); public enum TestEnum { Val1, Val2, Val3, Val4, Val5 } - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern TestEnum return_enum1(); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern TestEnum return_enum2(); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern TestEnum return_enum5(); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern TestEnum echo_enum(TestEnum e); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr echo_string(IntPtr str); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr return_empty_string(); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr return_hello(); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr return_copyright(); public static string? EchoString(string? str) diff --git a/Rubjerg.Graphviz/GraphvizCommand.cs b/Rubjerg.Graphviz/GraphvizCommand.cs index 87b8ec8f..7bc4350a 100644 --- a/Rubjerg.Graphviz/GraphvizCommand.cs +++ b/Rubjerg.Graphviz/GraphvizCommand.cs @@ -3,6 +3,7 @@ using System.IO; using System.Reflection; using System.Text; +using System.Runtime.InteropServices; namespace Rubjerg.Graphviz; @@ -11,6 +12,27 @@ namespace Rubjerg.Graphviz; /// public class GraphvizCommand { + internal static string Rid + { + get + { + var os = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "win" + : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "osx" + : "linux"; // default + + var arch = RuntimeInformation.ProcessArchitecture switch + { + Architecture.X64 => "x64", + Architecture.Arm64 => "arm64", + Architecture.X86 => "x86", + Architecture.Arm => "arm", + _ => "unknown" + }; + + return $"{os}-{arch}"; + } + } + public static RootGraph CreateLayout(Graph input, string engine = LayoutEngines.Dot, CoordinateSystem coordinateSystem = CoordinateSystem.BottomLeft) { var (stdout, stderr) = Exec(input, engine: engine); @@ -34,7 +56,7 @@ public static string ConvertBytesOutputToString(byte[] data) /// stderr may contain warnings, stdout is in utf8 encoding public static (byte[] stdout, string stderr) Exec(Graph input, string format = "xdot", string? outputPath = null, string engine = LayoutEngines.Dot) { - string exeName = "dot.exe"; + var exeName = Path.Combine(AppContext.BaseDirectory, "runtimes", Rid, "native", "dot"); string arguments = $"-T{format} -K{engine}"; if (outputPath != null) { diff --git a/Rubjerg.Graphviz/Marshaling.cs b/Rubjerg.Graphviz/Marshaling.cs index 154fc9ad..8a8c6eab 100644 --- a/Rubjerg.Graphviz/Marshaling.cs +++ b/Rubjerg.Graphviz/Marshaling.cs @@ -5,10 +5,12 @@ namespace Rubjerg.Graphviz; +using static Constants; + internal static class Marshaling { /// - /// Marshal a c-string in utf8 encoding to a + /// Marshal a c-string in utf8 encoding to a .NET string /// /// Pointer to the native c-string /// Whether to free the native c-string after marshaling @@ -87,6 +89,8 @@ public static T MarshalToUtf8(string? s, Func continuation, bool f return byteArray; } - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern void free_str(IntPtr ptr); + [DllImport(CGraphLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + private static extern void agstrfree(IntPtr root, IntPtr str); } diff --git a/Rubjerg.Graphviz/NativeMethods.cs b/Rubjerg.Graphviz/NativeMethods.cs index aaf766f2..1516af79 100644 --- a/Rubjerg.Graphviz/NativeMethods.cs +++ b/Rubjerg.Graphviz/NativeMethods.cs @@ -6,6 +6,7 @@ namespace Rubjerg.Graphviz; public static class NativeMethods { +#if _WINDOWS public static void CreateConsole() { _ = AllocConsole(); @@ -30,6 +31,7 @@ public static void CreateConsole() private static extern IntPtr GetStdHandle(uint nStdHandle); [DllImport("kernel32.dll")] private static extern void SetStdHandle(uint nStdHandle, IntPtr handle); - [DllImport("kernel32")] + [DllImport("kernel32.dll")] static extern bool AllocConsole(); +#endif } diff --git a/Rubjerg.Graphviz/RootGraph.cs b/Rubjerg.Graphviz/RootGraph.cs index 07e13dbb..cd9d1b10 100644 --- a/Rubjerg.Graphviz/RootGraph.cs +++ b/Rubjerg.Graphviz/RootGraph.cs @@ -19,10 +19,13 @@ public enum GraphType /// /// Wraps a cgraph root graph. /// NB: If there is no .net wrapper left that points to any part of a root graph, the root graph is destroyed. +/// This can also be done manually through the Close function, +/// but this is generally unnecessary unless the graphs are really big. /// -public class RootGraph : Graph +public sealed class RootGraph : Graph { private long _added_pressure = 0; + private bool _closed = false; public CoordinateSystem CoordinateSystem { get; } /// @@ -30,15 +33,29 @@ public class RootGraph : Graph /// public string? Warnings { get; internal set; } - protected RootGraph(IntPtr ptr, CoordinateSystem coordinateSystem) : base(ptr, null) + private RootGraph(IntPtr ptr, CoordinateSystem coordinateSystem) : base(ptr, null) { CoordinateSystem = coordinateSystem; } + ~RootGraph() { - if (_added_pressure > 0) - GC.RemoveMemoryPressure(_added_pressure); - _ = Agclose(_ptr); + Close(); + } + + /// + /// Manually destroy the graph. All subsequent method calls will likely crash. + /// Not recommended to call manually, as it is generally unnecessary, unless the graph is really big. + /// + public void Close() + { + if (!_closed) + { + _closed = true; + _ = Agclose(_ptr); + if (_added_pressure > 0) + GC.RemoveMemoryPressure(_added_pressure); + } } /// @@ -83,8 +100,7 @@ public static RootGraph FromDotFile(string filename) return FromDotString(input); } - protected static T FromDotString(string graph, Func constructor) - where T : RootGraph + public static RootGraph FromDotString(string graph, CoordinateSystem coordinateSystem = CoordinateSystem.BottomLeft) { // Just to be safe, make sure the input has unix line endings. Graphviz does not properly support // windows line endings passed to stdin when it comes to attribute line continuations. @@ -94,16 +110,11 @@ protected static T FromDotString(string graph, Func constructor) { throw new InvalidOperationException("Could not create graph"); } - var result = constructor(ptr); + var result = new RootGraph(ptr, coordinateSystem); result.UpdateMemoryPressure(); return result; } - public static RootGraph FromDotString(string graph, CoordinateSystem coordinateSystem = CoordinateSystem.BottomLeft) - { - return FromDotString(graph, ptr => new RootGraph(ptr, coordinateSystem)); - } - public void ConvertToUndirectedGraph() { ConvertToUndirected(_ptr); diff --git a/Rubjerg.Graphviz/Rubjerg.Graphviz.csproj b/Rubjerg.Graphviz/Rubjerg.Graphviz.csproj index 7cae382e..3bfc0b4a 100644 --- a/Rubjerg.Graphviz/Rubjerg.Graphviz.csproj +++ b/Rubjerg.Graphviz/Rubjerg.Graphviz.csproj @@ -1,47 +1,148 @@  + Library netstandard2.0 + + + win-x64;linux-x64 + x64 x64 latest AllEnabledByDefault true - Enable + enable 1701;1702;NU5100 - 2.0.2 - Chiel ten Brinke - Rubjerg - Lean wrapper around Graphviz for building graphs, reading/writing dot files, exporting images, or reading out layout parameters. - Copyright 2020 - graphviz dotnet graphdrawing - https://github.com/Rubjerg/Graphviz.NetWrapper - https://github.com/Rubjerg/Graphviz.NetWrapper - - LICENSE + embedded + + win-x64 + linux-x64 - + + + + true + + + + + true - - - false - - + + _WINDOWS + - - Always + + PreserveNewest + runtimes/$(Rid)/native/%(Filename)%(Extension) true - true + runtimes/$(Rid)/native/ - + + + PreserveNewest + runtimes/$(Rid)/native/graphviz/%(RecursiveDir)%(Filename)%(Extension) true - + runtimes/$(Rid)/native/graphviz/%(RecursiveDir) + + + + Chiel ten Brinke + Rubjerg + Lean wrapper around Graphviz for building graphs, reading/writing dot files, exporting images, or reading out layout parameters. + Copyright 2020 + graphviz dotnet graphdrawing + https://github.com/Rubjerg/Graphviz.NetWrapper + https://github.com/Rubjerg/Graphviz.NetWrapper + LICENSE + README.md + + + + + + + <_GitTmpFile>$([System.String]::Copy('$(IntermediateOutputPath)git-info.txt').Replace('\', '/')) + $([System.DateTime]::UtcNow.ToString("yyyyMMddHHmmss")) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $([System.Text.RegularExpressions.Regex]::Replace($(LatestTag), '^v', '')) + + + <_ResolvedVersion Condition="'$(ExactTag)' != '' and '$(IsDirty)' == 'no'"> + $(BaseVersion) + + + + <_ResolvedVersion Condition="'$(_ResolvedVersion)' == '' and '$(IsDirty)' == 'no' and '$(MasterDescendant)' == 'yes'"> + $(BaseVersion)-alpha-$(CommitHash) + + + + <_ResolvedVersion Condition="'$(_ResolvedVersion)' == ''"> + $(BaseVersion)-dev-$(Timestamp) + + + $([System.String]::Copy($(_ResolvedVersion)).Trim()) + + + + + + + + + + + + + + + diff --git a/Rubjerg.Graphviz/SubGraph.cs b/Rubjerg.Graphviz/SubGraph.cs index a825ba52..82240497 100644 --- a/Rubjerg.Graphviz/SubGraph.cs +++ b/Rubjerg.Graphviz/SubGraph.cs @@ -4,7 +4,7 @@ namespace Rubjerg.Graphviz; -public class SubGraph : Graph +public sealed class SubGraph : Graph { /// /// rootgraph must not be null diff --git a/Rubjerg.Graphviz/XDotFFI.cs b/Rubjerg.Graphviz/XDotFFI.cs index fee3dd24..b4e85a95 100644 --- a/Rubjerg.Graphviz/XDotFFI.cs +++ b/Rubjerg.Graphviz/XDotFFI.cs @@ -4,204 +4,205 @@ namespace Rubjerg.Graphviz; using static Marshaling; +using static Constants; /// /// See https://graphviz.org/docs/outputs/canon/#xdot /// internal static class XDotFFI { - [DllImport("xdot.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(XDotLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr parseXDot(IntPtr xdotString); public static IntPtr ParseXDot(string xdotString) => MarshalToUtf8(xdotString, parseXDot); - [DllImport("xdot.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(XDotLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern void freeXDot(IntPtr xdotptr); // Accessors for xdot - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern UIntPtr get_cnt(IntPtr xdot); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr get_ops(IntPtr xdot); // Accessors for xdot_image - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr get_name_image(IntPtr img); public static string? GetNameImage(IntPtr img) => MarshalFromUtf8(get_name_image(img), false); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr get_pos(IntPtr img); // Accessors for xdot_font - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_size(IntPtr font); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr get_name_font(IntPtr font); public static string? GetNameFont(IntPtr img) => MarshalFromUtf8(get_name_font(img), false); // Accessors for xdot_op - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern XDotKind get_kind(IntPtr op); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr get_ellipse(IntPtr op); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr get_polygon(IntPtr op); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr get_polyline(IntPtr op); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr get_bezier(IntPtr op); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr get_text(IntPtr op); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr get_image(IntPtr op); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr get_color(IntPtr op); public static string? GetColor(IntPtr op) => MarshalFromUtf8(get_color(op), false); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr get_grad_color(IntPtr op); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr get_font(IntPtr op); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr get_style(IntPtr op); public static string? GetStyle(IntPtr op) => MarshalFromUtf8(get_style(op), false); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern uint get_fontchar(IntPtr op); // Accessors for xdot_color - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern XDotGradType get_type(IntPtr clr); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr get_clr(IntPtr clr); public static string? GetClr(IntPtr clr) => MarshalFromUtf8(get_clr(clr), false); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr get_ling(IntPtr clr); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr get_ring(IntPtr clr); // Accessors for xdot_text - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_x_text(IntPtr txt); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_y_text(IntPtr txt); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern TextAlign get_align(IntPtr txt); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_width(IntPtr txt); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr get_text_str(IntPtr txt); public static string? GetTextStr(IntPtr txt) => MarshalFromUtf8(get_text_str(txt), false); // Accessors for xdot_linear_grad - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_x0_ling(IntPtr ling); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_y0_ling(IntPtr ling); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_x1_ling(IntPtr ling); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_y1_ling(IntPtr ling); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int get_n_stops_ling(IntPtr ling); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr get_stops_ling(IntPtr ling); // Accessors for xdot_radial_grad - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_x0_ring(IntPtr ring); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_y0_ring(IntPtr ring); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_r0_ring(IntPtr ring); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_x1_ring(IntPtr ring); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_y1_ring(IntPtr ring); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_r1_ring(IntPtr ring); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int get_n_stops_ring(IntPtr ring); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr get_stops_ring(IntPtr ring); // Accessors for xdot_color_stop - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern float get_frac(IntPtr stop); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr get_color_stop(IntPtr stop); public static string? GetColorStop(IntPtr stop) => MarshalFromUtf8(get_color_stop(stop), false); // Accessors for xdot_polyline - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern UIntPtr get_cnt_polyline(IntPtr polyline); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr get_pts_polyline(IntPtr polyline); // Accessors for xdot_point - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_x_point(IntPtr point); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_y_point(IntPtr point); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_z_point(IntPtr point); // Accessors for xdot_rect - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_x_rect(IntPtr rect); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_y_rect(IntPtr rect); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_w_rect(IntPtr rect); - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern double get_h_rect(IntPtr rect); // Index function for xdot_color_stop array - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr get_color_stop_at_index(IntPtr stops, int index); // Index function for xdot_op array - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr get_op_at_index(IntPtr ops, int index); // Index function for xdot_pt array - [DllImport("GraphvizWrapper.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + [DllImport(GraphvizWrapperLib, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr get_pt_at_index(IntPtr pts, int index); } diff --git a/build-release.sh b/build-release.sh deleted file mode 100644 index 4d3052e1..00000000 --- a/build-release.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -git clean -dfx && nuget restore Rubjerg.Graphviz.sln && C:\\Program\ Files\\Microsoft\ Visual\ Studio\\2022\\Professional\\Msbuild\\Current\\Bin\\MSBuild.exe //p:configuration=release Rubjerg.Graphviz.sln diff --git a/codecov.yml b/codecov.yml deleted file mode 100644 index c9e3f9e2..00000000 --- a/codecov.yml +++ /dev/null @@ -1,10 +0,0 @@ -coverage: - range: "60...90" - status: - project: - default: - target: 70% - patch: - default: - target: 100% - informational: true \ No newline at end of file diff --git a/format-code.sh b/format-code.sh deleted file mode 100644 index 36f48790..00000000 --- a/format-code.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -dotnet format whitespace -v diag Rubjerg.Graphviz.sln -dotnet format whitespace -v diag Rubjerg.Graphviz.NugetTests.sln diff --git a/justfile b/justfile new file mode 100644 index 00000000..eaa7a5fa --- /dev/null +++ b/justfile @@ -0,0 +1,82 @@ +set shell := ["sh", "-cu"] +is-windows := `uname -s | grep -qi 'mingw\|msys' && echo true || echo false` + +# Complete build and test +default: test-all + +find-msbuild: + powershell -NoProfile -Command '& { & "${env:ProgramFiles(x86)}\\Microsoft Visual Studio\\Installer\\vswhere.exe" -latest -requires Microsoft.Component.MSBuild -find MSBuild\\**\\Bin\\MSBuild.exe }' + +# Restore .NET tools +restore-tools: + dotnet tool restore + +# Restore main solution packages +restore: restore-tools + dotnet restore Rubjerg.Graphviz.sln + +# Build main app +build-package: restore + if {{is-windows}}; then \ + MSBuild.exe Rubjerg.Graphviz.sln //p:Configuration=Release; \ + else \ + dotnet build Rubjerg.Graphviz.sln --configuration Release --no-restore; \ + fi + +# Restore test project packages +restore-tests: build-package + dotnet restore Rubjerg.Graphviz.Tests.sln + +# Build test projects +build-tests: restore-tests + if {{is-windows}}; then \ + MSBuild.exe Rubjerg.Graphviz.Tests.sln //p:Configuration=Release; \ + else \ + dotnet build Rubjerg.Graphviz.Tests.sln --configuration Release --no-restore; \ + fi + +# Run unit tests for a project +test PROJECT: + dotnet test --no-build \ + -p:OutputPath=bin/x64/Release/net8.0 \ + -c Release \ + -f net8.0 \ + -v d \ + --filter "Category != Flaky & Category != Slow" \ + {{PROJECT}} + +# Run both test projects +test-all: build-tests + just test Rubjerg.Graphviz.Test/Rubjerg.Graphviz.Test.csproj + just test Rubjerg.Graphviz.TransitiveTest/Rubjerg.Graphviz.TransitiveTest.csproj + +locate-nupkg GITHUB_OUTPUT: + echo "package=$(find . -name "Rubjerg.Graphviz.*.nupkg" | head -1)" >> "{{GITHUB_OUTPUT}}" + +generate-readme: + echo Generating README.md + cat README-src.md > README.md + printf '```cs \r\n' >> README.md + cat Rubjerg.Graphviz.Test/Tutorial.cs >> README.md + printf '```\r\n' >> README.md + +# Strip trailing spaces and normalize line endings to crlf +normalize: + bash -c "git ls-files -- ':!GraphvizWrapper/*' | xargs sed -i -b 's/[ \t]*$//' " + bash -c "git ls-files -- ':!GraphvizWrapper/graphvizfiles/*' ':!*.sh' | xargs unix2dos" + +# Format the code +format: + dotnet format whitespace -v diag Rubjerg.Graphviz.sln + dotnet format whitespace -v diag Rubjerg.Graphviz.Tests.sln + +# Check that none of the actions generated a diff +check-diff: + git diff --exit-code + +# Check for unfinished work +check-fixme: + bash -c "! git grep 'FIX''NOW'" + +check-all: generate-readme normalize format check-diff check-fixme + diff --git a/nuget.config b/nuget.config index 0c4083d6..79fe94ed 100644 --- a/nuget.config +++ b/nuget.config @@ -1,27 +1,23 @@ - + - - - - - - - + + + + + + - - - + + + + + + - - - - - - diff --git a/nunit-console.sh b/nunit-console.sh deleted file mode 100644 index ff1f0ee2..00000000 --- a/nunit-console.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -packages\\nunit.consolerunner\\3.18.3\\tools\\nunit3-console.exe "$@" --trace=Off --where "cat!=Slow and cat!=Flaky" diff --git a/run-tests-netcore.sh b/run-tests-netcore.sh deleted file mode 100644 index 778d9b8b..00000000 --- a/run-tests-netcore.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -dotnet test -p:Platform=x64 --no-build -c Release -f net8.0 -v d --filter "Category != Flaky & Category != Slow" "$@" diff --git a/runtests.sh b/runtests.sh deleted file mode 100644 index 5ed40db1..00000000 --- a/runtests.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -msbuild.exe Rubjerg.Graphviz.sln && find . -wholename './Rubjerg.Graphviz.Test/bin/**/net48/*Test.dll' | xargs ./nunit-console.sh -rm *.log