1.子目录的CMakeLists文件
注意其中的三个要点,特别注意那个set ....PARENT_SCOPE
那条语句才把子目录里定义的对象让上层目录可见。
#这是子目录的CMakefile, 编译过程中的提示信息
message(STATUS "Enter mqtt dir...")#要点1:这个MODULE_MQTT需要在源代码根目录被引用
set(MODULE_MQTT gpMqtt)#要点2:通过这个set语句。${MODULE_MQTT}这个模块才会被上层应用访问到
set(MODULE_MQTT ${MODULE_MQTT} PARENT_SCOPE)#这个是普通做法,指示当前目录下的所有源代码参与编译add_library.无需逐个文件手工指定
aux_source_directory (. SOURCES_MQTT)#要点3:子目录在要点1被定义为一个子模块,为了参与主目录的工程的编译,它需要被编译为一个动态库或者静态库:动态库:SHARED|静态库:STATIC
add_library(${MODULE_MQTT} STATIC ${SOURCES_MQTT})#这里是方便这个模块访问其它目录下的头文件。
include_directories (${PROJECT_SOURCE_DIR}/../include)
include_directories (${PROJECT_SOURCE_DIR}/../calc)
include_directories (${PROJECT_SOURCE_DIR}/../common)
include_directories (${PROJECT_SOURCE_DIR}/../sensor)
include_directories (${PROJECT_SOURCE_DIR}/../include)
include_directories (${PROJECT_SOURCE_DIR}/../mqtt)
include_directories (${PROJECT_SOURCE_DIR})
2.主工程添加对子工程的代码依赖
#这是正常的编译目标,假定输出的二进制可执行文件叫my_app
add_executable (my_app ${SOURCES})#注意这里添加的对子目录library的依赖
target_link_libraries(my_app ${MODULE_MQTT})
3.结语:
- CMakeLists单目录的语法未给出,这个自行查阅即可。
- 这只是其中的一种多目录代码联合编译的方法。存在其他途径,但是这个够用。
- 可以参照那个暴露子目录的符号定义给上级目录的语法,直接关联源代码,理论上也是可以的。
附录1:FAQ:
要特别谨慎在.so动态库的函数里使用static char[1024].因为.so随时可能从内存中卸载,例如:
//gptimestr(),这个函数用来返回一个时间字符串,它的定义如下: const char *gptimestr(void) {time_t rawtime;struct tm *timeinfo;// 获取当前时间time(&rawtime);timeinfo = localtime(&rawtime);// 获取年、月、日、小时、分钟、秒int year = timeinfo->tm_year + 1900;int month = timeinfo->tm_mon + 1;int day = timeinfo->tm_mday;int hour = timeinfo->tm_hour;int minute = timeinfo->tm_min;int second = timeinfo->tm_sec;static char dumb[128];// 打印结果sprintf(dumb, "%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second);return dumb; }
上面这个函数直接在主工程里使用没有问题,但是一旦在子工程中编译,就会遇到segment fault.调试时,发现返回的static char dumb[128]已经被废弃。
解决方案有两点:
1.在函数中使用静态成员变量避免malloc free在多线程或者类似这种跨.so动态库调用,都会出现问题。
2.可以针对子模块的输出lib,始终采用static静态库的形式。