-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Add static_c_args
to library()
#3304
Comments
It defines extra cflags to pass only when building the static version of the library. When building both shared and static libraries and static_c_args is not empty, it will build the library twice instead of extracting objects. Closes mesonbuild#3304
I believe static makes sense for multiple languages, e.g. C++
|
The patch I made adds for c and cpp because I have real use case for them. What other language would need it? |
Fortran, objc, Rust, D, and everything that compiles into native code. It could also be argued that you should make it possible to add args to shared libs and exes as well. Possibly also based on the build type. This gives |
Well, for static_c_args there are valid real world use-case: glib and gstreamer do have a -DSTATIC_COMPILATION to define dllexport on windows which is different for static/shared. We could have static_args : {'c' : '-DSTUFF'}, but I'm not sure the interpreter supports dict, does it? For shared_args I have no use case for it, but if there are, I don't think it's a big deal to add it later. |
Just got an idea to make it scalable: Add a new type CompileArgs. Something like this:
Making existing Note: IMO the proposed |
Or perhaps mirroring how cargs = compile_args()
cargs.add_args('-foo', language: 'c', targettype : 'static_library')
library(.., extra_args : cargs) ? |
The principal use-case is to pass different compiler flags to library() depending if it's building the static or shared library. Closes: mesonbuild#3304
Actually I like that idea of having an holder for all the build configs that can be passed to many library() executable() calls. It can replace add_global_arguments() for args that needs to be on most but not all targets. It could also be extended to more than compiler args later. For example why not args.set_install_dir('/myprefix/lib', target_type: 'library'). All your settings could be in one place and you pass that object down to all your build targets. Anyway, that's for later if we see the need. For now the real use-case for me is static c flags. |
The principal use-case is to pass different compiler flags to library() depending if it's building the static or shared library. Closes: mesonbuild#3304
The principal use-case is to pass different compiler flags to library() depending if it's building the static or shared library. Closes: mesonbuild#3304
The principal use-case is to pass different compiler flags to library() depending if it's building the static or shared library. Closes: mesonbuild#3304
I wonder if people need to pass arbitrary custom |
I would argue that special defines for building dynamic libs is often the case on windows. Sometimes it is even necessary to have special defines only when building with the intention of linking dynamically. Real world examples: hdf5 has to set #ifdef _WIN32
# ifdef MODULE_API_EXPORTS
# define MODULE_API __declspec(dllexport)
# else
# define MODULE_API __declspec(dllimport)
# endif
#else
# define MODULE_API
#endif Source: https://stackoverflow.com/a/19547601/3804521 One could also argue that #if defined _WIN32 || defined __CYGWIN__
#ifdef BUILDING_DLL
#ifdef __GNUC__
#define DLL_PUBLIC __attribute__ ((dllexport))
#else
#define DLL_PUBLIC __declspec(dllexport) // Note: actually gcc seems to also supports this syntax.
#endif
#else
#ifdef __GNUC__
#define DLL_PUBLIC __attribute__ ((dllimport))
#else
#define DLL_PUBLIC __declspec(dllimport) // Note: actually gcc seems to also supports this syntax.
#endif
#endif
#define DLL_LOCAL
#else
#if __GNUC__ >= 4
#define DLL_PUBLIC __attribute__ ((visibility ("default")))
#define DLL_LOCAL __attribute__ ((visibility ("hidden")))
#else
#define DLL_PUBLIC
#define DLL_LOCAL
#endif
#endif Source: https://gcc.gnu.org/wiki/Visibility In both cases either |
Exactly, I've only ever seen people need to pass special defines on Windows when doing static/dynamic linking, and the implementation for that is much simpler than special arguments. |
Maybe I'm going off-topic but: I think an abstraction involving defines would be helpful. It was not immediately obvious to me that |
fwiw, @xclaesse I think we can probably add that generic mechanism when people ask for it, but it's better to implement a feature with smaller scope first. I would actually imagine this being implemented as: library('foo', 'foo.c',
defines: {'static': ['FOO=bar', 'BAR=baz'],
'shared': ['BAH=blah']} and then the defines get added to all possible languages. @jpakkane what do you think? |
NO new kwargs only for defines. |
What about: library('foo', 'foo.c',
static_args : {'c' : ['-DFOO'],
'cpp': ['-DBAR']}
) |
Or library('foo', 'foo.c',
c_args : {'static' : ['-DFOO'],
'shared': ['-DBAR']}
) I actually prefer this one, because it doesn't introduce new kwarg, it just extend the value types we can pass to it. If it's a dictionnary, the key is the targettype. |
Could be used to group all args into a common dict that can be passed to any target. cargs = {'executable' : ['-DEXE'],
'shared_library' : ['-DSHARED'],
'static_library' : ['-DSTATIC']}
executable('app', 'app.c', c_args : cargs)
library('lib', 'lib.c', c_args : cargs) |
I like the last one. I think it would be cool if it was supported on: cargs = {'shared_library' : ['-DH5_BUILT_AS_DYNAMIC_LIB']}
lib = library('lib', 'lib.c')
dep = declare_dependency(link_with: lib, compile_args: cargs)
executable('app', 'app.c', dependencies: dep) # <-- should get -DH5_BUILT_AS_DYNAMIC_LIB if lib was built/found as dynamic lib. Unless I completely missunderstood the |
The advantage of new kwargs for defines would be to have them apply to all languages at once, and not have to worry about setting it individually for each language. For instance, in the use-case that @NickeZ posted above, the |
AFAIK rustc doesn't really have defines but they have Maybe some abstraction could be created that maps to all languages.. https://doc.rust-lang.org/reference/attributes.html#conditional-compilation https://doc.rust-lang.org/book/first-edition/conditional-compilation.html |
The dict must map a target type to a list of compiler args. This makes possible to pass different c_args to static and shared libraries when using both_libraries(). In that case sources will be compiled twice. Closes mesonbuild#3304.
The dict must map a target type to a list of compiler args. This makes possible to pass different c_args to static and shared libraries when using both_libraries(). In that case sources will be compiled twice. Closes mesonbuild#3304.
The dict must map a target type to a list of compiler args. This makes possible to pass different c_args to static and shared libraries when using both_libraries(). In that case sources will be compiled twice. Closes mesonbuild#3304.
The dict must map a target type to a list of compiler args. This makes possible to pass different c_args to static and shared libraries when using both_libraries(). In that case sources will be compiled twice. Closes mesonbuild#3304.
For the method in #3304 (comment) to work with dllimport / dllexport on Windows, I think there must be a way to differentiate between defines that are used when the library gets compiled and ones that get used when it is used as a dependency. |
Any flags specified in the |
Ah true, then this would probably work quite nicely. |
@xclaesse you said earlier in this thread you had a patch for this around 2 years ago. Any thoughts on picking that up? Or I could potentially if your old work no longer applies/don't have time. Seems like the dictionary version of |
@tristan957 other developers did not like the dictionary approach. The last suggested idea was to do that with add_project_arguments(): #4159 (comment). |
Let me add to this mess. Rust has several additional library (crate) types : c static, c dynamic, rust static, and rust dynamic. So we have at least two additional options here that I need today. So, I'd be in favor of the dictionary, but in a flat library(
c_args : {
'common': ['foo', 'bar'],
'static' : '-DSTATIC',
'shared' : '-DSHARED',
},
cpp_args : 'foo',
) And for rust that could like like: library(
rust_args : {
'common' : ['--cfg', 'always'],
'rlib': ['--cfg', 'opt'], # rust static
'static': ['--cfg', 'static'],
'cdylib': ['--cfg', 'dylib'],
}
) |
I'm at this point we need to agree to paint the dang shed, even if it's not perfect because this is starting to be a real problem. |
I'd be in favor of I'm also in favor of having a target_type argument to |
That's what I suggested 4 yearts ago too: #3304 (comment). Not sure we need common, as you can easily have a variable for that and do |
This allows having different cflags for static and shared library when using both_libraries(). Fixes: mesonbuild#3304
Let's just do it: #11501 |
Can this be closed, now that #11981 is merged? |
It is common to pass different cflags depending if it's a static or shared library, for example -DSTATIC_COMPILATION.
I suggest adding
static_c_args
that will be appended to c_args if it's a static build. If static_c_args is not empty anddefault_library=='both'
then it will have to build twice instead of extracting objects.The text was updated successfully, but these errors were encountered: