build-cpp / cmkr

Modern build system based on CMake and TOML.
https://cmkr.build
MIT License
439 stars 27 forks source link

How can I pass one linker option on one platform and another for a different platform? #67

Closed xtremegamer1 closed 2 years ago

xtremegamer1 commented 2 years ago

I'm compiling VTIL with cmkr, and VTIL has absolutely obscene stack usage (1.4 megabytes in a single frame, and that's before even executing main!) so I need to use the linker flag for increasing stack size. Anyway am preparing to get a laptop with linux on it (because windows performance is intolerable on subpar hardware) so I would like a way that's cross platform and picks the relevant linker flag based on what compiler is chosen. tysm

mrexodia commented 2 years ago

You’re looking for “condition” in the reference.

xtremegamer1 commented 2 years ago

You’re looking for “condition” in the reference.

Thanks for the reply

[project] name = "conditions" cmake-after = "set(CUSTOM ON)"

[conditions] custom = "CUSTOM"

[target.example] type = "executable" sources = ["src/main.cpp"] windows.sources = ["src/windows_specific.cpp"] cmake-after = "message(STATUS cmake-after)" windows.cmake-after = "message(STATUS win32-after)" macos.cmake-after = "message(STATUS macos-after)" linux.cmake-after = "message(STATUS linux-after)" unix.cmake-after = "message(STATUS unix-after)" custom.cmake-after = "message(STATUS custom-after)"

[target.example.properties] AUTOMOC = false custom.OUTPUT_NAME = "example2" custom.AUTORCC = true AUTOGEN = "ON"

so which command in this sequence is conditional? I don't understand as to me this looks like a series of sequentially executed instructions with no jccs

mrexodia commented 2 years ago

The default conditions are:

[conditions]
windows = "WIN32"
macos = "CMAKE_SYSTEM_NAME MATCHES \"Darwin\""
unix = "UNIX"
bsd = "CMAKE_SYSTEM_NAME MATCHES \"BSD\""
linux = "CMAKE_SYSTEM_NAME MATCHES \"Linux\""
gcc = "CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\" OR CMAKE_C_COMPILER_ID STREQUAL \"GNU\""
clang = "CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" OR CMAKE_C_COMPILER_ID MATCHES \"Clang\""
msvc = "MSVC"
root = "CMKR_ROOT_PROJECT"
x64 = "CMAKE_SIZEOF_VOID_P EQUAL 8"
x32 = "CMAKE_SIZEOF_VOID_P EQUAL 4"

The list or cmake variables can be found at https://cmake.org/cmake/help/latest/manual/cmake-variables.7.html

You can also use the [options] like so:

[options]
BUILD_TESTS = false

[conditions]
tests = "BUILD_TESTS"

[target.blah]
tests.compile-options = ["..."]

(on the phone so might be slightly wrong, but that’s the idea)

mrexodia commented 2 years ago

Ah and the missing part, you can control the options from the command line like so:

cmake -B build -DBUILD_TESTS=ON

The conditions like msvc and linux are based on CMAKE_ variables though, so those are automatically set depending on your platform.

Probably what you are looking for:

[target.my-vtil]
type = "executable"
msvc.link-options = ["/STACK:0x1000000"]
xtremegamer1 commented 2 years ago

So if a command comes after (condition). then it will be executed conditionally? I see, to me that reminds me of struct member resolution and not conditional statement. But, that may be because i have never used scripting languages like json before. Thank you for your help, cmkr #1 :)

mrexodia commented 2 years ago

Yeah, the format <condition>.key is supported in all places you would expect. The exception is conditional targets and subdirectories (basically there is no [<condition>.section], those have a condition key to prevent impossible scenarios):

[conditions]
tests = "..." # see above

# Only build the my-tests target when the `tests` condition evaluates to true
[target.my-tests]
condition = "tests"
type = "executable"
sources = ["*.cpp"]

# Similar with subdirectories, only include the "tests" subdirectory when building with tests
[subdir.tests]
condition = "tests"

I agree this is a bit unintuitive initially, but there is no such thing as a conditional in TOML so this is the workaround.

And thanks btw, I will update the documentation with an example to explain this properly.

mrexodia commented 2 years ago

Oh and the VTIL target itself already has the flags for MSVC, so all you should need is (didn't test):

[project]
name = "My-VTIL-Project"

[fetch-content.VTIL]
git = "https://github.com/vtil-project/VTIL-Core"
tag = "6f21abb3d4734d1d1a194d879b8d3f1518d4ec4e"

[target.my-vtil]
type = "executable"
sources = ["main.cpp"]
link-libraries = ["VTIL"] # This will apply the stack flags to my-vtil as well
xtremegamer1 commented 2 years ago

Oh i see. I was linking all the subdirectories of Vtil-Core seperately. I do not see VTIL.lib. So, I am guessing that "link libraries" deals with a "library" concept that is a little more abstract than a literal .lib file? So a "library" on Cmake can be a collection of multiple libraries?

mrexodia commented 2 years ago

Indeed, the VTIL library is an INTERFACE library, which describes a set of flags and other libraries to link to.