TL;DR: Is there a way to specify custom link order when CMake managed dependencies seems not enough?
I'm developing a toy OS for fun and having trouble linking in the GCC crt* files responsible for calling global constructors. I read that objects must be linked in this exact order: crti.o crtbegin.o mykernel.o crtend.o crtn.o, but don't know how to enforce that exact order using CMake.
I'm aware that by target_link_libraries(), CMake automatically manages the link order, but it does not guarantee any specific order, namely put crtbegin.o before and crtend.o after.
Currently I'm using the work-around below and it becomes infeasible if you try to link in more libraries. This is my temporary solution:
add_library(crti OBJECT path/to/crti.s)
add_library(crtn OBJECT path/to/crtn.s)
# the actual target
add_executable(awesome_kernel
myAwesomeKernel.cc
)
add_dependencies(myAwesomeKernel crti crtn)
set_property(TARGET myAwesomeKernel APPEND PROPERTY LINK_DEPENDS path/to/crti.s)
set_property(TARGET myAwesomeKernel APPEND PROPERTY LINK_DEPENDS path/to/crtn.s)
set_property(TARGET myAwesomeKernel APPEND PROPERTY LINK_DEPENDS path/to/linker_script)
# custom link line
set(CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS} -T path/to/linker_script CMakeFiles/crti.dir/crti.s.obj ${CRTBEGIN_OBJ} <OBJECTS> ${CRTEND_OBJ} CMakeFiles/crtn.dir/crtn.s.obj -o myAwesomeKernel")
set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS} -T path/to/linker_script CMakeFiles/crti.dir/crti.s.obj ${CRTBEGIN_OBJ} <OBJECTS> ${CRTEND_OBJ} CMakeFiles/crtn.dir/crtn.s.obj -o myAwesomeKernel")
However, it's awkward and unable to link other libraries to myAwesomeKernel without compromising the desired link line. (Yes, you could use target_link_libraries() but it left you without the ability to put your programs between crtbegin.o and crtend.o)
Aside: something bothers me..
- How to get rid of hard-coded
CMakeFiles/crti.dir/crti.s.obj? Generator expression (to get target file) is not supported insidesetcommand. - In the custom link line, how does
<OBJECTS>work? Why does it get expanded to target executable?