如何在 C for Windows 中正确链接到库

问题描述 投票:0回答:1

我目前正在尝试 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

你能给我一个解决方案吗?

c windows gcc makefile mingw-w64
1个回答
0
投票

你的变量没有正确分离。

您需要将 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)
    
© www.soinside.com 2019 - 2024. All rights reserved.