I have multiple implementations(.c or .cpp files) that implements different function of the same header file. I have the makefile approach for build and I want to reimplement it with cmake.(Note that I cannot change the implementation files or headers. If I could, I wouldn't design and implement the solution as it is.) I have prepared smaller case to point out my issue.
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:(this is building and linking)
# 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
With the makefile, these commands are executed:
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
What I have tried with cmake up to now:(you can observe my failed attempts as commented)
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>)
This cmake file successfully generates the build and also compiles. But when linking I got errors that I couldn't resolve:
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
I am definitely missing some key point about cmake build generation. Hopefully, some can help.