关于C#:如何防止在静态库中出现重复的符号?

 2021-04-09 

How to prevent duplicate symbols in static library?

如果创建带有重复符号的静态库,是否可以创建警告或错误?给定下面的示例项目,我可以通过包含-all_load选项在链接期间创建一个错误,但否则似乎无法避免ld在没有任何警告的情况下静默选择第一个符号。

CMakeLists.txt

1
2
3
4
5
6
7
cmake_minimum_required(VERSION 3.8)
project(hello)

set(SOURCE_FILES hello1.cpp hello2.cpp hello.h)
add_library(hellolib ${SOURCE_FILES})
add_executable(hellobin main.cpp)
target_link_libraries(hellobin hellolib)

你好

1
2
3
#pragma once

void hello();

hello1.cpp

1
2
3
4
5
6
#include"hello.h"
#include <iostream>

void hello() {
  std::cout <<"Hello, World!" << std::endl;
}

hello2.cpp

1
2
3
4
5
6
#include"hello.h"
#include <iostream>

void hello() {
  std::cout <<"Goodbye, World!" << std::endl;
}

main.cpp

1
2
3
4
5
#include"hello.h"

int main() {
  hello();
}

如上所述,如果将all_load选项添加到CMakeLists.txt

1
set(CMAKE_EXE_LINKER_FLAGS"${CMAKE_EXE_LINKER_FLAGS} -all_load")

是否有某种方法可以在静态库生成步骤中生成它?

更新

如果我对nm执行以下检查并将自定义命令添加到我的CMakeLists.txt中,则能够使CMake引发错误(尽管它似乎仍然很笨拙):

CMakeLists.txt

1
add_custom_command(TARGET hellolib POST_BUILD COMMAND ${CMAKE_SOURCE_DIR}/check_build.sh ${CMAKE_CURRENT_BINARY_DIR}/libhellolib.a)

check_build.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env bash
if ["$#" -ne 1 ];
then
    echo"err: usage ./check_build.sh <lib file>"
    exit 1
fi

MAX_SYM=`nm $1 | perl -ne 'print if / T .+$/' | sort | uniq -c | sort -n | tail -n 1 | awk '{print $1}'`

if ["$MAX_SYM" -ne"1" ]
then
    echo"Saw duplicate symbol."
    exit 1
fi


这实际上不是一种很好的编码方式。如果确实需要使用相同的名称,则可以inline该函数。但是,请真正考虑使用名称空间正确地做到这一点。

将hello()放在不同的名称空间中可以防止意外的双重实现。我不认为您想要做的事对于单独的编译单元来说是可行的,这些编译单元只能看到部分代码。

无论如何我要为此付2美分。


我认为角色不是gcc的责任。那是ld的责任。所以这很有意义。

gcc在静态库中检测重复的符号/功能