CMake - Link 项目以正确的顺序包含 C 运行时对象文件
CMake - Link project with C runtime object files in correct order
有 C 运行时/启动文件:crt0.o
、crti.o
、crtbegin.o
… crtend.o
、crtn.o
.
crtbegin.o
和 crtend.o
由工具链 (GCC) 提供
crt0.o
、crti.o
和crtn.o
是我自己实现的
项目范围。
该项目是关于 运行 i686 裸机上的可执行文件,因此没有 OS。
问题出在最终可执行文件的 linking 中 - 项目目标文件与上述所有 C 运行时文件 linked 的顺序很重要。
我的构建系统是 CMake,我使用 target_sources
命令来定义可执行文件使用的源文件(编译然后 linked 在一起):
set( BARE_METAL app.bin )
add_executable( ${BARE_METAL} "" )
target_sources( ${BARE_METAL}
PRIVATE
boot.s # contains symbols analogical to crt0.s
crti.s
crtn.s
a.cpp
b.cpp
# … other files go here
)
target_link_options( ${BARE_METAL}
PUBLIC
-t linker.ld
-nostdlib
-nostartfiles
)
target_link_libraries( ${BARE_METAL}
PUBLIC
support
)
问题是 GCC 没有 link 使用 crtbegin.o
和 crtend.o
,即使它可以在我的工具链中找到:
toolchain/i686-elf/lib/gcc/i686-elf/10.0.1/crtbegin.o
toolchain/i686-elf/lib/gcc/i686-elf/10.0.1/crtend.o
你能告诉我如何从 CMake 以正确的顺序调用带有所有必需参数的 linker 吗?我希望 link 命令类似于
./i686-elf-ld -t linker.ld -nostdlib -nostartfiles boot.o crti.o crtbegin.o a.o b.o -libsupport.a crtend.o crtn.o
请注意C运行时文件的顺序。我已经简化了所有文件的目录结构,但关键点应该在这里。
非常感谢任何愿意帮助我的人……马丁
更新:
我试图同时调查更多,等待任何类型的建议,有前途的方法似乎是使用 CMAKE_CXX_LINK_EXECUTABLE
为 linking 定义项目特定的构建规则。
我的项目使用了在 root/main project() 语句之前设置的工具链文件。在子项目中,我设置了 CMAKE_CXX_LINK_EXECUTABLE
并且它似乎对其他子项目没有影响。这就是为什么我称之为有前途的原因,尽管整个事情还没有奏效。
我的计划是从三个项目特定的 C 运行时文件 crt0.o
、crti.o
和 crtn.o
中创建一个对象库,以将它们从 <OBJECTS>
中删除,使该项目依赖于此对象库,但在 link 构建规则中手动管理运行时文件。
你觉得这样能顺利结束吗?我会post有结果了...
感谢@KamilCuk,我已经成功做到了 运行。这是我做的解决方案(供任何试图解决相同问题的人使用)
project( Bare_Metal LANGUAGES CXX C ASM )
set( BARE_METAL app.bin )
set( BARE_METAL_CRTS app-crts )
add_library( ${BARE_METAL_CRTS} OBJECT
boot.s # contains symbols analogical to crt0.s
crti.s
crtn.s
)
add_executable( ${BARE_METAL} "" )
target_sources( ${BARE_METAL}
PRIVATE
a.cpp
b.cpp
# … other files go here
)
target_link_options( ${BARE_METAL}
PUBLIC
-t linker.ld
-nostdlib
-nostartfiles
)
target_link_libraries( ${BARE_METAL}
PUBLIC
support
)
# This ensures the boot.o crti.o, crtn.o to be build prior to BARE_METAL target
add_dependencies( ${BARE_METAL} ${BARE_METAL_CRTS} )
# Ask GCC to get the full path name of crtbegin. and crtend.o
execute_process( COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=crtbegin.o OUTPUT_VARIABLE CRTBEGIN_O OUTPUT_STRIP_TRAILING_WHITESPACE )
execute_process( COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=crtend.o OUTPUT_VARIABLE CRTEND_O OUTPUT_STRIP_TRAILING_WHITESPACE)
# Set linker executable to be used - navigate to the toolchain used (might be setup in toolchain file)
set( BARE_METAL_LINKER ${BARE_METAL_TOOLCHAIN_ROOT}/bin/${CMAKE_TARGET_PROCESSOR}-elf-ld )
set( CMAKE_CXX_LINK_EXECUTABLE "${BARE_METAL_LINKER} <CMAKE_C_LINK_FLAGS> <FLAGS> <LINK_FLAGS> boot.obj crti.obj ${REVOLTA_CRTBEGIN} <OBJECTS> -o <TARGET> <LINK_LIBRARIES> ${REVOLTA_CRTEND} crtn.obj" )
请记住上面的代码不是复制粘贴的解决方案,而是完整的,可以用作 guide/inspiration 来做这些事情:)
有 C 运行时/启动文件:crt0.o
、crti.o
、crtbegin.o
… crtend.o
、crtn.o
.
crtbegin.o
和crtend.o
由工具链 (GCC) 提供crt0.o
、crti.o
和crtn.o
是我自己实现的 项目范围。
该项目是关于 运行 i686 裸机上的可执行文件,因此没有 OS。
问题出在最终可执行文件的 linking 中 - 项目目标文件与上述所有 C 运行时文件 linked 的顺序很重要。
我的构建系统是 CMake,我使用 target_sources
命令来定义可执行文件使用的源文件(编译然后 linked 在一起):
set( BARE_METAL app.bin )
add_executable( ${BARE_METAL} "" )
target_sources( ${BARE_METAL}
PRIVATE
boot.s # contains symbols analogical to crt0.s
crti.s
crtn.s
a.cpp
b.cpp
# … other files go here
)
target_link_options( ${BARE_METAL}
PUBLIC
-t linker.ld
-nostdlib
-nostartfiles
)
target_link_libraries( ${BARE_METAL}
PUBLIC
support
)
问题是 GCC 没有 link 使用 crtbegin.o
和 crtend.o
,即使它可以在我的工具链中找到:
toolchain/i686-elf/lib/gcc/i686-elf/10.0.1/crtbegin.o
toolchain/i686-elf/lib/gcc/i686-elf/10.0.1/crtend.o
你能告诉我如何从 CMake 以正确的顺序调用带有所有必需参数的 linker 吗?我希望 link 命令类似于
./i686-elf-ld -t linker.ld -nostdlib -nostartfiles boot.o crti.o crtbegin.o a.o b.o -libsupport.a crtend.o crtn.o
请注意C运行时文件的顺序。我已经简化了所有文件的目录结构,但关键点应该在这里。
非常感谢任何愿意帮助我的人……马丁
更新:
我试图同时调查更多,等待任何类型的建议,有前途的方法似乎是使用 CMAKE_CXX_LINK_EXECUTABLE
为 linking 定义项目特定的构建规则。
我的项目使用了在 root/main project() 语句之前设置的工具链文件。在子项目中,我设置了 CMAKE_CXX_LINK_EXECUTABLE
并且它似乎对其他子项目没有影响。这就是为什么我称之为有前途的原因,尽管整个事情还没有奏效。
我的计划是从三个项目特定的 C 运行时文件 crt0.o
、crti.o
和 crtn.o
中创建一个对象库,以将它们从 <OBJECTS>
中删除,使该项目依赖于此对象库,但在 link 构建规则中手动管理运行时文件。
你觉得这样能顺利结束吗?我会post有结果了...
感谢@KamilCuk,我已经成功做到了 运行。这是我做的解决方案(供任何试图解决相同问题的人使用)
project( Bare_Metal LANGUAGES CXX C ASM )
set( BARE_METAL app.bin )
set( BARE_METAL_CRTS app-crts )
add_library( ${BARE_METAL_CRTS} OBJECT
boot.s # contains symbols analogical to crt0.s
crti.s
crtn.s
)
add_executable( ${BARE_METAL} "" )
target_sources( ${BARE_METAL}
PRIVATE
a.cpp
b.cpp
# … other files go here
)
target_link_options( ${BARE_METAL}
PUBLIC
-t linker.ld
-nostdlib
-nostartfiles
)
target_link_libraries( ${BARE_METAL}
PUBLIC
support
)
# This ensures the boot.o crti.o, crtn.o to be build prior to BARE_METAL target
add_dependencies( ${BARE_METAL} ${BARE_METAL_CRTS} )
# Ask GCC to get the full path name of crtbegin. and crtend.o
execute_process( COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=crtbegin.o OUTPUT_VARIABLE CRTBEGIN_O OUTPUT_STRIP_TRAILING_WHITESPACE )
execute_process( COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=crtend.o OUTPUT_VARIABLE CRTEND_O OUTPUT_STRIP_TRAILING_WHITESPACE)
# Set linker executable to be used - navigate to the toolchain used (might be setup in toolchain file)
set( BARE_METAL_LINKER ${BARE_METAL_TOOLCHAIN_ROOT}/bin/${CMAKE_TARGET_PROCESSOR}-elf-ld )
set( CMAKE_CXX_LINK_EXECUTABLE "${BARE_METAL_LINKER} <CMAKE_C_LINK_FLAGS> <FLAGS> <LINK_FLAGS> boot.obj crti.obj ${REVOLTA_CRTBEGIN} <OBJECTS> -o <TARGET> <LINK_LIBRARIES> ${REVOLTA_CRTEND} crtn.obj" )
请记住上面的代码不是复制粘贴的解决方案,而是完整的,可以用作 guide/inspiration 来做这些事情:)