tk.h 在 /usr/include 中寻找 tcl.h 但 tcl.h 在 /usr/include/tcl 中。我没有写入 tk.h 权限来修复代码

tk.h looks for tcl.h in /usr/include but tcl.h is in /usr/include/tcl. I don't have write tk.h privilege to fix code

我在 macOS BigSur 上通过 VMWare 使用 Ubuntu 20.04.2 LTS。我安装了最新版本的 tcl、tcl-dev、tk 和 tk-dev - 版本 8.6。我想为 Architecture lab project. The source code is from 2016 and located in the self-study handout 编译源代码。编译失败[错误消息详述如下],可能是由于源代码依赖于 tcl8.5 而不是最新版本。安装这些软件包的 8.5 版会解决问题吗?

为了使 GUI 工作,在项目 Makefile 中我需要分配一个变量 [我已经完成] 并更新另外两个以便 gcc 可以找到相关的库 [libtcl.so 和 libtk.so] 和头文件 [tcl.h 和 tk.h].

# ******* variable 1 **********

# Assigning GUIMODE=-DHAS_GUI causes the necessary GUI support code in the simulator sources to be included.
GUIMODE=-DHAS_GUI

# ******* variable 2 **********

# Modify the following line so that gcc can find the libtcl.so and
# libtk.so libraries on your system. You may need to use the -L option
# to tell gcc which directory to look in. Comment this out if you
# don't have Tcl/Tk.

# TKLIBS variable tells gcc where to look for the libtcl.so and libtk.so libraries.
# TKLIBS=-L/usr/lib -ltk -ltcl

# ******* variable 3 **********

# Modify the following line so that gcc can find the tcl.h and tk.h
# header files on your system. Comment this out if you don't have
# Tcl/Tk.

# TKINC variable tells gcc where to find the tcl.h and tk.h header files.
# TKINC=-isystem /usr/include/tcl8.5

##################################################
# You shouldn't need to modify anything below here
##################################################

# Use this rule (make all) to build the Y86-64 tools. The variables you've
# assigned to GUIMODE, TKLIBS, and TKINC will override the values that
# are currently assigned in seq/Makefile and pipe/Makefile.
all:
        (cd misc; make all)
        (cd pipe; make all GUIMODE=$(GUIMODE) TKLIBS="$(TKLIBS)" TKINC="$(TKINC)")
        (cd seq; make all GUIMODE=$(GUIMODE) TKLIBS="$(TKLIBS)" TKINC="$(TKINC)")
        (cd y86-code; make all)

clean:
        rm -f *~ core
        (cd misc; make clean)
        (cd pipe; make clean)
        (cd seq; make clean)
        (cd y86-code; make clean)
        (cd ptest; make clean)

基于

$ locate libtcl.so
/usr/lib/x86_64-linux-gnu/libtcl.so

$ locate libtk.so
/usr/lib/x86_64-linux-gnu/libtk.so

我将 TKLIBS 更新为

TKLIBS=-L/usr/lib/x86_64-linux-gnu -ltk -ltcl

tcl.h 和 tk.h 头文件位于:

$ locate tcl.h
/usr/include/tcl8.6/tcl.h
/usr/include/tcl8.6/tcl-private/generic/tcl.h

$ locate tk.h
/usr/include/tcl8.6/tk.h
/usr/include/tcl8.6/tk-private/generic/tk.h
/And many other folders, but only these two locations also have tcl.h

当我更新 TKINC 到

TKINC=-isystem /usr/include/tcl8.6

我收到以下错误。

az@ubuntu:~/Desktop/archlab-handout/sim$ make clean; make
rm -f *~ core
(cd misc; make clean)
make[1]: Entering directory '/home/az/Desktop/archlab-handout/sim/misc'
rm -f *.o *.yo *.exe yis yas hcl2c mux4 *~ core.* 
rm -f hcl.tab.c hcl.tab.h lex.yy.c yas-grammar.c
make[1]: Leaving directory '/home/az/Desktop/archlab-handout/sim/misc'
(cd pipe; make clean)
make[1]: Entering directory '/home/az/Desktop/archlab-handout/sim/pipe'
rm -f psim pipe-*.c *.o *.exe *~ 
make[1]: Leaving directory '/home/az/Desktop/archlab-handout/sim/pipe'
(cd seq; make clean)
make[1]: Entering directory '/home/az/Desktop/archlab-handout/sim/seq'
rm -f ssim ssim+ seq*-*.c *.o *~ *.exe *.yo *.ys
make[1]: Leaving directory '/home/az/Desktop/archlab-handout/sim/seq'
(cd y86-code; make clean)
make[1]: Entering directory '/home/az/Desktop/archlab-handout/sim/y86-code'
rm -f *.o *.yis *~ *.yo *.pipe *.seq *.seq+ core
make[1]: Leaving directory '/home/az/Desktop/archlab-handout/sim/y86-code'
(cd ptest; make clean)
make[1]: Entering directory '/home/az/Desktop/archlab-handout/sim/ptest'
rm -f *.o *~ *.yo *.ys
make[1]: Leaving directory '/home/az/Desktop/archlab-handout/sim/ptest'
(cd misc; make all)
make[1]: Entering directory '/home/az/Desktop/archlab-handout/sim/misc'
gcc -Wall -O1 -g -c yis.c
gcc -Wall -O1 -g -c isa.c
gcc -Wall -O1 -g yis.o isa.o -o yis
gcc -Wall -O1 -g -c yas.c
flex yas-grammar.lex
mv lex.yy.c yas-grammar.c
gcc -O1 -c yas-grammar.c
gcc -Wall -O1 -g yas-grammar.o yas.o isa.o -lfl -o yas
bison -d hcl.y
flex hcl.lex
gcc -O1 node.c lex.yy.c hcl.tab.c outgen.c -o hcl2c
make[1]: Leaving directory '/home/az/Desktop/archlab-handout/sim/misc'
(cd pipe; make all GUIMODE=-DHAS_GUI TKLIBS="-L/usr/lib/x86_64-linux-gnu -ltk -ltcl" TKINC="-isystem /usr/include/tcl8.6")
make[1]: Entering directory '/home/az/Desktop/archlab-handout/sim/pipe'
# Building the pipe-std.hcl version of PIPE
../misc/hcl2c -n pipe-std.hcl < pipe-std.hcl > pipe-std.c
gcc -Wall -O2 -isystem /usr/include/tcl8.6 -I../misc -DHAS_GUI -o psim psim.c pipe-std.c \
    ../misc/isa.c -L/usr/lib/x86_64-linux-gnu -ltk -ltcl -lm
psim.c: In function ‘simResetCmd’:
psim.c:853:8: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  853 |  interp->result = "No arguments allowed";
      |        ^~
psim.c:861:11: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  861 |     interp->result = stat_name(STAT_AOK);
      |           ^~
psim.c: In function ‘simLoadCodeCmd’:
psim.c:872:8: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  872 |  interp->result = "One argument required";
      |        ^~
psim.c:878:8: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  878 |  interp->result = tcl_msg;
      |        ^~
psim.c:885:11: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  885 |     interp->result = tcl_msg;
      |           ^~
psim.c: In function ‘simLoadDataCmd’:
psim.c:895:11: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  895 |     interp->result = "Not implemented";
      |           ^~
psim.c:901:8: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  901 |  interp->result = "One argument required";
      |        ^~
psim.c:907:8: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  907 |  interp->result = tcl_msg;
      |        ^~
psim.c:911:11: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  911 |     interp->result = tcl_msg;
      |           ^~
psim.c: In function ‘simRunCmd’:
psim.c:925:8: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  925 |  interp->result = "At most one argument allowed";
      |        ^~
psim.c:932:8: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  932 |  interp->result = tcl_msg;
      |        ^~
psim.c:936:11: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  936 |     interp->result = stat_name(status);
      |           ^~
psim.c: In function ‘simModeCmd’:
psim.c:945:8: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  945 |  interp->result = "One argument required";
      |        ^~
psim.c:948:11: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  948 |     interp->result = argv[1];
      |           ^~
psim.c:957:8: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  957 |  interp->result = tcl_msg;
      |        ^~
psim.c: In function ‘signal_register_update’:
psim.c:994:56: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  994 |  fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                        ^~
psim.c: In function ‘create_memory_display’:
psim.c:1005:56: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1005 |  fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                        ^~
psim.c:1020:60: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1020 |      fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                            ^~
psim.c: In function ‘set_memory’:
psim.c:1055:60: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1055 |      fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                            ^~
psim.c: In function ‘show_cc’:
psim.c:1069:56: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1069 |  fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                        ^~
psim.c: In function ‘show_stat’:
psim.c:1081:56: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1081 |  fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                        ^~
psim.c: In function ‘show_cpi’:
psim.c:1096:56: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1096 |  fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                        ^~
psim.c: In function ‘signal_sources’:
psim.c:1110:56: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1110 |  fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                        ^~
psim.c: In function ‘signal_register_clear’:
psim.c:1120:56: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1120 |  fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                        ^~
psim.c: In function ‘report_line’:
psim.c:1134:56: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1134 |  fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                        ^~
psim.c: In function ‘report_pc’:
psim.c:1190:56: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1190 |  fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                        ^~
psim.c: In function ‘report_state’:
psim.c:1204:58: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1204 |  fprintf(stderr, "\tError Message was '%s'\n", sim_interp->result);
      |                                                          ^~
make[1]: *** [Makefile:44: psim] Error 1
make[1]: Leaving directory '/home/az/Desktop/archlab-handout/sim/pipe'
make: *** [Makefile:30: all] Error 2

psim.c 有 1000 多行代码,导致第一个错误的部分在第 853 行:

/******************************************************************************
 *      tcl command definitions
 ******************************************************************************/

/* Implement command versions of the simulation functions */
int simResetCmd(ClientData clientData, Tcl_Interp *interp,
                int argc, char *argv[])
{
    sim_interp = interp;
    if (argc != 1) {
        interp->result = "No arguments allowed";
        return TCL_ERROR;
    }
    sim_reset();
    if (post_load_mem) {
        free_mem(mem);
        mem = copy_mem(post_load_mem);
    }
    interp->result = stat_name(STAT_AOK);
    return TCL_OK;
}

这会不会是 tcl/tk 版本不同造成的?我想知道版本 8.5 是否会像 Makefile 中 TKINC 变量的默认值所暗示的那样有所帮助。

如何安装 8.5 版本并确保 gcc 使用该版本?

谢谢。

直接访问 Tcl_Interp 结构一直是 deprecated。鉴于这是单个源文件 (psim.c),您可能需要对其进行修补以正确使用:

  • Tcl_SetResult(),例如: 将 interp->result = "No arguments allowed"; 更改为 Tcl_SetResult(interp, "No arguments allowed", TCL_STATIC);
  • Tcl_GetStringResult(),例如: 将 fprintf(stderr, "Error Message was '%s'\n", sim_interp->result); 更改为 fprintf(stderr, "Error Message was '%s'\n", Tcl_GetStringResult(sim_interp));

这是向后兼容的。


不推荐,但可行:设置宏

#define USE_INTERP_RESULT

另见 Deprecated Interfaces / Direct access to interp->result