Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

關於 option() 有幾個建議和問題 #317

Closed
orzuk-lmj opened this issue Jan 4, 2019 · 18 comments
Closed

關於 option() 有幾個建議和問題 #317

orzuk-lmj opened this issue Jan 4, 2019 · 18 comments

Comments

@orzuk-lmj
Copy link
Contributor

orzuk-lmj commented Jan 4, 2019

  • 語意模糊,很容易混淆的部分,例如說實際作用為檢查XX是否存在,但命名為add_XX 。底下這些非常容易和 add_links 、 add_defines 之類實際有添加內容作用的API 造成語意、學習上的困擾。

    option() 內
        add_cincludes
        add_cxxincludes
        add_ctypes
        add_cxxtypes
        add_cxxtypes
        add_csnippet
        add_cxxsnippet
        add_cxxsnippet
  • 有一種情境,目前的解法有些麻煩。現在打算檢查 pthread 是否存在,若存在則 add_defines() 。但檢查過程的條件稍微有些不同;

    1. 例如在 linux 上需要額外查找 -lpthread 的連結是否成功
    2. 在 android 平台下完全不需要查找連結 -lpthread
    3. 在 orbis / durango 平台下使用pthread會需要查找另一個名字的 link library
    -- 尋找標頭檔,完全OK
    option("search_pthread_header")
        add_cincludes("pthread.h")
        add_defines("GTEST_HAS_PTHREAD=1")
    
    option("search_pthread_linker")
        add_links("pthread")   <--------------------   這裡需要一個可以查找link用的API
  • 現在解法其中一個是暫時切割成多個 option 分別檢查部分內容,但此時麻煩就出在 plat 檢查,而且就沒法用完整條件驗證通過才添加define;另一個解法則是自定義 on_check 可滿足 plat 檢查但稍微有些繁瑣。

  • 當前 target 為 static 或 shared 的時候,分別需要設置不同的 add_options 不確定該怎麼做。而且貌似沒法反向讓 option 知道連接到的 target 是哪一種類型。

  • 簡單來說當前用的比較順手的方式,得自定義 option 的 on_check 然後使用 has_cincludes、has_ctypes
    check_cxsnippets 這種方法

  • 需要 has_links 這種的API,目前暫時使用了 has_flags 不確定是否合適? 因為設置它的 toolname 和 program 實在有些麻煩。

  • 編譯腳本發布前都會對 xmake 下達 -D 來顯示除錯資訊,這時候關注的通常都是自己寫出來的錯誤,但是呼叫 has_cincludes、has_ctypes、check_cxsnippets 只要找不到指定內容,就會打印出一大堆的stack traceback ,即便我呼叫他們的時候已經傳入 { verbose = false} 結果也沒變。

@waruqi
Copy link
Member

waruqi commented Jan 4, 2019

語意模糊,很容易混淆的部分,例如說實際作用為檢查XX是否存在,但命名為add_XX 。底下這些非常容易和 add_links 、 add_defines 之類實際有添加內容作用的API 造成語意、學習上的困擾。

xmake.lua的描述api里面,除了if条件判断存在has_xxx等前缀,对于option/target/rule/task/platform等描述域设置,都只有add_, set_, on_等前缀,表示添加、设置某个配置值到option ...

这块可以看下命名规范:

image

你也可以先看下文档的option描述:https://xmake.io/#/zh/manual?id=optionset_default

image

只有在没有设置set_default()的情况下,option才会去自动检测附加的add xxx所有配置,语义就是:附加所有xxx到option,一起检测,所有条件都满足,启用option,并且附加这些xxx到对应的target

如果设置了set_default(true),则不会去check,所有的add xxx都会直接附加到target

@waruqi
Copy link
Member

waruqi commented Jan 4, 2019

底下這些非常容易和 add_links 、 add_defines 之類實際有添加內容作用的API 造成語意、學習上的困擾。

只要是添加到option的内容,都有可能用于作为检测条件,并不混淆,因为option自身的语义就是:选项配置+选项检测

add_links, add_defines都会参与检测条件设置,通过后附加到对应的target

@waruqi
Copy link
Member

waruqi commented Jan 4, 2019

有一種情境,目前的解法有些麻煩。現在打算檢查 pthread 是否存在,若存在則 add_defines() 。但檢查過程的條件稍微有些不同;

例如在 linux 上需要額外查找 -lpthread 的連結是否成功
在 android 平台下完全不需要查找連結 -lpthread
在 orbis / durango 平台下使用pthread會需要查找另一個名字的 link library
-- 尋找標頭檔,完全OK
option("search_pthread_header")
add_cincludes("pthread.h")
add_defines("GTEST_HAS_PTHREAD=1")

option("search_pthread_linker")
add_links("pthread") <-------------------- 這裡需要一個可以查找link用的API

可以试试

option("pthread")
    add_cincludes("pthread.h")
    add_defines("GTEST_HAS_PTHREAD=1")
    before_check(function (option)
        if is_plat("linux") then
            option:add("links", "pthread") 
        elseif is_plat("durango", "orbis") then
            option:add("links", "other_pthread") 
        end
    end)

不需要拆成多个 option,一个就够了

@orzuk-lmj
Copy link
Contributor Author

底下這些非常容易和 add_links 、 add_defines 之類實際有添加內容作用的API 造成語意、學習上的困擾。

只要是添加到option的内容,都有可能用于作为检测条件,并不混淆,因为option自身的语义就是:选项配置+选项检测

add_links, add_defines都会参与检测条件设置,通过后附加到对应的target

最初接觸xmake的時候,option 內容的 add_includedirs, add_cincludes, add_cxxincludes 困擾我了一段時間,初期閱讀代碼的時候難以分辨 添加的是要給target使用的內容 或是 添加的是準備要拿來檢查的項目 。這部分若是命名為 add_check_cincludes 之類的對一開始學習的人都更好理解。

@waruqi
Copy link
Member

waruqi commented Jan 4, 2019

這部分若是命名為 add_check_cincludes 之類的對一開始學習的人都更好理解。

只要记住,直接add xxx到option的设置,都会参与检测和结果附加就行了,并不难理解,只是文档描述我可能没写详细。

如果按你这样定义法,一个是api名字太长了,另外一个api数量得翻一倍,因为基本上80%的target设置api,例如 set_links add_defines ..等等,都能设置到option中,也都能用于参与检测,翻了一倍的api量,文档手册,我维护更新起来就更繁琐了,而且很冗余。。

能尽量精简,还是精简下。。

如果你想检测条件 和 最后的结果设置 分离,可以这么做:

option("xxx")
    add_defines("xxx")
    add_links("xxxx")
    after_check(function (option)
        if option:enabled() then
             option:add("links", "xxx")  -- 此处的设置,只在检测通过后附加,不参与检测
        end
    end)

@orzuk-lmj
Copy link
Contributor Author

orzuk-lmj commented Jan 4, 2019

可以试试

option("pthread")
    add_cincludes("pthread.h")
    add_defines("GTEST_HAS_PTHREAD=1")
    before_check(function (option)
        if is_plat("linux") then
            option:add("links", "pthread") 
        elseif is_plat("durango", "orbis") then
            option:add("links", "other_pthread") 
        end
    end)

不需要拆成多个 option,一个就够了

現在我的確是用這種使用方法,目前比較困擾的是如果打算查找 -lpthread 或 -lXXXX 是否能通過編譯的這件事(倚賴平台去檢測),預期是如果能通過編譯且標頭的到然後附加條件通過,才會當作option啟用。最後 option 啟用的結果也會被其他地方 config.get() 取用。

@waruqi
Copy link
Member

waruqi commented Jan 4, 2019

現在我的確是用這種使用方法,目前比較困擾的是如果打算查找 -lpthread 或 -lXXXX 是否能通過編譯的這件事(倚賴平台去檢測),預期是如果能通過編譯且標頭的到然後附加條件通過,才會當作option啟用

? 没明白,现在不就是检测通过,才附加的么。。

通过了,config.get("xxx") 就能获取了

@waruqi
Copy link
Member

waruqi commented Jan 4, 2019

當前 target 為 static 或 shared 的時候,分別需要設置不同的 add_options 不確定該怎麼做。而且貌似沒法反向讓 option 知道連接到的 target 是哪一種類型。

这个直接在target设置的时候,区分添加不同的add_options的不就行了

想要反向针对不同target,设置不同的设置,得用rule,你可以在rule里对不同Target添加不同的option,这个不是option改干的事,option仅仅只是配置选项,附带了检测功能而已

@waruqi
Copy link
Member

waruqi commented Jan 4, 2019

需要 has_links 這種的API,目前暫時使用了 has_flags 不確定是否合適? 因為設置它的 toolname 和 program 實在有些麻煩。

直接在option内通过add_links添加就行了

@waruqi
Copy link
Member

waruqi commented Jan 4, 2019

編譯腳本發布前都會對 xmake 下達 -D 來顯示除錯資訊,這時候關注的通常都是自己寫出來的錯誤,但是呼叫 has_cincludes、has_ctypes、check_cxsnippets 只要找不到指定內容,就會打印出一大堆的stack traceback ,即便我呼叫他們的時候已經傳入 { verbose = false} 結果也沒變。

-D 选项原本就不是给用户使用的,这个参数会打印详细的诊断log,包括栈,检测错误信息等,各种详细信息,一般用于用户报障反馈这些信息给我,用来分析和定位xmake的一些问题和bug的

所以,-D主要是给xmake的开发者用的,使用的前提,就是已经完全了解打印的各种log信息,以及如何分析和定位问题。。

所以-D不受verbose = false的干扰,因为就是要尽可能多的获取信息给xmake的开发者,也不需要关注打印的log是否很友好

一般的用户只需要使用 -v 打印比较友好的详细信息就行了。。

@orzuk-lmj
Copy link
Contributor Author

orzuk-lmj commented Jan 4, 2019

現在我的確是用這種使用方法,目前比較困擾的是如果打算查找 -lpthread 或 -lXXXX 是否能通過編譯的這件事(倚賴平台去檢測),預期是如果能通過編譯且標頭的到然後附加條件通過,才會當作option啟用

? 没明白,现在不就是检测通过,才附加的么。。

通过了,config.get("xxx") 就能获取了

我出現問題的代碼大概是:

option("search_pthread")
    on_check(function (option)
        import("lib.detect.has_cincludes")
        import("lib.detect.has_flags")
        
        local header_ok = has_cincludes({"pthread.h"}, {verbose = false})
        if header_ok and not (is_plat("windows") or is_plat("mingw")) then
            if is_plat("linux") then
                local link_ok = has_link( ... )  <=========  這裡會需要能查找 link 是否成功的解決方法
                if link_ok then
                    option:add({links = {"pthread"}})
                end
            elseif is_plat("other") then
                ....
            end
            option:add({defines = {"GTEST_HAS_PTHREAD=1"}})
            option:set_value(true)
        end
    end)

為什麼不直接在option 區域內添加 add_links,是因為:

  • 全平台都會執行查找,很慢。一般狀況下會批次執行編譯,然後光是在windows上面就重複執行數百次的別平台才用的到的查找。這種時候真心只想找平台相關的就好。
  • 大量出現錯誤訊息 stack traceback ,目前不能只關掉這種查找的反饋訊息,因為就是剛好需要 -D 參數去 debug 的狀況下才開的,會開這個也是為了更深入的理解運行流程。結果因為我整個專案都使用這種檢查方法,打印出一大堆屬於option:add_link / add_cincludes 的錯誤訊息。
  • 存在一些特例,我需要在target是 shared 的狀況下在 rule 中設置一些東西,但需要好用的查找link功能

@waruqi
Copy link
Member

waruqi commented Jan 4, 2019

為什麼不直接在option 區域內添加 add_links,是因為:
全平台都會執行查找,很慢

那就放到before_check里面去添加就行了啊,option:add_links("xxx"),然后不去复写on_check,使用默认的option检测机制去检测就行了,就像我刚贴的。。

option("pthread")
    add_cincludes("pthread.h")
    add_defines("GTEST_HAS_PTHREAD=1")
    before_check(function (option)
        if is_plat("linux") then
            option:add("links", "pthread") 
        elseif is_plat("durango", "orbis") then
            option:add("links", "other_pthread") 
        end
    end)

你复写了on_check,那就要自己实现各种检测逻辑了,这样会很繁琐,如果用户需要高度定制化,才需要这么干。

大量出現錯誤訊息 stack traceback ,目前不能只關掉這種查找的反饋訊息,因為就是剛好需要 -D 參數去 debug 的狀況下才開的。結果因為我整個專案都使用這種檢查方法,打印出一大堆訊息。

这个刚已经说明了,无所谓的,就不是给用户看的

@waruqi
Copy link
Member

waruqi commented Jan 4, 2019

存在一些特例,我需要在target是 shared 的狀況下在 rule 中設置一些東西,但需要好用的查找link功能

那你就在定义rule的附近,定义两个带有add_links("xxx")的option,然后在rule里面,通过target kind 区分static/shared,分别添加不同的option就行了

或者你在rule里直接通过check_cxsnippets检测links就行了,这个接口是通用的,includes, defines, types links都能检测

你可以试试

local ok = check_cxsnippets(nil, {links = "pthread"})

代码片段以及其他参数都是可选设置,你可以仅仅用于检测links

如果你还想附加target的所有设置,作为检测条件,只需要

local ok = check_cxsnippets(nil, {links = "pthread", target = target})

@orzuk-lmj
Copy link
Contributor Author

感謝,大致上理解了,之前應該是對 before_check 理解有了誤會,原來這裡面的 add_links 還會再檢測一次,而不是和 on_check 裡面的 add_links 那樣就直接添加了。

@waruqi
Copy link
Member

waruqi commented Jan 4, 2019

原來這裡面的 add_links 還會再檢測一次,而不是和 on_check 裡面的 add_links 那樣就直接添加了。

只要你不覆写on_check,那么before_check里面的所有设置就相当于外层的add_links,给你在检测前有机会动态添加检测配置

@orzuk-lmj
Copy link
Contributor Author

原來這裡面的 add_links 還會再檢測一次,而不是和 on_check 裡面的 add_links 那樣就直接添加了。

只要你不覆写on_check,那么before_check里面的所有设置就相当于外层的add_links,给你在检测前有机会动态添加检测配置

這裡剛好就是一個很好的例子,相近/相同的名字的API,用在鄰近的事件接口,卻發揮不同的功能,因為沒法直接印射聯想,不小心就誤會了。得深入代碼看機制、上網查找詢問,或是倚賴文檔充分說明,但我相信寫文檔是相當耗費心力。。。 再次感謝

@waruqi
Copy link
Member

waruqi commented Jan 4, 2019

這裡剛好就是一個很好的例子,相近/相同的名字的API,用在鄰近的事件接口,卻發揮不同的功能,因為沒法直接印射聯想,不小心就誤會了。得深入代碼看機制、上網查找詢問,或是倚賴文檔充分說明,但我相信寫文檔是相當耗費心力。。。

api名字写的再长,表达给用户的信息终归是有限的,也许你看明白了,其他用户还是会有理解偏差的,总归还是要以文档为主的

我只能在在尽量精简的同时,保证一定程度的可读性,相对做一些取舍,保证xmake.lua整体内容的精简,不过于臃肿冗余

而且目前api定义是有一致的文档规范的,如果您熟悉了xmake的命名规范,即使新增其他类似on_xx before_xx api,没有文档也能理解的大概。。

你可以先熟悉下xmake的命名规范,https://xmake.io/#/zh/manual?id=命名规范

根据规范说明,on_xx就是会覆写内置脚本,而before_xx不会,哪怕是我现在新增其他before_xx api ,没有文档也大概知道怎么回事的,before_build on_build也类似

@waruqi waruqi closed this as completed Jan 4, 2019
@waruqi
Copy link
Member

waruqi commented Feb 6, 2019

关于检测这块,我改进了下,通过includes("check_links"), includes("check_ctypes")等一系列内置帮助函数,去简化对option()的使用,并且能够配合add_configfiles()set_configvar()模板配置文件,进行快速方便的检测配置,具体详情见:#342

目前仅在dev分支上才可使用,你可以试试。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants