## 基礎知識
在本文開始之前
可先瀏覽 [Lua 模塊與包-菜鳥教程](http://www.runoob.com/lua/lua-modules-packages.html)
粗略了解下關于 Lua 模塊/包 的基礎知識
特別是 package.path 的相關內容
## 我的研究
在 [VS 調試 Lua](vsdebug.md) 中
得知了可以向 VS 項目中添加 `命令參數`
以達到執行命令行 `$ lua ~/Projects/Lua51/script/main.lua` 類似的效果
但在我研究的過程中
總是需要運行測試不同的 lua 代碼
如果要因此而頻繁去修改 `命令參數` 配置
顯然不合適
因此我把要測試的 lua 代碼文件
在 main.lua 中 require 進來
這樣可不修改 lua 源碼工程的配置
即可執行不同的 lua 文件
## require lua 文件
解壓的 lua 源碼目錄下的 test 目錄
有很多測試用的 lua 腳本代碼
把 test 目錄復制到 `Lua51/script` 目錄下
編輯 `script/main.lua` ,內容如下:
```lua
modules = {
--"test.bisect", --bisection method for solving non-linear equations
--"test.cf", --temperature conversion table (celsius to farenheit)
--"test.echo", --echo command line arguments
--"test.env", --environment variables as automatic global variables
--"test.factorial", --factorial without recursion
--"test.fib", --fibonacci function with cache
--"test.fibfor", --fibonacci numbers with coroutines and generators
--"test.globals", --report global variable usage
--"test.hello", --the first program in every languag
--"test.life", --Conway's Game of Life
--"test.luac", --bare-bones luac
"test.printf", --an implementation of printf
--"test.readonly", --make global variables readonly
--"test.sieve", --the sieve of of Eratosthenes programmed with coroutines
--"test.sort", --two implementations of a sort function
--"test.table", --make table, grouping all data for the same item
--"test.trace-calls", --trace calls
--"test.trace-globals", --trace assigments to global variables
--"test.xd", --hex dump
}
for i, v in ipairs(modules) do
require(v);
end
```
注意,代碼中除了 test.printf 一行,其他都注釋了
此時運行會報如下錯誤:
```text
module 'test.printf' not found:
no field package.preload['test.printf']
no file '.\test\printf.lua'
no file 'X:\Lua51\x64\Debug\lua\test\printf.lua'
no file 'X:\Lua51\x64\Debug\lua\test\printf\init.lua'
no file 'X:\Lua51\x64\Debug\test\printf.lua'
no file 'X:\Lua51\x64\Debug\test\printf\init.lua'
no file '.\test\printf.dll'
no file 'X:\Lua51\x64\Debug\test\printf.dll'
no file 'X:\Lua51\x64\Debug\loadall.dll'
no file '.\test.dll'
no file 'X:\Lua51\x64\Debug\test.dll'
no file 'X:\Lua51\x64\Debug\loadall.dll'
stack traceback:
[C]: in function 'require'
X:\Lua51\script\main.lua:24: in main chunk
[C]: ?
```
此時若在 main.lua 中添加如下代碼運行:
```text
print(package.path);
```
輸出如下:
```text
.\?.lua;X:\Lua51\x64\Debug\lua\?.lua;X:\Lua51\x64\Debug\lua\?\init.lua;X:\Lua51\x64\Debug\?.lua;X:\Lua51\x64\Debug\?\init.lua
```
顯然沒有 `Lua51/script` 目錄
## package.path
從 [Lua 參考手冊](http://www.runoob.com/manual/lua53doc/manual.html#pdf-package.pat) 中得知:
```text
package.path
在啟動時,Lua 用環境變量 LUA_PATH_5_1 或環境變量 LUA_PATH 來初始化這個變量。
或采用 luaconf.h 中的默認路徑。
```
luaconf.h 中有這段代碼:
```c
/*
** In Windows, any exclamation mark ('!') in the path is replaced by the
** path of the directory of the executable file of the current process.
*/
#define LUA_LDIR "!\\lua\\"
#define LUA_CDIR "!\\"
#define LUA_PATH_DEFAULT \
".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua"
```
其中的注釋翻譯如下:
```text
在 Windows 中,路徑中的所有感嘆號('!')都會被替換為當前進程的可執行文件的目錄路徑。
```
`X:\Lua51\x64\Debug` 這個路徑因此而來
那在路徑中 . 所代表的當前路徑是什么路徑?
在 main.lua 中加入以下代碼:
```lua
local f = io.open("./lua_path.tmp", "w");
f:close();
```
在命令行中輸入:
```text
$ cd ~/Desktop/
$ lua ~/Projects/Lua51/script/main.lua
```
會在 `~/Desktop/` 目錄下生成 lua\_path.tmp 文件
如果運行 VS 的 lua 項目
則會在 `X:\Lua51\lua\` 目錄下生成 lua\_path.tmp 文件
推論得出:
```text
路徑中 . 所代表的當前路徑為執行 lua 程序時所在的目錄路徑
```
## 把 script 目錄路徑加入到 package.path
有兩種方法
1. 在 lua 腳本中修改 package.path 字符串
2. 修改 lua 源碼中對 package.path 變量的賦值
我采用的是第一種方法
在 main.lua 文件開頭添加如下代碼即可:
```lua
local info = debug.getinfo(1, "S");
local path = info.short_src;
local dir = string.match(path, "^.*[/\\]");
if dir then
package.path = package.path .. ";" .. dir .. "?.lua";
end
```