CMAKE三日谈-第二谈compile和link属性

CMAKE三日谈-第二谈compile和link属性

我的理解,来自自己的测试得出,不要指望通过我的文章来获取芝士.

target_compile_options
target_compile_options(<target> [BEFORE]
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])

假如:target是foo

1.BEFORE这个属性是指在编译这个foo,在编译foo之前添加好,
foo编译的时候就会存在了;必须指定

2.后边的INTERFACE|PUBLIC|PRIVATE属性的作用和其他target的属性类型相同:
PUBLIC|PRIVATE ->会应用在foo的编译属性(compile_options)上,
INTERFACE|PUBLIC ->会应用在foo的接口编译属性(INTERFACE_COMPILE_OPTIONS)上,
之前搞不清这个概念,后来做了个实验:

practice:

env:

  • Android
  • CMake

1.现在包一个日志库,静态编译
CMakeLists.txt文件

project(tools)
file(GLOB SRC_UTILS ${PROJECT_SOURCE_DIR}/*.cpp)
add_library(${PROJECT_NAME} STATIC ${SRC_UTILS})
target_include_directories(${PROJECT_NAME}
        INTERFACE  $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/>  $<INSTALL_INTERFACE:include>
        )
target_compile_options(${PROJECT_NAME}
        BEFORE
        PRIVATE -DLOG_TAG="TOOLS")
message(STATUS "当前目录:${CMAKE_CURRENT_SOURCE_DIR}")

tools.cpp文件

#include "tools.h"
void faklog(std::string str) {
    unsigned int max_len = 4096;
    unsigned int str_len = str.length();
    for (int i = 0; i <= str_len / max_len; ++i) {
        unsigned int end = i * max_len + max_len;
        LOGD("%s", str.substr(i * max_len, end > str_len ? str_len : end).c_str());
    }
}

tools.h文件

#include <android/log.h>

#define LOGD(...)   __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define LOGI(...)   __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGV(...)   __android_log_print(ANDROID_LOG_VERBOSE,LOG_TAG,__VA_ARGS__)
#define LOGE(...)   __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

2.现在创建一个binary工程引用这个工程:

CMakeLists.txt文件

project(helloworld )

set(SRC_LIST hello.cpp)
add_executable(${PROJECT_NAME} ${SRC_LIST})
target_link_libraries(${PROJECT_NAME} tools log)
target_compile_options(${PROJECT_NAME}
        BEFORE
        PRIVATE -DLOG_TAG="HELLO")

hello.cpp文件


#include <stdio.h>
#include <unistd.h>
#include <android/log.h>
#include "tools.h"

#define MYLOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)

int main() {
    do {
        MYLOGD("Hello world!");
        LOGD("Hello world!");
        printf("hello world!\n");
        sleep(5);///sleep 1s;
    } while (1);
    return 0;
}

3.实验结果:
target_compile_options 注意这里的属性全部为PRIVATE,
结果为

11-28 06:08:02.740 18186-18186/? D/HELLO: Hello world! from binary 
11-28 06:08:02.740 18186-18186/? D/HELLO: Hello world! from static lib 

看到LOG_TAG都是来自binary

重新修改静态库的PRIVATE为PUBLIC—>

11-28 06:38:17.900 12479-12479/? D/TOOLS: Hello world! from binary 
11-28 06:38:17.900 12479-12479/? D/TOOLS: Hello world! from static lib 

看到来自于静态库的Definetion
再次修改静态库为INTERFACE,会得到这个错误

cpp\tools\tools.cpp:86:9: error: use of undeclared identifier 'LOG_TAG'

现在改动binary的PRIVATE为PUBLIC

cpp\tools\tools.cpp:86:9: error: use of undeclared identifier 'LOG_TAG'

剩下两种组合方式均为错误;
于是在官方的MailList

Hopefully the explanation that follows helps clarify what PRIVATE, PUBLIC
and INTERFACE mean and do. From my understanding of things, I think there
may have been some subtle inaccuracies in some of the discussions so far,
so hopefully the following is helpful and if I've got something wrong, then
by all means please point out the inaccuracies.


   - When A links in B as *PRIVATE*, it is saying that A uses B in its
   implementation, but B is not used in any part of A's public API. Any code
   that makes calls into A would not need to refer directly to anything from
   B. An example of this could be a networking library A which can be built to
   use one of a number of different SSL libraries internally (which B
   represents). A presents a unified interface for client code which does not
   reference any of the internal SSL data structures or functions. Client code
   would have no idea what SSL implementation (B) is being used by A, nor does
   that client code need to care.
   - When A links in B as *INTERFACE*, it is saying that A does not use B
   in its implementation, but B is used in A's public API. Code that calls
   into A may need to refer to things from B in order to make such calls. One
   example of this is an interface library which simply forwards calls along
   to another library but doesn't actually reference the objects on the way
   through other than by a pointer or reference. Another example is where A is
   defined in CMake as an interface library, meaning it has no actual
   implementation itself, it is effectively just a collection of other
   libraries (I'm probably over-simplifying here, but you get the picture).
   - When A links in B as *PUBLIC*, it is essentially a combination of
   PRIVATE and INTERFACE. It says that A uses B in its implementation and B is
   also used in A's public API.

这个PRIVATE|PUBLIC|INTERFACE 是当前目标的定义域的问题:
当A使用PRIVATE去link B的PRIVATE时候使用的是自己的LOG_TAG而不是link第三方库的->因此是HELLO
当A使用PRIVATE去link B的PUBLIC时候使用的是TOOL的LOG_TAG而不是link第三方库的->因此是TOOL

这样就解释了上边LOG_TAG定义域的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值