如何防止静态库中的重复符号?

时间:2018-05-28 08:14:34

标签: c++ gcc cmake ld

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

的CMakeLists.txt

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)

hello.h

#pragma once

void hello();

hello1.cpp

#include "hello.h"
#include <iostream>

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

hello2.cpp

#include "hello.h"
#include <iostream>

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

的main.cpp

#include "hello.h"

int main() {
  hello();
}

如上所述,如果我将all_load选项添加到CMakeLists.txt,我可能会产生问题:

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

有没有办法在静态库生成步骤中生成它?

更新

如果我使用nm执行以下检查并向我的CMakeLists.txt添加自定义命令(虽然它看起来仍然很糟糕),我可以导致CMake抛出错误:

的CMakeLists.txt

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

check_build.sh

#!/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

2 个答案:

答案 0 :(得分:1)

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

将hello()放在不同的命名空间中可以防止意外的双重实现。我不认为你想要做的事情可以通过单独的编译单元来实现,它们只能看到部分代码。

无论如何我的2美分。

答案 1 :(得分:0)

我认为这个角色不是gcc的责任。这是ld的责任。所以这是有道理的。

gcc detect duplicate symbols/functions in static libraries