Closed htfy96 closed 7 years ago
xmake also provide these features, so I don't intend to wrap them.
Compiler detection of xmake is perfect
"Package search" is working on the way. You could have a look branch repo
Thanks for caring :smiley:
Thanks for reply. I'm just a little bit worried that there might be a lot more to do than you think. Take C++ as an example, we may need:
Supporting .cmake
may reduce some kind of work, I guess.
I'd like to have a quick look into it this week
@htfy96 You can use option
to detect types
, includes
, funcs
, links
, cflags
, ldflags
and etc ..
for example:
option("test")
add_define_if_ok("ENABLE_TEST")
add_ctypes("wchar_t")
add_cincludes("setjmp.h")
add_cfuncs("sigsetjmp", "setjmp")
-- add_cfuncs("sigsetjmp((void*)0, 0)")
-- add_cfuncs("sigsetjmp{int a = 0; sigsetjmp((void*)a, a);}")
add_links("pthread")
target("demo")
add_options("test")
...
It will detect wchat_t
, "setjmp.h", libpthread.a
and sigsetjmp
.
The demo
target will define -DENABLE_TEST
and link -lpthread
if all tests are passed
And you can add add_cxflags("-fsanitize=address", "-ftrapv")
directly.
If compiler does not support these flags, It will ignore it automatically.
xmake will detect msvc on windows by default automatically. If you want to use other compiler, you can set it manually. for example:
$ xmake f --cc=clang --cxx=clang --ld=clang
$ xmake
And it will detect clang, gcc, .. on linux/macos.
@waruqi
IIUC, according to your example xmake
currently has no plan for builtin feature detection based on compiler version, instead, it provides basic utilities like add_cxxfuncs
to allow custom detection. The main drawbacks of the absence of builtin has_variadic_template
/support_cxx_11
include:
add_cfuns(sigsetjmp((void*)0, 0)
and requires heavy templates and domain knowledgeActually I'm more willing to see something like enable_sanitize_address
which adds proper flags for every compiler supporting this feature. Hard-coded/compiler-dependent flags are not encouraged from my perspective, and I want to completely eliminate these in my build scripts.
I'm referring to Clang/C2 frontend of MSVC. Take a look into CMake's patch set, and you'll find that checking _MSC_VER
is not enough.
@htfy96 Yes, xmake currently has no plan for builtin feature detection based on compiler version.
We have to compile during configuration for many times if we have a lot of orthogonal features to detect
This is only configured and detected once
Some feature detections are not as simple as
add_cfuns(sigsetjmp((void*)0, 0)
and requires heavy templates and domain knowledge
This is not a problem, the detection rules can be improved more flexibly.
Hard-coded/compiler-dependent flags
xmake takes the gcc flags as the standard and will map to other compiler flags smartly.
So these flags (-fsanitize=addres
, -fomit-frame-pointer
) are not hard-coded/compiler-dependent
, you can see #71
About enable_sanitize_address
, why not do the testing directly in the code?
#if (defined(__has_feature) && __has_feature(address_sanitizer)) || \
defined(__SANITIZE_ADDRESS__)
...
#endif
@waruqi Thanks for detailed reply. One more question, how can I switch flags based on whether a code snippet can compile without error? For example, I want to detect constexpr support:
option("test_cxx11_constexpr")
add_defines_if_ok("CXX11_CONSTEXPR")
add_cxxfuncs("has_cxx11_constexpr{ constexpr int f(int x) { return x ? x+f(x-1) : 0; } constexpr int x = f(5); static_assert(x == 15); ")
option("test_cxx14_constexpr")
add_defines_if_ok("CXX14_CONSTEXPR")
add_cxxfuncs("has_cxx14_constexpr{ constexpr int f(int x) { int sum=0; for (int i=0; i<=x; ++i) sum += i; return sum; } constexpr int x = f(5); static_assert(x == 15);")
This doesn't seem to work. Older compilers do not support __has_feature
Actually I'm more willing to see something like enable_sanitize_address
Now for flags adding, xmake uses gcc flags mapping
Advantage:
Disadvantage:
-coverage
is not mapped. And compilers are difficult so some flags cannot be implemented on some compilerI agree with generic flags like what you said as a second choice
A good problem @htfy96
Seems that not supported yet, right? @waruqi
And consider this case: user specified -fsanitize=address
in xmake.lua
, but actually the machine is running an older version of C2 on MSVC(e.g. Clang/C2 in MSVC14 Update 1) which has not sanitize
support. How do you deal with such kind of issue?
The initiative of this issue is that compatibility/detection is extremely difficult. Manual checking could be very time-consuming and complicated. It is difficult to implement your own compiler database like CMake
from scratch as well, since if you want to support N
compilers, each of which has K
versions, and you have P
features to check, the database will soon balloons to N * K * P
. Therefore, the best choice in this case is to adapt existing CMake databases.
@htfy96 add_cxxfuncs
and add_cfuncs
only used to detect if the function interface exists. I will add add_cxxsnippets()
to detect other feature support in the future, for example:
option("constexpr")
add_csnippets("...")
add_cxxsnippets("constexpr int f(int x) { int sum=0; for (int i=0; i<=x; ++i) sum += i; return sum; } constexpr int x = f(5); static_assert(x == 15);")
And consider this case: user specified -fsanitize=address in xmake.lua, but actually the machine is running an older version of C2 on MSVC(e.g. Clang/C2 in MSVC14 Update 1) which has not sanitize support. How do you deal with such kind of issue?
If has not sanitize support, add_cxflags("-fsanitize=addres")
will be ignored automatically when building project
The initiative of this issue is that compatibility/detection is extremely difficult. Manual checking could be very time-consuming and complicated. It is difficult to implement your own compiler database like CMake from scratch as well, since if you want to support N compilers, each of which has K versions, and you have P features to check, the database will soon balloons to N K P. Therefore, the best choice in this case is to adapt existing CMake databases.
Therefore, even using the CMake database does not guarantee all compilers, versions and archs. And this need instant update compiler database to detect new features and versions.
The most stable way is that try to compile it to detect it.
@waruqi Validity check of snippets cannot be bulk-executed since an error in one snippet can easily affect others.
The -fsanitize
example actually targets the underlying problem compiler detection: in order to detect whether this flag is supported, you need to compile with it during configuration instead of mapping it manually in scripts, as what you just mentioned.
Moreover, some features cannot be detected at compile-time without compiler mapping. For example: <regex>
in g++-4.8 defined all functions with empty implementation.
@htfy96 add_cxxfuncs and add_cfuncs only used to detect if the function interface exists. I will add add_snippet() to detect other feature support in the future, for example:
:+1: @waruqi
add_snippet()
is great. Just like my way to check if libreadline
exists in Makefile in #80 . I'd like to try writing a first implement these days
The initiative of this issue is that compatibility/detection is extremely difficult. Manual checking could be very time-consuming and complicated. It is difficult to implement your own compiler database like CMake from scratch as well, since if you want to support N compilers, each of which has K versions, and you have P features to check, the database will soon balloons to N K P. Therefore, the best choice in this case is to adapt existing CMake databases.
You're right @htfy96
in order to detect whether this flag is supported, you need to compile with it during configuration instead of mapping it manually in scripts, as what you just mentioned.
xmake does you say, compile with it during configuration to check whether a flag is available @htfy96
Moreover, some features cannot be detected at compile-time. For example:
in g++-4.8 defined all functions with empty implementation.
Great example :+1: @htfy96
Maybe best solution is
@htfy96
Validity check of snippets cannot be bulk-executed since an error in one snippet can easily affect others.
You can define one option
with a snippet to detect only one feature.
The -fsanitize example actually targets the underlying problem compiler detection: in order to detect whether this flag is supported, you need to compile with it during configuration instead of mapping it manually in scripts, as what you just mentioned.
You also can use option to detect flags. Although I don't support it now, I'll improve it.
option("fsanitize_address")
add_cxflags("-fsanitize=address") <-- I'll improve it here.
add_ldflags("-fsanitize=address")
@TitanSnow
Just like my way to check if libreadline exists in Makefile in #80 . I'd like to try writing a first implement these days
I've detected it in xmake.lua
, just old core/makefile
doesn't support. You can see core/src/xmake/xmake.lua
add_cfunc("API", "readline", nil, {"readline/readline.h"}, "readline")
@htfy96
Moreover, some features cannot be detected at compile-time. For example:
in g++-4.8 defined all functions with empty implementation.
But many vendors will modify the compiler (for some cross-toolchains), even the compiler with the same version does not guarantee that many implementations exist or not.
So there is the same problem with the database.
Yep @waruqi but this is just a example that not so exact and other code snippets could be used
So there is the same problem with the database.
Database is not no use at all! @waruqi
@TitanSnow @htfy96 So I'm still more inclined to use compile detection. Perhaps xmake's detection is not flexible enough, but I will improve it.
@waruqi
It is OK to just provide minimal feature detection support, I guess. Users have to deal with it something like Boost.config
, though in many cases we don't want to introduce Boost dependency. Quite looks like the way of premake
.
Thanks for your effort. It would be piles of work to implement proper compiler detection.
@htfy96 😄
add_snippet()
is great. Just like my way to check iflibreadline
exists in Makefile in #80 . I'd like to try writing a first implement these days
Sorry, but for me there's still trouble to implement add_snippet()
@TitanSnow I will implement it in last these days.
@htfy96 I have quickly looked through *.cmake
in cmake/modules
I found that your idea is great :+1:
Many things are useful like findQt.cmake
In fact trying to link with Qt in xmake might be troublesome or I don't get the way? @waruqi
And FindGit.cmake
might be useful for you @waruqi . I know you recently work on branch repo
requires git
If .cmake
adapter comes up in the future, I think things will be easier and better.
In this way, I agree with @htfy96
My option is on-fly detection is the first hand, off-fly data & script is the second hand
This idea should be minded @waruqi
Does you have a preliminary way to implement the adapter, @htfy96 ? Or could you do some work on this and finally give a PR?
@TitanSnow
And FindGit.cmake might be useful for you @waruqi . I know you recently work on branch repo requires git
Git is a necessary component for xmake require
action, not just looking for it. So it's not enough to use FindGit.cmake
. xmake will install winenv with git when using xmake require
to ensure git exist.
xmake also support tool detection and only for internal detection. In the future I will provide public interfaces to find tools like find_tool
, find_package
..
If .cmake adapter comes up in the future, I think things will be easier and better.
Xmake has its own design pattern, not depend on .cmake
or wrap it. But I will provide similar functionality in the future.
In fact trying to link with Qt in xmake might be troublesome or I don't get the way? @waruqi
This is really a good feature. I will improve option
to support simular feature.
@htfy96 I have implemented add_cxxsnippet
to detect compiler feature. for example:
-- define option for detecting constexpr feature
option("constexpr")
set_languages("cxx14")
add_defines_if_ok("CONSTEXPR_ENABLE")
add_cxxsnippet("constexpr", "constexpr int f(int x) { int sum=0; for (int i=0; i<=x; ++i) sum += i; return sum; } constexpr int x = f(5); static_assert(x == 15);")
-- add target
target("test")
-- set kind
set_kind("binary")
-- add files
add_files("src/*.cpp")
-- need constexpr
add_options("constexpr")
I'll focus on improving option
to provide more flexible detection in the future, but now I need to finish xmake require
first. Please wait some time...
for example, provide some builtin options in xmake/options
directory, like .cmake/Modules
option("find_qt")
on_check(function (option)
-- check qt ...
-- add links, linkdirs .. to option
end)
option("xxx_interface")
add_links("xxx")
on_check(function (option)
-- try compile codes
-- try run and test codes (empty implementation?)
end)
Maybe just translate some .cmake
files manually is enough to finish the goal
I found cmake is licensed under BSD-3 so there's no problem
It doesn't have to make a adapter, hand-work is enough @htfy96
@TitanSnow But I don't like cmake's grammar and design, and don't want to be overly reliant on and use them.
For grammar, I do not like cmake's either
But at least we could quickly look through them and come up with some ideas
Yes, it provides some good features and ideas. I will refer to them when I begin to improve option
.
But I don't want to parse them for fast implementation, I need design the whole architecture first. Even if it will delay some time.
Yeah, it might be best solution
@htfy96 @TitanSnow
I've started to implement some detection modules.
I'll add a new interface has_feature
to make it easier to judge all compiler features in the future. for example:
target("test")
set_kind("binary")
if has_features("const_expr") then
add_defines("-DCONST_EXPR")
add_files("src/*.cpp")
end
if has_features("sanitize_address", "floating_point") then
...
end
And I will improve option
and target
to support them.
target("test")
set_kind("binary")
before_build(function (target)
-- import find_library
import("lib.detect.find_library")
-- find zlib and add links
zlib = find_library("zlib")
if zlib then
target:add_links(zlib.links)
target:add_linkdirs(zlib.linkdirs)
end
end
Or
option("zlib")
on_check(function (option)
-- import find_library
import("lib.detect.find_library")
-- find zlib and add links
zlib = find_library("zlib")
if zlib then
option:add_links(zlib.links)
option:add_linkdirs(zlib.linkdirs)
end
end
target("test")
add_options("zlib")
detect modules roadmap:
lib.detect.*
)
os.files
os.filedirs
os.files
and os.filedirs
pkg-config
which
detect.tool.*
)
detect.sdk.*
)
lib.detect.has_flags
)
xxx --help
lib.detect.check_cxsnippets
for c/c++lib.detect.has_features
)
cpp_const_expr
c_variadic_macros
c_static_assert
xmake.lua
option.on_check()
, option.after_check()
, option.before_check()
target:add()
in before_build()
option:add()
in on_check()
option.add_csnippet
, option.add_cxxsnippet
winreg roadmap:
@htfy96 @TitanSnow I have implemented these features, please see: new-features-v2.1.5
The main reason why I still stick to CMake is its builtin modules which provide compiler detection/package search/etc. It is unnecessary to reinvent the wheels, so I was wondering is it possible to provide (at least kind of)
.cmake
support and wrap these modules intoxmake
utilities?