Skip to content

Tweaks to build the whole project on Windows with CMake/MSVC 19 in 2026 - #305

Open
twdragon wants to merge 8 commits into
Beckhoff:masterfrom
twdragon:master
Open

Tweaks to build the whole project on Windows with CMake/MSVC 19 in 2026#305
twdragon wants to merge 8 commits into
Beckhoff:masterfrom
twdragon:master

Conversation

@twdragon

Copy link
Copy Markdown
  • Fixed the PLC port definitions mistakenly left in the BSD section in the test program
  • Added CMake tweaks to successfully build the project on Windows natively using git/MSVC/PowerShell
  • Implemented TcAdsDll_ROOT CMake variable to let the build system catch the libraries from non-standard locations. Tested on non-native installation in Windows 10.0.19045 and SDK 10.0.26100.0

twdragon added 2 commits July 30, 2026 16:55
    - Fixed the PLC port definitions mistakenly left in the BSD section
      in the test program
    - Added CMake tweaks to successfully build the project on Windows natively
      using git/MSVC/PowerShell
    - Implemented TcAdsDll_ROOT CMake variable to let the build system catch
      the libraries from non-standard locations. Tested on non-native
      installation in Windows 10.0.19045 and SDK 10.0.26100.0
@juarezr-mvtec

juarezr-mvtec commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Hello, I am not the maintainer, but I authored the FindTcAdsDll.cmake file that you are editing. I suggest that you should keep the support for finding TcAdsDll in old TwinCAT versions ? The way you are doing it is correct but will only work for the newest versions.
So instead of changing the variable value just try make it an array :
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
set(TcAdsDll_IMPLIB_DIR "${TcAdsDll_ROOT_DIR}/Lib/x64" "${TcAdsDll_ROOT_DIR}/x64/lib")
set(TcAdsDll_DLL_DIR "${TcAdsDll_ROOT_DIR}/x64" "${TcAdsDll_ROOT_DIR}/../../Common64")
elseif (CMAKE_SIZEOF_VOID_P EQUAL 4)
set(TcAdsDll_IMPLIB_DIR "${TcAdsDll_ROOT_DIR}/Lib")
set(TcAdsDll_DLL_DIR "${TcAdsDll_ROOT_DIR}" "${TcAdsDll_ROOT_DIR}/../../Common32")
endif()

The find_library and find_file PATHS argument take an array anyways.

Additionally, since the default location is no longer C:/TwinCAT/.. in the new version so we can probably change it to something like this:

if (WIN32 AND NOT DEFINED TcAdsDll_ROOT)
# Typical install locations on Windows
set(_TcAdsDll_PATH "$ENV{SystemDrive}/TwinCAT/AdsApi/TcAdsDll")
if( NOT EXISTS ${_TcAdsDll_PATH})
# New TwinCAT 3.5+ default location
set(_TcAdsDll_PATH "$ENV{ProgramFiles(x86)}/Beckhoff/TwinCAT/AdsApi/TcAdsDll")
endif()
else ()

Try them out, tell me if it works.

@twdragon

twdragon commented Aug 6, 2026

Copy link
Copy Markdown
Author

@juarezr-mvtec thanks for the suggestion! Unfortunately, direct introduction of array-like path lists did not work, so I used separate variables.

@twdragon

twdragon commented Aug 6, 2026

Copy link
Copy Markdown
Author

@juarezr-mvtec I will also try to fix the Linux pipeline, but I cannot promise to do it now, so likely it will be a separate PR

@juarezr-mvtec

Copy link
Copy Markdown
Contributor

Hello @twdragon

The problem is that we are passing the variable PATHS with "" like :

find_library(TcAdsDll_IMPLIB
NAMES TcAdsDll.lib
PATHS "${TcAdsDll_IMPLIB_DIR}"
NO_DEFAULT_PATH
)

this makes find_library consider TcAdsDll_IMPLIB_DIR as a single string instead of a list. So removing the "" fixes the issue with passing multiple paths. I tested this on my setup (old version path) and this is working for me:

if (CMAKE_SIZEOF_VOID_P EQUAL 8)
    set(TcAdsDll_IMPLIB_DIR "${TcAdsDll_ROOT_DIR}/Lib/x64" "${TcAdsDll_ROOT_DIR}/x64/lib")
    set(TcAdsDll_DLL_DIR "${TcAdsDll_ROOT_DIR}/x64" "${TcAdsDll_ROOT_DIR}/../../Common64")
elseif (CMAKE_SIZEOF_VOID_P EQUAL 4)
    set(TcAdsDll_IMPLIB_DIR "${TcAdsDll_ROOT_DIR}/Lib")
    set(TcAdsDll_DLL_DIR "${TcAdsDll_ROOT_DIR}" "${TcAdsDll_ROOT_DIR}/../../Common32")
endif ()
find_library(TcAdsDll_IMPLIB
        NAMES TcAdsDll.lib
        PATHS ${TcAdsDll_IMPLIB_DIR}
        NO_DEFAULT_PATH
)
find_file(TcAdsDll_LIBRARY
        NAMES TcAdsDll.dll
        PATHS ${TcAdsDll_DLL_DIR}
        NO_DEFAULT_PATH
)

I have not personally tested it but linux should work out of the box at least according to the maintainer (see #295).
I have another pull request where I remove some of those "not tested on linux" comments but it is still waiting for a review. #300

@twdragon

twdragon commented Aug 7, 2026

Copy link
Copy Markdown
Author

@juarezr-mvtec now it looks like:

if (WIN32 AND NOT DEFINED TcAdsDll_ROOT)
    # Typical install locations on Windows
    list(APPEND _TcAdsDll_PATH
        "$ENV{SystemDrive}/TwinCAT/AdsApi/TcAdsDll" # Old location (TwinCAT < 3.5)
        "$ENV{ProgramFiles(x86)}/Beckhoff/TwinCAT/AdsApi/TcAdsDll" # New location (TwinCAT 3.5+)
    )
else ()
    set(_TcAdsDll_PATH)
endif ()
# Find the include headers

find_path(TcAdsDll_INCLUDE_DIR
        NAMES TcAdsApi.h TcAdsDef.h
        PATHS "${_TcAdsDll_PATH_OLD}" "${_TcAdsDll_PATH_NEW}"
        PATH_SUFFIXES "Include" "include"
)
# Find all related files base on the include files location. This is done
# assuming that the files are ordered as install by TwinCat. If they are
# in some other configuration this will not work.
if (WIN32)
    cmake_path(GET TcAdsDll_INCLUDE_DIR PARENT_PATH TcAdsDll_ROOT_DIR)
    if (NOT TcAdsDll_FIND_QUIETLY)
        message(STATUS "Searching TcAdsDll in ROOT ${TcAdsDll_ROOT_DIR}")
    endif ()
    if (CMAKE_SIZEOF_VOID_P EQUAL 8)
        set(TcAdsDll_IMPLIB_DIR "${TcAdsDll_ROOT_DIR}/Lib/x64")
        list(APPEND TcAdsDll_DLL_DIR 
            "${TcAdsDll_ROOT_DIR}/x64"
            "${TcAdsDll_ROOT_DIR}/../../Common64"
        )
    elseif (CMAKE_SIZEOF_VOID_P EQUAL 4)
        set(TcAdsDll_IMPLIB_DIR "${TcAdsDll_ROOT_DIR}/Lib")
        list(APPEND TcAdsDll_DLL_DIR 
            "${TcAdsDll_ROOT_DIR}"
            "${TcAdsDll_ROOT_DIR}/../../Common32"
        )
    endif ()
    find_library(TcAdsDll_IMPLIB
            NAMES TcAdsDll.lib
            PATHS ${TcAdsDll_IMPLIB_DIR}
            NO_DEFAULT_PATH
    )
    find_file(TcAdsDll_LIBRARY
            NAMES TcAdsDll.dll
            PATHS ${TcAdsDll_DLL_DIR}
            NO_DEFAULT_PATH
    )
else ()
    find_library(TcAdsDll_LIBRARY
            NAMES TcAdsDll
    )
endif ()

Attested to work on Windows. Thanks again!

@twdragon

twdragon commented Aug 7, 2026

Copy link
Copy Markdown
Author

Hoping to get attention from @pbruenn. It could also close #275, as it implies usage of the Winsock2 library.

Comment thread cmake/FindTcAdsDll.cmake Outdated
Comment thread cmake/FindTcAdsDll.cmake Outdated
Comment thread cmake/FindTcAdsDll.cmake
@twdragon

twdragon commented Aug 7, 2026

Copy link
Copy Markdown
Author

@juarezr-mvtec I implemented and tested it, thanks again!

@twdragon

twdragon commented Aug 7, 2026

Copy link
Copy Markdown
Author

@juarezr-mvtec I unfortunately don't have a different version of TwinCAT libraries on my workstation, so I cannot fully test the setup

@juarezr-mvtec juarezr-mvtec left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more changes. With the changes this should work as expected.
I download the latest TwinCAT version and I tested this now with and without setting TcAdsDll_ROOT.

Once the changes are complete I will suggest that you SQUASH all of these changes into a single commit to keep a clean git history. :)

Comment thread cmake/FindTcAdsDll.cmake Outdated
Comment thread cmake/FindTcAdsDll.cmake
Comment thread cmake/FindTcAdsDll.cmake Outdated
@twdragon

twdragon commented Aug 7, 2026

Copy link
Copy Markdown
Author

Once the changes are complete I will suggest that you SQUASH all of these changes into a single commit to keep a clean git history. :)

@juarezr-mvtec I will do)) I have not so much time to work on this repo, so I do quick and dirty

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants