使用-gc-sections减小生成文件大小

环境:

  Linux平台:CentOS Linux relase 7.2.1511、GCC_4.8.5-4、cmake version 2.8.11

场景:

  当项目中使用了很多静态库文件(.a),会导致编译生成的文件非常大。其实,这些静态库中的函数,并非所有都有调用,项目只使用了其中一小部分。使用"-gc-sections"参数,将不链接未用的函数,减少文件的大小。

开始:

一、静态库示例(libtest_1.a)

    test_1.cpp

#include <stdio.h>
__attribute__((visibility("default"))) void test_a()
{
    printf("test_a\n");
}
__attribute__((visibility("default"))) void test_b()
{
    printf("test_b\n");
}

二、动态库示例(libtest_2.so)

    test_2.cpp

#include <stdio.h>
void test_a();
void test_b();
__attribute__((visibility("default"))) void test_2()
{
    printf("test_2\n");
    test_a();
    printf("test_2\n");
}
__attribute__((visibility("default"))) void test_2_1()
{
    printf("test_2_1\n");
}

三、可执行程序示例(test_3)

    test_3.cpp

#include <stdio.h>
void test_a();
void test_b();
void test_2();
void test_2_1();
int main()
{
    test_a();
    return 0;
}

四、使用cmake编译生成

project(demo)
cmake_minimum_required(VERSION 2.6)

set(PRJ_VER "0.0.0")
set(ROOT ${PROJECT_SOURCE_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${ROOT}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${ROOT}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${ROOT}/lib)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(CMAKE_VERBOSE_MAKEFILE ON)

set(TEST_1 "test_1")
set(TEST_2 "test_2")
set(TEST_3 "test_3")

#####include_directories#####
include_directories(${ROOT})
#####link_directories#####
link_directories(${ROOT}/lib)

#CMAKE_CXX_FLAGS
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11")
message("CMAKE_CXX_FLAGS = " ${CMAKE_CXX_FLAGS})
#LINK_FLAGS
string(REGEX REPLACE "-rdynamic" "" CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS}")
string(REGEX REPLACE "-rdynamic" "" CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS}")
message("CMAKE_SHARED_LIBRARY_LINK_C_FLAGS = " ${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS})
message("CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS = " ${CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS})

add_library(${TEST_1} STATIC ${ROOT}/test_1.cpp)
set_target_properties(${TEST_1} PROPERTIES COMPILE_FLAGS "-fPIC -ffunction-sections -fdata-sections")

add_library(${TEST_2} SHARED ${ROOT}/test_2.cpp)
target_link_libraries(${TEST_2} LINK_PRIVATE ${TEST_1})
set_target_properties(${TEST_2} PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -ffunction-sections -fdata-sections")
set_target_properties(${TEST_2} PROPERTIES LINK_FLAGS "-Wl,-exclude-libs=ALL,-gc-sections")

add_executable(${TEST_3} ${ROOT}/test_3.cpp)
target_link_libraries(${TEST_3} LINK_PRIVATE ${TEST_1})
set_target_properties(${TEST_3} PROPERTIES LINK_FLAGS "-Wl,-exclude-libs=ALL,-gc-sections")

#####CopyRuntimeFiles#####
add_custom_command(TARGET ${TEST_3} POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:${TEST_1}> ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
    COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:${TEST_2}> ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
    COMMENT "[${TEST_3}] copy runtime files")

    4.1)libtest_1.a使用 "-ffunction-sections -fdata-sections"参数,表示为每一个函数或符号生成sections

  objdump -x libtest_1.a | grep test

    函数test_a和test_b在2个sections(.text._Z6test_av和.text._Z6test_bv)中:

    去掉"-ffunction-sections -fdata-sections"参数编译,函数test_a和test_b在1个sections(.text)中:

     4.2)libtest_2.so使用"-Wl,-gc-sections"参数,表示不链接未用的函数和符号

  objdump -t libtest_2.so | grep test

    libtest_2.so只使用了函数test_a,所以只链接函数test_a,不链接函数test_b

     libtest_2.so去掉"-Wl,-gc-sections"参数编译,函数test_a和test_b都会链接

     4.3)test_3同4.2,这里不再详述

结尾

     注意:使用cmake链接时会自动添加"-rdynamic"参数,会导致"-Wl,-gc-sections"无效,所以需要删除"-rdynamic"参数

#删除LINK_FLAGS中"-rdynamic"参数
string(REGEX REPLACE "-rdynamic" "" CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS}")
string(REGEX REPLACE "-rdynamic" "" CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS}")
message("CMAKE_SHARED_LIBRARY_LINK_C_FLAGS = " ${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS})
message("CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS = " ${CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS})

参考资料

    CMake 2.8.8 Documentation https://cmake.org/cmake/help/v2.8.8/cmake.html

 

posted on 2023-05-12 16:32  dchao  阅读(633)  评论(0编辑  收藏  举报

导航