Skip to content

linux平台使用set_pcxxheader 自動產生的 .gch 和 .gch.d 路徑有問題 #301

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

Closed
orzuk-lmj opened this issue Dec 20, 2018 · 17 comments

Comments

@orzuk-lmj
Copy link
Contributor

  • 測試平台為 Ubuntu18, Manjaro17, archlinux20180901
  • set_pcxxheader 自動生成的 .gch 和 .gch.d 會儲存到原代碼目錄中
  • 希望能保持原代碼目錄乾淨,把自動生成的路徑改到 build 中
set_pcxxheader("private/PrecompiledHeader.h")
自動生成的路徑會放在:private/PrecompiledHeader.h.gch
@waruqi
Copy link
Member

waruqi commented Dec 20, 2018

如果是clang, 生成的pch目前就是隔离到build目录下的,而gcc的预编译生成 gch,目前我没研究出来指定到其他目录生成,这也是没办法的行为,要支持gcc的预编译,只能在当前源码下生成对应的*.gch,才能正常工作。

如果你能找到gcc预编译可以指定生成到其他目录的方法,我很乐意去修改下生成路径的。

@orzuk-lmj
Copy link
Contributor Author

orzuk-lmj commented Dec 20, 2018

我在cmake中使用 ADD_CUSTOM_COMMAND 下指令,可以指定路徑。
使用 -o "pch_binary_output" 指向最終生成路徑。

SET(pch_binary_output "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${pch_base_name}.gch")

# c++使用 -x c++-header
# c 使用 -x c-header
ADD_CUSTOM_COMMAND(
    OUTPUT "${pch_binary_output}"
    COMMAND ${CMAKE_CXX_COMPILER} ${pch_compiler_flags} -x c++-header -c "${real_pcheader_path}" -o "${pch_binary_output}"
    DEPENDS "${real_pcheader_path}"
    COMMAND_EXPAND_LISTS
)

然後對所有cpp單檔指定 "-include ${real_pcheader_path} -Winvalid-pch" 旗標去編譯

你試試看

@waruqi
Copy link
Member

waruqi commented Dec 20, 2018

能否提供下编译时候的完整命令行?

@orzuk-lmj
Copy link
Contributor Author

orzuk-lmj commented Dec 20, 2018

概念是這樣,使用cmake蒐集其他cpp正常編譯過程需要的所有旗標,然後產生 gch 檔案。

  • 設置的 pch_compiler_flags 裡面包含了編譯期間需要的 -std=c++11 / -I include_dirs / -D defs 。
  • 變量 real_pcheader_path 提供標頭檔的絕對路徑
  • 變量 pch_binary_output 提供最終要放置 .gch 的絕對路徑
  • 執行命令產生 .gch 然後對所有的 cpp 檔案設置 "-include ${real_pcheader_path} -Winvalid-pch" 旗標
g++ $pch_compiler_flags -x c++-header -c "$real_pcheader_path" -o "$pch_binary_output"

因為 cmake 的 ADD_CUSTOM_COMMAND 可以建立出一個 target ,所以必要時可以明確的指定重新編譯這個target ,達到強制刷新 pch 的目的,挺方便的。

我實際開了 ubuntu 執行 cmake 腳本,然後把完整命令行萃取出來:

g++ -mfpmath=sse -msse2 -fopenmp -g -std=gnu++11 
-I"/home/localuser/apx/Externals/original_libraries/utf8/include" 
-I"/home/localuser/apx/Externals/SDKs/linux-m32/zlib-1.2.8/Debug/include" 
-I"/home/localuser/apx/core/_build/makefiles-linux-m32-debug/TemporarySource" 
-I"/home/localuser/apx/core/sources/public" 
-I"/home/localuser/apx/core/sources/private" 
-DAPX_CORE_DYN -DAPX_BUILD_TYPE_DEBUG 
-x c++-header -c /home/localuser/apx/core/sources/private/stdafx.h 
-o /home/localuser/apx/core/_build/makefiles-linux-m32-debug/stdafx.h.gch

@waruqi
Copy link
Member

waruqi commented Dec 20, 2018

这块我有点忘记了,刚没说清楚,生成gch是可以指定路径的,应该是之前因为在编译源码指定使用某个pch/gch文件的时候,clang可以通过 -include-pch xxxx.pch来指定特定目录的pch文件来使用

ccache xcrun -sdk macosx clang -c -include src/header.h -include-pch build/header.h.pch -o xxx.o xxxx.c

而gcc没这个参数,没法指定使用其他目录下xxx.gch文件,只能生成到xxx.h对应的当前目录下xxx.h.gch,编译源码的时候才会自动找到使用。

所以即使gcc编译生成gch到指定其他目录,但是编译.c的时候,没法通过-include-pch xxx.gch 指定使用其他目录下的gch文件,所以没找到好的解决办法,就直接生成到当前目录下了。。

你可以看看cmake有没有好的处理方式,如果可以的话,可以贴下对应的完整命令行给我参考下。。

@orzuk-lmj
Copy link
Contributor Author

orzuk-lmj commented Dec 21, 2018

暫時查到 cmake 的 pch 做法,都是直接套用 gcc -include XXX 然後用 -Winvalid-pch 驗證。而不直接使用 ccache。。。

另外一個選擇就是使用 before_build 事件,把預編譯頭複製到 build 路徑裡,然後就地產生gch,最後在正常編譯期間使用放在 build 裡的私有檔案。。。

@waruqi
Copy link
Member

waruqi commented Dec 21, 2018

这个跟ccache没啥关系,不用你可以禁用掉,如果只有-include xxx.h 怎么指定使用 其他目录下的*.gch文件呢?clang有 -include-pch xxx.pch可以独立指定

@orzuk-lmj
Copy link
Contributor Author

orzuk-lmj commented Dec 21, 2018

ccache 暫且不熟,有了些誤會,抱歉。
要不嘗試了一下 before_build 的方式產生 pch? 我看到的實做方式這佔了大多數。
讓 XXX.h 和 XXX.gch 都放在build 裡的同一個目錄中。指定 -include xxx.h 的時候會使用到同層路徑下的 gch 吧?

@orzuk-lmj orzuk-lmj reopened this Dec 21, 2018
@waruqi
Copy link
Member

waruqi commented Dec 21, 2018

要不嘗試了一下 before_build 的方式產生 pch? 我看到的實做方式這佔了大多數。

目前就是在before build阶段预生成的,这跟此issues没啥直接关系。

讓 XXX.h 和 XXX.gch 都放在build 裡的同一個目錄中。指定 -include xxx.h 的時候會使用到同層路徑下的 gch 吧?

这样的话,生成gch的时候,还需要将使用的headers copy到build对应目录下,这种方式可以尝试下,但不知道是否有其他坑,可以先试试

@waruqi
Copy link
Member

waruqi commented Dec 24, 2018

这块我改进过了,你试试吧,请更新下dev分支代码,目前做了如下改动:

  1. gcc下,通过-include xxx.h -Ibuild/xxx/ 来定向使用build/xxx/xxx.h.gch文件,这样也不需要copy一份header文件,并且build/xxx目录下只有.gch文件,也不会造成头文件搜索路径污染

  2. 顺便将gcc/clang下的依赖头文件生成,从原来的-E -MM改成了-H,这样减少了一次预处理编译过程(不在额外进行一次-E -MM的预编译处理),整体编译速度提升了不少,同时也解决了之前-E -MM编译对上述gcc处理过程不支持的情况

由于这次变动还是有点的,你这边可以多测下,预编译以及头文件依赖编译相关的逻辑。

@orzuk-lmj
Copy link
Contributor Author

orzuk-lmj commented Dec 25, 2018

xmake build 開啟 -w 後比以往多出一些警告,類似於:

. /usr/include/stdlib.h
.. /usr/include/features.h
... /usr/include/sys/cdefs.h
.... /usr/include/bits/wordsize.h
... /usr/include/gnu/stubs.h
.... /usr/include/gnu/stubs-32.h
.. /usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stddef.h
.. /usr/include/bits/waitflags.h
dynmod/private/Mod/Mod.cpp
. dynmod/private/Mod/FuncExport.h
.. dynmod/public/Mod/DefineAPI.h
Multiple include guards may be useful for:
/usr/include/asm/errno.h
/usr/include/bits/byteswap-16.h
/usr/include/bits/byteswap.h
/usr/include/bits/endian.h
/usr/include/bits/errno.h
. dynmod/private/PrecompiledHeader.h
. dynmod/public/Mod/Mod.h
.. dynmod/public/Mod/DefineAPI.h
Multiple include guards may be useful for:
/usr/include/asm/errno.h
/usr/include/bits/byteswap-16.h
/usr/include/bits/byteswap.h
/usr/include/bits/endian.h
. core/public/Core/Core.h
. dynmod/private/Mod/FuncExport.h
.. dynmod/public/Mod/DefineAPI.h

除此之外也確認 .gch/ .gch.d 放置在build路逕了。win/mingw/ndk/linux 四個平台+多種設置,都可以編譯成功且可運行。晚些找時間再來多測試一下 macosx 和 ios 。。。

@waruqi
Copy link
Member

waruqi commented Dec 25, 2018

哦哦 ,警告这块忘记过滤了 我回头改进下

@waruqi
Copy link
Member

waruqi commented Dec 25, 2018

我改进过了,你可以更新下dev再试试,xmake update dev

由于目前改成 -H 去生成头文件依赖信息,因此会输出到stderr,跟警告信息,错误信息输出混在一起,但比起通过-E -MM方式两次执行预编译的效率损失,这点代价还是能接受的。

目前只能通过一些特征模式,进行过滤提取分离两者,对于警告信息,错误信息的提取,经测试gcc/clang下都ok,但是中文版本的gcc/clang我这没有,如果你这有的话,也可以测测,理论上应该也没啥问题。

@orzuk-lmj
Copy link
Contributor Author

剩下 mingw 會打印出警告:

checking for the flags (-H) ... ok
C:/mingw-builds/x86_64-7.3.0-release-posix-seh-rt_v5-rev0/mingw64/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++/clocale
C:/mingw-builds/x86_64-7.3.0-release-posix-seh-rt_v5-rev0/mingw64/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++/cmath
C:/mingw-builds/x86_64-7.3.0-release-posix-seh-rt_v5-rev0/mingw64/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++/cstdio
C:/mingw-builds/x86_64-7.3.0-release-posix-seh-rt_v5-rev0/mingw64/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++/ctime
C:/mingw-builds/x86_64-7.3.0-release-posix-seh-rt_v5-rev0/mingw64/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++/cwctype

或是
C:/mingw-builds/i686-7.3.0-release-posix-dwarf-rt_v5-rev0/mingw32/lib/gcc/i686-w64-mingw32/7.3.0/include/c++/clocale
C:/mingw-builds/i686-7.3.0-release-posix-dwarf-rt_v5-rev0/mingw32/lib/gcc/i686-w64-mingw32/7.3.0/include/c++/cmath
C:/mingw-builds/i686-7.3.0-release-posix-dwarf-rt_v5-rev0/mingw32/lib/gcc/i686-w64-mingw32/7.3.0/include/c++/cstdio
C:/mingw-builds/i686-7.3.0-release-posix-dwarf-rt_v5-rev0/mingw32/lib/gcc/i686-w64-mingw32/7.3.0/include/c++/ctime
C:/mingw-builds/i686-7.3.0-release-posix-dwarf-rt_v5-rev0/mingw32/lib/gcc/i686-w64-mingw32/7.3.0/include/c++/cwctype

@waruqi
Copy link
Member

waruqi commented Dec 26, 2018

好吧,看来还是过滤不全,我再改进下 = =

@waruqi
Copy link
Member

waruqi commented Dec 26, 2018

可以了,你再试试,xmake update dev,windows上dev包我也更新了

@waruqi waruqi added this to the v2.2.4 milestone Dec 26, 2018
@orzuk-lmj
Copy link
Contributor Author

windows/mingw/linux/android 多種設置搭配測試OK,感謝

@waruqi waruqi closed this as completed Dec 27, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants