# Directly invoke the linker

**URL:** https://discourse.cmake.org/t/directly-invoke-the-linker/433
**Category:** Code
**Created:** [December 23, 2019, 9:16pm UTC](https://discourse.cmake.org/t/directly-invoke-the-linker/433 "2019-12-23T21:16:40Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![Acsor](https://discourse.cmake.org/user_avatar/discourse.cmake.org/acsor/32/263_2.png) [@Acsor](https://discourse.cmake.org/u/Acsor)
#### Post date: [December 23, 2019, 9:16pm UTC](https://discourse.cmake.org/t/directly-invoke-the-linker/433/1 "2019-12-23T21:16:40Z")

</div>

I am setting up a cross-compiling C project targeting two micro architectures, inspired by ARM and MIPS. Without loss of generality, I’ll focus on the micro ARM architecture, where the compile instructions I was given are

```auto
arm-none-eabi-gcc <COMPILE_FLAGS> -o hello.o hello.c
arm-none-eabi-gcc <COMPILE_FLAGS> -o termprint.o termprint.c
arm-none-eabi-gcc <COMPILE_FLAGS> -o crtso.o ./uarm/crtso.s
arm-none-eabi-gcc <COMPILE_FLAGS> -o libuarm.o ./uarm/libuarm.s
arm-none-eabi-ld <LINK_FLAGS> -o kernel.uarm hello.o termprint.o crtso.o libuarm.o

```

I have tried to reproduce these instructions with CMake in the following snippet

```cmake
# Project include, source and library dirs for uarm-related files
set(BKA_UARM_INC ${PROJECT_SOURCE_DIR}/${BKA_INC}/uarm)
set(BKA_UARM_SRC ${PROJECT_SOURCE_DIR}/${BKA_SRC}/uarm)

set(CFLAGS_UARM -mcpu=arm7tdmi)
set(LDFLAGS_UARM "-G 0 -nostdlib -T ${BKA_UARM_SRC}/elf32ltsarm.h.uarmcore.x")

add_compile_options(${CFLAGS_UARM})

add_library(libuarm OBJECT ${BKA_UARM_SRC}/libuarm.s)
add_library(crtso OBJECT ${BKA_UARM_SRC}/crtso.s)

target_include_directories(libuarm PRIVATE ${BKA_UARM_INC})

add_executable(kernel.uarm ${BKA_SRC}/phase0.c)
target_link_libraries(kernel.uarm crtso libuarm io)
set_property(TARGET kernel.uarm PROPERTY LINK_FLAGS ${LDFLAGS_UARM})

```

but they fail rather badly. Indeed, by choosing `make` as the build-system, I do

```bash
$ make VERBOSE=1 kernel.uarm

```

and get

```auto
[80%] Linking C executable kernel.uarm
/usr/bin/cmake -E cmake_link_script CMakeFiles/kernel.uarm.dir/link.txt --verbose=3
/usr/local/bin/arm-none-eabi-gcc -rdynamic -G 0 -nostdlib -T /home/acsor/Software/BiKaya/src/uarm/elf32ltsarm.h.uarmcore.x CMakeFiles/kernel.uarm.dir/src/phase0.c.o CMakeFiles/crtso.dir/src/uarm/crtso.s.o CMakeFiles/libuarm.dir/src/uarm/libuarm.s.o CMakeFiles/io.dir/src/io.c.o -o kernel.uarm
arm-linux-gnu-gcc: error: 0: No such file or directory
arm-linux-gnu-gcc: error: unrecognized command line option ‘-G’

```

This obviously is due to CMake running the compiler prior to linking, which does not recognize the `-G` option. My real intention here though is to _completely_ skip the `arm-linux-gnu-gcc` invocation, and simply feed the linker likeso

```bash
arm-none-eabi-ld <LINK_FLAGS> -o kernel.uarm hello.o termprint.o crtso.o libuarm.o

```

Can I redefine the compile steps in some way? If not, any other way of properly compiling and linking my execuables will be very appreciated.

---

<div class="post-metadata">

### Author: ![kyle.edwards](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/k/65b543/32.png) [@kyle.edwards](https://discourse.cmake.org/u/kyle.edwards)
#### Post date: [December 23, 2019, 9:20pm UTC](https://discourse.cmake.org/t/directly-invoke-the-linker/433/2 "2019-12-23T21:20:16Z")

</div>

Use the `-Wl` option of GCC. Example:

```cmake
set(LDFLAGS_UARM "-Wl,-G,0,-nostdlib,-T,${BKA_UARM_SRC}/elf32ltsarm.h.uarmcore.x")

```

Edit: simplified by removing duplicate `-Wl` options

---

<div class="post-metadata">

### Author: ![marc.chevrier](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/ecb155/32.png) [@marc.chevrier](https://discourse.cmake.org/u/marc.chevrier)
#### Post date: [December 23, 2019, 10:01pm UTC](https://discourse.cmake.org/t/directly-invoke-the-linker/433/3 "2019-12-23T22:01:00Z")

</div>

Use preferably `target_link_options` which supports advanced capabilties (genex and “LINKER:” prefix). So we have:

```cmake
target_link_options (kernel.uarm PRIVATE "LINKER:-G,0,-nostdlib,-${BKA_UARM_SRC}/elf32ltsarm.h.uarmcore.x")

```

---

<div class="post-metadata">

### Author: ![Acsor](https://discourse.cmake.org/user_avatar/discourse.cmake.org/acsor/32/263_2.png) [@Acsor](https://discourse.cmake.org/u/Acsor)
#### Post date: [December 23, 2019, 10:59pm UTC](https://discourse.cmake.org/t/directly-invoke-the-linker/433/4 "2019-12-23T22:59:55Z")

</div>

Both the previous solutions give rise to a fresh new error – and it’s exactly the same

```bash
$ make VERBOSE=1 kernel.uarm
...
/usr/bin/cmake -E cmake_link_script CMakeFiles/kernel.uarm.dir/link.txt --verbose=1
/usr/local/bin/arm-none-eabi-gcc -rdynamic "-Wl,-G,0,-nostdlib,-T /home/acsor/Software/BiKaya/src/uarm/elf32ltsarm.h.uarmcore.x" CMakeFiles/kernel.uarm.dir/src/phase0.c.o CMakeFiles/crtso.dir/src/uarm/crtso.s.o CMakeFiles/libuarm.dir/src/uarm/libuarm.s.o CMakeFiles/io.dir/src/io.c.o -o kernel.uarm
/usr/bin/arm-linux-gnu-ld: cannot find crt1.o: No such file or directory
/usr/bin/arm-linux-gnu-ld: cannot find crti.o: No such file or directory
...

```

> [@marc.chevrier](#):
>
> Use preferably `target_link_options` which supports advanced capabilties (genex and “LINKER:” prefix). So we have:

I wish I could do that, but I want to support at least up to version `3.7.2` which doesn’t come with `target_link_options()`.

---

<div class="post-metadata">

### Author: ![Acsor](https://discourse.cmake.org/user_avatar/discourse.cmake.org/acsor/32/263_2.png) [@Acsor](https://discourse.cmake.org/u/Acsor)
#### Post date: [December 23, 2019, 11:05pm UTC](https://discourse.cmake.org/t/directly-invoke-the-linker/433/5 "2019-12-23T23:05:05Z")

</div>

Just to mention it, one solution I can quite work with is the following. One small flaw is that relies on capabilities only recently introduced, so I can’t use with on some lab. computers running CMake `3.7.2`.

```cmake
add_custom_target(
	kernel.uarm
	DEPENDS crtso libuarm io phase0
	COMMAND ${CMAKE_C_LINKER} ${LDFLAGS_UARM}
	$<TARGET_OBJECTS:crtso> $<TARGET_OBJECTS:libuarm>
	$<TARGET_OBJECTS:io> $<TARGET_OBJECTS:phase0>
	-o kernel.uarm
)

```

---

<div class="post-metadata">

### Author: ![Acsor](https://discourse.cmake.org/user_avatar/discourse.cmake.org/acsor/32/263_2.png) [@Acsor](https://discourse.cmake.org/u/Acsor)
#### Post date: [December 25, 2019, 10:35pm UTC](https://discourse.cmake.org/t/directly-invoke-the-linker/433/6 "2019-12-25T22:35:41Z")

</div>

Update: despite profused efforts, it appears the link process is still looking for the standard C library.

I updated the `uarm.cmake` file likeso

```cmake
# Project include, source and library dirs for uarm-related files
set(BKA_UARM_INC ${PROJECT_SOURCE_DIR}/${BKA_INC}/uarm)
set(BKA_UARM_SRC ${PROJECT_SOURCE_DIR}/${BKA_SRC}/uarm)

set(CFLAGS_UARM -nostdlib -O0 -mcpu=arm7tdmi)
set(LDFLAGS_UARM "-Wl,-G,0,-nostdlib,-T,${BKA_UARM_SRC}/elf32ltsarm.h.uarmcore.x")
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")

add_executable(
    kernel.uarm
    ${BKA_SRC}/phase0.c ${BKA_UARM_SRC}/libuarm.s ${BKA_UARM_SRC}/crtso.s ${BKA_SRC}/io.c
)
target_include_directories(kernel.uarm PRIVATE ${BKA_UARM_INC})
set_property(TARGET kernel.uarm PROPERTY COMPILE_OPTIONS ${CFLAGS_UARM})
set_property(TARGET kernel.uarm PROPERTY LINK_FLAGS ${LDFLAGS_UARM})

```

and tried to run with

```bash
$ make VERBOSE=1 kernel.uarm
...
/usr/bin/arm-none-eabi-gcc -Wl,-G,0,-nostdlib,-T,/home/students/acsor/08574-Sistemi-Operativi/BiKaya/src/uarm/elf32ltsarm.h.uarmcore.x CMakeFiles/kernel.uarm.dir/src/phase0.c.o CMakeFiles/kernel.uarm.dir/src/uarm/libuarm.s.o CMakeFiles/kernel.uarm.dir/src/uarm/crtso.s.o CMakeFiles/kernel.uarm.dir/src/io.c.o -o kernel.uarm
/usr/lib/gcc/arm-none-eabi/5.4.1/../../../arm-none-eabi/lib/libc.a(lib_a-exit.o): In function `exit':
/build/newlib-XAuz1P/newlib-2.4.0.20160527/build/arm-none-eabi/newlib/libc/stdlib/../../../../../newlib/libc/stdlib/exit.c:70: undefined reference to `_exit'
...

```

---

<div class="post-metadata">

### Author: ![kyle.edwards](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/k/65b543/32.png) [@kyle.edwards](https://discourse.cmake.org/u/kyle.edwards)
#### Post date: [December 26, 2019, 3:53pm UTC](https://discourse.cmake.org/t/directly-invoke-the-linker/433/7 "2019-12-26T15:53:53Z")

</div>

Maybe try passing `-nostdlib` to GCC itself rather than to the linker? So then you would have:

```cmake
set(LDFLAGS_UARM "-nostdlib -Wl,-G,0,-T,${BKA_UARM_SRC}/elf32ltsarm.h.uarmcore.x")

```

---

<div class="post-metadata">

### Author: ![Acsor](https://discourse.cmake.org/user_avatar/discourse.cmake.org/acsor/32/263_2.png) [@Acsor](https://discourse.cmake.org/u/Acsor)
#### Post date: [December 26, 2019, 5:35pm UTC](https://discourse.cmake.org/t/directly-invoke-the-linker/433/8 "2019-12-26T17:35:25Z")

</div>

Love you! It works flawlessly, but only on the micro ARM architecture.
