我目前正在尝试 Windows 的 C 编程。我有 Windows 11,我在 VS Code 上编码,并且我已经安装了 MinGW 并将其正确添加到 PATH 中。问题是我无法将我的程序链接到
libiphlapi
和 ws2_32
库。
这是我的工作环境:
tree /F
D:.
│ Makefile
│
├───.vscode
│ settings.json
│
├───build
├───include
│ windows_backup_scheduler.h
│
├───obj
│ hwid.o
│ main.o
│
└───src
hwid.c
main.c
生成文件:
BUILD_DIR := build
INCLUDE_DIR := include
OBJ_DIR := obj
SRC_DIR := src
NAME := windows_backup_scheduler.exe
CC := gcc
CFLAGS := -m64 -fPIE -Wall -Wextra -Werror -pedantic -g3
LFLAGS := -I$(INCLUDE_DIR) -I"C:\MinGW\include" -L"C:\MinGW\x86_64-w64-mingw32\lib" -liphlpapi -lws2_32 -static-libgcc
SRC_FILES := $(wildcard $(SRC_DIR)/*.c)
OBJ_FILES := $(patsubst $(SRC_DIR)/%.c, $(OBJ_DIR)/%.o, $(SRC_FILES))
TARGET := $(BUILD_DIR)/$(NAME)
all: $(TARGET)
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) $(LFLAGS) -c $< -o $@
$(TARGET): $(OBJ_FILES)
$(CC) $(CFLAGS) $(LFLAGS) -o $@ $^
clean:
@del /Q $(OBJ_DIR)\*.o
fclean: clean
@del /Q $(BUILD_DIR)\$(NAME)
re: fclean all
windows_backup_scheduler.h
#ifndef WINDOWS_BACKUP_SCHEDULER_H
#define WINDOWS_BACKUP_SCHEDULER_H
#ifndef NULL
#define NULL (void *)0;
#endif
#include <stdio.h>
#include <tchar.h>
#include <winsock2.h>
#include <iphlpapi.h>
#include <windows.h>
char *GetMACAddress(void);
#endif
main.c
#include <windows_backup_scheduler.h>
int main(void)
{
printf("MAC %s\n", GetMACAddress());
return (0);
}
hwid.c
#include <windows_backup_scheduler.h>
char *GetMACAddress(void)
{
IP_ADAPTER_INFO* AdapterInfo = NULL;
ULONG ulBufLen = 0;
DWORD dwStatus = 0;
char* macAddr = NULL;
if (GetAdaptersInfo(AdapterInfo, &ulBufLen) == ERROR_BUFFER_OVERFLOW) {
if ((AdapterInfo = malloc(ulBufLen)) == NULL) {
return (NULL);
}
}
if ((dwStatus = GetAdaptersInfo(AdapterInfo, &ulBufLen)) != ERROR_SUCCESS) {
free(AdapterInfo);
return (NULL);
}
if ((macAddr = (char*)malloc(18)) == NULL) {
free(AdapterInfo);
return (NULL);
}
snprintf(macAddr, 18, "%02X-%02X-%02X-%02X-%02X-%02X",
AdapterInfo[0].Address[0], AdapterInfo[0].Address[1],
AdapterInfo[0].Address[2], AdapterInfo[0].Address[3],
AdapterInfo[0].Address[4], AdapterInfo[0].Address[5]);
free(AdapterInfo);
return (macAddr);
}
当我尝试编译时,我得到这个:
D:\WMP\Training\Windows_Backup_Scheduler>make re
Unable to find D:\WMP\Training\Windows_Backup_Scheduler\build\windows_backup_scheduler.exe
gcc -m64 -fPIE -Wall -Wextra -Werror -pedantic -g3 -Iinclude -I"C:\MinGW\include" -L"C:\MinGW\x86_64-w64-mingw32\lib" -liphlpapi -lws2_32 -static-libgcc -c src/hwid.c -o obj/hwid.o
gcc -m64 -fPIE -Wall -Wextra -Werror -pedantic -g3 -Iinclude -I"C:\MinGW\include" -L"C:\MinGW\x86_64-w64-mingw32\lib" -liphlpapi -lws2_32 -static-libgcc -c src/main.c -o obj/main.o
gcc -m64 -fPIE -Wall -Wextra -Werror -pedantic -g3 -Iinclude -I"C:\MinGW\include" -L"C:\MinGW\x86_64-w64-mingw32\lib" -liphlpapi -lws2_32 -static-libgcc -o build/windows_backup_scheduler.exe obj/hwid.o obj/main.o
c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: obj/hwid.o: in function `GetMACAddress':
D:\WMP\Training\Windows_Backup_Scheduler/src/hwid.c:10: undefined reference to `GetAdaptersInfo'
c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: D:\WMP\Training\Windows_Backup_Scheduler/src/hwid.c:15: undefined reference to `GetAdaptersInfo'
collect2.exe: error: ld returned 1 exit status
make: *** [Makefile:21: build/windows_backup_scheduler.exe] Error 1
VSCode 找到了头文件,
libiphlapi.a
和 ws2_32.a
在 C:\MinGW\x86_64-w64-mingw32\lib
中,头文件在 C:\MinGW\include
中
你能给我一个解决方案吗?
你的变量没有正确分离。
您需要将 compiler 的标志放入一组变量中,并将 linker 的标志放入另一组不同的变量中。举个例子:
LFLAGS := -I$(INCLUDE_DIR) -I"C:\MinGW\include" -L"C:\MinGW\x86_64-w64-mingw32\lib" -liphlpapi -lws2_32 -static-libgcc
这是错误的,因为
-I
是 compiler 选项,而 -L
和 -l
是 linker 选项。您不应该将它们放在同一个变量中,因为您不需要将编译器标志传递给链接器,并且您绝对不想将链接器标志传递给编译器。
但是您在链接错误中看到的主要直接问题是您必须将库 (
-l....
) 放在链接行中的目标文件之后。大多数链接器是“单通道”链接器,这意味着它们仅链接在命令行上处理库时所需的符号,并且链接器在处理目标文件之前不会知道需要哪些符号。
如果您想使用标准 make 变量(当然,如果您不想,则不必这样做),您应该使用:
CC := gcc
CFLAGS := -m64 -fPIE -Wall -Wextra -Werror -pedantic -g3
CPPFLAGS := -I$(INCLUDE_DIR) -I"C:\MinGW\include"
LDFLAGS := -L"C:\MinGW\x86_64-w64-mingw32\lib"
LDLIBS := -liphlpapi -lws2_32 -static-libgcc
然后你会写:
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
$(TARGET): $(OBJ_FILES)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)