set_include_path和get_include_path用法详解

本文详细介绍了PHP中set_include_path函数的作用及用法,包括如何动态修改PHP.ini中的include_path,简化include和require语句的路径配置,并展示了如何正确设置多路径的示例。

现在我总结一下吧:

首先set_include_path这个函数呢,是在脚本里动态地对PHP.ini中include_path进行修改的。

而这个include_path呢,它可以针对下面的include和require的路径范围进行限定,或者说是预定义一下。

就好像:

如果我们没有设置这个值,可能我们需要写一些完全的路径:

   <?php
      include("123/test1.php");
      include("123/test2.php");
      include("123/test3.php");
      require("123/test4.php");
      require("123/test5.php");
   ?>

来引入很多外部文件,但是如果我们设置了set_include_path(“123/”),我们就可以用下面这段代码代替。

   <?php
      set_include_path("123/");
      include("test1.php");
      include("test2.php");
      include("test3.php");
      require("test4.php");
      require("test5.php");
   ?>

因为呢,当执行include或者require操作时,就会去include_path指定的路径去查找要引入的文件,虽然我现在不知道这样会不会在性能上有所优化,但是可以肯定的是,可以节省一部分代码。呵呵~

那么刚开始的时候,我以为它加不加都是一样的没什么不同,是因为我只包含了一个本文件夹下的文件。

后来,终于发现了其中的玄机!可恨的是,网上居然没有一篇像我这样的文章….都是同一篇文章转来转去的。

那么这个函数它不仅可以定义一个文件夹,我们可以定义很多文件夹。如下所示,我要写一个初始化函数:

function initialize()
{
    set_include_path(get_include_path().PATH_SEPARATOR . "core/");
    set_include_path(get_include_path().PATH_SEPARATOR . "app/");
    set_include_path(get_include_path().PATH_SEPARATOR . "admin/");
    set_include_path(get_include_path().PATH_SEPARATOR . "lib/");
    set_include_path(get_include_path().PATH_SEPARATOR . "include/");
    set_include_path(get_include_path().PATH_SEPARATOR."data/");
    set_include_path(get_include_path().PATH_SEPARATOR."cache/");
}

这样它的路径就成了:

.;C:\php5\pear;core/;app/;admin/;lib/;include/;data/;cache/

哎,我们发现前面还有个.;C:\php5\pear;这到底是怎么回事呢,其实我们如果什么也不写直接先输出一下include_path的默认值,就会发现它就是

.;C:\php5\pear;

它可以允许随便去一个引入文件。

如果再加载了许多文件夹的话,我们直接写文件名就可以了!

但是正如我最开始那个问题一样,为什么我们公司的代码和人家的就不一样呢,原来,如果我就写一个set_include_path(dirname(__FILE__));
然后去引入其他文件夹的文件,就会报错,说在我指定的这个文件夹内找不到。

首先,我们先用另外一种方法输出一下:

   <?php
       set_include_path(dirname(__FILE__));
       $include_value = ini_get('include_path');
       echo $include_value;
   ?>

结果是:D:\AppServ\www
我如果去www下找test4.php这个文件,则没有报错

  include("test4.php");

但是我如果去找
include(“test1.php”);
就会报错:

  Warning: include() [function.include]: Failed opening 'test1.php' for inclusion (include_path='D:\AppServ\www') in D:\AppServ\www\test.php on line 6

而且我们还发现.;C:\php5\pear;已经被替换掉了。所以我们在使用的时候,如果不是仅在一个文件夹下引入文件,我们就需要在前面加上

get_include_path().PATH_SEPARATOR .

解释一下:

get_include_path()是获取当前include_path的默认值

PATH_SEPARATOR 是个常量,是include的路径分界符合,在window上是;在unix和Linux上是:

最后,我还要说一下,其实我们也可以通过另外一种方法:即最原始的:

       ini_set('include_path', '目录名'); 

另外,需要注意的两点就是:

如果在指定的目录下找不到所要求包含的文件,而在当前页面目录下正好存在这个名称的文件时,则默认引入当前目录下的该文件。

当指定了多个目录为 include_path ,而所要求包含的文件在这几个目录都有相同名称的文件存在时,php选择使用设定 include_path 时排位居前的目录下的文件。

<think>我们正在讨论CMake中的`target_include_directories`命令,特别是以下用法: `target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ...)` 根据引用内容,我们可以分解如下: 1. **基本语法**(引用[4]): ```cmake target_include_directories(target_name [SYSTEM] [BEFORE] <INTERFACE|PUBLIC|PRIVATE> [items1...] [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...]) ``` 其中: - `target_name`:目标名称,由`add_executable`或`add_library`定义。 - 关键字`PRIVATE`、`PUBLIC`、`INTERFACE`指定了包含路径的传播范围。 2. **命令作用**(引用[2]): 该命令用于指定编译目标时的头文件搜索路径。 3. **访问说明符的含义**(引用[2]): - `PRIVATE`:包含目录仅用于当前目标(不传播给依赖此目标的其他目标)。 - `PUBLIC`:包含目录既用于当前目标,也传播给依赖此目标的其他目标。 - `INTERFACE`:包含目录不用于当前目标,但传播给依赖此目标的其他目标。 4. **变量`${CMAKE_PROJECT_NAME}`**: 这是CMake内置变量,表示在`project()`命令中设置的当前项目名称。通常,在同一个项目中,我们会创建同名的可执行文件或库,但这不是必须的。因此,`${CMAKE_PROJECT_NAME}`作为目标名使用时,需要确保已经通过`add_executable`或`add_library`定义了同名目标。 现在,针对用户的问题:`target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ...)`的使用方法含义。 ### 使用方法 1. 确保已经定义了目标:在使用该命令之前,必须已经通过`add_executable`或`add_library`创建了名为`${CMAKE_PROJECT_NAME}`的目标。 2. 指定包含目录:在`PRIVATE`关键字后面添加需要包含的目录(可以是绝对路径或相对路径,相对路径是相对于当前CMakeLists.txt文件所在目录)。 示例: ```cmake cmake_minimum_required(VERSION 3.10) project(MyProject) # 此时${CMAKE_PROJECT_NAME}为"MyProject" # 定义可执行目标,名字与项目名相同 add_executable(${CMAKE_PROJECT_NAME} main.cpp) # 添加私有包含目录(仅MyProject目标使用,不传播给其他目标) target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/src ) ``` ### 含义 - `PRIVATE`表示后面指定的包含目录仅用于编译目标`${CMAKE_PROJECT_NAME}`(即可执行文件或库本身)。 - 这些包含目录不会传递给任何链接(使用)此目标的其他目标(即不会出现在其他目标的`INTERFACE_INCLUDE_DIRECTORIES`属性中)。 ### 常见问题与处理方法 1. **目标未定义错误**: 如果`${CMAKE_PROJECT_NAME}`对应的目标尚未创建(即没有调用`add_executable`或`add_library`),则会报错。 **解决**:确保在调用`target_include_directories`之前已经创建目标。 2. **变量未设置或为空**: 若`${CMAKE_PROJECT_NAME}`未定义(通常不会,因为`project()`会设置它),则命令无效。 **解决**:检查`project()`命令是否已调用。 3. **路径问题**: 相对路径是相对于当前`CMakeLists.txt`文件。若路径不存在,编译时可能出现头文件找不到的错误。 **解决**:使用`${CMAKE_CURRENT_SOURCE_DIR}`构建绝对路径。 4. **作用理解错误**: 如果期望其他目标(如链接了此库的目标)也能使用这些包含目录,则需要使用`PUBLIC`或`INTERFACE`。 **示例**:库目标需要将其公共头文件目录设置为`PUBLIC`或`INTERFACE`。 ### 属性查看 引用[3]展示了如何查看目标的包含目录属性: ```cmake get_property(dirs_interface TARGET main PROPERTY INTERFACE_INCLUDE_DIRECTORIES) get_property(dirs_normal TARGET main PROPERTY INCLUDE_DIRECTORIES) ``` - `INTERFACE_INCLUDE_DIRECTORIES`:接口包含目录(即`PUBLIC``INTERFACE`指定的目录)。 - `INCLUDE_DIRECTORIES`:私有包含目录(即`PRIVATE``PUBLIC`指定的目录,但不包括`INTERFACE`)。 ### 总结 `target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ...)`用于为当前项目的主目标(可执行文件或库)添加私有的头文件包含路径。这些路径仅用于编译该目标自身,不会传递给其他目标。 §§相关问题§§ 1. `target_include_directories`中的`PUBLIC``INTERFACE`有什么区别? 2. 在CMake中如何正确设置库的头文件路径以供使用者包含? 3. 为什么有时使用`target_include_directories`后仍出现头文件找不到的错误? 4. 如何查看一个目标(target)的包含目录属性?[^3] </think>### CMake `target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ...)` 详解 #### 一、核心语法解析 ```cmake target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE [路径1] [路径2] ... ) ``` 1. **${CMAKE_PROJECT_NAME}** CMake 内置变量,表示在 `project()` 命令中定义的项目名称。例如: ```cmake project(MyApp) # 此时 ${CMAKE_PROJECT_NAME} = "MyApp" ``` 2. **PRIVATE 关键字** 作用域限定符,表示包含路径: - ✅ **当前目标可见**:仅作用于 `${CMAKE_PROJECT_NAME}` 目标的编译过程 - ❌ **不传递给依赖者**:依赖此目标的其他目标无法访问这些路径[^2] 3. **路径参数** 支持绝对路径或相对路径(相对当前 `CMakeLists.txt`),常用变量: ```cmake ${CMAKE_CURRENT_SOURCE_DIR} # 当前CMakeLists.txt所在目录 ${PROJECT_SOURCE_DIR} # 项目根目录 ``` #### 二、典型使用场景 **场景1:添加私有头文件路径** ```cmake add_executable(MyApp main.cpp) target_include_directories(MyApp PRIVATE src/ # 相对路径 ${CMAKE_CURRENT_SOURCE_DIR}/include # 绝对路径 ) ``` → `main.cpp` 可包含 `#include "src/utils.h"` **场景2:避免污染全局包含路径** ```cmake # 错误:全局添加(影响所有目标) include_directories(include) # 正确:限定作用域 target_include_directories(MyApp PRIVATE include) ``` #### 三、PRIVATE vs PUBLIC vs INTERFACE | 关键字 | 当前目标可用 | 依赖目标可用 | 典型场景 | |-----------|-------------|-------------|----------------------------| | `PRIVATE` | ✅ | ❌ | 内部实现专用头文件 | | `PUBLIC` | ✅ | ✅ | 库的公开API头文件 | | `INTERFACE`| ❌ | ✅ | 头文件库(无实现文件) | **示例对比**: ```cmake # 库目标 add_library(MyLib lib.cpp) target_include_directories(MyLib PRIVATE src/internal # 仅库内部使用 PUBLIC include # 库用户也需要此路径 ) # 可执行文件(依赖库) add_executable(MyApp app.cpp) target_link_libraries(MyApp PRIVATE MyLib) # 自动获得 include/ 路径,但无法访问 src/internal ``` #### 四、常见错误处理 1. **目标未定义错误** ```bash CMake Error: Cannot specify include directories for target "MyApp" which is not built by this project. ``` **原因**:`target_include_directories()` 在 `add_executable/add_library` 之前调用 **修复**:确保先创建目标: ```cmake add_executable(${CMAKE_PROJECT_NAME} main.cpp) # 先定义目标 target_include_directories(...) # 后设置属性 ``` 2. **路径不存在警告** ```bash CMake Warning: Cannot find directory: /wrong/path ``` **修复**:使用 `if(IS_DIRECTORY)` 验证: ```cmake if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include) target_include_directories(...) endif() ``` 3. **作用域混淆导致的头文件缺失** **现象**:依赖目标编译时找不到头文件 **解决**:库的公共头文件应使用 `PUBLIC`: ```cmake # 库定义 target_include_directories(MyLib PUBLIC include) # ✅ 用户可访问 # 错误做法 target_include_directories(MyLib PRIVATE include) # ❌ 用户不可见 ``` #### 五、最佳实践 1. **优先使用目标级命令** 替代全局 `include_directories()`,避免路径污染 2. **路径变量标准化** ```cmake set(MYAPP_INC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/third_party ) target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ${MYAPP_INC_DIRS}) ``` 3. **结合生成器表达式** 区分不同构建配置: ```cmake target_include_directories(MyApp PRIVATE $<$<CONFIG:Debug>:${DEBUG_INC_DIR}> $<$<CONFIG:Release>:${RELEASE_INC_DIR}> ) ``` > **调试提示**:查看最终包含路径 > ```bash > cmake --build build/ --target MyApp -v # 查看详细编译命令 > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值