我正在玩裸机x86,并且遇到了将我的构建从直接makefile移植到cmake的麻烦。
在我的makefile中,我的对象是这样定义的:
LINK_LIST=\
$(LDFLAGS) \
$(ARCHDIR)/crti.o \
$(ARCHDIR)/crtbegin.o \
$(KERNEL_OBJS) \
$(LIBS) \
$(ARCHDIR)/crtend.o \
$(ARCHDIR)/crtn.o \
crtbegin.o和crtend.o是“生成的”,即由我的交叉编译器提供(-print-file-name标志)。 $(LIBS)是-l标志,例如-lgcc等。由于此标志直接传递给链接器,因此顺序是指定的。
我的cmake目标定义如下:
ADD_EXECUTABLE(loader
"${INIT_SRC}"
"${INIT_OBJ}"
"${PLATFORM_SRCS}"
"${ISA_SRCS}"
"${GENERIC_SRCS}"
"${FINI_OBJ}"
"${FINI_SRC}")
INIT_OBJ和FINI_OBJ在源文件属性中将EXTERNAL_OBJECT和GENERATED设置为true。在运行生成的生成文件时查看命令行,我看到所有源文件都按指定的顺序执行,但是init和fini对象位于列表的最后。
这是结果命令行(为简洁起见进行了编辑):
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
-lgcc标志在我的LINK_FLAGS中是显式的,这也是我要更改的地方。
所以我对此有一些疑问:
为什么cmake不使用两个外部对象文件的顺序,而是将其用于编译后的外部文件?
我如何告诉cmake将这些对象与我的来源中的对象一样对待?
我如何获得我在Makefile中拥有的设置的完整副本(目标文件之间带有库标志)
我也确实检查了CMAKE_C_LINK_EXECUTABLE,但是似乎没有足够的粒度/对链接程序参数的控制来实现这一目标。
我正在Ubuntu上使用cmake 3.10.2。
另一个关于cmake的问题(题外):
它不会将.S视为标准程序集文件扩展名。我尝试用LIST(APPEND CMAKE_ASM-ATT_SOURCE_FILE_EXTENSIONS S)
添加它,并且确实添加得很好,但是除非将其更改为.s,否则文件仍不会得到编译。还有其他人遇到过这个问题吗?
谢谢!
答案 0 :(得分:0)
对象crtbegin.o
和crtend.o
可被视为工具链的一部分。如果您决定这样做,则可以设置变量CMAKE_C_LINK_EXECUTABLE
来反映这一特定要求:
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")
此设置应在工具链文件中完成,该文件通过选项cmake
传递到-DCMAKE_TOOLCHAIN=<path/to/toolchain/file>
。
使用这种工具链,您可以在CMakeLists.txt
中简单地编写
ADD_EXECUTABLE(loader ${PLATFORM_SRCS} ${ISA_SRCS} ${GENERIC_SRCS})
使用CMAKE_C_LINK_EXECUTABLE
变量,您还可以放置诸如
-nostdlib -ffreestanding -nostdinc -T linker.ld -lgcc
与工具链也非常相关。
另请参阅此邮件:https://cmake.org/pipermail/cmake/2010-June/037641.html。