Hacker News new | past | comments | ask | show | jobs | submit login
GoQt (github.com/visualfc)
281 points by T-A on Jan 24, 2016 | hide | past | favorite | 100 comments



Qt has evolved fantastically since Digia's acquisition. Just throughout the 5.0 series it has gained incredible feature support for almost anything from full multimedia faculties to websockets to a revitalized 3d rendering engine. And QML is such a breakout success in UI design and just general applications programming compared to the competition - if you have not, you must try coming up with a simple program idea and then try implementing it in QML. Compared to any other tech - GTK, HTML, even Android's ADT the mechanism behind QML is incredibly elegant.

I dream of seeing a day in ten years or so where everyone expects right once run everywhere native look and feel applications out of Qt, a toolkit that provides you mechanism to access the full power of your target devices without having to lock yourself into whatever vendors SDK is and thus forcing you to rewrite the same program 5 times for 5 different target devices.

Its not there yet - just the other week I was arguing with someone on reddit about the usability of Qt on mobile and conceded it lacks a prebaked gesture support library to easily just do a two finger swipe rather than having to use the multitoucharea type to specify how two finger motion works - but it is getting so very close.


The last time I checked, it lacked almost everything in what concerns native mobile widgets, device hardware support, OS events, background services and IPC between apps.

Someone made me aware that they are now in yet another reboot for mobile support.

Using C++ with standard libraries like Boost plus platform specific language is less effort than re-writing QML for each platform, which still doesn't feel native, while having anyway the work to wrap platform API ourselves.


I wished Qt just split into a different widget set for mobile. The interaction behavior is significantly different that attempting to reuse the same UI for both mobile and desktop will result in a terrible experience on both.

Likewise, QML is just plainly useless on the desktop, and much slower to booth. Unfortunately, the performance regression in Qt5 is there also if you don't use it, and that shouldn't be.

Qt5 being slower than Qt4 is the main reason I've been moving slowly towards copperspice (http://www.copperspice.com/) for newer projects. The fact that moc is no longer necessary removes also the main paint point of qt.


I found QML items to be very useful on the desktop. Unlike the old widgets, they can easily be overlayed over an OpenGL scene. That makes them a great choice for a whole swath of software.


I'm definitely intending to try writing a Doom clone when 5.7 comes out - thats when the QML Compiler is open sourced, and thats the first iteration after Qt3D is API stable, so it should be fun to work with.

I'm just curious of how much force multiplier you can get writing the menus with QML and the game with Qt3d.


How exactly is QML and Qt5 slower? It's quick to start and UI actions are immediate and smooth.

Forgive me for not knowing, since I've never used Qt Widgets before. I'm writing a desktop app with QML and it's fast and smooth thanks to the OpenGL acceleration.


If you have a classical desktop interface where you reach 100+ widgets (which sounds like a lot but is easily reachable with just a toolbar, some buttons and a form), the difference is noticeable when interacting even on recent hardware (i5+).

For example, since I work in visualization, I often tie data widgets to the GL canvas in order to provide realtime feedback. I also use Qt5 in order to provide keyboard accelerators. With QT5 the rendering latency grew so high that I couldn't provide realtime feedback anymore, and I had to batch requests (and finally reverted to Qt4).

Incidentally Qt5 widgets can be used in a GL context directly, but are way too slow to render and manage events to be used consistently at 60 fps (they're not designed for that, so their scope in this sense is not as broad as it can really be). It's actually faster to give them their own GL context in order not to interfere with your pipeline, which kinds-of defeat the point.

I've also found that the additional JS glue doesn't provide any benefit unless you go entirely QML.


Interesting.

What exactly is each 'widget' when you say there are 100+ widgets? Each overall feature, or each Item within the feature?

In my photo editor I have a histogram of how many photos you've taken each day: http://i.imgur.com/7yAYsP9.png

The histogram is actually a ListView, and each delegate is actually not just the bar for each date, but also the background color, the highlight color for the current date, and the date text that's above each bar. Using model updating, it responds nearly instantly even though there are a thousand days in the view, and the source data is a big ol' SQLite query with C++ postprocessing.

I don't know if that's helpful to you, though. Would that count as one widget in your parlance?


By Widget I mean any object which is a QWidget and is bound by some other widget (so I do not count plain QObjects) that you need for your UI.

ListViews are optimized for display of lists, obviously, so they generally instantiate only visible elements in the view, and delegates do not even undergo geometry negotiation so they're a bit lighter than a regular widget.

Still, if you do visualization or animation, the UI must respond within 1ms in order not to be noticeable, and that's very hard to attain with Qt5.

I doubt people using QML on mobile devices really understand the issue either, since when mobile developers speak of "animations" they generally mean some random transition of the UI itself. Often, the operation is not even performed in the background, but rather simply sequenced (so that the animation appears to be smooth, but the actual delay is completely absorbed by the user). In these scenarios, times up to 250ms/300ms might still be felt "instantaneous" as they're shorter than the transition. For me, it's outrageous.


CopperSpice looks interesting, though is it really a clean-room reimplementation?

Also why on earth do they tout being built with autotools as a feature?!


Read their own introduction page. CopperSpice is a fork of Qt4.


It says it is "derived from" and "inspired by" it. But it also says "Our libraries can be linked directly into any standard C++ application" which the LGPL of Qt 4 disallows (unless your application is open source, but then that isn't any application).


Copperspice is LGPL. Like Qt, it can be dynamically linked into any standard C++ application. The key is that the user needs to be able to instead use their own version of Qt/CS, if they want.


I'm not sure I'd call QML a "breakout success". There are definitely huge issues with it, notably:

* It's quite incomplete. There are a lot of things you just can't do in it. For example try doing a widget of the kind you'd use for compilation output in an IDE. There is a multiline text editor widget, but the only efficient operation is appending text - you can't remove the first line for example.

* If you decide you will write your own QML widget (e.g. for the compilation output), you find that there is no way to render text! The scene graph text nodes are still private.

* You have to use Javascript (ugh)

* There's quite a lot of friction converting C++ types to Javascript and vice versa. Especially with lists and arrays. For example when you access a C++ array from Javascript it has to copy the whole array into a native Javascript array, and then modifications are lost.

* The scope of files and IDs is quite messy - parents can refer to their children's IDs, so there is no concept of data encapsulation. To be honest I still haven't totally worked out the rules, but they're a mess in any case.

* Dynamically creating dialogs and UI elements is a bit of a mess. The "standard" way to have dialogs is (more or less) to create all dialogs the program needs at startup and hide them all until needed. Obviously that doesn't scale well for things like tooltips. Creating them dynamically is rather painful (especially when there are no examples for how to do it!)

QML is definitely a nice idea, but I think they need to give it a third try, and probably not use Javascript.


What tripped me up when I did some QML is that interop of lists between C++ and QML is usually shown in tutorials as going via QQmlListProperty but that is actually not what it's supposed to be used for, resulting in subtle memory leaks and crashes when ownership gets mixed up.

Additionally, it only JUST got a TreeView (Qt 5.5 I believe) and a lot of additional widgets you would need to implement a regular desktop app are just missing.


Yeah me too. Took me ages to realise you should use QAbstractListModel.


Does QML have native widgets by now? When I used it last (2 years ago?) you had to make nearly all widgets yourself. Was no problem for our project, which didn't have a native environment to match, but would be an issue for normal applications.


It does, but I'm not sure if material design is ready now. There is qml-material[0] though, and it's pretty good. But: The last time I checked (maybe 5 or 6 months ago), QML/Qt Quick apps on Android took way too long to launch. I couldn't do anything about it, so haven't used it since then.

[0] https://github.com/papyros/qml-material


> QML/Qt Quick apps on Android took way too long to launch. I couldn't do anything about it, so haven't used it since then.

Thankfully Qt just announced that their commercial-only components will be added to the open source version soon, including the QML-to-C++ compiler.

I haven't had an opportunity to try it myself but they claim it improves startup times significantly.


Nice, I didn't know they'd add the compiler. I tried it back then, during the commercial license trial. But it didn't make much of a difference, if any. I remember being in a hurry, though, so maybe I did something wrong and I'd love to give it another try.


It's always been slower, but I don't think that can be completely fixed since Qt needs to load all of its libraries. Anyway, it's still possible to optimize the startup to be very usable.

You'll want to use a splash screen implemented with minimal UI code (no widgets of any kind yet, just an image with a background). While showing the splash screen, load dynamically a minimal main UI and some critical services -- only the parts that will affect the initial view.

Then hide the splash screen. You'll have a small bit of time after the UI becomes visible and before the user will actually use it. You'll want to use this time to load the rest of your services and preload more UI components to avoid the creation lag on UI thread later on.

I've done this kind of three-stage loading on Android without technical users even realizing it's not a native app. Would I do it again? Not really if platform native code is an option. There are too many details one has to handle when imitating platform visuals and interaction.


Still too slow on android.


I toyed with QML a few months ago. It seemed like it lacked even the most basic of events such as keydown/up in a text area. I didn't get very far and ended up using nw.js instead.


All QML visual elements support keyevents: http://doc.qt.io/qt-5/qml-qtquick-keys.html


I am currently toying with it again and none of those signals appear to be working on http://doc.qt.io/qt-5/qml-qtquick-controls-textarea.html#sig...


Hmm, then the documentation is to blame for not making the signaling inheritance clear.


Whenever I hear of a golang binding to a library implemented in C++ I'm always interested to see how they map the class hierarchy to golang's type model which doesn't have traditional inheritence.

Does QT's class hierarchy map cleanly to Go? Is it just interfaces everywhere?

(I'm not trying to start a language war, just genuinely curious.)


So it uses interfaces and anonymous fields. So if you are familiar with Qt, something like QPushButton would be implemented in go by having an anonymous field for QAbstractButton which would have an anonymous field for QWidget. Furthermore, this class has to implement an interface so it can be passed around like a normal QWidget in C++ would.

That was kind of a ramble, but thats the gist of it.


How does it manage C++ bindings? Rust struggled with that, and it has a lot of issues because of compiler specific name decorations and etc.

https://en.wikipedia.org/wiki/Name_mangling#How_different_co...


The difficulty in importing C++ libraries from other languages don't really represent a Rust issue, but rather a C++ issue, of course.

As to the very interesting question of how it's handled here, it looks like part of the project (the "qtdrv" folder) is a shared library written in C++ that includes Qt, wraps the desired functionality, and exports it as C-style symbols (with extern "C"). This is a pretty standard way of circumventing the name mangling problem.

What I find interesting is that everything appears to be wrapped into a single exported function "qtdrv". Might be a wrapping technique that I'm not aware of, or maybe I'm completely misreading the source. I'm actually quite interested in knowing how the wrapping code was generated, having projects where the same kind of C++ wrapping is required.


I haven't looked into the source, but Qt use a "MOC" pre-compilation system to generate introspection data. Once you have access to that, you don't have to mess with C++ symbols anymore. Same for the objects properties, you can get/set them by name.


In principle, yes, but a) access via MOC is certainly slower than compiling a direct function call into a single `call` opcode, and b) MOC only covers signals, slots, and Q_INVOKABLE methods. For QObjects, that means that the remaining methods are not accessible. And methods for non-QObject-derived classes are also inaccessible.


I guess success of such approach depends on how well C++ logic can be wrapped in C. It's not always straightforward or even possible.


Rust has #[no_mangle] and ffi types. I've done some FFI in Rust, and I've found it to be pretty pleasant. What are the "lot of issues" you're talking about?


C++ names decoration is a problem. no_mangle refers to Rust (i.e. it's useful for calling Rust code from other languages). Rust has no control over C++ names mangling.


Okay, sorry, read your original comment backwards.

Calling into C++ is generally a big problem in any programming language though, and for most, you have to write a C wrapper.


Not a problem for Julia: https://github.com/Keno/Cxx.jl


Looks like that uses Clang/LLVM. Does it work with C++ libraries built with GCC or MSVC?


MSVC: probably not; Clang's MSVC ABI support is coming along well, but last time I checked there was no COFF support in the JIT. GCC on Itanium ABI platforms should be fine, although mixing C++ stdlib versions would be risky (primarily an issue on OS X).


Note that C++ has "extern C" for the same purpose, and many people do not seem to be aware of it.

You can perfectly write a C++ library and expose a C-safe subset. I've done so many times.

The problem arises if you need to expose objects (with virtual methods), which C obviously doesn't have as the ffi is basically restricted to plain functions and record types.


[deleted]


Yes sorry, typo (fixed).


Rust has good C FFI. The Book (https://doc.rust-lang.org/book/ffi.html) itself says that Rust is not able to call directly into a C++ library.


Rust can call directly into a C++ library as long as it uses the C ABI: there aren't bindings to (a compiler-specific implementation of) the C++ type system. Go is just the same. This isn't really a language restriction, more a result of how rich the C type system is and how compiler-specific it is. The only languages that have direct C++ interop are those that directly use a C++ compiler (like Objective-C++).

It appears that GoQt has this giant pile of wrappers around C++ types, casting pointers back and forth:

https://raw.githubusercontent.com/visualfc/goqt/master/qtdrv...

I would have expected this to require an `extern "C"` declaration. I'm sort of surprised it doesn't, but maybe the common C++ ABIs match the C ones if only C types are passed to and from the function?

(Also, is this file auto-generated?)


I wonder though why C++ couldn't come up with a standard for names decoration? It would solve tons of such issues.


Name decoration isn't the hard part; it's types that are hard. Remember that a simple string is a std::basic_string<char, std::char_traits<char>, std::allocator<char>>; passing a string from one place to another requires either sharing the latter two, or having a way to convey pointers to what the latter two do. And that's not even considering things like, oh, throwing an exception whose class uses multiple inheritance and virtual methods.

Take a look at the Itanium C++ ABI, the de facto standard on GNU/Linux etc. for a sense of the scale of the problem: https://mentorembedded.github.io/cxx-abi/abi.html

And that doesn't even standardize the layout of the actual types in std::* themselves, just the typesystem. That just gives you enough information to correctly access someone else's implementation of std::string; you still need to have that precise implementation around at compile time. There is, however, a proposal to standardize the layout of std: https://isocpp.org/files/papers/n4028.pdf

To be fair, you have the exact same problem when trying to call into e.g. Rust from e.g. C. Rust's typesystem is complex and its libstd is involved and not stabilized, so the easiest way is, again, to route through C types instead of trying to access Rust's String type in C.


It'd be an improvement if everyone used the Itanium ABI, though.


> here is, however, a proposal to standardize the layout of std

That's interesting, thanks.


Compiler and OS vendors. The same behind undefined behavior.

Although people like to bash C++, there isn't any programming language with an ABI as part of the language standard, not even C.

The C ABI that so many people adhere to, only exists in OS written either in C or C++ (via extern "C").

By the historical accident that all commercial major OSes are mostly written in C, developers that aren't language lawyers tend to think C ABI is somehow defined in some standard.

In OSes that weren't written C, with C compilers available, like OS/400, VMS, Lillith, Lisp Machines, Oberon, the ABI being used isn't the C one.


Yes, the C ABI / calling convention is OS- and platform-specific. (Which does lead to practical problems on modern systems when you assume the ABI behaves similarly on different platforms; a good example is https://github.com/rust-lang/rust/pull/22862 , caused by 64-bit iOS treating varargs differently from OS X on x86-64 or even Linux on aarch64.)

However, within a given platform, the ABI tends to be small, clear, and well-documented. It's not documented in the C language standard, but there is documentation for it, from whoever defines the platform.

I thought I had mentioned this in another comment, but to be clear, I'm not trying to "bash C++"; plenty of other type systems and standard libraries have the same issue (including Go, Rust, Python, etc.). I'm just relaying the fact that, on the platforms where Go and Rust support FFI, they do so by implementing the C ABI, which is a stable ABI defined in the platform documentation, and the C++ ABI tends not to be well-defined or stable and is also much more complex to implement. This isn't a criticism of C++, just a fact. (And there are good things about this; for instance, C++'s type system is so much more useful than C's.)


Fair enough, my reaction was more to those that bash C++ without recognition that the issue is not C++ specific.


The answer is in the wikipedia article you linked to earlier...

    [it] would not suffice to guarantee C++ compiler
    interoperability and it might even create a false
    impression that interoperability is possible and
    safe when it isn't.


Oh, that's a very good point: if you have two different implementations of std::string, you want them to name-mangle differently so that you don't accidentally pass e.g. a GNU std::string to a function expecting an LLVM one.


It doesn't really answer the question. It's not only about compilers interoperability, but about improving situation with bindings from other languages. And making name mangling standard would surely improve it (at least somewhat).


I'm wondering how they deal with Go's garbage collector, which is allowed to move objects in memory.


The Go garbage collector only concerns itself with memory allocated in Go, not with memory allocated in C-land. So, it doesn't move C objects. (C objects are typically freed using finalizers, or an explicit method call.)

Of course, moving can cause problems for Go pointers in C land, but keeping Go pointers beyond a cgo function call will be prohibited in Go 1.6:

https://tip.golang.org/doc/go1.6#cgo


Yes, the callback functions (registered in Qt, calling back into Go) will probably be a problem then. I guess they will need to handle the situation through a kind of lookup-table approach, which of course will come at a cost.


Look in the doc folder of the project. It explains the design and memory layout. Its not as difficult as rust.


I'm not sure how it can be easier or harder for some languages (to make bindings to C++). C++ is just hard to make bindings to. Even if you do it from C to C++.



Last commit is from a year ago.


So does this mean you could write a QT application in Go on Linux and cross compile the whole mess for Windows?


I mean, theoretically, yes, if you're masochistic, but why wouldn't you just compile on Windows? This set of bindings even supports Windows: https://github.com/visualfc/goqt#system


Mostly because I don't have access to a copy of Windows to compile on :)


Totally understand that :)

Maybe https://www.appveyor.com/ would work out for you? It's free for OSS projects.


Anyone can get a free 180 day trial of any version of Windows. Just do a fresh install twice a year in a VM, no big deal :)


I like LiteIDE, I will have to give this a shake.


Yeah someday maybe we can get a vertical split pane like other environments have had for a decade or more!


A good thing liteIDE is free and opensource then, the one guy maintaining it is waiting for your invaluable contribution.


so, why don't you do it ?


Awesome, but them are going to be some fat static binaries. Of course I get the sense that shared libraries are being abandoned so that seems to be how things are going. You have to ship qt with any qt app anyway.


It's unfortunate on Linux, but on Windows and Mac, as you note, you're already shipping your users a copy of Qt with the application.

And, in the modern world of big computers (desktops and laptops), it is not all that big of a deal (I don't actually know, but I would guess it's on the order of a few MB, maybe in the tens of MBs), and from what I can tell a lot of applications are already built statically for distribution to Windows and Mac OS X.


UPX might be an option, if binary size is a concern.

I agree with you on "big computers" to an extent. I just bought a temporary [1] laptop. It's beefy enough, but only has 2GB of RAM and 32GB of relatively slow flash storage [2].

Mobile broadband prices have been falling in Australia but it's still at the point where I have to thing before downloading anything >5MB.

[1]: http://www.pendo.com.au/pendopad/pendopads-windows-8/pendo11... (I didn't pay RRP)

[2]: Okay, okay, it's still eMMC, but it feels slow.


In fact, Qt’s – or even Java’s – program sizes, if you bundle the runtime and all libs, are still smaller than what is currently distributed as node-webkit apps.


I personally think it's a complexity management problem and a version management problem. Shared libraries make sense for "timeless" stuff like math or very core system stuff, but beyond that there is too much variation both in version and in approach. Unless your target is a platform as rigidly managed as Apple, you must ship it all or you will get missing shared library errors.

I do think changes in how shared libraries are shipped or managed may help. I've had ideas for ages around using cryptographic hashes but have no time to experiment with such things.


Thw thing about Apple is they give no fucks about backwards compatibility for developers anyway. You're a developer and you're working with Apple tech, so naturally you were waiting in line in the cold to get their latest hw and sw, weren't you?

This bit me on the ass when Apple forced a libstdc++ update on OS X 10.3 with a new ABI, permanently breaking all C++ compilation on my Mac. Compiling C++ programs for 10.3 was still possible, but you needed a 10.4 machine, the latest Xcode, and compatibility libraries to do it.


That wasn't just Apple. The reason that happened was because gcc went from 3 to 4 in that time frame. gcc and C++ never guaranteed binary compatibility, especially between major versions.

I had similar problems on Linux and Solaris because of that transition. My own fault (actually my employer's) for assuming binary compatibility when it was never promised.


GCC transition from 3 to 4 didn't break the ABI. The last required ABI break was 3.0 to 3.1.


I'm not being pedantic. libstdc++ was mentioned. That always can break.

The ABI between g++ transitions is also platform and architecture dependent. Mac was PowerPC back then. Sun used Sparc. Not everything is always x86, even on Linux.


You are right, I had forgot that GCC broke the libstdc++ ABI between 3.3 and 3.4 (not 3.x to 4.x though). That was 12 years ago, though, the ABI has been stable ever since [1].

I still would characterize it a fairly stable ABI, not something that "can always break", especially compared with other vendors that break the library ABI every release.

[1] A new libstdc++ C++11 ABI was added in GCC 5.x but it is optional even in C++11 mode.


Indeed, but most Linux distros of the era did not force a new-ABI libstdc++ upgrade on you, breaking C++ compilation with a mandatory security update. Apple did. Therefore I bite my thumb at them.


Go typically uses dynamic linking for interfacing with foreign functions. The static-linking-only rule doesn't go quite that far.


It links to the qtdrv libraries it produces dynamically


Just built the "wiggly" example on OS X, the binary is 22 MB.


Is that stripped? What if you UPX it?


QMessageBoxWarningWithParentTitleTextButtonsStandardbutton

And people make fun about Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch in Wales.


Whoa cool. I was working on a fork of his original goui library and updating it for Qt5. Awesome to see this and im pumped to not have to keep working on the other fork.


my phone is showing there being a lot of empty comments from five decades ago. clearly signs consistent with time travel.


While Qt is awesome, I'm not so sure about it's recent license change. I know lots of people would love that, but for other programmers (stuck in big companies) this simply means that they can't use it, as not always money would be approved for commercial projects, even if the project do have a big budget.


I don't understand this comment. Isn't it still under LGPL or more liberal licenses, depending on the component, as it has always been? According to the website, it is.

http://doc.qt.io/qt-5/licensing.html

I see nothing in that list that seems different or that would prevent one from building commercial products on Qt without licensing fees.


LGPL v3 is _really_ complicated. That's a red flag for a lot of corporate lawyers.

As a result, some issues arise, such as code that is stuck on GPLv2 (e.g. removed the upgrade clause like the Linux kernel) may be incompatible with LGPLv3.

This blog tries to explain some of the issues. http://nmav.gnutls.org/2013/03/the-perils-of-lgplv3.html


I strongly disagree, since at a conceptual level it is a very simple license. As a distributor, you got provide users with the source code of the LGPLv3 parts and permit/provide so they can replace it with a modified version of their choice.

To make a car analogy, if the tires are made under LGPLv3, you got to tell them what kind of rubber it is made of and permit car owners to change the tire without the car saying "unapproved parts used, so I will refuse to start now until you have bought approved tires from an official car dealer". Every car made before 2000 managed to do this without even thinking about it.

FSF consider GPLv2 to be incompatible with this deal from a US-legal view, which is the same view that claim "further restrictions" only covers restrictions made from software licenses.


It's gone from (L)GPL v2 to v3, which some companies care a lot about (e.g. Apple).


Apple already refused to use LGPL v2 stuff. They refused to use anything (L)GPL in the past and now they continue to refuse to use anything (L)GPL. Apple is not a useful data point about what has changed, because they have not changed position based on v2 vs v3.


The move from LGPL 2.1 to 3 should only affect you if you ship locked-down devices, not if you develop "normal" software.


Wouldn't it prevent people writing GPL2 software from using it, as the anti-tivoization would not be GPL2 no additional restrictions clause friendly? See the GPL FAQ compatibility chart [1], bottom left. The case I'm thinking of is where if you fork somebody else's GPL2 project and don't expect to be able to ask them to relicense (e.g. code from a company that no longer exists).

[1]: https://www.gnu.org/licenses/gpl-faq.html#gpl-compat-matrix


Seems so, missed that aspect.


[deleted]


The FSF's interpretation is valid for GPLv2 and LGPLv2 as well, since the line "You may not impose any further restrictions on the recipients' exercise of the rights granted herein." is also in there (not everyone agrees with this interpreation, but that's beside the point). The anti-tivoization clauses are not considered to be the problem, generally, since app developers are not distributing tivoized hardware or tivoizing it with their software.

Also, the path for solving compliance problems for (L)GPLv3 is much more well defined, as opposed to the case of v2. That's a plus.


But that isn't new with the version change, is it? LGPL 2.1 also requires you to make your source code or object files available for iOS apps, and the restrictions clause is there as well.


I'm moving towards using Qt at work. My understanding is that nothing major changed with regards to licensing recently. Why do you think it is now more restrictive?


It's not, but it scares company lawyers nonetheless. For example if you develop a tool for internal use, and later decide to ship to 3rd parties, or more general audience (say mod tool editor for a game).




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: