Skip to content

Commit 8bbeed0

Browse files
[libc] [startup] add cmake function to merge separated crt1 objects (#75413)
As part of startup refactoring, this patch adds a function to merge multiple objects into a single relocatable object: cc -r obj1.o obj2.o -o obj.o A relocatable object is an object file that is not fully linked into an executable or a shared library. It is an intermediate file format that can be passed into the linker. A crt object can have arch-specific code and arch-agnostic code. To reduce code cohesion, the implementation is splitted into multiple units. As a result, we need to merge them into a single relocatable object.
1 parent e4f4022 commit 8bbeed0

File tree

1 file changed

+60
-11
lines changed

1 file changed

+60
-11
lines changed

libc/startup/linux/CMakeLists.txt

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,62 @@
1+
# This function merges multiple objects into a single relocatable object
2+
# cc -r obj1.o obj2.o -o obj.o
3+
# A relocatable object is an object file that is not fully linked into an
4+
# executable or a shared library. It is an intermediate file format that can
5+
# be passed into the linker.
6+
# A crt object has arch-specific code and arch-agnostic code. To reduce code
7+
# duplication, the implementation is split into multiple units. As a result,
8+
# we need to merge them into a single relocatable object.
9+
# See also: https://maskray.me/blog/2022-11-21-relocatable-linking
10+
function(merge_relocatable_object name)
11+
set(obj_list "")
12+
set(fq_link_libraries "")
13+
get_fq_deps_list(fq_dep_list ${ARGN})
14+
foreach(target IN LISTS fq_dep_list)
15+
list(APPEND obj_list "$<TARGET_OBJECTS:${target}>")
16+
get_target_property(libs ${target} DEPS)
17+
list(APPEND fq_link_libraries "${libs}")
18+
endforeach()
19+
list(REMOVE_DUPLICATES obj_list)
20+
list(REMOVE_DUPLICATES fq_link_libraries)
21+
get_fq_target_name(${name} fq_name)
22+
set(relocatable_target "${fq_name}.__relocatable__")
23+
add_executable(
24+
${relocatable_target}
25+
${obj_list}
26+
)
27+
# Pass -r to the driver is much cleaner than passing -Wl,-r: the compiler knows it is
28+
# a relocatable linking and will not pass other irrelevant flags to the linker.
29+
target_link_options(${relocatable_target} PRIVATE -r)
30+
set_target_properties(
31+
${relocatable_target}
32+
PROPERTIES
33+
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
34+
OUTPUT_NAME ${name}.o
35+
)
36+
add_library(${fq_name} OBJECT IMPORTED GLOBAL)
37+
add_dependencies(${fq_name} ${relocatable_target})
38+
target_link_libraries(${fq_name} INTERFACE ${fq_link_libraries})
39+
set_target_properties(
40+
${fq_name}
41+
PROPERTIES
42+
LINKER_LANGUAGE CXX
43+
IMPORTED_OBJECTS ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
44+
TARGET_TYPE ${OBJECT_LIBRARY_TARGET_TYPE}
45+
DEPS "${fq_link_libraries}"
46+
)
47+
endfunction()
48+
149
function(add_startup_object name)
250
cmake_parse_arguments(
351
"ADD_STARTUP_OBJECT"
4-
"ALIAS" # Option argument
52+
"" # Option argument
553
"SRC" # Single value arguments
654
"DEPENDS;COMPILE_OPTIONS" # Multi value arguments
755
${ARGN}
856
)
957

1058
get_fq_target_name(${name} fq_target_name)
11-
if(ADD_STARTUP_OBJECT_ALIAS)
12-
get_fq_deps_list(fq_dep_list ${ADD_STARTUP_OBJECT_DEPENDS})
13-
add_library(${fq_target_name} ALIAS ${fq_dep_list})
14-
return()
15-
endif()
16-
59+
1760
add_object_library(
1861
${name}
1962
SRCS ${ADD_STARTUP_OBJECT_SRC}
@@ -27,18 +70,24 @@ function(add_startup_object name)
2770
)
2871
endfunction()
2972

73+
check_cxx_compiler_flag("-r" LIBC_LINKER_SUPPORTS_RELOCATABLE)
74+
75+
if(NOT LIBC_LINKER_SUPPORTS_RELOCATABLE)
76+
message(STATUS "Skipping startup for target architecture ${LIBC_TARGET_ARCHITECTURE}: linker does not support -r")
77+
return()
78+
endif()
79+
3080
if(NOT (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_ARCHITECTURE}))
3181
message(STATUS "Skipping startup for target architecture ${LIBC_TARGET_ARCHITECTURE}")
3282
return()
3383
endif()
3484

3585
add_subdirectory(${LIBC_TARGET_ARCHITECTURE})
3686

37-
add_startup_object(
87+
# TODO: factor out crt1 into multiple objects
88+
merge_relocatable_object(
3889
crt1
39-
ALIAS
40-
DEPENDS
41-
.${LIBC_TARGET_ARCHITECTURE}.crt1
90+
.${LIBC_TARGET_ARCHITECTURE}.crt1
4291
)
4392

4493
add_startup_object(

0 commit comments

Comments
 (0)