Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cmake: Link order of external (generated) and compiled objects, and libs

Tags:

cmake

I'm playing around with bare-metal x86 and I've hit a snag porting my build from straight-up makefiles to cmake.

In my makefile my objects are defined like this:

LINK_LIST=\
$(LDFLAGS) \
$(ARCHDIR)/crti.o \
$(ARCHDIR)/crtbegin.o \
$(KERNEL_OBJS) \
$(LIBS) \
$(ARCHDIR)/crtend.o \
$(ARCHDIR)/crtn.o \

crtbegin.o and crtend.o are 'generated', that is, provided by my cross-compiler (-print-file-name flag). $(LIBS) are -l flags, like -lgcc, etc. Since this is passed directly to the linker the order is as specified.

My cmake target is defines as follows:

ADD_EXECUTABLE(loader 
    "${INIT_SRC}"
    "${INIT_OBJ}"
    "${PLATFORM_SRCS}"
    "${ISA_SRCS}"
    "${GENERIC_SRCS}"
    "${FINI_OBJ}"
    "${FINI_SRC}")

INIT_OBJ and FINI_OBJ have EXTERNAL_OBJECT and GENERATED set to true in source file properties. Looking at the command line when running the generated makefile I see that all source files are in the order specified, but init and fini objects are last in the list.

Here is the resulting command line (edited for brevity):

i686-elf-gcc -nostdlib -ffreestanding -nostdinc -T linker.ld -lgcc crti.s.obj boot.s.obj loader.c.obj crtn.s.obj crtbegin.o crtend.o -o loader

The -lgcc flag is explicit in my LINK_FLAGS, which is also something I would like to change.

So I have a few questions regarding this:

  1. Why isn't cmake using the order for the two external object files, but IS using it for the compiled ones?

  2. How can I tell cmake to treat these objects the same as the ones coming from my sources?

  3. How could I get a complete clone of the setup I have in my Makefile (with the library flags between my object files)

I did also check out CMAKE_C_LINK_EXECUTABLE as well, but it doesn't seem to have enough granularity/control over the linker params to achieve this.

I'm using cmake 3.10.2 on ubuntu.

And another (off-topic) question about cmake:

It doesn't treat .S as a standard assembly file extension. I tried adding it with LIST(APPEND CMAKE_ASM-ATT_SOURCE_FILE_EXTENSIONS S), and it does add it just fine, however the files still aren't getting compiled unless I change it to .s. Has anyone else had this issue?

Thanks!

like image 604
mike john harry Avatar asked Nov 30 '25 00:11

mike john harry


1 Answers

Objects crtbegin.o and crtend.o, which has specific requirement about position in the link command, may be treated as a part of toolchain. If you decide that, then you can set the variable CMAKE_C_LINK_EXECUTABLE to reflect this specific:

SET(ARCHDIR "<...>")
# Object 'crtbegin.o' will be linked before all other objects and libraries.
# Object 'crtend.o' will be linked after all other objects and libraries.
SET(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> 
    <LINK_FLAGS>
    ${ARCHDIR}/crtbegin.o
    <OBJECTS> -o <TARGET> <LINK_LIBRARIES>
    ${ARCHDIR}/crtend.o")

This setting should be done in the toolchain file, which is passed to cmake with option -DCMAKE_TOOLCHAIN=<path/to/toolchain/file>.

With such toolchain, in the CMakeLists.txt you may simply write

ADD_EXECUTABLE(loader ${PLATFORM_SRCS} ${ISA_SRCS} ${GENERIC_SRCS})

Using CMAKE_C_LINK_EXECUTABLE variable you may also position options such as

-nostdlib -ffreestanding -nostdinc -T linker.ld -lgcc

which are very toolchain-related too.

See also this mailing: https://cmake.org/pipermail/cmake/2010-June/037641.html.

like image 91
Tsyvarev Avatar answered Dec 01 '25 17:12

Tsyvarev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!