FindTCL: Find Tk 9 libraries and Homebrew headers

Tk 9 names its library with a "tcl9" prefix (tcl9tk90.lib,
libtcl9tk9.0.so), which our tk90/tk9.0 patterns don't match. We now
search for these names too, and also look in include/tcl-tk for the
headers, where Homebrew installs them.

Fixes: #28129
This commit is contained in:
Daksh Mamodiya committed 2026-10-01 21:24:12 +05:30
1 parent 5159500924
commit 9589c88e10
13 files changed
+213 -2

No files matched your search

@@ -96,6 +96,7 @@ set(CMake_TEST_FindPython3_PyPy "ON" CACHE BOOL "")
set(CMake_TEST_FindRuby "ON" CACHE BOOL "")
set(CMake_TEST_FindSDL "ON" CACHE BOOL "")
set(CMake_TEST_FindSQLite3 "ON" CACHE BOOL "")
set(CMake_TEST_FindTCL "ON" CACHE BOOL "")
set(CMake_TEST_FindTIFF "ON" CACHE BOOL "")
set(CMake_TEST_FindwxWidgets "ON" CACHE BOOL "")
set(CMake_TEST_FindX11 "ON" CACHE BOOL "")
@@ -94,6 +94,7 @@ set(CMake_TEST_FindRuby_RBENV "ON" CACHE BOOL "")
set(CMake_TEST_FindRuby_RVM "ON" CACHE BOOL "")
set(CMake_TEST_FindSDL "ON" CACHE BOOL "")
set(CMake_TEST_FindSQLite3 "ON" CACHE BOOL "")
set(CMake_TEST_FindTCL "ON" CACHE BOOL "")
set(CMake_TEST_FindTIFF "ON" CACHE BOOL "")
set(CMake_TEST_FindwxWidgets "ON" CACHE BOOL "")
set(CMake_TEST_FindX11 "ON" CACHE BOOL "")
@@ -94,6 +94,7 @@ set(CMake_TEST_FindRuby_RBENV "ON" CACHE BOOL "")
set(CMake_TEST_FindRuby_RVM "ON" CACHE BOOL "")
set(CMake_TEST_FindSDL "ON" CACHE BOOL "")
set(CMake_TEST_FindSQLite3 "ON" CACHE BOOL "")
set(CMake_TEST_FindTCL "ON" CACHE BOOL "")
set(CMake_TEST_FindTIFF "ON" CACHE BOOL "")
set(CMake_TEST_FindwxWidgets "ON" CACHE BOOL "")
set(CMake_TEST_FindX11 "ON" CACHE BOOL "")
+3 -2
View File
@@ -161,8 +161,8 @@ find_library(TK_LIBRARY
NAMES
tk
tk${TK_LIBRARY_VERSION} tk${TCL_TCLSH_VERSION} tk${TK_WISH_VERSION}
tk91 tk9.1 tk91t tk9.1t
tk90 tk9.0 tk90t tk9.0t
tcl9tk91 tcl9tk9.1 tk91 tk9.1 tk91t tk9.1t
tcl9tk90 tcl9tk9.0 tk90 tk9.0 tk90t tk9.0t
tk86 tk8.6 tk86t tk8.6t
tk85 tk8.5
tk84 tk8.4
@@ -222,6 +222,7 @@ set(TCLTK_POSSIBLE_INCLUDE_PATH_SUFFIXES
include/tcl8.3
include/tcl8.2
include/tcl8.0
include/tcl-tk
)
if(WIN32)
+1
View File
@@ -1538,6 +1538,7 @@ if(BUILD_TESTING)
Protobuf
SDL
SQLite3
TCL
TIFF
Vulkan
wxWidgets
+10
View File
@@ -0,0 +1,10 @@
add_test(NAME FindTCL.Test COMMAND
${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
--build-and-test
"${CMake_SOURCE_DIR}/Tests/FindTCL/Test"
"${CMake_BINARY_DIR}/Tests/FindTCL/Test"
${build_generator_args}
--build-project TestFindTCL
--build-options ${build_options}
--test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
)
+15
View File
@@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.10)
project(TestFindTCL C)
include(CTest)
find_package(TCL REQUIRED)
add_executable(test_tcl main.c)
target_include_directories(test_tcl PRIVATE ${TCL_INCLUDE_PATH})
target_link_libraries(test_tcl PRIVATE ${TCL_LIBRARY})
add_test(NAME test_tcl COMMAND test_tcl)
add_executable(test_tk main_tk.c)
target_include_directories(test_tk PRIVATE ${TK_INCLUDE_PATH} ${TCL_INCLUDE_PATH})
target_link_libraries(test_tk PRIVATE ${TK_LIBRARY} ${TCL_LIBRARY})
add_test(NAME test_tk COMMAND test_tk)
+32
View File
@@ -0,0 +1,32 @@
#include <stdio.h>
#include <string.h>
#include <tcl.h>
int main(int argc, char* argv[])
{
int major;
int minor;
int ok;
Tcl_Interp* interp;
(void)argc;
Tcl_FindExecutable(argv[0]);
Tcl_GetVersion(&major, &minor, NULL, NULL);
printf("Found Tcl library %d.%d, headers %d.%d\n", major, minor,
TCL_MAJOR_VERSION, TCL_MINOR_VERSION);
if (major != TCL_MAJOR_VERSION || minor != TCL_MINOR_VERSION) {
fprintf(stderr, "Tcl library does not match Tcl headers\n");
return 1;
}
interp = Tcl_CreateInterp();
ok = Tcl_EvalEx(interp, "expr {6 * 7}", -1, 0) == TCL_OK &&
strcmp(Tcl_GetStringResult(interp), "42") == 0;
if (!ok) {
fprintf(stderr, "Tcl evaluation failed: %s\n",
Tcl_GetStringResult(interp));
}
Tcl_DeleteInterp(interp);
return ok ? 0 : 1;
}
+26
View File
@@ -0,0 +1,26 @@
#include <stdio.h>
#include <tk.h>
int main(int argc, char* argv[])
{
int major;
int minor;
Tcl_Interp* interp;
Tk_Window mainWindow;
(void)argc;
Tcl_FindExecutable(argv[0]);
Tcl_GetVersion(&major, &minor, NULL, NULL);
printf("Found Tcl library %d.%d, Tk headers %d.%d\n", major, minor,
TK_MAJOR_VERSION, TK_MINOR_VERSION);
if (major != TK_MAJOR_VERSION) {
fprintf(stderr, "Tcl library does not match Tk headers\n");
return 1;
}
interp = Tcl_CreateInterp();
mainWindow = Tk_MainWindow(interp);
Tcl_DeleteInterp(interp);
return mainWindow ? 1 : 0;
}
+1
View File
@@ -543,6 +543,7 @@ if(CMake_TEST_FindPython2 OR CMake_TEST_FindPython2_SABIModule OR CMake_TEST_Fin
endif()
add_RunCMake_test(FindBoost)
add_RunCMake_test(FindLua)
add_RunCMake_test(FindTCL)
if(CMake_TEST_FindRuby)
add_RunCMake_test(FindRuby
-DCMake_TEST_FindRuby_RBENV=${CMake_TEST_FindRuby_RBENV}
+3
View File
@@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 4.0)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
+116
View File
@@ -0,0 +1,116 @@
set(CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH OFF)
set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH OFF)
set(CMAKE_FIND_USE_CMAKE_SYSTEM_PATH OFF)
set(CMAKE_FIND_FRAMEWORK NEVER)
# FIXME: Avoid unchecked construction of TCLTK_POSSIBLE_BIN_PATHS
# and TCLTK_POSSIBLE_LIB_PATHS. Fix FindTclsh and FindTCL later.
set(CMAKE_IGNORE_PATH /bin /lib)
function(check_layout name)
cmake_parse_arguments(PARSE_ARGV 1 arg ""
"ARCH;TCL_LIBRARY;TK_LIBRARY;INCLUDE_PATH" "PREFIXES;SUFFIXES;FILES")
set(prefix "${CMAKE_CURRENT_BINARY_DIR}/${name}")
file(REMOVE_RECURSE "${prefix}")
foreach(f IN LISTS arg_FILES)
get_filename_component(dir "${prefix}/${f}" DIRECTORY)
file(MAKE_DIRECTORY "${dir}")
file(WRITE "${prefix}/${f}" "")
endforeach()
set(CMAKE_FIND_LIBRARY_PREFIXES "${arg_PREFIXES}")
set(CMAKE_FIND_LIBRARY_SUFFIXES "${arg_SUFFIXES}")
set(CMAKE_LIBRARY_ARCHITECTURE "${arg_ARCH}")
set(CMAKE_PREFIX_PATH "${prefix}")
# Empty skips the host tclsh/wish search, and FindTclsh running tclsh
set(TCL_TCLSH "")
set(TK_WISH "")
find_package(TCL QUIET)
set(TCL_INCLUDE_PATH_expect "${arg_INCLUDE_PATH}")
set(TK_INCLUDE_PATH_expect "${arg_INCLUDE_PATH}")
set(TCL_LIBRARY_expect "${arg_TCL_LIBRARY}")
set(TK_LIBRARY_expect "${arg_TK_LIBRARY}")
foreach(var IN ITEMS TCL_LIBRARY TK_LIBRARY TCL_INCLUDE_PATH TK_INCLUDE_PATH)
if(NOT "${${var}}" STREQUAL "${prefix}/${${var}_expect}")
message(SEND_ERROR "${name}: ${var} is\n ${${var}}\n"
"but expected\n ${prefix}/${${var}_expect}")
endif()
unset(${var} CACHE)
endforeach()
endfunction()
check_layout(Tk9-nmake
PREFIXES "" SUFFIXES .lib
FILES include/tcl.h include/tk.h lib/tcl90.lib lib/tcl9tk90.lib
TCL_LIBRARY lib/tcl90.lib TK_LIBRARY lib/tcl9tk90.lib INCLUDE_PATH include
)
check_layout(Tk9-mingw
PREFIXES lib "" SUFFIXES .dll.a .a .lib
FILES include/tcl.h include/tk.h lib/libtcl90.dll.a lib/libtcl9tk90.dll.a
TCL_LIBRARY lib/libtcl90.dll.a TK_LIBRARY lib/libtcl9tk90.dll.a
INCLUDE_PATH include
)
check_layout(Tk9-unix
PREFIXES lib SUFFIXES .so
FILES include/tcl.h include/tk.h lib/libtcl9.0.so lib/libtcl9tk9.0.so
TCL_LIBRARY lib/libtcl9.0.so TK_LIBRARY lib/libtcl9tk9.0.so
INCLUDE_PATH include
)
check_layout(Tk9-homebrew
PREFIXES lib SUFFIXES .dylib
FILES include/tcl-tk/tcl.h include/tcl-tk/tk.h
lib/libtcl9.0.dylib lib/libtcl9tk9.0.dylib
TCL_LIBRARY lib/libtcl9.0.dylib TK_LIBRARY lib/libtcl9tk9.0.dylib
INCLUDE_PATH include/tcl-tk
)
check_layout(Tk86-Tk9-nmake
PREFIXES "" SUFFIXES .lib
FILES include/tcl.h include/tk.h lib/tcl86t.lib lib/tk86t.lib
lib/tcl90.lib lib/tcl9tk90.lib
TCL_LIBRARY lib/tcl90.lib TK_LIBRARY lib/tcl9tk90.lib INCLUDE_PATH include
)
check_layout(Tk86-Tk9-unix
PREFIXES lib SUFFIXES .so
FILES include/tcl8.6/tcl.h include/tcl8.6/tk.h
include/tcl9.0/tcl.h include/tcl9.0/tk.h
lib/libtcl8.6.so lib/libtk8.6.so lib/libtcl9.0.so lib/libtcl9tk9.0.so
TCL_LIBRARY lib/libtcl9.0.so TK_LIBRARY lib/libtcl9tk9.0.so
INCLUDE_PATH include/tcl9.0
)
check_layout(Tk86-nmake
PREFIXES "" SUFFIXES .lib
FILES include/tcl.h include/tk.h lib/tcl86t.lib lib/tk86t.lib
TCL_LIBRARY lib/tcl86t.lib TK_LIBRARY lib/tk86t.lib INCLUDE_PATH include
)
check_layout(Tk86-debian
ARCH x86_64-linux-gnu PREFIXES lib SUFFIXES .so
FILES include/tcl8.6/tcl.h include/tcl8.6/tk.h
lib/x86_64-linux-gnu/libtcl8.6.so lib/x86_64-linux-gnu/libtk8.6.so
TCL_LIBRARY lib/x86_64-linux-gnu/libtcl8.6.so
TK_LIBRARY lib/x86_64-linux-gnu/libtk8.6.so
INCLUDE_PATH include/tcl8.6
)
# Distro default links (libtcl.so, libtk.so, include/tcl) still win.
check_layout(Tk86-Tk9-debian
ARCH x86_64-linux-gnu PREFIXES lib SUFFIXES .so
FILES include/tcl/tcl.h include/tcl/tk.h
include/tcl8.6/tcl.h include/tcl8.6/tk.h
include/tcl9.0/tcl.h include/tcl9.0/tk.h
lib/x86_64-linux-gnu/libtcl.so lib/x86_64-linux-gnu/libtk.so
lib/x86_64-linux-gnu/libtcl8.6.so lib/x86_64-linux-gnu/libtk8.6.so
lib/x86_64-linux-gnu/libtcl9.0.so lib/x86_64-linux-gnu/libtcl9tk9.0.so
TCL_LIBRARY lib/x86_64-linux-gnu/libtcl.so
TK_LIBRARY lib/x86_64-linux-gnu/libtk.so
INCLUDE_PATH include/tcl
)
@@ -0,0 +1,3 @@
include(RunCMake)
run_cmake(FindTCLTest)