gcc 如何在C for Windows中正确链接到库[复制]

fgw7neuy  于 5个月前  发布在  Windows
关注(0)|答案(1)|浏览(61)

此问题在此处已有答案

Why does the order in which libraries are linked sometimes cause errors in GCC?(10个答案)
13小时前关闭
我目前正在尝试Windows下的C编程。我有Windows 11,我在VS Code上编写代码,我已经安装了MinGW并将其正确添加到PATH中。问题是我无法将我的程序链接到libiphlapiws2_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.aws2_32.a位于C:\MinGW\x86_64-w64-mingw32\lib中,头文件位于C:\MinGW\include
你能给我一个解决方案吗?

pgccezyw

pgccezyw1#

你的变量没有被正确分离。
你需要把 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-llinker 选项。你不应该把它们放在同一个变量中,因为你不需要把编译器标志传递给链接器,你肯定不想把链接器标志传递给编译器。
但是你看到的链接错误的主要直接问题是你必须把库(-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)

相关问题