簡體   English   中英

將具有循環鏈接依賴關系的makefile轉換為CMake

[英]Converting makefile with circular link dependency to CMake

我有多個實現(.c或.cpp文件),可實現同一頭文件的不同功能。 我有用於make的makefile方法,我想用cmake重新實現它。(請注意,我無法更改實現文件或標頭。如果可以的話,我不會按原樣設計和實現該解決方案。)案例來指出我的問題。

head.h:

#ifndef __HEAD__
#define __HEAD__

int foo(float e, float b);
void boo(float *eo, float *eh);
void setup();
int load(int* n);

#endif

impl1.c:

#include "head.h"

void boo(float *eo, float *eh)
{
  *eo = 0.4f;
  *eh = 2.3f;
}

impl2.c:

#include <stdio.h>
#include "head.h"
void setup()
{
  printf("hello!\n");
  int m = 13;
  int* n = &m;
  load(n);
}

impl3.c:

#include "head.h"
int load(int* n)
{
  n = 0;
  return 0;
}

main.cpp:

#include "head.h"
int main()
{
  setup();
  return 0;
}
int foo(float e, float b)
{
  float i, j;
  boo(&i, &j);
  return 4;
}

makefile :(這是構建和鏈接)

# C compiler
CC = g++
CC_FLAGS = -g -O2

main: impl1.o impl2.o impl3.o
    $(CC) $(CC_FLAGS) main.cpp impl1.o impl2.o impl3.o -o main

%.o: %.[ch]
    $(CC) $(CC_FLAGS) $< -c

impl1.o: impl1.c
    $(CC) $(CC_FLAGS) impl1.c -c

impl2.o: impl2.c
    $(CC) $(CC_FLAGS) impl2.c -c

impl3.o: impl3.c
    $(CC) $(CC_FLAGS) impl3.c -c

clean:
    rm -f *.o *~ main *.linkinfo

使用makefile,將執行以下命令:

g++ -g -O2 impl1.c -c
g++ -g -O2 impl2.c -c
g++ -g -O2 impl3.c -c
g++ -g -O2 main.cpp impl1.o impl2.o impl3.o -o main

到目前為止,我使用cmake所做的嘗試:(您可以觀察到我的失敗嘗試已得到評論)

add_executable(${PROJECT_NAME} impl1.c impl2.c impl3.c main.cpp)

# add_library(impl1 OBJECT impl1.c)
# add_library(impl2 OBJECT impl2.c)
# add_library(impl3 OBJECT impl3.c)
# add_executable(${PROJECT_NAME} main.cpp $<TARGET_OBJECTS:impl3> $<TARGET_OBJECTS:impl2> $<TARGET_OBJECTS:impl1>)

# add_library(impl1 STATIC impl1.c)
# add_library(impl2 STATIC impl2.c)
# add_library(impl3 STATIC impl3.c)
# add_executable(main main.cpp)
#
# set(LIBS impl1 impl2 impl3)
#
# target_link_libraries(main ${LIBS} ${LIBS})

# add_library(headextra impl1.c impl2.c impl3.c)
# add_executable(${PROJECT_NAME} main.cpp)
# target_link_libraries(${PROJECT_NAME} headextra)

# add_library(headextra impl1.c impl2.c impl3.c main.cpp)
# add_executable(${PROJECT_NAME} $<TARGET_OBJECTS:headextra>)

該cmake文件成功生成了構建並進行了編譯。 但是在鏈接時出現無法解決的錯誤:

make -f CMakeFiles/cmake_test.dir/build.make CMakeFiles/cmake_test.dir/build
/usr/bin/cc    -o CMakeFiles/cmake_test.dir/impl1.c.o   -c /home/ahmet/Desktop/cmake_test/impl1.c
/usr/bin/cc    -o CMakeFiles/cmake_test.dir/impl2.c.o   -c /home/ahmet/Desktop/cmake_test/impl2.c
/usr/bin/cc    -o CMakeFiles/cmake_test.dir/impl3.c.o   -c /home/ahmet/Desktop/cmake_test/impl3.c
/usr/bin/c++     -o CMakeFiles/cmake_test.dir/main.cpp.o -c /home/ahmet/Desktop/cmake_test/main.cpp
/usr/bin/cmake -E cmake_link_script CMakeFiles/cmake_test.dir/link.txt --verbose=1
/usr/bin/c++      CMakeFiles/cmake_test.dir/impl1.c.o CMakeFiles/cmake_test.dir/impl2.c.o CMakeFiles/cmake_test.dir/impl3.c.o CMakeFiles/cmake_test.dir/main.cpp.o  -o cmake_test -rdynamic 
CMakeFiles/cmake_test.dir/main.cpp.o: In function `main':
main.cpp:(.text+0x5): undefined reference to `setup()'
CMakeFiles/cmake_test.dir/main.cpp.o: In function `foo(float, float)':
main.cpp:(.text+0x31): undefined reference to `boo(float*, float*)'
collect2: error: ld returned 1 exit status
make[2]: *** [cmake_test] Error 1
make[1]: *** [CMakeFiles/cmake_test.dir/all] Error 2
make: *** [all] Error 

我肯定缺少有關cmake構建生成的一些關鍵點。 希望能有所幫助。

即使在舊的Makefile中,這也不起作用,因為您正在混合使用C和C ++。 該問題實際上與您的構建系統無關,並且僅與C和C ++的混合有關。

要解決該問題,請將頭文件更改為:

#ifndef HEAD_H
#define HEAD_H

#ifdef __cplusplus
extern "C" {
#endif

int foo(float e, float b);
void boo(float *eo, float *eh);
void setup();
int load(int* n);

#ifdef __cplusplus
}
#endif

#endif

最大的變化是,在頭文件中,我添加了對__cplusplus宏的檢查,該檢查將由C ++編譯器而不是C編譯器定義。 定義__cplusplus ,我已告訴編譯器將函數聲明視為“ C”聲明,這意味着將不對函數進行名稱處理

問題是,C ++編譯器軋液的函數名,以使函數重載。 這就意味着在編譯為C ++時,例如功能setup的符號有所不同。 extern "C"告訴C ++編譯器不要弄亂名稱。

請參閱此參考資料 ,以獲取有關extern "C"更多信息。

還要注意,我更改了標頭包括防護,因為在所有作用域中,所有帶有雙引號下划線的符號都保留用於“實現”(即編譯器和標准庫)。 參見例如這個古老的問答

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM