
注意其中的三个要点,特别注意那个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})
- #这是正常的编译目标,假定输出的二进制可执行文件叫my_app
- add_executable (my_app ${SOURCES})
-
- #注意这里添加的对子目录library的依赖
- target_link_libraries(my_app ${MODULE_MQTT})
要特别谨慎在.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静态库的形式。